summaryrefslogtreecommitdiffhomepage
path: root/dev
diff options
context:
space:
mode:
authorAmlal <amlal@el-mahrouss-logic.com>2024-10-24 16:53:42 +0200
committerAmlal <amlal@el-mahrouss-logic.com>2024-10-24 16:53:42 +0200
commit6e3be96bb9a9b3047aee59da639819453eaab6ac (patch)
treef690833cefc4e041c0964bc831fc6dd32ea14eef /dev
parent08e69a55cfda4722277d16ddb632669edde3580b (diff)
IMP: Pushing important code.
Signed-off-by: Amlal <amlal@el-mahrouss-logic.com>
Diffstat (limited to 'dev')
-rw-r--r--dev/zba/BootKit/BitManip.h4
-rw-r--r--dev/zka/HALKit/AMD64/Storage/AHCI.cc126
-rw-r--r--dev/zka/KernelKit/LPC.h4
-rw-r--r--dev/zka/KernelKit/LockDelegate.h6
4 files changed, 115 insertions, 25 deletions
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 <modules/AHCI/AHCI.h>
#include <KernelKit/PCI/Iterator.h>
#include <NewKit/Utils.h>
+#include <KernelKit/LockDelegate.h>
+
+#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<kMaxAhciPoll> 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<kMaxAhciPoll> 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;
}