Modules/AHCI - Slowly fiddling
authorJohn Hodge <[email protected]>
Mon, 17 Jun 2013 04:04:24 +0000 (12:04 +0800)
committerJohn Hodge <[email protected]>
Mon, 17 Jun 2013 04:04:24 +0000 (12:04 +0800)
KernelLand/Modules/Storage/AHCI/Makefile [new file with mode: 0644]
KernelLand/Modules/Storage/AHCI/ahci.c
KernelLand/Modules/Storage/AHCI/ahci.h
KernelLand/Modules/Storage/AHCI/ahci_hw.h [new file with mode: 0644]

diff --git a/KernelLand/Modules/Storage/AHCI/Makefile b/KernelLand/Modules/Storage/AHCI/Makefile
new file mode 100644 (file)
index 0000000..5422446
--- /dev/null
@@ -0,0 +1,8 @@
+#
+#
+
+OBJ = ahci.o
+NAME = AHCI
+
+-include ../Makefile.tpl
+
index 7a94aa4..ffd66de 100644 (file)
@@ -1,25 +1,99 @@
 /*
-* Acess2 Kernel - AHCI Driver
-* - By John Hodge (thePowersGang)
-*
-* ahci.c
-*/
+ * Acess2 Kernel - AHCI Driver
+ * - By John Hodge (thePowersGang)
+ *
+ * ahci.c
+ * - Driver core
+ */
+#define DEBUG  1
+#define VERSION        0x0001
+#include <acess.h>
+#include <modules.h>
 #include <drv_pci.h>
 #include "ahci.h"
 
+// === CONSTANTS ===
+#define MAX_CONTROLLERS        4
+
+// === PROTOTYPES ===
+ int   AHCI_Install(char **Arguments);
+ int   AHCI_Cleanup(void);
+
+// === GLOABLS ===
+MODULE_DEFINE(0, VERSION, AHCI, AHCI_Install, AHCI_Cleanup, "LVM", NULL);
+tAHCI_Ctrlr    gaAHCI_Controllers[MAX_CONTROLLERS];
+
 // === CODE ====
 int AHCI_Install(char **Arguments)
 {
-       // 010601/FFFFFF
-       while( (id = PCI_GetDeviceByClass(0x010000, 0xFF0000, id)) >= 0 && i < MAX_CONTROLLERS )
+
+       LOG("offsetof(struct sAHCI_MemSpace, Ports) = %x", offsetof(struct sAHCI_MemSpace, Ports));
+       ASSERT( offsetof(struct sAHCI_MemSpace, Ports) == 0x100 );
+
+       // 0106XX = Standard, 010400 = RAID
+        int    i = 0;
+        int    id = -1;
+       while( (id = PCI_GetDeviceByClass(0x010601, 0xFFFFFF, id)) >= 0 && i < MAX_CONTROLLERS )
        {
+               tAHCI_Ctrlr *ctrlr = &gaAHCI_Controllers[i];
                ctrlr->PMemBase = PCI_GetBAR(id, 5);
+               // 
                if( !ctrlr->PMemBase )
                {
+                       // ctrlr->PMemBase = PCI_AllocateBAR(id, 5);
                        // TODO: Allocate space
+                       continue ;
+               }
+               // - IO Address?
+               if( (ctrlr->PMemBase & 0x1FFF) ) {
+                       Log_Warning("AHCI", "Controller %i [PCI %i] is invalid (BAR5=%P)",
+                               i, id, ctrlr->PMemBase);
+                       continue;
                }
                
-               ctrlr->IRQNum = PCI_GetIRQ(id);
+               ctrlr->IRQ = PCI_GetIRQ(id);
+
+               // Prepare MMIO (two pages according to the spec)
+               ctrlr->MMIO = (void*)MM_MapHWPages(ctrlr->PMemBase, 2);
+
+               LOG("%i [%i]: %P/IRQ%i mapped to %p",
+                       i, id, ctrlr->PMemBase, ctrlr->IRQ, ctrlr->MMIO);
+
+               LOG(" CAP = %x, PI = %x, VS = %x",
+                       ctrlr->MMIO->CAP, ctrlr->MMIO->PI, ctrlr->MMIO->VS);
+       
+               i ++;
+       }
+       if( id >= 0 ) {
+               Log_Notice("AHCI", "Only up to %i controllers are supported", MAX_CONTROLLERS);
        }
+       
        return 0;
 }
