From 9c7df214d8790f5cfebb32824f06f4844b4e69dd Mon Sep 17 00:00:00 2001 From: John Hodge Date: Mon, 17 Jun 2013 12:04:24 +0800 Subject: [PATCH] Modules/AHCI - Slowly fiddling --- KernelLand/Modules/Storage/AHCI/Makefile | 8 ++ KernelLand/Modules/Storage/AHCI/ahci.c | 90 +++++++++++++++++++++-- KernelLand/Modules/Storage/AHCI/ahci.h | 46 ++---------- KernelLand/Modules/Storage/AHCI/ahci_hw.h | 79 ++++++++++++++++++++ 4 files changed, 177 insertions(+), 46 deletions(-) create mode 100644 KernelLand/Modules/Storage/AHCI/Makefile create mode 100644 KernelLand/Modules/Storage/AHCI/ahci_hw.h diff --git a/KernelLand/Modules/Storage/AHCI/Makefile b/KernelLand/Modules/Storage/AHCI/Makefile new file mode 100644 index 00000000..5422446c --- /dev/null +++ b/KernelLand/Modules/Storage/AHCI/Makefile @@ -0,0 +1,8 @@ +# +# + +OBJ = ahci.o +NAME = AHCI + +-include ../Makefile.tpl + diff --git a/KernelLand/Modules/Storage/AHCI/ahci.c b/KernelLand/Modules/Storage/AHCI/ahci.c index 7a94aa4e..ffd66de6 100644 --- a/KernelLand/Modules/Storage/AHCI/ahci.c +++ b/KernelLand/Modules/Storage/AHCI/ahci.c @@ -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 +#include #include #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; +} + diff --git a/KernelLand/Modules/Storage/AHCI/ahci.h b/KernelLand/Modules/Storage/AHCI/ahci.h index cfed404c..39652956 100644 --- a/KernelLand/Modules/Storage/AHCI/ahci.h +++ b/KernelLand/Modules/Storage/AHCI/ahci.h @@ -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 index 00000000..c4a94f9f --- /dev/null +++ b/KernelLand/Modules/Storage/AHCI/ahci_hw.h @@ -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 + -- 2.20.1