From 6e3be96bb9a9b3047aee59da639819453eaab6ac Mon Sep 17 00:00:00 2001 From: Amlal Date: Thu, 24 Oct 2024 16:53:42 +0200 Subject: IMP: Pushing important code. Signed-off-by: Amlal --- dev/zba/BootKit/BitManip.h | 4 +- dev/zka/HALKit/AMD64/Storage/AHCI.cc | 126 +++++++++++++++++++++++++++++------ dev/zka/KernelKit/LPC.h | 4 +- dev/zka/KernelKit/LockDelegate.h | 6 +- 4 files changed, 115 insertions(+), 25 deletions(-) (limited to 'dev') diff --git a/dev/zba/BootKit/BitManip.h b/dev/zba/BootKit/BitManip.h index ad893b02..bb52b172 100644 --- a/dev/zba/BootKit/BitManip.h +++ b/dev/zba/BootKit/BitManip.h @@ -7,8 +7,8 @@ #ifndef __BITMANIP_H__ #define __BITMANIP_H__ -/// Name: Bits API. -/// Purpose: Bit manip helpers, based on CoreBoot header. +/// File: BitManip.h +/// Purpose: Bit manipulation helpers, based on coreboot-dev. #define bk_set_bit(X, O) X = (1 << O) | X #define bk_clear_bit(X, O) X = ~(1 << O) & X diff --git a/dev/zka/HALKit/AMD64/Storage/AHCI.cc b/dev/zka/HALKit/AMD64/Storage/AHCI.cc index 05481d73..a7635c46 100644 --- a/dev/zka/HALKit/AMD64/Storage/AHCI.cc +++ b/dev/zka/HALKit/AMD64/Storage/AHCI.cc @@ -18,6 +18,9 @@ #include #include #include +#include + +#define kMaxAhciPoll 100000 #ifdef __AHCI__ enum @@ -41,39 +44,39 @@ Kernel::Boolean drv_std_init(Kernel::UInt16& PortsImplemented) for (SizeT devIndex = 0; devIndex < ZKA_BUS_COUNT; ++devIndex) { + // if SATA and then interface is AHCI... if (iterator[devIndex].Leak().Subclass() == kSATASubClass && iterator[devIndex].Leak().ProgIf() == kSATAProgIfAHCI) { - iterator[devIndex].Leak().EnableMmio(0x24); /// enable the memory index_byte/o for this ahci device. - iterator[devIndex].Leak().BecomeBusMaster(0x24); /// become bus master for this ahci device, so that we can control it. + iterator[devIndex].Leak().EnableMmio(0x24); // Enable the memory index_byte/o for this ahci device. + iterator[devIndex].Leak().BecomeBusMaster(0x24); // Become bus master for this ahci device, so that we can control it. - kAhciDevice = iterator[devIndex].Leak(); /// and then leak the reference. + kAhciDevice = iterator[devIndex].Leak(); // And then leak the reference. HbaMem* mem_ahci = (HbaMem*)kAhciDevice.Bar(0x24); Kernel::UInt32 ports_implemented = mem_ahci->Pi; - Int32 ahci_index = 0; + Kernel::UInt16 ahci_index = 0; - const auto cMaxAhciDevices = 32; - const auto cAhciSig = 0x00000101; - const auto cAhciPresent = 0x03; - const auto cAhciIPMActive = 0x01; + const Kernel::UInt16 kMaxPortsImplemented = 32; + const Kernel::UInt32 kSATASignature = 0x00000101; + const Kernel::UInt8 kAhciPresent = 0x03; + const Kernel::UInt8 kAhciIPMActive = 0x01; - auto detected = false; + Kernel::Boolean detected = false; - while (ahci_index < cMaxAhciDevices) + while (ahci_index < kMaxPortsImplemented) { if (ports_implemented) { - kcout << "Port is implemented by host.\r"; + kcout << "Port is implemented by Host.\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 == cAhciSig) + if (mem_ahci->Ports[ahci_index].Sig == kSATASignature) { kcout << "Found AHCI controller.\r"; - kcout << "Device is of SATA type.\r"; detected = true; @@ -93,7 +96,7 @@ Kernel::Boolean drv_std_init(Kernel::UInt16& PortsImplemented) } } - return false; + return No; } Kernel::Boolean drv_std_detected(Kernel::Void) @@ -105,8 +108,10 @@ Kernel::Void drv_std_read(Kernel::UInt64 Lba, Kernel::Char* Buf, Kernel::SizeT S { STATIC Kernel::Boolean kSlotIsUsed = No; - while (kSlotIsUsed) - ; + Kernel::LockDelegate lock(&kSlotIsUsed); + + if (lock.HasTimedOut()) + return; kSlotIsUsed = Yes; @@ -175,7 +180,7 @@ Kernel::Void drv_std_read(Kernel::UInt64 Lba, Kernel::Char* Buf, Kernel::SizeT S { break; // Command has completed } - if (kAhciPort->Is & (1 << 30)) + else if (kAhciPort->Is & (1 << 30)) { return; // Error in task file } @@ -186,10 +191,93 @@ Kernel::Void drv_std_read(Kernel::UInt64 Lba, Kernel::Char* Buf, Kernel::SizeT S Kernel::Void drv_std_write(Kernel::UInt64 Lba, Kernel::Char* Buf, Kernel::SizeT SectorSz, Kernel::SizeT Size) { + STATIC Kernel::Boolean kSlotIsUsed = No; + + Kernel::LockDelegate lock(&kSlotIsUsed); + + if (lock.HasTimedOut()) + return; + + kSlotIsUsed = Yes; + + Kernel::Int64 free_slot = 0; + + // Prepare command header. + + HbaCmdHeader* cmd_header = (HbaCmdHeader*)kAhciPort->Clb; + cmd_header += free_slot; + + // Read operation/set entries count. + + cmd_header->Write = Yes; + cmd_header->Prdtl = (Kernel::UInt16)((Size - 1) >> 4) + 1; // PRDT entries count + + // Prepare command table. + + HbaCmdTbl* cmd_tbl = (HbaCmdTbl*)cmd_header->Ctba; + Kernel::rt_set_memory(cmd_tbl, 0, sizeof(HbaCmdTbl)); + + Kernel::UInt64 size = Size * kAHCISectorSize; + Kernel::Int64 index_byte = 0L; + + for (index_byte = 0; index_byte < cmd_header->Prdtl - 1; index_byte++) + { + cmd_tbl->prdtEntries[index_byte].Dba = (Kernel::UInt32)(Kernel::UIntPtr)Buf; + cmd_tbl->prdtEntries[index_byte].Dbc = (8 * 1024) - 1; // 8KB Buf size + cmd_tbl->prdtEntries[index_byte].InterruptBit = 1; // Interrupt on completion + + Size -= 8 * 1024; + Buf += 4 * 1024; // Move the Buf pointer forward + } + + // Last PRDT entry + cmd_tbl->prdtEntries[index_byte].Dba = (Kernel::UInt32)(Kernel::UIntPtr)Buf; + cmd_tbl->prdtEntries[index_byte].Dbc = Size - 1; // Byte count left + cmd_tbl->prdtEntries[index_byte].InterruptBit = 1; + + // 5. Prepare the command FIS (Frame Information Structure) + FisRegH2D* cmd_fis = (FisRegH2D*)(&cmd_tbl->Cfis); + Kernel::rt_set_memory(cmd_fis, 0, sizeof(FisRegH2D)); + + cmd_fis->FisType = kFISTypeRegH2D; + cmd_fis->CmdOrCtrl = 1; // Command + cmd_fis->Command = kAHCICmdReadDmaEx; + + cmd_fis->Lba0 = (Kernel::UInt8)Lba; + cmd_fis->Lba1 = (Kernel::UInt8)(Lba >> 8); + cmd_fis->Lba2 = (Kernel::UInt8)(Lba >> 16); + cmd_fis->Device = 1 << 6; // LBA mode + + cmd_fis->Lba3 = (Kernel::UInt8)(Lba >> 24); + cmd_fis->Lba4 = (Kernel::UInt8)(Lba >> 32); + cmd_fis->Lba5 = (Kernel::UInt8)(Lba >> 40); + + cmd_fis->CountLow = Size & 0xFF; + cmd_fis->CountHigh = (Size >> 8) & 0xFF; + + // 6. Issue the command by writing to the kAhciPort's command issue register (CI) + kAhciPort->Ci = 1 << free_slot; + + // 7. Wait for the command to complete (simple spinlock, no need for an object here) + while (Yes) + { + if (!(kAhciPort->Ci & (1 << free_slot))) + { + break; // Command has completed + } + else if (kAhciPort->Is & (1 << 30)) + { + return; // Error in task file + } + } + + kSlotIsUsed = No; } + /*** - @brief Getter, gets the number of sectors inside the drive. -*/ + @brief Gets the number of sectors inside the drive. + @return Sector size in bytes. + */ Kernel::SizeT drv_get_sector_count() { return 0; diff --git a/dev/zka/KernelKit/LPC.h b/dev/zka/KernelKit/LPC.h index b0b0fae8..305b504d 100644 --- a/dev/zka/KernelKit/LPC.h +++ b/dev/zka/KernelKit/LPC.h @@ -51,11 +51,11 @@ namespace Kernel inline constexpr HError kErrorInvalidCreds = 61; inline constexpr HError kErrorUnimplemented = 0; - /// @brief Reports a bug to system check. + /// @brief Raises a bug check stop code. Void err_bug_check_raise(void) noexcept; /// @brief Does a system wide bug check. - /// @param void no params. + /// @param void no params are needed. /// @return if error-free: false, otherwise true. Boolean err_bug_check(void) noexcept; } // namespace Kernel diff --git a/dev/zka/KernelKit/LockDelegate.h b/dev/zka/KernelKit/LockDelegate.h index 8f7e9a42..f0e3791f 100644 --- a/dev/zka/KernelKit/LockDelegate.h +++ b/dev/zka/KernelKit/LockDelegate.h @@ -33,16 +33,18 @@ namespace Kernel { auto spin = 0U; - while (spin != N) + while (spin < N) { if (*expr) { fLockStatus | kLockDone; break; } + + ++spin; } - if (spin == N) + if (spin > N) fLockStatus | kLockTimedOut; } -- cgit v1.2.3