--- /dev/null
+#
+#
+
+OBJ = ahci.o
+NAME = AHCI
+
+-include ../Makefile.tpl
+
/*
-* 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;
+}
+
#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
--- /dev/null
+/*
+ * 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
+