From 8524f8d12470679940f88a9fc50770f132acd658 Mon Sep 17 00:00:00 2001 From: John Hodge Date: Thu, 20 Jun 2013 14:46:11 +0800 Subject: [PATCH] Modules/AHCI - Reading the boot sector works --- KernelLand/Modules/Storage/AHCI/ahci.c | 407 +++++++++++++++++++++- KernelLand/Modules/Storage/AHCI/ahci.h | 22 +- KernelLand/Modules/Storage/AHCI/ahci_hw.h | 16 +- KernelLand/Modules/Storage/AHCI/ata.h | 52 +++ KernelLand/Modules/Storage/AHCI/sata.h | 3 + 5 files changed, 483 insertions(+), 17 deletions(-) create mode 100644 KernelLand/Modules/Storage/AHCI/ata.h diff --git a/KernelLand/Modules/Storage/AHCI/ahci.c b/KernelLand/Modules/Storage/AHCI/ahci.c index dfb7deba..691050b2 100644 --- a/KernelLand/Modules/Storage/AHCI/ahci.c +++ b/KernelLand/Modules/Storage/AHCI/ahci.c @@ -21,10 +21,33 @@ int AHCI_Cleanup(void); // - Hardware init int AHCI_InitSys(tAHCI_Ctrlr *Ctrlr); +void AHCI_QueryDevice(tAHCI_Ctrlr *Ctrlr, int PortNum); +void AHCI_IRQHandler(int UNUSED(IRQ), void *Data); +void AHCI_int_IRQHandlerPort(tAHCI_Port *Port); +// - LVM Interface +int AHCI_ReadSectors(void *Ptr, Uint64 Address, size_t Count, void *Buffer); +int AHCI_WriteSectors(void *Ptr, Uint64 Address, size_t Count, const void *Buffer); +// - Low Level + int AHCI_SendLBA28Cmd(tAHCI_Port *Port, int bWrite, + Uint8 Dev, Uint8 Sectors, Uint64 LBA, Uint8 Cmd, size_t Size, void *Data + ); + int AHCI_SendLBA48Cmd(tAHCI_Port *Port, int bWrite, + Uint8 Dev, Uint8 Sectors, Uint64 LBA, Uint8 Cmd, size_t Size, void *Data + ); + int AHCI_DoFIS(tAHCI_Port *Port, int bWrite, + size_t CmdSize, const void *CmdData, size_t PktSize, const void *PktData, + size_t OutSize, void *OutData + ); + int AHCI_WaitForInterrupt(tAHCI_Port *Port, unsigned int Timeout); // === GLOABLS === MODULE_DEFINE(0, VERSION, AHCI, AHCI_Install, AHCI_Cleanup, "LVM", NULL); tAHCI_Ctrlr gaAHCI_Controllers[MAX_CONTROLLERS]; +tLVM_VolType gAHCI_VolumeType = { + .Name = "AHCI", + .Read = AHCI_ReadSectors, + .Write = AHCI_WriteSectors + }; // === CODE ==== int AHCI_Install(char **Arguments) @@ -55,6 +78,7 @@ int AHCI_Install(char **Arguments) } ctrlr->IRQ = PCI_GetIRQ(id); + IRQ_AddHandler(ctrlr->IRQ, AHCI_IRQHandler, ctrlr); // Prepare MMIO (two pages according to the spec) ctrlr->MMIO = (void*)MM_MapHWPages(ctrlr->PMemBase, 2); @@ -101,6 +125,17 @@ static inline void *AHCI_AllocPage(tAHCI_Ctrlr *Ctrlr, const char *AllocName) return ret; } +static inline void AHCI_int_SetAddr(tAHCI_Ctrlr *Ctrlr, volatile Uint32 *Addr, tPAddr PAddr) +{ + Addr[0] = PAddr; + #if PHYS_BITS > 32 + if(Ctrlr->Supports64Bit) + Addr[1] = PAddr >> 32; + else + #endif + Addr[1] = 0; +} + int AHCI_InitSys(tAHCI_Ctrlr *Ctrlr) { // 1. Set GHC.AE @@ -135,6 +170,7 @@ int AHCI_InitSys(tAHCI_Ctrlr *Ctrlr) if( !(Ctrlr->MMIO->PI & (1 << i)) ) continue ; volatile struct s_port *port = &Ctrlr->MMIO->Ports[i]; + Ctrlr->Ports[idx].Ctrlr = Ctrlr; Ctrlr->Ports[idx].Idx = i; Ctrlr->Ports[idx].MMIO = port; idx ++; @@ -152,22 +188,21 @@ int AHCI_InitSys(tAHCI_Ctrlr *Ctrlr) // 5. Allocate PxCLB and PxFB for each port (setting PxCMD.FRE once done) struct sAHCI_RcvdFIS *fis_vpage = NULL; struct sAHCI_CmdHdr *cl_vpage = NULL; + struct sAHCI_CmdTable *ct_vpage = NULL; for( int i = 0; i < Ctrlr->PortCount; i ++ ) { + tAHCI_Port *port = &Ctrlr->Ports[i]; // CLB First (1 KB alignemnt) if( ((tVAddr)cl_vpage & 0xFFF) == 0 ) { cl_vpage = AHCI_AllocPage(Ctrlr, "CLB"); if( !cl_vpage ) return MODULE_ERR_MALLOC; } - Ctrlr->Ports[i].CmdList = cl_vpage; + port->CmdList = cl_vpage; cl_vpage += 1024/sizeof(*cl_vpage); - tPAddr cl_paddr = MM_GetPhysAddr(Ctrlr->Ports[i].CmdList); - Ctrlr->Ports[i].MMIO->PxCLB = cl_paddr; - #if PHYS_BITS > 32 - Ctrlr->Ports[i].MMIO->PxCLBU = cl_paddr >> 32; - #endif + tPAddr cl_paddr = MM_GetPhysAddr(port->CmdList); + AHCI_int_SetAddr(Ctrlr, &port->MMIO->PxCLB, cl_paddr); // Received FIS Area // - If there is space for the FIS in the end of the 1K block, use it @@ -186,18 +221,49 @@ int AHCI_InitSys(tAHCI_Ctrlr *Ctrlr) fis_vpage ++; } tPAddr fis_paddr = MM_GetPhysAddr(Ctrlr->Ports[i].RcvdFIS); - Ctrlr->Ports[i].MMIO->PxFB = fis_paddr; - #if PHYS_BITS > 32 - Ctrlr->Ports[i].MMIO->PxFBU = fis_paddr >> 32; - #endif + AHCI_int_SetAddr(Ctrlr, &port->MMIO->PxFB, fis_paddr); + + // Command tables + for( int j = 0; j < Ctrlr->NCS; j ++ ) + { + if( ((tVAddr)ct_vpage & 0xFFF) == 0 ) { + ct_vpage = AHCI_AllocPage(Ctrlr, "CmdTab"); + if( !ct_vpage ) + return MODULE_ERR_MALLOC; + } + port->CommandTables[j] = ct_vpage; + port->CmdList[j].Flags = 0; + port->CmdList[j].PRDTL = 0; + port->CmdList[j].PRDBC = 0; + AHCI_int_SetAddr(Ctrlr, &port->CmdList[j].CTBA, MM_GetPhysAddr(ct_vpage)); + ct_vpage ++; + } LOG("Port #%i: CLB=%p/%P, FB=%p/%P", i, Ctrlr->Ports[i].CmdList, cl_paddr, Ctrlr->Ports[i].RcvdFIS, fis_paddr); } + // 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 + for( int i = 0; i < Ctrlr->PortCount; i ++ ) + { + tAHCI_Port *port = &Ctrlr->Ports[i]; + + port->MMIO->PxSERR = 0x3FF783; + port->MMIO->PxIS = -1; + port->MMIO->PxIE = AHCI_PxIS_CPDS|AHCI_PxIS_DSS|AHCI_PxIS_PSS|AHCI_PxIS_DHRS; + } + Ctrlr->MMIO->IS = -1; + Ctrlr->MMIO->GHC |= AHCI_GHC_IE; + + // Start command engine on all implimented ports + for( int i = 0; i < Ctrlr->PortCount; i ++ ) + { + tAHCI_Port *port = &Ctrlr->Ports[i]; + port->MMIO->PxCMD |= AHCI_PxCMD_ST|AHCI_PxCMD_FRE; + } // Detect present ports using: // > PxTFD.STS.BSY = 0, PxTFD.STS.DRQ = 0, and PxSSTS.DET = 3 @@ -210,7 +276,326 @@ int AHCI_InitSys(tAHCI_Ctrlr *Ctrlr) LOG("Port #%i: Connection detected", i); Ctrlr->Ports[i].bPresent = 1; - // TODO: Query volumes connected + AHCI_QueryDevice(Ctrlr, i); + } + return 0; +} + +static inline void _flipChars(char *buffer, size_t pairs) +{ + for( int i = 0; i < pairs; i ++ ) + { + char tmp = buffer[i*2]; + buffer[i*2] = buffer[i*2+1]; + buffer[i*2+1] = tmp; + } +} + +void AHCI_QueryDevice(tAHCI_Ctrlr *Ctrlr, int PortNum) +{ + tAHCI_Port *const Port = &Ctrlr->Ports[PortNum]; + tATA_Identify data; + + AHCI_SendLBA28Cmd(Port, false, 0, 0, 0, ATA_CMD_IDENTIFY_DEVICE, sizeof(data), &data); + AHCI_WaitForInterrupt(Port, 1000); + // TODO: Check status from command + + // TODO: on error, mark device as bad and return + + _flipChars(data.SerialNum, 20/2); + _flipChars(data.FirmwareVer, 8/2); + _flipChars(data.ModelNumber, 40/2); + LOG("data.SerialNum = '%.20s'", data.SerialNum); + LOG("data.FirmwareVer = '%.8s'", data.FirmwareVer); + LOG("data.ModelNumber = '%.40s'", data.ModelNumber); + + Uint64 sector_count; + if( data.Sectors48 != 0 ) { + // Use LBA48 size + LOG("Size[48] = 0x%X", (Uint64)data.Sectors48); + sector_count = data.Sectors48; + } + else { + // Use LBA28 size + LOG("Size[28] = 0x%x", data.Sectors28); + sector_count = data.Sectors28; + } + + // Create LVM name + char lvmname[4+1+20+1]; + strcpy(lvmname, "AHCI:"); + memcpy(lvmname+5, data.SerialNum, 20); + for(int i = 20+5; i-- && lvmname[i] == ' '; ) + lvmname[i] = '\0'; + + // Register with LVM + Port->LVMHandle = LVM_AddVolume(&gAHCI_VolumeType, lvmname, Port, 512, sector_count); +} + +void AHCI_IRQHandler(int UNUSED(IRQ), void *Data) +{ + tAHCI_Ctrlr *Ctrlr = Data; + tAHCI_Port *port = &Ctrlr->Ports[0]; + + Uint32 IS = Ctrlr->MMIO->IS; + Uint32 PI = Ctrlr->MMIO->PI; + LOG("Ctrlr->MMIO->IS = %x", IS); + + for( int i = 0; i < 32; i ++ ) + { + if( !(PI & (1 << i)) ) + continue ; + if( IS & (1 << i) ) + { + AHCI_int_IRQHandlerPort(port); + } + port ++; + } + + Ctrlr->MMIO->IS = IS; +} + +void AHCI_int_IRQHandlerPort(tAHCI_Port *Port) +{ + Uint32 PxIS = Port->MMIO->PxIS; + LOG("port->MMIO->PxIS = %x", PxIS); + Port->LastIS |= PxIS; + if( PxIS & AHCI_PxIS_CPDS ) { + // Port change detected + } + + if( PxIS & AHCI_PxIS_DHRS ) { + LOG("Port->RcvdFIS->RFIS = {"); + LOG(".Status = 0x%02x", Port->RcvdFIS->RFIS.Status); + LOG(".Error = 0x%02x", Port->RcvdFIS->RFIS.Error); + LOG("}"); + } + + // Get bitfield of completed commands (Issued but no activity) + Uint32 done_commands = Port->IssuedCommands ^ Port->MMIO->PxSACT; + LOG("done_commands = %x", done_commands); + for( int i = 0; i < 32; i ++ ) + { + if( !(done_commands & (1 << i)) ) + continue; + ASSERT( Port->IssuedCommands & (1 << i) ); + // If complete, post a SHORTWAIT + if( Port->CommandThreads[i] ) { + LOG("%i - Poking thread %p", i, Port->CommandThreads[i]); + Threads_PostEvent(Port->CommandThreads[i], THREAD_EVENT_SHORTWAIT); + Port->CommandThreads[i] = NULL; + } + Port->IssuedCommands &= ~(1 << i); + } + Port->MMIO->PxIS = PxIS; +} + +// - LVM Interface +int AHCI_ReadSectors(void *Ptr, Uint64 Address, size_t Count, void *Buffer) +{ + tAHCI_Port *Port = Ptr; + + memset(Buffer, 0xFF, Count*512); + + ASSERT(Count <= 8096/512); + if( (Address+Count) < (1 << 24) ) + AHCI_SendLBA28Cmd(Port, 0, 0, Count, Address, ATA_CMD_READDMA28, Count*512, Buffer); + else + AHCI_SendLBA48Cmd(Port, 0, 0, Count, Address, ATA_CMD_READDMA48, Count*512, Buffer); + if( AHCI_WaitForInterrupt(Port, 1000) ) + return 0; + //Debug_HexDump("AHCI_ReadSectors", Buffer, Count*512); + // TODO: Check status from command + return Count; +} + +int AHCI_WriteSectors(void *Ptr, Uint64 Address, size_t Count, const void *Buffer) +{ + return 0; +} + +// -- Internals +int AHCI_int_GetCommandSlot(tAHCI_Port *Port) +{ + Mutex_Acquire(&Port->lCommandSlots); + Uint32 PxCI = Port->MMIO->PxCI; + Uint32 PxSACT = Port->MMIO->PxSACT; + for( int i = 0; i < Port->Ctrlr->NCS; i ++ ) + { + if( PxCI & (1 << i) ) + continue ; + if( PxSACT & (1 << i) ) + continue ; + LOG("Allocated slot %i", i); + Port->IssuedCommands |= (1 << i); + return i; + } + return -1; +} +void AHCI_int_StartCommand(tAHCI_Port *Port, int Slot) +{ + Port->MMIO->PxCI = 1 << Slot; + Mutex_Release(&Port->lCommandSlots); +} +void AHCI_int_CancelCommand(tAHCI_Port *Port, int Slot) +{ + // Release command + Port->IssuedCommands &= ~(1 << Slot); + Mutex_Release(&Port->lCommandSlots); +} + +// -- Low Level +int AHCI_SendLBA48Cmd(tAHCI_Port *Port, int bWrite, + Uint8 Dev, Uint8 Sectors, Uint64 LBA, Uint8 Cmd, size_t Size, void *Data) +{ + struct sSATA_FIS_H2DRegister regs; + + regs.Type = SATA_FIS_H2DRegister; + regs.Flags = 0x80; // [7]: Update to command register + regs.Command = Cmd; + regs.Features = 0; + + regs.SectorNum = LBA; + regs.CylLow = LBA >> 8; + regs.CylHigh = LBA >> 16; + regs.Dev_Head = 0x40|Dev; // TODO: Need others? + + regs.SectorNumExp = LBA >> 24; + regs.CylLowExp = LBA >> 32; + regs.CylHighExp = LBA >> 40; + regs.FeaturesExp = 0; + + regs.SectorCount = Sectors; + regs.SectorCountExp = 0; + regs.Control = 0; + + LOG("Sending command %02x with %p+0x%x", Cmd, Data, Size); + AHCI_DoFIS(Port, bWrite, sizeof(regs), ®s, 0, NULL, Size, Data); + + return 0; +} + +int AHCI_SendLBA28Cmd(tAHCI_Port *Port, int bWrite, + Uint8 Dev, Uint8 Sectors, Uint64 LBA, Uint8 Cmd, size_t Size, void *Data) +{ + struct sSATA_FIS_H2DRegister regs; + + ASSERT(LBA < (1 << 24)); + + regs.Type = SATA_FIS_H2DRegister; + regs.Flags = 0x80; // [7]: Update to command register + regs.Command = Cmd; + regs.Features = 0; + + regs.SectorNum = LBA; + regs.CylLow = LBA >> 8; + regs.CylHigh = LBA >> 16; + regs.Dev_Head = 0x40|Dev|(LBA >> 24); + + regs.SectorNumExp = 0; + regs.CylLowExp = 0; + regs.CylHighExp = 0; + regs.FeaturesExp = 0; + + regs.SectorCount = Sectors; + regs.SectorCountExp = 0; + regs.Control = 0; + + LOG("Sending command %02x with %p+0x%x", Cmd, Data, Size); + AHCI_DoFIS(Port, bWrite, sizeof(regs), ®s, 0, NULL, Size, Data); + + return 0; +} + +int AHCI_ReadFIS(tAHCI_Port *Port, + size_t CmdSize, const void *CmdData, size_t PktSize, const void *PktData, + size_t InSize, void *InData) +{ + return AHCI_DoFIS(Port, 0, CmdSize, CmdData, PktSize, PktData, InSize, InData); +} +int AHCI_WriteFIS(tAHCI_Port *Port, + size_t CmdSize, const void *CmdData, size_t PktSize, const void *PktData, + size_t OutSize, const void *OutData) +{ + return AHCI_DoFIS(Port, 1, CmdSize, CmdData, PktSize, PktData, OutSize, (void*)OutData); +} + +int AHCI_DoFIS(tAHCI_Port *Port, int bWrite, + size_t CmdSize, const void *CmdData, size_t PktSize, const void *PktData, + size_t OutSize, void *OutData) +{ + // 1. Obtain a command slot + int slot = AHCI_int_GetCommandSlot(Port); + if( slot < 0 ) { + return -1; + } + ASSERT(slot < 32); + struct sAHCI_CmdTable *cmdt = Port->CommandTables[slot]; + + // 2. Fill commands + if( CmdSize > 64 ) { + Log_Error("AHCI", "_DoFIS: Command FIS size %i > 64", CmdSize); + goto error; + } + memcpy(cmdt->CFIS, CmdData, CmdSize); + if(PktSize > 16) { + Log_Error("AHCI", "_DoFIS: ATAPI packet size %i > 64", PktSize); + goto error; + } + memcpy(cmdt->ACMD, PktData, PktSize); + + // 3. Set pointers + size_t ofs = 0; + int prdtl = 0; + while( ofs < OutSize ) + { + tPAddr phys = MM_GetPhysAddr( (char*)OutData + ofs ); + ASSERT( !(phys & 3) ); + // TODO: must be 4 byte aligned, and handle 64-bit addressing + size_t len = MIN(OutSize - ofs, PAGE_SIZE - (phys % PAGE_SIZE)); + ASSERT( !(len & 1) ); + ASSERT( len < 4*1024*1024 ); + LOG("PRDTL[%i] = %P+%i", prdtl, phys, len); + // TODO: count must be even. + AHCI_int_SetAddr(Port->Ctrlr, &cmdt->PRDT[prdtl].DBA, phys); + cmdt->PRDT[prdtl].DBC = len-1; + prdtl ++; + ofs += len; + } + ASSERT(ofs == OutSize); + cmdt->PRDT[prdtl-1].DBC |= (1<<31); // Set IOC + + // TODO: Port multipliers + Port->CmdList[slot].PRDTL = prdtl; + Port->CmdList[slot].Flags = (bWrite << 6) | (CmdSize / 4); + + // Prepare interrupt + Port->CommandThreads[slot] = Proc_GetCurThread(); + Threads_ClearEvent(THREAD_EVENT_SHORTWAIT); + + // 4. Dispatch + AHCI_int_StartCommand(Port, slot); + + return 0; +error: + AHCI_int_CancelCommand(Port, slot); + return -1; +} + +int AHCI_WaitForInterrupt(tAHCI_Port *Port, unsigned int Timeout) +{ + // Set up a timeout callback + Threads_ClearEvent(THREAD_EVENT_TIMER); + tTimer *timeout = Time_AllocateTimer(NULL, NULL); + Time_ScheduleTimer(timeout, Timeout); + + // Wait until an interrupt arrives or the timeout fires + Uint32 ev = Threads_WaitEvents(THREAD_EVENT_SHORTWAIT|THREAD_EVENT_TIMER); + Time_FreeTimer(timeout); + + if( ev & THREAD_EVENT_TIMER ) { + Log_Notice("AHCI", "Timeout of %i ms exceeded", Timeout); + return 1; } return 0; } diff --git a/KernelLand/Modules/Storage/AHCI/ahci.h b/KernelLand/Modules/Storage/AHCI/ahci.h index bc822d5e..7052b3d8 100644 --- a/KernelLand/Modules/Storage/AHCI/ahci.h +++ b/KernelLand/Modules/Storage/AHCI/ahci.h @@ -11,7 +11,9 @@ #include "ahci_hw.h" #include #include +#include #include +#include typedef struct sAHCI_Ctrlr tAHCI_Ctrlr; typedef struct sAHCI_Port tAHCI_Port; @@ -21,6 +23,8 @@ struct sAHCI_Ctrlr int IRQ; tPAddr PMemBase; tAHCI_MemSpace *MMIO; + + bool Supports64Bit; int NCS; @@ -31,14 +35,22 @@ struct sAHCI_Ctrlr struct sAHCI_Port { int Idx; // Hardware index + tAHCI_Ctrlr *Ctrlr; volatile struct s_port *MMIO; - bool bHotplug; - bool bPresent; - tSemaphore CommandListSem; - volatile struct sAHCI_CmdHdr *CmdList; + tMutex lCommandSlots; + Uint32 IssuedCommands; + volatile struct sAHCI_CmdHdr *CmdList; + struct sAHCI_CmdTable *CommandTables[32]; + tThread *CommandThreads[32]; + volatile struct sAHCI_RcvdFIS *RcvdFIS; - volatile struct sAHCI_RcvdFIS *RcvdFIS; + tSemaphore InterruptSem; + Uint32 LastIS; + + bool bHotplug; + bool bPresent; + bool bATAPI; void *LVMHandle; }; diff --git a/KernelLand/Modules/Storage/AHCI/ahci_hw.h b/KernelLand/Modules/Storage/AHCI/ahci_hw.h index 0610ad1e..d74f8224 100644 --- a/KernelLand/Modules/Storage/AHCI/ahci_hw.h +++ b/KernelLand/Modules/Storage/AHCI/ahci_hw.h @@ -137,7 +137,13 @@ struct sAHCI_CmdHdr Uint32 PRDBC; Uint32 CTBA; // 128-byte alignment Uint32 CTBAU; - Uint32 resdv[4]; + union { + struct { + struct sThread *Thread; + struct sAHCI_CmdTable *TablePtr; + } PACKED Ptrs; + Uint32 resdv[4]; + } Resvd; } PACKED; struct sAHCI_CmdEnt @@ -148,5 +154,13 @@ struct sAHCI_CmdEnt Uint32 DBC; // Data byte count (31: IOC, 21:0 count) 0=1, 1=2, ... } PACKED; +struct sAHCI_CmdTable +{ + Uint32 CFIS[64/4]; + Uint32 ACMD[16/4]; + Uint32 _resvd[0x30/4]; + struct sAHCI_CmdEnt PRDT[0x80/16]; +} PACKED; + #endif diff --git a/KernelLand/Modules/Storage/AHCI/ata.h b/KernelLand/Modules/Storage/AHCI/ata.h new file mode 100644 index 00000000..df36dac9 --- /dev/null +++ b/KernelLand/Modules/Storage/AHCI/ata.h @@ -0,0 +1,52 @@ +/* + * Acess2 + * - By John Hodge (thePowersGang) + * + * ata.h + * - ATA Definitions + */ +#ifndef _AHCI__ATA_H_ +#define _AHCI__ATA_H_ + +enum eATA_Commands +{ + ATA_CMD_IDENTIFY_DEVICE = 0xEC, + ATA_CMD_READDMA48 = 0x25, + ATA_CMD_READDMA28 = 0xC8, +}; + +#define ATA_STATUS_ERR 0x01 // Error encountered +#define ATA_STATUS_DRQ 0x08 // Data Request +#define ATA_STATUS_CDEP 0x10 // Command-dependent +#define ATA_STATUS_DF 0x20 // Device Fault +#define ATA_STATUS_DRDY 0x40 // Device ready +#define ATA_STATUS_BSY 0x80 // Device busy + +typedef struct sATA_Identify tATA_Identify; + +/** + * \brief Structure returned by the ATA IDENTIFY command + */ +struct sATA_Identify +{ + Uint16 Flags; // 1 + Uint16 Usused1[9]; // 10 + char SerialNum[20]; // 20 + Uint16 Usused2[3]; // 23 + char FirmwareVer[8]; // 27 + char ModelNumber[40]; // 47 + Uint16 SectPerInt; // 48 - Low byte only + Uint16 Unused3; // 49 + Uint16 Capabilities[2]; // 51 + Uint16 Unused4[2]; // 53 + Uint16 ValidExtData; // 54 + Uint16 Unused5[5]; // 59 + Uint16 SizeOfRWMultiple; // 60 + Uint32 Sectors28; // LBA 28 Sector Count + Uint16 Unused6[100-62]; + Uint64 Sectors48; // LBA 48 Sector Count + Uint16 Unused7[256-104]; +} PACKED; + +#endif + diff --git a/KernelLand/Modules/Storage/AHCI/sata.h b/KernelLand/Modules/Storage/AHCI/sata.h index f17b7242..7730c753 100644 --- a/KernelLand/Modules/Storage/AHCI/sata.h +++ b/KernelLand/Modules/Storage/AHCI/sata.h @@ -8,8 +8,11 @@ #ifndef _AHCI__SATA_H_ #define _AHCI__SATA_H_ +#include "ata.h" + enum eSATA_FIS_Types { + SATA_FIS_H2DRegister = 0x27, SATA_FIS_D2HRegister = 0x34, SATA_FIS_DMASetup = 0x41, SATA_FIS_Data = 0x46, -- 2.20.1