diff options
Diffstat (limited to 'dev/Kernel/HALKit/AMD64')
| -rw-r--r-- | dev/Kernel/HALKit/AMD64/PCI/Device.cc | 2 | ||||
| -rw-r--r-- | dev/Kernel/HALKit/AMD64/Storage/ATA.cc | 4 | ||||
| -rw-r--r-- | dev/Kernel/HALKit/AMD64/Storage/SATA.cc | 174 |
3 files changed, 91 insertions, 89 deletions
diff --git a/dev/Kernel/HALKit/AMD64/PCI/Device.cc b/dev/Kernel/HALKit/AMD64/PCI/Device.cc index 7b0f64b3..d02c7e22 100644 --- a/dev/Kernel/HALKit/AMD64/PCI/Device.cc +++ b/dev/Kernel/HALKit/AMD64/PCI/Device.cc @@ -106,7 +106,7 @@ namespace Kernel::PCI void Device::EnableMmio(UInt32 bar_in) { - bool enable = Read(bar_in, sizeof(UChar)) | (1 << 1); + bool enable = Read(bar_in, sizeof(UShort)) | (1 << 1); Write(bar_in, enable, sizeof(UShort)); } diff --git a/dev/Kernel/HALKit/AMD64/Storage/ATA.cc b/dev/Kernel/HALKit/AMD64/Storage/ATA.cc index 0e1120a2..9b16d866 100644 --- a/dev/Kernel/HALKit/AMD64/Storage/ATA.cc +++ b/dev/Kernel/HALKit/AMD64/Storage/ATA.cc @@ -157,7 +157,7 @@ Void drv_std_read(UInt64 Lba, UInt16 IO, UInt8 Master, Char* Buf, SizeT SectorSz rt_out8(IO + ATA_REG_SEC_COUNT0, ((Size + SectorSz - 1) / SectorSz)); - rt_out8(IO + ATA_REG_LBA0, (Lba) & 0xFF); + rt_out8(IO + ATA_REG_LBA0, (Lba)&0xFF); rt_out8(IO + ATA_REG_LBA1, (Lba) >> 8); rt_out8(IO + ATA_REG_LBA2, (Lba) >> 16); rt_out8(IO + ATA_REG_LBA3, (Lba) >> 24); @@ -209,7 +209,7 @@ Void drv_std_write(UInt64 Lba, UInt16 IO, UInt8 Master, Char* Buf, SizeT SectorS rt_out8(IO + ATA_REG_SEC_COUNT0, ((Size + (SectorSz - 1)) / SectorSz)); - rt_out8(IO + ATA_REG_LBA0, (Lba) & 0xFF); + rt_out8(IO + ATA_REG_LBA0, (Lba)&0xFF); rt_out8(IO + ATA_REG_LBA1, (Lba) >> 8); rt_out8(IO + ATA_REG_LBA2, (Lba) >> 16); rt_out8(IO + ATA_REG_LBA3, (Lba) >> 24); diff --git a/dev/Kernel/HALKit/AMD64/Storage/SATA.cc b/dev/Kernel/HALKit/AMD64/Storage/SATA.cc index 66793b3e..71161ed4 100644 --- a/dev/Kernel/HALKit/AMD64/Storage/SATA.cc +++ b/dev/Kernel/HALKit/AMD64/Storage/SATA.cc @@ -1,6 +1,6 @@ /* ------------------------------------------- - Copyright (C) 2024, Amlal EL Mahrouss, all rights reserved. + Copyright (C) 2024-2025, Amlal EL Mahrouss, all rights reserved. ------------------------------------------- */ @@ -15,7 +15,6 @@ * */ -#include <stdint.h> #include <KernelKit/UserProcessScheduler.h> #include <KernelKit/LPC.h> @@ -48,10 +47,9 @@ enum }; STATIC Kernel::PCI::Device kPCIDevice; -STATIC HbaMem* kSATAPort = nullptr; +STATIC HbaMem* kSATAPort = nullptr; STATIC Kernel::SizeT kSATAPortIdx = 0UL; STATIC Kernel::Lba kCurrentDiskSectorCount = 0UL; -STATIC Kernel::Char kModel[41] = {0}; template <BOOL Write, BOOL CommandOrCTRL, BOOL Identify> static Kernel::Void drv_std_input_output(Kernel::UInt64 lba, Kernel::UInt8* buffer, Kernel::SizeT sector_sz, Kernel::SizeT size_buffer) noexcept; @@ -64,28 +62,14 @@ static Kernel::Void drv_calculate_disk_geometry() noexcept { kCurrentDiskSectorCount = 0UL; - Kernel::UInt8 identify_data[256] = {0}; + Kernel::UInt8 identify_data[kib_cast(4)] = {}; - drv_std_input_output<NO, YES, YES>(0, identify_data, 0, 256); + drv_std_input_output<NO, YES, YES>(0, identify_data, 0, kib_cast(8)); - Kernel::UInt32 lba28_sectors = (identify_data[61] << 16) | identify_data[60]; + kCurrentDiskSectorCount = (identify_data[61] << 16) | identify_data[60]; - kCurrentDiskSectorCount = lba28_sectors; - - Kernel::UInt32 i = 0; - - for (i = 0; i < 20; i++) - { - // 20 words = 40 bytes - kModel[i * 2] = identify_data[27 + i] >> 8; // High byte first - kModel[i * 2 + 1] = identify_data[27 + i] & 0xFF; // Low byte - } - - kModel[40] = '\0'; // Null-terminate - - kcout << "Disk Model: " << kModel << endl; kcout << "Disk Size: " << Kernel::number(drv_get_size()) << endl; - kcout << "Disk Highest LBA: " << Kernel::number(kCurrentDiskSectorCount) << endl; + kcout << "Highest Disk LBA: " << Kernel::number(kCurrentDiskSectorCount) << endl; } /// @brief Initializes an AHCI disk. @@ -105,11 +89,11 @@ Kernel::Boolean drv_std_init(Kernel::UInt16& PortsImplemented) if (kPCIDevice.Subclass() == kSATASubClass && kPCIDevice.ProgIf() == kSATAProgIfAHCI) { - HbaMem* mem_ahci = (HbaMem*)kPCIDevice.Bar(kSATABar5); - kPCIDevice.EnableMmio(kSATABar5); // Enable the memory index_byte/o for this ahci device. kPCIDevice.BecomeBusMaster(kSATABar5); // Become bus master for this ahci device, so that we can control it. + HbaMem* mem_ahci = (HbaMem*)kPCIDevice.Bar(kSATABar5); + Kernel::UInt32 ports_implemented = mem_ahci->Pi; Kernel::UInt16 ahci_index = 0; @@ -131,42 +115,72 @@ Kernel::Boolean drv_std_init(Kernel::UInt16& PortsImplemented) if (mem_ahci->Ports[ahci_index].Sig == kSATASignature && det == 3 && ipm == 1) { - kcout << "Port is SATA.\r"; + kcout << "Port is implemented as SATA.\r"; kSATAPortIdx = ahci_index; kSATAPort = mem_ahci; - // Enable AHCI Mode FIRST - kSATAPort->Ghc |= (1 << 31); + kSATAPort->Ports[kSATAPortIdx].Cmd &= ~kHBAPxCmdST; + kSATAPort->Ports[kSATAPortIdx].Cmd &= ~kHBAPxCmdFre; - const int timeout = 1000000; - int attempts = 0; - while ((kSATAPort->Ports[kSATAPortIdx].Tfd & 0x80) && (attempts < timeout)) + while (YES) { - attempts++; + if (kSATAPort->Ports[kSATAPortIdx].Cmd & kHBAPxCmdFR) + continue; + + if (kSATAPort->Ports[kSATAPortIdx].Cmd & kHBAPxCmdCR) + continue; + + break; } - if (attempts == timeout) + + const auto kAHCIBaseAddress = mib_cast(4); + + kSATAPort->Ports[kSATAPortIdx].Clb = kAHCIBaseAddress + (kSATAPortIdx << 10); + kSATAPort->Ports[kSATAPortIdx].Clbu = 0; + + rt_set_memory((VoidPtr)((UIntPtr)kSATAPort->Ports[kSATAPortIdx].Clb), 0, 1024); + + kSATAPort->Ports[kSATAPortIdx].Fb = kAHCIBaseAddress + (32 << 10) + (kSATAPortIdx << 8); + kSATAPort->Ports[kSATAPortIdx].Fbu = 0; + + rt_set_memory((VoidPtr)((UIntPtr)kSATAPort->Ports[kSATAPortIdx].Fb), 0, 256); + + HbaCmdHeader* cmd_header = (HbaCmdHeader*)((UIntPtr)kSATAPort->Ports[kSATAPortIdx].Clb); + + for (Int32 i = 0; i < 32; i++) { - kcout << "Error: Drive is still busy after waiting.\r"; - return NO; + cmd_header[i].Prdtl = 8; + + cmd_header[i].Ctba = kAHCIBaseAddress + (40 << 10) + (kSATAPortIdx << 13) + (i << 8); + cmd_header[i].Ctbau = 0; + + rt_set_memory((VoidPtr)(UIntPtr)cmd_header[i].Ctba, 0, 256); } - kSATAPort->Ports[kSATAPortIdx].Cmd |= kHBAPxCmdST; + while (kSATAPort->Ports[kSATAPortIdx].Cmd & kHBAPxCmdCR) + ; + kSATAPort->Ports[kSATAPortIdx].Cmd |= kHBAPxCmdFre; + kSATAPort->Ports[kSATAPortIdx].Cmd |= kHBAPxCmdST; drv_calculate_disk_geometry(); - return YES; + detected = YES; + + break; } } ports_implemented >>= 1; ++ahci_index; } + + return detected; } } - return NO; + return No; } Kernel::Boolean drv_std_detected(Kernel::Void) @@ -189,14 +203,14 @@ static Kernel::Int32 drv_find_cmd_slot(HbaPort* port) noexcept if (port == nullptr) return -1; - kcout << "Finding a slot...\r"; - Kernel::UInt32 slots = (kSATAPort->Ports[kSATAPortIdx].Sact | kSATAPort->Ports[kSATAPortIdx].Ci); for (Kernel::Int32 i = 0; i < ((kSATAPort->Cap & 0x1F) + 1); i++) { - if ((slots & (1 << i)) == 0) + if ((slots & 1) == 0) return i; + + slots >>= 1; } return -1; @@ -205,6 +219,11 @@ static Kernel::Int32 drv_find_cmd_slot(HbaPort* port) noexcept template <BOOL Write, BOOL CommandOrCTRL, BOOL Identify> static Kernel::Void drv_std_input_output(Kernel::UInt64 lba, Kernel::UInt8* buffer, Kernel::SizeT sector_sz, Kernel::SizeT size_buffer) noexcept { + if (!CommandOrCTRL) + return; + + kSATAPort->Ports[kSATAPortIdx].Is = -1; + auto slot = 0L; slot = drv_find_cmd_slot(&kSATAPort->Ports[kSATAPortIdx]); @@ -212,43 +231,35 @@ static Kernel::Void drv_std_input_output(Kernel::UInt64 lba, Kernel::UInt8* buff if (slot == -1) return; - if (size_buffer > kib_cast(8)) - return; + volatile HbaCmdHeader* command_header = ((volatile HbaCmdHeader*)((Kernel::UInt64)kSATAPort->Ports[kSATAPortIdx].Clb + kSATAPort->Ports[kSATAPortIdx].Clbu)); - volatile HbaCmdHeader* command_header = ((volatile HbaCmdHeader*)((Kernel::UInt64)kSATAPort->Ports[kSATAPortIdx].Clb)); command_header += slot; MUST_PASS(command_header); command_header->Cfl = sizeof(FisRegH2D) / sizeof(Kernel::UInt32); command_header->Write = Write; - command_header->Prdtl = (Kernel::UInt16)(kib_cast(8) - 1) >> 4 + 1; - - volatile HbaCmdTbl* command_table = (volatile HbaCmdTbl*)((Kernel::UInt64)command_header->Ctba); + command_header->Prdtl = (Kernel::UInt16)((size_buffer - 1) >> 4) + 1; - Kernel::rt_set_memory((void*)command_table, 0, sizeof(HbaCmdTbl)); + volatile HbaCmdTbl* command_table = (volatile HbaCmdTbl*)((Kernel::UInt64)command_header->Ctba + command_header->Ctbau); MUST_PASS(command_table); - Kernel::UInt8* buffer_ahci = new Kernel::UInt8[kib_cast(8)]; - - Kernel::Int32 i = 0; - - command_table->Prdt[0].Dba = (uint32_t)(uint64_t)buffer_ahci & 0xFFFFFFFF; - command_table->Prdt[0].Dbau = (uint32_t)(uint64_t)buffer_ahci >> 32; - command_table->Prdt[0].Dbc = (size_buffer << 9) - 1; // 512 bytes per sector - command_table->Prdt[0].InterruptBit = 1; + for (Kernel::SizeT i = 0; i < (command_header->Prdtl - 1); i++) + { + command_table->PrdtEntries[i].Dba = ((Kernel::UInt32)(Kernel::UInt64)buffer & 0xFFFFFFFF); + command_table->PrdtEntries[i].Dbau = (((Kernel::UInt64)buffer >> 32) & 0xFFFFFFFF); + command_table->PrdtEntries[i].Dbc = (size_buffer - 1); + command_table->PrdtEntries[i].InterruptBit = YES; - kcout << "LBA: " << Kernel::hex_number(lba) << endl; - kcout << "PRDT Entry - Dba (Low): " << Kernel::hex_number(command_table->Prdt[0].Dba) << endl; - kcout << "PRDT Entry - DbaU (High): " << Kernel::hex_number(command_table->Prdt[0].Dbau) << endl; - kcout << "PRDT Entry - Dbc: " << Kernel::hex_number(command_table->Prdt[0].Dbc) << endl; + size_buffer -= 16; + buffer += kib_cast(4); + } - volatile FisRegH2D* h2d_fis = (volatile FisRegH2D*)(&command_table->Cfis); + volatile FisRegH2D* h2d_fis = (volatile FisRegH2D*)((Kernel::UInt64)command_table->Cfis); - Kernel::rt_set_memory((void*)h2d_fis, 0, sizeof(FisRegH2D)); + h2d_fis->FisType = kFISTypeRegH2D; - h2d_fis->FisType = 0x27; // H2D h2d_fis->CmdOrCtrl = CommandOrCTRL; h2d_fis->Command = Write ? kAHCICmdWriteDmaEx : kAHCICmdReadDmaEx; @@ -256,45 +267,36 @@ static Kernel::Void drv_std_input_output(Kernel::UInt64 lba, Kernel::UInt8* buff if (Identify) h2d_fis->Command = kAHCICmdIdentify; - h2d_fis->Lba0 = (Kernel::UInt32)(lba) & 0xFF; - h2d_fis->Lba1 = (Kernel::UInt8)(lba >> 8) & 0xFF; - h2d_fis->Lba2 = (Kernel::UInt8)(lba >> 16) & 0xFF; + h2d_fis->Lba0 = lba; + h2d_fis->Lba1 = lba >> 8; + h2d_fis->Lba2 = lba >> 16; + h2d_fis->Lba3 = lba >> 24; - h2d_fis->Lba3 = (Kernel::UInt8)(lba >> 24) & 0xFF; - h2d_fis->Lba4 = (Kernel::UInt8)(lba >> 32) & 0xFF; - h2d_fis->Lba5 = (Kernel::UInt8)(lba >> 40) & 0xFF; + h2d_fis->Device = kSataLBAMode; - h2d_fis->Device = 0; // master device. + // 28-bit LBA mode, fis is done being configured. h2d_fis->CountLow = sector_sz & 0xFF; h2d_fis->CountHigh = (sector_sz >> 8) & 0xFF; while ((kSATAPort->Ports[kSATAPortIdx].Tfd & (kAhciSRBsy | kAhciSRDrq))) { - kcout << "waiting for slot to be ready\r\n"; + kcout << "Waiting for slot to be ready...\r\n"; } - Kernel::UInt32 ahci_status = kSATAPort->Ports[kSATAPortIdx].Tfd; - kcout << "AHCI Status Before Write: " << Kernel::hex_number(ahci_status) << endl; + if (kSATAPort->Is & kHBAErrTaskFile) + Kernel::ke_panic(RUNTIME_CHECK_BAD_BEHAVIOR, "AHCI Read disk failure, faulty component."); - kSATAPort->Ports[kSATAPortIdx].Ci = 1 << slot; + // send fis/cmdtbl/cmdhdr. + kSATAPort->Ports[kSATAPortIdx].Ci |= 1 << slot; while (kSATAPort->Ports[kSATAPortIdx].Ci & (1 << slot)) + ; + + while ((kSATAPort->Ports[kSATAPortIdx].Tfd & (kAhciSRBsy | kAhciSRDrq))) { - Kernel::UInt32 tfd = kSATAPort->Ports[kSATAPortIdx].Tfd; - kcout << "AHCI TFD: " << Kernel::number(tfd) << endl; + kcout << "Waiting for slot to be ready...\r\n"; } - - kcout << "Last Command Sent: " << (int)Kernel::number(h2d_fis->Command) << endl; - - ahci_status = kSATAPort->Ports[kSATAPortIdx].Tfd; - - kcout << "AHCI Status After Write: " << Kernel::hex_number(ahci_status) << endl; - kcout << "AHCI STSS: " << Kernel::hex_number(kSATAPort->Ports[kSATAPortIdx].Ssts) << endl; - kcout << "AHCI SERR: " << Kernel::hex_number(kSATAPort->Ports[kSATAPortIdx].Serr) << endl; - - Kernel::rt_copy_memory(buffer_ahci, buffer, size_buffer); - delete[] buffer_ahci; } /*** |