+
+int AHCI_Cleanup(void)
+{
+       return 0;
+}
+
+int AHCI_InitSys(tAHCI_Ctrlr *Ctrlr)
+{
+       // 1. Set GHC.AE
+       Ctrlr->MMIO->GHC |= AHCI_GHC_AE;
+       // 2. Enumerate ports using PI
+       // 3. (for each port) Ensure that port is not running
+       //  - if PxCMD.(ST|CR|FRE|FR) all are clear, port is idle
+       //  - Idle is set by clearing PxCMD.ST and waiting for .CR to clear (timeout 500ms)
+       //  - AND .FRE = 0, checking .FR (timeout 500ms again)
+       //  > On timeout, port/HBA reset
+       // 4. Read CAP.NCS 
+       // 5. Allocate PxCLB and PxFB for each port (setting PxCMD.FRE once done)
+       // 6. Clear PxSERR with 1 to each implimented bit
+       // > Clear PxIS then IS.IPS before setting PxIE/GHC.IE
+       // 7. Set PxIE with desired interrupts and set GHC.IE
+       
+       // Detect present ports using:
+       // > PxTFD.STS.BSY = 0, PxTFD.STS.DRQ = 0, and PxSSTS.DET = 3
+       return 0;
+}
+
index cfed404..3965295 100644 (file)
@@ -8,47 +8,17 @@
 #ifndef _AHCI__AHCI_H_
 #define _AHCI__AHCI_H_
 
-#define AHCI_CAP_S64A  (1 << 31)       // Supports 64-bit addressing
-#define AHCI_CAP_SNCQ  (1 << 30)       // Supports Native Command Queuing
-#define AHCI_CAP_SXS   (1 << 5)        // Support External SATA
+#include "ahci_hw.h"
 
-struct sAHCI_MemSpace
+typedef struct sAHCI_Ctrlr     tAHCI_Ctrlr;
+
+struct sAHCI_Ctrlr
 {
-       Uint32  CAP;    // Host Capabilities
-       Uint32  GHC;    // Global Host Control;
-       Uint16  IS;     // Interrupt Status
-       Uint16  PI;     // Ports Implemented
-       Uint32  VS;     // Version
-       Uint32  CCC_CTL;        // Command Completion Coalsecing Control
-       Uint16  CCC_PORTS;      // Command Completion Coalsecing Ports
-       Uint32  EM_LOC; // Enclosure Management Location
-       Uint32  CAP2;   // Host Capabilities Extended
-       Uint16  BOHC;   // BIOS/OS Handoff Control and Status
-       
-       Uint16  _padding[(0x100-0x2C)/2];
+        int    PortCount;      
 
-       struct s_port
-       {
-               Uint32  PxCLB;  // Command List Base Address
-               Uint32  PxCLBU; // (High of above)
-               Uint32  PxFB;   // FIS Base Address
-               Uint32  PxFBU;  // (high of above)
-               Uint32  PxIS;   // Interrupt Status
-               Uint32  PxIE;   // Interrupt Enable
-               Uint32  PxCMD;  // Command and Status
-               Uint32  _resvd;
-               Uint32  PxTFD;  // Task File Data
-               Uint32  PxSIG;  // Signature
-               Uint32  PxSSTS; // Serial ATA Status
-               Uint32  PxSCTL; // Serial ATA Control
-               Uint32  PxSERR; // Serial ATA Error
-               Uint32  PxSACT; // Serial ATA Active
-               Uint32  PxCI;   // Command Issue
-               Uint32  PxSNTF; // Serial ATA Notification
-               Uint32  PxFBS;  // FIS-based Switching Control
-               Uint32  _resvd2[(0x70-0x44)/4];
-               Uint32  PxVS[4];
-       }       Ports[32];
+        int    IRQ;
+       tPAddr  PMemBase;
+       struct sAHCI_MemSpace   *MMIO;
 };
 
 #endif
