From c4fcd4e0c762334b039fabd35c712a6a8fd491bf Mon Sep 17 00:00:00 2001 From: John Hodge Date: Mon, 17 Jun 2013 15:59:42 +0800 Subject: [PATCH] Modules/AHCI - Creeping towards useful --- KernelLand/Modules/Storage/AHCI/ahci.c | 38 ++++++++++++++++---- KernelLand/Modules/Storage/AHCI/ahci_hw.h | 42 +++++++++++++++++++++++ 2 files changed, 74 insertions(+), 6 deletions(-) diff --git a/KernelLand/Modules/Storage/AHCI/ahci.c b/KernelLand/Modules/Storage/AHCI/ahci.c index ffd66de6..fc123776 100644 --- a/KernelLand/Modules/Storage/AHCI/ahci.c +++ b/KernelLand/Modules/Storage/AHCI/ahci.c @@ -81,12 +81,38 @@ 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 + tTime basetime; + for( int i = 0; i < 32; i ++ ) + { + if( !(Ctrlr->MMIO->PI & (1 << i)) ) + continue ; + volatile struct s_port *port = &Ctrlr->MMIO->Ports[i]; + nPorts ++; + // 3. (for each port) Ensure that port is not running + // - if PxCMD.(ST|CR|FRE|FR) all are clear, port is idle + if( (port->PxCMD & (AHCI_PxCMD_ST|AHCI_PxCMD_CR|AHCI_PxCMD_FRE|AHCI_PxCMD_FR)) == 0 ) + continue ; + // - Idle is set by clearing PxCMD.ST and waiting for .CR to clear (timeout 500ms) + // - AND .FRE = 0, checking .FR (timeout 500ms again) + port->PxCMD = 0; + basetime = now(); + // > On timeout, port/HBA reset + } + for( int i = 0; i < 32; i ++ ) + { + if( !(Ctrlr->MMIO->PI & (1 << i)) ) + continue ; + volatile struct s_port *port = &Ctrlr->MMIO->Ports[i]; + + while( (port->PxCMD & (AHCI_PxCMD_CR|AHCI_PxCMD_FR)) && now()-basetime < 500 ) + Time_Delay(10); + + if( !(port->PxCMD & (AHCI_PxCMD_CR|AHCI_PxCMD_FR)) ) + { + Log_Error("AHCI", "Port %i did not return to idle", i); + } + } + // 4. Read CAP.NCS to get number of command slots // 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 diff --git a/KernelLand/Modules/Storage/AHCI/ahci_hw.h b/KernelLand/Modules/Storage/AHCI/ahci_hw.h index c4a94f9f..bbfcbd13 100644 --- a/KernelLand/Modules/Storage/AHCI/ahci_hw.h +++ b/KernelLand/Modules/Storage/AHCI/ahci_hw.h @@ -11,12 +11,54 @@ #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_CAP_NCS (31 << 8) // Number of command slots (mask) #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) +#define AHCI_PxIS_CPDS (1 << 31) // Cold Port Detect Status +#define AHCI_PxIS_TFES (1 << 30) // Task File Error Status +#define AHCI_PxIS_HBFS (1 << 29) // Host Bus Fatal error Status +#define AHCI_PxIS_HBDS (1 << 28) // Host Bus Data error Status +#define AHCI_PxIS_IFS (1 << 27) // Interface Fatal error Status +#define AHCI_PxIS_INFS (1 << 26) // Interface Non-Fatal error status +#define AHCI_PxIS_OFS (1 << 24) // OverFlow Status +#define AHCI_PxIS_IPMS (1 << 23) // Incorrect Port Multipier Status +#define AHCI_PxIS_PRCS (1 << 22) // PhyRdy Change Status +#define AHCI_PxIS_DMPS (1 << 7) // Device Mechanical Presence Status +#define AHCI_PxIS_PCS (1 << 6) // Port Connect change Status +#define AHCI_PxIS_DPS (1 << 5) // Descriptor Processed +#define AHCI_PxIS_UFI (1 << 4) // Unknown FIX Interrupt +#define AHCI_PxIS_SDBS (1 << 3) // Set Device Bits Interrupt +#define AHCI_PxIS_DSS (1 << 2) // DMA Setup FIS Interrupt +#define AHCI_PxIS_PSS (1 << 1) // PIO Setup FIX Interrupt +#define AHCI_PxIS_DHRS (1 << 0) // Device to Host Register FIS Interrupt + +#define AHCI_PxCMD_ICC (15 << 28) // Interface Communication Control (mask) +#define AHCI_PxCMD_ASP (1 << 27) // Agressive Slumber / Partial +#define AHCI_PxCMD_ALPE (1 << 26) // Agressive Link Power Management Enable +#define AHCI_PxCMD_DLAE (1 << 25) // Drive LED on ATAPI Enable +#define AHCI_PxCMD_ATAPI (1 << 24) // Device is ATAPI +#define AHCI_PxCMD_APSTE (1 << 23) // Automatic Partial to Slumber Transitions Enabled +#define AHCI_PxCMD_FBSCP (1 << 22) // FIS-based Switching Capable Port +#define AHCI_PxCMD_ESP (1 << 21) // External SATA Port +#define AHCI_PxCMD_CPD (1 << 20) // Cold Presence Detection +#define AHCI_PxCMD_MPSP (1 << 19) // Mechanical Presence Switch attached to Port +#define AHCI_PxCMD_HPCP (1 << 18) // Hot Plut Capable Port +#define AHCI_PxCMD_PMA (1 << 17) // Port Multiplier Attached +#define AHCI_PxCMD_CPS (1 << 16) // Cold Presence State +#define AHCI_PxCMD_CR (1 << 15) // Command List Running +#define AHCI_PxCMD_FR (1 << 14) // FIS Receive Running +#define AHCI_PxCMD_MPSS (1 << 13) // Mechanical Presence Switch State +#define AHCI_PxCMD_CCS (31 << 8) // Current Command Slot (mask) +#define AHCI_PxCMD_FRE (1 << 4) // FIS Receive Enable +#define AHCI_PxCMD_CLO (1 << 3) // Command List Override +#define AHCI_PxCMD_POD (1 << 2) // Power On Device +#define AHCI_PxCMD_SUD (1 << 1) // Spin-Up Device +#define AHCI_PxCMD_ST (1 << 0) // Start + struct sAHCI_MemSpace { Uint32 CAP; // Host Capabilities -- 2.20.1