diff options
| author | Amlal El Mahrouss <amlal.elmahrouss@icloud.com> | 2025-01-05 09:29:00 +0100 |
|---|---|---|
| committer | Amlal El Mahrouss <amlal.elmahrouss@icloud.com> | 2025-01-05 09:29:00 +0100 |
| commit | 5903f0c8eca69916c3acffcbe0a20a9af36fdf27 (patch) | |
| tree | 307f5c3289c3208f613425eb55f04bccd69da8d8 /dev/Kernel/HALKit | |
| parent | 188550e4f26c77e33dcc2a83c4775d17e47dcb39 (diff) | |
ADD: Managed to get some progress on SATA support.
ADD: A new patch for the NeFS the backend.
ADD: Don't let BootKit write the first catalogs.
Signed-off-by: Amlal El Mahrouss <amlal.elmahrouss@icloud.com>
Diffstat (limited to 'dev/Kernel/HALKit')
| -rw-r--r-- | dev/Kernel/HALKit/AMD64/Storage/SATA-DMA.cc | 170 |
1 files changed, 85 insertions, 85 deletions
diff --git a/dev/Kernel/HALKit/AMD64/Storage/SATA-DMA.cc b/dev/Kernel/HALKit/AMD64/Storage/SATA-DMA.cc index 5d3acd16..a0d65c3a 100644 --- a/dev/Kernel/HALKit/AMD64/Storage/SATA-DMA.cc +++ b/dev/Kernel/HALKit/AMD64/Storage/SATA-DMA.cc @@ -15,7 +15,6 @@ * */ -#include "NewKit/Defines.h" #include <KernelKit/UserProcessScheduler.h> #include <KernelKit/LPC.h> @@ -33,18 +32,13 @@ #define HBA_PxCMD_FR 0x4000 #define HBA_PxCMD_CR 0x8000 -#define kAhciStartAddress mib_cast(4) - -#define kAhciLBAMode (1 << 6) - -#define kAhciMaxPoll (100000U) - -#define kCmdOrCtrlCmd 1 -#define kCmdOrCtrlCtrl 0 +#define kSataLBAMode (1 << 6) #define kAhciSRBsy 0x80 #define kAhciSRDrq 0x08 +#define kAhciPortCnt 32 + enum { kSATAProgIfAHCI = 0x01, @@ -52,12 +46,14 @@ enum kSATABar5 = 0x24, }; -STATIC Kernel::PCI::Device kAhciDevice; -STATIC HbaPort* kAhciPort = nullptr; +STATIC Kernel::PCI::Device kPCIDevice; +STATIC HbaPort* kSATAPort = nullptr; STATIC Kernel::Lba kCurrentDiskSectorCount = 0UL; -template <BOOL ReadWrite, BOOL CommandOrCTRL, BOOL Identify> -static Kernel::Void drv_std_input_output(Kernel::UInt64 lba, Kernel::UInt8* buffer, Kernel::SizeT sector_cnt, Kernel::SizeT size_buffer); +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; + +static Kernel::Int32 drv_find_cmd_slot(HbaPort* port) noexcept; static Kernel::Void drv_calculate_disk_geometry() noexcept; @@ -72,11 +68,11 @@ static Kernel::Void drv_calculate_disk_geometry() noexcept kCurrentDiskSectorCount = (identify_data[61] << 16) | identify_data[60]; kcout << "Disk Size: " << Kernel::number(drv_get_size()) << endl; - kcout << "Highest AHCI LBA: " << Kernel::number(kCurrentDiskSectorCount) << endl; + kcout << "Highest LBA: " << Kernel::number(kCurrentDiskSectorCount) << endl; } /// @brief Initializes an AHCI disk. -/// @param PortsImplemented the amount of kAhciPort that have been detected. +/// @param PortsImplemented the amount of kSATAPort that have been detected. /// @return if the disk was successfully initialized or not. Kernel::Boolean drv_std_init(Kernel::UInt16& PortsImplemented) { @@ -86,21 +82,21 @@ Kernel::Boolean drv_std_init(Kernel::UInt16& PortsImplemented) for (SizeT device_index = 0; device_index < ZKA_BUS_COUNT; ++device_index) { - kAhciDevice = iterator[device_index].Leak(); // And then leak the reference. + kPCIDevice = iterator[device_index].Leak(); // And then leak the reference. // if SATA and then interface is AHCI... - if (kAhciDevice.Subclass() == kSATASubClass && - kAhciDevice.ProgIf() == kSATAProgIfAHCI) + if (kPCIDevice.Subclass() == kSATASubClass && + kPCIDevice.ProgIf() == kSATAProgIfAHCI) { - kAhciDevice.EnableMmio(0x24); // Enable the memory index_byte/o for this ahci device. - kAhciDevice.BecomeBusMaster(0x24); // Become bus master for this ahci device, so that we can control it. + kPCIDevice.EnableMmio(0x24); // Enable the memory index_byte/o for this ahci device. + kPCIDevice.BecomeBusMaster(0x24); // Become bus master for this ahci device, so that we can control it. - HbaMem* mem_ahci = (HbaMem*)kAhciDevice.Bar(0x24); + HbaMem* mem_ahci = (HbaMem*)kPCIDevice.Bar(0x24); Kernel::UInt32 ports_implemented = mem_ahci->Pi; Kernel::UInt16 ahci_index = 0; - const Kernel::UInt16 kMaxPortsImplemented = 32; + const Kernel::UInt16 kMaxPortsImplemented = kAhciPortCnt; const Kernel::UInt32 kSATASignature = 0x00000101; const Kernel::UInt8 kAhciPresent = 0x03; const Kernel::UInt8 kAhciIPMActive = 0x01; @@ -111,40 +107,27 @@ Kernel::Boolean drv_std_init(Kernel::UInt16& PortsImplemented) { if (ports_implemented) { - kcout << "Port is implemented by host.\r"; + kcout << "Port is implemented.\r"; Kernel::UInt8 ipm = (mem_ahci->Ports[ahci_index].Ssts >> 8) & 0x0F; Kernel::UInt8 det = mem_ahci->Ports[ahci_index].Ssts & 0x0F; if (mem_ahci->Ports[ahci_index].Sig == kSATASignature) { - kcout << "Port is AHCI controller.\r"; - - detected = true; - - kAhciPort = &mem_ahci->Ports[ahci_index]; - - kAhciPort->Cmd &= ~HBA_PxCMD_FRE; - - // Clear FRE (bit4) - kAhciPort->Cmd &= ~HBA_PxCMD_ST; + kcout << "Port is SATA.\r"; - // Wait until FR (bit14), CR (bit15) are cleared - while (YES) - { - if (kAhciPort->Cmd & HBA_PxCMD_CR) - continue; + kSATAPort = &mem_ahci->Ports[ahci_index]; - if (kAhciPort->Cmd & HBA_PxCMD_FR) - continue; - break; - } + while (kSATAPort->Cmd & HBA_PxCMD_CR) + ; - kAhciPort->Cmd |= HBA_PxCMD_FRE; - kAhciPort->Cmd |= HBA_PxCMD_ST; + kSATAPort->Cmd |= HBA_PxCMD_FRE; + kSATAPort->Cmd |= HBA_PxCMD_ST; drv_calculate_disk_geometry(); + detected = YES; + break; } } @@ -162,84 +145,101 @@ Kernel::Boolean drv_std_init(Kernel::UInt16& PortsImplemented) Kernel::Boolean drv_std_detected(Kernel::Void) { - return kAhciDevice.DeviceId() != 0xFFFF; + return kPCIDevice.DeviceId() != 0xFFFF; +} + +Kernel::Void drv_std_write(Kernel::UInt64 lba, Kernel::Char* buffer, Kernel::SizeT sector_sz, Kernel::SizeT size_buffer) +{ + lba /= sector_sz; + + drv_std_input_output<YES, YES, NO>(lba, (Kernel::UInt8*)buffer, sector_sz, size_buffer); } -Kernel::Void drv_std_write(Kernel::UInt64 lba, Kernel::Char* buffer, Kernel::SizeT sector_cnt, Kernel::SizeT size_buffer) +Kernel::Void drv_std_read(Kernel::UInt64 lba, Kernel::Char* buffer, Kernel::SizeT sector_sz, Kernel::SizeT size_buffer) { - lba /= sector_cnt; + lba /= sector_sz; - drv_std_input_output<YES, YES, NO>(lba, (Kernel::UInt8*)buffer, sector_cnt, size_buffer); + drv_std_input_output<NO, YES, NO>(lba, (Kernel::UInt8*)buffer, sector_sz, size_buffer); } -Kernel::Void drv_std_read(Kernel::UInt64 lba, Kernel::Char* buffer, Kernel::SizeT sector_cnt, Kernel::SizeT size_buffer) +static Kernel::Int32 drv_find_cmd_slot(HbaPort* port) noexcept { - lba /= sector_cnt; + Kernel::UInt32 slots = (port->Sact | port->Ci); - drv_std_input_output<NO, YES, NO>(lba, (Kernel::UInt8*)buffer, sector_cnt, size_buffer); + for (Kernel::Int32 i = 0; i < kAhciPortCnt; i++) + { + if ((slots & 1) == 0) + return i; + + slots >>= 1; + } + + return -1; } template <BOOL Write, BOOL CommandOrCTRL, BOOL Identify> -static Kernel::Void drv_std_input_output(Kernel::UInt64 lba, Kernel::UInt8* buffer, Kernel::SizeT sector_cnt, Kernel::SizeT size_buffer) +static Kernel::Void drv_std_input_output(Kernel::UInt64 lba, Kernel::UInt8* buffer, Kernel::SizeT sector_sz, Kernel::SizeT size_buffer) noexcept { - volatile HbaCmdHeader* command_header = *(HbaCmdHeader**)&kAhciPort->Clb; + if (!CommandOrCTRL) + return; - command_header->Cfl = sizeof(FisRegH2D) / sizeof(Kernel::UInt32); + volatile HbaCmdHeader* command_header = (HbaCmdHeader*)kSATAPort->Clb; + auto slot = drv_find_cmd_slot(kSATAPort); + + if (slot == -1) + return; + + command_header += slot; + + command_header->Cfl = sizeof(FisRegH2D) / sizeof(Kernel::UInt32); command_header->Write = Write; command_header->Prdtl = (Kernel::UInt16)((size_buffer - 1) >> 4) + 1; - HbaCmdTbl* command_table = (HbaCmdTbl*)(command_header->Ctba); + volatile HbaCmdTbl* command_table = (HbaCmdTbl*)(command_header->Ctba); - command_table->PrdtEntries[0].Dba = *(Kernel::UInt32*)&buffer; - command_table->PrdtEntries[0].Dbc = size_buffer; + command_table->PrdtEntries[0].Dba = (*(Kernel::UInt32*)buffer & __UINT32_MAX__); + command_table->PrdtEntries[0].Dbau = ((*(Kernel::UInt32*)buffer >> 8) & __UINT32_MAX__); + command_table->PrdtEntries[0].Dbc = size_buffer - 1; command_table->PrdtEntries[0].InterruptBit = 1; - FisRegH2D* h2d_fis = (FisRegH2D*)(&command_table->Cfis); + volatile FisRegH2D* h2d_fis = (FisRegH2D*)(&command_table->Cfis); + + if (CommandOrCTRL) + { + h2d_fis->Command = Write ? kAHCICmdWriteDmaEx : kAHCICmdReadDmaEx; + + if (Identify) + h2d_fis->Command = kAHCICmdIdentify; + + h2d_fis->CmdOrCtrl = 1; + } + + h2d_fis->FisType = kFISTypeRegH2D; - h2d_fis->Command = Write ? kAHCICmdWriteDmaEx : kAHCICmdReadDmaEx; - h2d_fis->FisType = kFISTypeRegH2D; - h2d_fis->CmdOrCtrl = CommandOrCTRL; + h2d_fis->Device = kSataLBAMode; h2d_fis->Lba0 = lba & 0xFF; h2d_fis->Lba1 = lba >> 8; h2d_fis->Lba2 = lba >> 16; - - h2d_fis->Device = 1 << 6; - h2d_fis->Lba3 = lba >> 24; - h2d_fis->Lba4 = lba >> 32; - h2d_fis->Lba5 = lba >> 40; - h2d_fis->CountLow = sector_cnt & 0xFF; - h2d_fis->CountHigh = (sector_cnt >> 8) & 0xFF; + h2d_fis->CountLow = sector_sz & 0xFF; + h2d_fis->CountHigh = (sector_sz >> 8) & 0xFF; - kAhciPort->Ci |= (1 << 0); // Command Issue + kSATAPort->Ci = (1 << slot); - while (kAhciPort->Ci & (1 << 0)) + while ((kSATAPort->Ci & (1 << slot)) != 0) { - if (kAhciPort->Is & HBA_ERR_TFE) // Task file error + if (kSATAPort->Is & HBA_ERR_TFE) { - kcout << "AHCI: Read disk error.\r"; + kcout << "AHCI: Task file disk error, setting global err...\r"; err_global_get() = Kernel::kErrorUnrecoverableDisk; return; } } - - // Check again for the last time. - if (kAhciPort->Is & HBA_ERR_TFE) // task file error status - { - using namespace Kernel; - - kcout << "AHCI: Read disk error.\r"; - *buffer = 0; - - err_global_get() = kErrorUnrecoverableDisk; - - return; - } } /*** |