diff --git a/KernelLand/Modules/Storage/AHCI/ahci_hw.h b/KernelLand/Modules/Storage/AHCI/ahci_hw.h
new file mode 100644 (file)
index 0000000..c4a94f9
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * Acess2 Kernel - AHCI Driver
+ * - By John Hodge (thePowersGang)
+ *
+ * ahci_hw.h
+ * - Hardware Definitions
+ */
+#ifndef _AHCI__AHCI_HW_H_
+#define _AHCI__AHCI_HW_H_
+
+#define AHCI_CAP_S64A  (1 << 31)       // Supports 64-bit addressing
+#define AHCI_CAP_SNCQ  (1 << 30)       // Supports Native Command Queuing
+#define AHCI_CAP_SXS   (1 << 5)        // Support External SATA
+
+#define AHCI_GHC_AE    (1 << 31)       // AHCI Enable
+#define AHCI_GHC_MRSM  (1 << 2)        // MSI Revert to Single Message
+#define AHCI_GHC_IE    (1 << 1)        // Interrupt Enable
+#define ACHI_GHC_HR    (1 << 0)        // HBA Reset (Clears once complete)
+
+struct sAHCI_MemSpace
+{
+       Uint32  CAP;    // Host Capabilities
+       Uint32  GHC;    // Global Host Control;
+       Uint32  IS;     // Interrupt Status
+       Uint32  PI;     // Ports Implemented
+       Uint32  VS;     // Version
+       Uint32  CCC_CTL;        // Command Completion Coalsecing Control
+       Uint32  CCC_PORTS;      // Command Completion Coalsecing Ports
+       Uint32  EM_LOC; // Enclosure Management Location
+       Uint32  EM_CTL; // Enclosure management control
+       Uint32  CAP2;   // Host Capabilities Extended
+       Uint32  BOHC;   // BIOS/OS Handoff Control and Status
+       
+       Uint16  _padding[(0x100-0x2C)/2];
+
+       struct s_port
+       {
+               Uint32  PxCLB;  // Command List Base Address
+               Uint32  PxCLBU; // (High of above)
+               Uint32  PxFB;   // FIS Base Address
+               Uint32  PxFBU;  // (high of above)
+               Uint32  PxIS;   // Interrupt Status
+               Uint32  PxIE;   // Interrupt Enable
+               Uint32  PxCMD;  // Command and Status
+               Uint32  _resvd;
+               Uint32  PxTFD;  // Task File Data
+               Uint32  PxSIG;  // Signature
+               Uint32  PxSSTS; // Serial ATA Status
+               Uint32  PxSCTL; // Serial ATA Control
+               Uint32  PxSERR; // Serial ATA Error
+               Uint32  PxSACT; // Serial ATA Active
+               Uint32  PxCI;   // Command Issue
+               Uint32  PxSNTF; // Serial ATA Notification
+               Uint32  PxFBS;  // FIS-based Switching Control
+               Uint32  _resvd2[(0x70-0x44)/4];
+               Uint32  PxVS[4];
+       }       Ports[32];
+} PACKED;
+
+struct sAHCI_CmdHdr
+{
+       Uint16  Flags;
+       Uint16  PRDTL;
+       Uint32  PRDBC;
+       Uint32  CTBA;   // 128-byte alignment
+       Uint32  CTBAU;
+       Uint32  resdv[4];
+} PACKED;
+
+struct sAHCI_CmdEnt
+{
+       Uint32  DBA;    // Data base address
+       Uint32  DBAU;   // (upper)
+       Uint32  resvd;
+       Uint32  DBC;    // Data byte count (31: IOC, 21:0 count) 0=1, 1=2, ...
+} PACKED;
+
+#endif
+

UCC git Repository :: git.ucc.asn.au