diff --git a/src/include/ahci.h b/src/include/ahci.h index 8c63ca2..957ed3e 100644 --- a/src/include/ahci.h +++ b/src/include/ahci.h @@ -99,7 +99,9 @@ typedef struct { uint8_t FISType; - uint8_t PortMultiplier; + uint8_t PortMultiplier : 4; + uint8_t reserved : 3; + uint8_t commandControl : 1; uint8_t command; uint8_t FeatureLow; diff --git a/src/include/ahci.h b/src/include/ahci.h index 8c63ca2..957ed3e 100644 --- a/src/include/ahci.h +++ b/src/include/ahci.h @@ -99,7 +99,9 @@ typedef struct { uint8_t FISType; - uint8_t PortMultiplier; + uint8_t PortMultiplier : 4; + uint8_t reserved : 3; + uint8_t commandControl : 1; uint8_t command; uint8_t FeatureLow; diff --git a/src/kernel/drivers/pci/hardDrive/ahciController.c b/src/kernel/drivers/pci/hardDrive/ahciController.c index 8f3e441..98e7d02 100644 --- a/src/kernel/drivers/pci/hardDrive/ahciController.c +++ b/src/kernel/drivers/pci/hardDrive/ahciController.c @@ -47,11 +47,13 @@ Port *port = (void *)drive->interface; printf("start "); yields(); - ahciCommand(port->HBAPortPtr, lba, buffer, count, ATA_CMD_READ_DMA_EXT); + ahciCommand(port->HBAPortPtr, lba, buffer, count, ATA_CMD_READ_DMA_EX); printf("end %x\n", *(uint64_t *)buffer); yields(); } +void ahciIdentify(HBAPort *hbaPort, void *buffer); + void preparePorts(HBAMemory *hba, ListElement **drives) { for (uint8_t i = 0; i < 32; i++) { if (!(hba->PortsImplemented & (uint32_t)(1 << i))) { @@ -75,7 +77,8 @@ configurePort(port); printf("reconfigured the port\n"); yields(); - ahciCommand(port->HBAPortPtr, 0, &ident, 0, ATA_CMD_IDENTIFY); + // ahciCommand(port->HBAPortPtr, 0, &ident, 0, ATA_CMD_IDENTIFY); + ahciIdentify(port->HBAPortPtr, &ident); HardDrive *hardDrive = malloc(sizeof(HardDrive)); hardDrive->interface = port; hardDrive->access = accessAHCIDrive; @@ -131,16 +134,59 @@ #define HBA_PxIS_TFES (1 << 30) -bool ahciCommand(HBAPort *hbaPort, uint64_t Sector, void *Buffer, - uint32_t SectorCount, uint8_t command) { +void ahciIdentify(HBAPort *hbaPort, void *buffer) { hbaPort->InterruptStatus = (uint32_t)-1; hbaPort->InterruptEnable = (uint32_t)-1; HBACommandHeader *commandHeader = (void *)(uintptr_t)hbaPort->CommandListBase; commandHeader->CommandFISLength = sizeof(FisToDevice) / sizeof(uint32_t); commandHeader->Write = 0; - commandHeader->ClearBusy = SectorCount ? 1 : 0; + commandHeader->ClearBusy = 0; commandHeader->PRDTLength = 1; + commandHeader->PRDBCount = 0; + + HBACommandTable *CommandTable = + (void *)(uintptr_t)(commandHeader->CommandTableBaseAddress); + CommandTable->PRDTEntry[0].DataBaseAddress = LOWER(buffer); + CommandTable->PRDTEntry[0].ByteCount = 511; + CommandTable->PRDTEntry[0].InterruptOnCompletion = 1; + + FisToDevice *CommandFIS = (FisToDevice *)(&CommandTable->CommandFIS); + CommandFIS->FISType = FIS_TYPE_REG_H2D; + CommandFIS->command = ATA_CMD_IDENTIFY; + CommandFIS->commandControl = 1; + CommandFIS->DeviceRegister = (1 << 6); + uint64_t Spin = 0; + while ((hbaPort->TaskFileData & (ATA_DEV_BUSY | ATA_DEV_DRQ)) && + Spin < 1000000) { + Spin++; + } + if (Spin == 1000000) { + printf("ahci command timeout\n"); + return; + } + hbaPort->CommandIssue = 1; + while (true) { + if (hbaPort->CommandIssue == 0) { + break; + } + if (hbaPort->InterruptStatus & HBA_PxIS_TFES) { + return; + } + } + printf("count: %i ", commandHeader->PRDBCount); +} + +bool ahciCommand(HBAPort *hbaPort, uint64_t Sector, void *Buffer, + uint32_t SectorCount, uint8_t command) { + hbaPort->InterruptStatus = (uint32_t)-1; + HBACommandHeader *commandHeader = + (void *)(uintptr_t)hbaPort->CommandListBase; + commandHeader->CommandFISLength = sizeof(FisToDevice) / sizeof(uint32_t); + commandHeader->Write = 0; + // commandHeader->ClearBusy = 1; + commandHeader->PRDTLength = 1; + // commandHeader->PortMultiplier = 0; HBACommandTable *CommandTable = (void *)(uintptr_t)(commandHeader->CommandTableBaseAddress); @@ -148,13 +194,13 @@ CommandTable->PRDTEntry[0].DataBaseAddress = LOWER(Buffer); CommandTable->PRDTEntry[0].DataBaseAddressUpper = UPPER(Buffer); - CommandTable->PRDTEntry[0].ByteCount = - SectorCount ? 512 * SectorCount - 1 : 511; - CommandTable->PRDTEntry[0].InterruptOnCompletion = 0; // 1; + CommandTable->PRDTEntry[0].ByteCount = 512 * SectorCount - 1; + CommandTable->PRDTEntry[0].InterruptOnCompletion = 1; FisToDevice *CommandFIS = (FisToDevice *)(&CommandTable->CommandFIS); + memset(CommandFIS, 0, sizeof(FisToDevice)); CommandFIS->FISType = FIS_TYPE_REG_H2D; - CommandFIS->PortMultiplier = 1 << 7; + CommandFIS->commandControl = 1; CommandFIS->command = command; CommandFIS->LBA0 = (uint8_t)(Sector); CommandFIS->LBA1 = (uint8_t)(Sector >> 8); @@ -162,10 +208,9 @@ CommandFIS->LBA3 = (uint8_t)(Sector >> 24); CommandFIS->LBA4 = (uint8_t)(Sector >> 32); CommandFIS->LBA5 = (uint8_t)(Sector >> 40); - CommandFIS->DeviceRegister = (1 << 6); + CommandFIS->DeviceRegister = 1 << 6; CommandFIS->countLow = SectorCount & 0xFF; CommandFIS->countHigh = (SectorCount >> 8) & 0xFF; - CommandFIS->Control = 0; // 1 << 3; uint64_t Spin = 0; while ((hbaPort->TaskFileData & (ATA_DEV_BUSY | ATA_DEV_DRQ)) && Spin < 1000000) { @@ -200,7 +245,6 @@ printf("controller not in ahci mode!\n"); return; } - // hba->GlobalHostControl |= 1 << 31; if (hba->HostCapabilitiesExtended & 1) { printf("the os does not own the hba, getting it now...\n"); yields(); @@ -209,17 +253,5 @@ !(hba->BIOSHandoffControlStatus & OsOwnership)) { } } - // hba->GlobalHostControl |= 1; - // while (hba->GlobalHostControl & 1) { - //} - // hba->GlobalHostControl |= 1 << 31; - // sleep(1000); - // enabling bus mastering and memory access - // uint16_t command = pciConfigReadWord(pciDevice->bus, pciDevice->device, - // pciDevice->function, 4); - // command |= (1 << 1) | (1 << 2); - // pciConfigWriteByte(pciDevice->bus, pciDevice->device, - // pciDevice->function, - // 4, (uint8_t)command); preparePorts(hba, drives); } diff --git a/src/include/ahci.h b/src/include/ahci.h index 8c63ca2..957ed3e 100644 --- a/src/include/ahci.h +++ b/src/include/ahci.h @@ -99,7 +99,9 @@ typedef struct { uint8_t FISType; - uint8_t PortMultiplier; + uint8_t PortMultiplier : 4; + uint8_t reserved : 3; + uint8_t commandControl : 1; uint8_t command; uint8_t FeatureLow; diff --git a/src/kernel/drivers/pci/hardDrive/ahciController.c b/src/kernel/drivers/pci/hardDrive/ahciController.c index 8f3e441..98e7d02 100644 --- a/src/kernel/drivers/pci/hardDrive/ahciController.c +++ b/src/kernel/drivers/pci/hardDrive/ahciController.c @@ -47,11 +47,13 @@ Port *port = (void *)drive->interface; printf("start "); yields(); - ahciCommand(port->HBAPortPtr, lba, buffer, count, ATA_CMD_READ_DMA_EXT); + ahciCommand(port->HBAPortPtr, lba, buffer, count, ATA_CMD_READ_DMA_EX); printf("end %x\n", *(uint64_t *)buffer); yields(); } +void ahciIdentify(HBAPort *hbaPort, void *buffer); + void preparePorts(HBAMemory *hba, ListElement **drives) { for (uint8_t i = 0; i < 32; i++) { if (!(hba->PortsImplemented & (uint32_t)(1 << i))) { @@ -75,7 +77,8 @@ configurePort(port); printf("reconfigured the port\n"); yields(); - ahciCommand(port->HBAPortPtr, 0, &ident, 0, ATA_CMD_IDENTIFY); + // ahciCommand(port->HBAPortPtr, 0, &ident, 0, ATA_CMD_IDENTIFY); + ahciIdentify(port->HBAPortPtr, &ident); HardDrive *hardDrive = malloc(sizeof(HardDrive)); hardDrive->interface = port; hardDrive->access = accessAHCIDrive; @@ -131,16 +134,59 @@ #define HBA_PxIS_TFES (1 << 30) -bool ahciCommand(HBAPort *hbaPort, uint64_t Sector, void *Buffer, - uint32_t SectorCount, uint8_t command) { +void ahciIdentify(HBAPort *hbaPort, void *buffer) { hbaPort->InterruptStatus = (uint32_t)-1; hbaPort->InterruptEnable = (uint32_t)-1; HBACommandHeader *commandHeader = (void *)(uintptr_t)hbaPort->CommandListBase; commandHeader->CommandFISLength = sizeof(FisToDevice) / sizeof(uint32_t); commandHeader->Write = 0; - commandHeader->ClearBusy = SectorCount ? 1 : 0; + commandHeader->ClearBusy = 0; commandHeader->PRDTLength = 1; + commandHeader->PRDBCount = 0; + + HBACommandTable *CommandTable = + (void *)(uintptr_t)(commandHeader->CommandTableBaseAddress); + CommandTable->PRDTEntry[0].DataBaseAddress = LOWER(buffer); + CommandTable->PRDTEntry[0].ByteCount = 511; + CommandTable->PRDTEntry[0].InterruptOnCompletion = 1; + + FisToDevice *CommandFIS = (FisToDevice *)(&CommandTable->CommandFIS); + CommandFIS->FISType = FIS_TYPE_REG_H2D; + CommandFIS->command = ATA_CMD_IDENTIFY; + CommandFIS->commandControl = 1; + CommandFIS->DeviceRegister = (1 << 6); + uint64_t Spin = 0; + while ((hbaPort->TaskFileData & (ATA_DEV_BUSY | ATA_DEV_DRQ)) && + Spin < 1000000) { + Spin++; + } + if (Spin == 1000000) { + printf("ahci command timeout\n"); + return; + } + hbaPort->CommandIssue = 1; + while (true) { + if (hbaPort->CommandIssue == 0) { + break; + } + if (hbaPort->InterruptStatus & HBA_PxIS_TFES) { + return; + } + } + printf("count: %i ", commandHeader->PRDBCount); +} + +bool ahciCommand(HBAPort *hbaPort, uint64_t Sector, void *Buffer, + uint32_t SectorCount, uint8_t command) { + hbaPort->InterruptStatus = (uint32_t)-1; + HBACommandHeader *commandHeader = + (void *)(uintptr_t)hbaPort->CommandListBase; + commandHeader->CommandFISLength = sizeof(FisToDevice) / sizeof(uint32_t); + commandHeader->Write = 0; + // commandHeader->ClearBusy = 1; + commandHeader->PRDTLength = 1; + // commandHeader->PortMultiplier = 0; HBACommandTable *CommandTable = (void *)(uintptr_t)(commandHeader->CommandTableBaseAddress); @@ -148,13 +194,13 @@ CommandTable->PRDTEntry[0].DataBaseAddress = LOWER(Buffer); CommandTable->PRDTEntry[0].DataBaseAddressUpper = UPPER(Buffer); - CommandTable->PRDTEntry[0].ByteCount = - SectorCount ? 512 * SectorCount - 1 : 511; - CommandTable->PRDTEntry[0].InterruptOnCompletion = 0; // 1; + CommandTable->PRDTEntry[0].ByteCount = 512 * SectorCount - 1; + CommandTable->PRDTEntry[0].InterruptOnCompletion = 1; FisToDevice *CommandFIS = (FisToDevice *)(&CommandTable->CommandFIS); + memset(CommandFIS, 0, sizeof(FisToDevice)); CommandFIS->FISType = FIS_TYPE_REG_H2D; - CommandFIS->PortMultiplier = 1 << 7; + CommandFIS->commandControl = 1; CommandFIS->command = command; CommandFIS->LBA0 = (uint8_t)(Sector); CommandFIS->LBA1 = (uint8_t)(Sector >> 8); @@ -162,10 +208,9 @@ CommandFIS->LBA3 = (uint8_t)(Sector >> 24); CommandFIS->LBA4 = (uint8_t)(Sector >> 32); CommandFIS->LBA5 = (uint8_t)(Sector >> 40); - CommandFIS->DeviceRegister = (1 << 6); + CommandFIS->DeviceRegister = 1 << 6; CommandFIS->countLow = SectorCount & 0xFF; CommandFIS->countHigh = (SectorCount >> 8) & 0xFF; - CommandFIS->Control = 0; // 1 << 3; uint64_t Spin = 0; while ((hbaPort->TaskFileData & (ATA_DEV_BUSY | ATA_DEV_DRQ)) && Spin < 1000000) { @@ -200,7 +245,6 @@ printf("controller not in ahci mode!\n"); return; } - // hba->GlobalHostControl |= 1 << 31; if (hba->HostCapabilitiesExtended & 1) { printf("the os does not own the hba, getting it now...\n"); yields(); @@ -209,17 +253,5 @@ !(hba->BIOSHandoffControlStatus & OsOwnership)) { } } - // hba->GlobalHostControl |= 1; - // while (hba->GlobalHostControl & 1) { - //} - // hba->GlobalHostControl |= 1 << 31; - // sleep(1000); - // enabling bus mastering and memory access - // uint16_t command = pciConfigReadWord(pciDevice->bus, pciDevice->device, - // pciDevice->function, 4); - // command |= (1 << 1) | (1 << 2); - // pciConfigWriteByte(pciDevice->bus, pciDevice->device, - // pciDevice->function, - // 4, (uint8_t)command); preparePorts(hba, drives); } diff --git a/src/kernel/drivers/pci/hardDrive/hardDrive.c b/src/kernel/drivers/pci/hardDrive/hardDrive.c index 0e8c536..6e59023 100644 --- a/src/kernel/drivers/pci/hardDrive/hardDrive.c +++ b/src/kernel/drivers/pci/hardDrive/hardDrive.c @@ -5,6 +5,8 @@ #include <ports.h> #include <stdio.h> +#define CONTENT(ptr) *((uint32_t *)(ptr)) + extern void accessAHCIDrive(HardDrive *drive, uint64_t lba, void *buffer, uint16_t count, uint8_t direction); void scanHardDrives() { @@ -24,5 +26,14 @@ break; } } + void *buffer = malloc(512); + uint8_t i = 0; + foreach (drives) { + HardDrive *drive = current->data; + drive->access(drive, 0, buffer, 1, 0); + printf("drive %i start: %x end: %x\n", ++i, CONTENT(buffer), + CONTENT(buffer + 508)); + } + printf("count: %i\n", listCount(drives)); mountDisk(listGet(&drives, 1)); }