diff --git a/src/add-ons/kernel/busses/scsi/ahci/ahci_defs.h b/src/add-ons/kernel/busses/scsi/ahci/ahci_defs.h index 7e20cfec78..59902f08b4 100644 --- a/src/add-ons/kernel/busses/scsi/ahci/ahci_defs.h +++ b/src/add-ons/kernel/busses/scsi/ahci/ahci_defs.h @@ -113,6 +113,62 @@ typedef struct { } ahci_hba; +typedef struct { + uint8 dsfis[0x1c]; // DMA Setup FIS + uint8 res1[0x04]; + uint8 psfis[0x14]; // PIO Setup FIS + uint8 res2[0x0c]; + uint8 rfis[0x20]; // D2H Register FIS + uint8 res3[0x04]; + uint8 sdbfis[0x08]; // Set Device Bits FIS + uint8 ufis[0x40]; // Unknown FIS + uint8 res4[0x60]; +} fis; + + +typedef struct { + union { + struct { + uint16 prdtl; // physical region description table length; + uint16 pmp : 4; // Port Multiplier Port + uint16 : 1; + uint16 c : 1; // Clear Busy upon R_OK + uint16 b : 1; // Build In Self Test + uint16 r : 1; // Reset + uint16 p : 1; // Prefetchable + uint16 w : 1; // Write + uint16 a : 1;// ATAPI + uint16 cfl : 5; // command FIS length + }; + uint32 prdtl_flags_cfl; + }; + uint32 ctba; // command table desciptor base address (alignment 128 byte) + uint32 ctbau; // command table desciptor base address upper + uint8 res1[0x10]; +} command_list_entry; + +#define COMMAND_LIST_ENTRY_COUNT 32 + +typedef struct { + uint32 dba; // Data Base Address (2-byte aligned) + uint32 dbau; // Data Base Address Upper + uint32 res; + uint32 dbc; // Bytecount (0-based, even, max 4MB) + #define DBC_I 0x80000000 /* Interrupt on completition */ +} prd; + + +typedef struct { + uint8 cfis[0x40]; // command FIS + uint8 acmd[0x20]; // ATAPI command + uint8 res[0x20]; // reserved +} command_table; + + +#define PRD_TABLE_ENTRY_COUNT 168 + + + extern scsi_sim_interface gAHCISimInterface; extern device_manager_info *gDeviceManager; extern pci_device_module_info *gPCI; diff --git a/src/add-ons/kernel/busses/scsi/ahci/ahci_port.cpp b/src/add-ons/kernel/busses/scsi/ahci/ahci_port.cpp index f9d670a2c2..2200db89c2 100644 --- a/src/add-ons/kernel/busses/scsi/ahci/ahci_port.cpp +++ b/src/add-ons/kernel/busses/scsi/ahci/ahci_port.cpp @@ -9,6 +9,7 @@ #include #include +#include #define TRACE(a...) dprintf("\33[34mahci:\33[0m " a) #define FLOW(a...) dprintf("ahci: " a) @@ -32,27 +33,35 @@ AHCIPort::Init() { TRACE("AHCIPort::Init port %d\n", fIndex); - size_t size = 999; + size_t size = sizeof(command_list_entry) * COMMAND_LIST_ENTRY_COUNT + sizeof(fis) + sizeof(command_table) + sizeof(prd) * PRD_TABLE_ENTRY_COUNT; - void *virtAddr; - void *physAddr; + char *virtAddr; + char *physAddr; - fArea = alloc_mem(&virtAddr, &physAddr, size, 0, "some AHCI port"); + fArea = alloc_mem((void **)&virtAddr, (void **)&physAddr, size, 0, "some AHCI port"); if (fArea < B_OK) { TRACE("failed allocating memory for port %d\n", fIndex); return fArea; } + memset(virtAddr, 0, size); - void *virtClbAddr; - void *physClbAddr = physAddr; - void *virtFisAddr; - void *physFisAddr = (char *)physAddr + 1024; - - - fRegs->clb = LO32(physClbAddr); - fRegs->clbu = HI32(physClbAddr); - fRegs->fb = LO32(physFisAddr); - fRegs->fbu = HI32(physFisAddr); + fCommandList = (command_list_entry *)virtAddr; + virtAddr += sizeof(command_list_entry) * COMMAND_LIST_ENTRY_COUNT; + fFIS = (fis *)virtAddr; + virtAddr += sizeof(fis); + fCommandTable = (command_table *)virtAddr; + virtAddr += sizeof(command_table); + fPRDTable = (prd *)virtAddr; + + fRegs->clb = LO32(physAddr); + fRegs->clbu = HI32(physAddr); + physAddr += sizeof(command_list_entry) * COMMAND_LIST_ENTRY_COUNT; + fRegs->fb = LO32(physAddr); + fRegs->fbu = HI32(physAddr); + physAddr += sizeof(fis); + fCommandList[0].ctba = LO32(physAddr); + fCommandList[0].ctbau = HI32(physAddr); + // prdt follows after command table return B_OK; } diff --git a/src/add-ons/kernel/busses/scsi/ahci/ahci_port.h b/src/add-ons/kernel/busses/scsi/ahci/ahci_port.h index ce58406205..631d6384e8 100644 --- a/src/add-ons/kernel/busses/scsi/ahci/ahci_port.h +++ b/src/add-ons/kernel/busses/scsi/ahci/ahci_port.h @@ -30,7 +30,12 @@ private: private: int fIndex; volatile ahci_port * fRegs; -area_id fArea; + area_id fArea; + + volatile fis * fFIS; + volatile command_list_entry * fCommandList; + volatile command_table * fCommandTable; + volatile prd * fPRDTable; }; #endif // _AHCI_PORT_H diff --git a/src/add-ons/kernel/busses/scsi/ahci/util.c b/src/add-ons/kernel/busses/scsi/ahci/util.c index 4c4fee4f7c..f3b46cb272 100644 --- a/src/add-ons/kernel/busses/scsi/ahci/util.c +++ b/src/add-ons/kernel/busses/scsi/ahci/util.c @@ -40,7 +40,6 @@ alloc_mem(void **virt, void **phy, size_t size, uint32 protection, const char *n ERROR("couldn't get mapping for %s\n", name); return B_ERROR; } - memset(virtadr, 0, size); if (virt) *virt = virtadr; if (phy)