summaryrefslogtreecommitdiffhomepage
path: root/dev/zka
diff options
context:
space:
mode:
authorAmlal El Mahrouss <amlal.elmahrouss@icloud.com>2024-10-21 18:52:06 +0200
committerAmlal El Mahrouss <amlal.elmahrouss@icloud.com>2024-10-21 18:52:06 +0200
commit21b3da78f806d6765f9dffa6a84c21346f171cee (patch)
treedc57df6545c1106a82b9e871e301ac5d5c1cd876 /dev/zka
parent94a3d6b4656d4c2905da173b7ff6ecb074566ea3 (diff)
IMP: Implement AHCI support, can detect and read AHCI disks.
TODO: Add Write support to the AHCI driver. Signed-off-by: Amlal El Mahrouss <amlal.elmahrouss@icloud.com>
Diffstat (limited to 'dev/zka')
-rw-r--r--dev/zka/HALKit/AMD64/PCI/Device.cxx20
-rw-r--r--dev/zka/HALKit/AMD64/PCI/Iterator.cxx4
-rw-r--r--dev/zka/HALKit/AMD64/Storage/AHCI.cxx105
-rw-r--r--dev/zka/KernelKit/PCI/Device.hxx6
4 files changed, 107 insertions, 28 deletions
diff --git a/dev/zka/HALKit/AMD64/PCI/Device.cxx b/dev/zka/HALKit/AMD64/PCI/Device.cxx
index d83cf660..d55683d5 100644
--- a/dev/zka/HALKit/AMD64/PCI/Device.cxx
+++ b/dev/zka/HALKit/AMD64/PCI/Device.cxx
@@ -39,9 +39,6 @@ namespace Kernel::PCI
Device::Device(UShort bus, UShort device, UShort func, UInt32 bar)
: fBus(bus), fDevice(device), fFunction(func), fBar(bar)
{
- // get bar 0
- auto bar_zero = 0x10 + bar * sizeof(UInt32);
- fBar = this->Read(bar_zero, 4);
}
Device::~Device() = default;
@@ -107,21 +104,22 @@ namespace Kernel::PCI
return (UChar)(ZKA_PCIReadRaw(0xC, fBus, fDevice, fFunction) >> 16);
}
- void Device::EnableMmio()
+ void Device::EnableMmio(UInt32 bar_in)
{
- bool enable = Read(0x04, sizeof(UChar)) | (1 << 1);
- Write(0x04, enable, sizeof(UShort));
+ bool enable = Read(bar_in, sizeof(UChar)) | (1 << 1);
+ Write(bar_in, enable, sizeof(UShort));
}
- void Device::BecomeBusMaster()
+ void Device::BecomeBusMaster(UInt32 bar_in)
{
- bool enable = Read(0x04, sizeof(UShort)) | (1 << 2);
- Write(0x04, enable, sizeof(UShort));
+ bool enable = Read(bar_in, sizeof(UShort)) | (1 << 2);
+ Write(bar_in, enable, sizeof(UShort));
}
- UInt32 Device::Bar()
+ UInt32 Device::Bar(UInt32 bar_in)
{
- return fBar;
+ UInt32 bar = ZKA_PCIReadRaw(bar_in, fBus, fDevice, fFunction);
+ return bar;
}
UShort Device::Vendor()
diff --git a/dev/zka/HALKit/AMD64/PCI/Iterator.cxx b/dev/zka/HALKit/AMD64/PCI/Iterator.cxx
index 8d7e7acf..f0d52c5d 100644
--- a/dev/zka/HALKit/AMD64/PCI/Iterator.cxx
+++ b/dev/zka/HALKit/AMD64/PCI/Iterator.cxx
@@ -17,7 +17,9 @@ namespace Kernel::PCI
{
for (int function = 0; function < ZKA_FUNCTION_COUNT; ++function)
{
- Device dev(bus, device, function, type == Types::PciDeviceKind::MassStorageController ? 5 : 1);
+ auto bar = 0x00;
+
+ Device dev(bus, device, function, bar);
if (dev.Class() == (UChar)type)
{
diff --git a/dev/zka/HALKit/AMD64/Storage/AHCI.cxx b/dev/zka/HALKit/AMD64/Storage/AHCI.cxx
index 315a9996..0a318d6d 100644
--- a/dev/zka/HALKit/AMD64/Storage/AHCI.cxx
+++ b/dev/zka/HALKit/AMD64/Storage/AHCI.cxx
@@ -17,6 +17,7 @@
#include <modules/AHCI/AHCI.hxx>
#include <KernelKit/PCI/Iterator.hxx>
+#include <NewKit/Utils.hxx>
#ifdef __AHCI__
enum
@@ -29,7 +30,7 @@ STATIC Kernel::PCI::Device kAhciDevice;
STATIC HbaPort* kAhciPort = nullptr;
/// @brief Initializes an AHCI disk.
-/// @param PortsImplemented the amount of port that have been detected.
+/// @param PortsImplemented the amount of kAhciPort that have been detected.
/// @return
Kernel::Boolean drv_std_init(Kernel::UInt16& PortsImplemented)
{
@@ -42,14 +43,14 @@ Kernel::Boolean drv_std_init(Kernel::UInt16& PortsImplemented)
if (iterator[devIndex].Leak().Subclass() == kSATASubClass &&
iterator[devIndex].Leak().ProgIf() == kSATAProgIfAHCI)
{
- iterator[devIndex].Leak().EnableMmio(); /// enable the memory i/o for this ahci device.
- iterator[devIndex].Leak().BecomeBusMaster(); /// 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.
- HbaMem* mem_ahci = (HbaMem*)kAhciDevice.Bar();
+ HbaMem* mem_ahci = (HbaMem*)kAhciDevice.Bar(0x24);
- UInt32 ports_implemented = mem_ahci->Pi;
+ Kernel::UInt32 ports_implemented = mem_ahci->Pi;
Int32 ahci_index = 0;
const auto cMaxAhciDevices = 32;
@@ -65,27 +66,26 @@ Kernel::Boolean drv_std_init(Kernel::UInt16& PortsImplemented)
{
kcout << "Port is implemented by host.\r";
- UInt8 ipm = (mem_ahci->Ports[ahci_index].Ssts >> 8) & 0x0F;
- UInt8 det = mem_ahci->Ports[ahci_index].Ssts & 0x0F;
+ 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 &&
- det == cAhciPresent &&
- ipm == cAhciIPMActive)
+ if (mem_ahci->Ports[ahci_index].Sig == cAhciSig)
{
kcout << "Found AHCI controller.\r";
kcout << "Device is of SATA type.\r";
detected = true;
+ mem_ahci->Ghc |= (1 << kAhciGHC_AE);
+
kAhciPort = &mem_ahci->Ports[ahci_index];
- // start command engine.
- // drv_start_ahci_engine();
+ break;
}
}
ports_implemented >>= 1;
- ahci_index++;
+ ++ahci_index;
}
return detected;
@@ -102,6 +102,85 @@ Kernel::Boolean drv_std_detected(Kernel::Void)
Kernel::Void drv_std_read(Kernel::UInt64 Lba, Kernel::Char* Buf, Kernel::SizeT SectorSz, Kernel::SizeT Size)
{
+ STATIC Kernel::Boolean kSlotIsUsed = No;
+
+ while (kSlotIsUsed)
+ ;
+
+ 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 = No;
+ 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
+ }
+ if (kAhciPort->Is & (1 << 30))
+ {
+ return; // Error in task file
+ }
+ }
+
+ kSlotIsUsed = No;
}
Kernel::Void drv_std_write(Kernel::UInt64 Lba, Kernel::Char* Buf, Kernel::SizeT SectorSz, Kernel::SizeT Size)
diff --git a/dev/zka/KernelKit/PCI/Device.hxx b/dev/zka/KernelKit/PCI/Device.hxx
index 180e7200..bc1b4eb7 100644
--- a/dev/zka/KernelKit/PCI/Device.hxx
+++ b/dev/zka/KernelKit/PCI/Device.hxx
@@ -60,11 +60,11 @@ namespace Kernel::PCI
UChar Subclass();
UChar ProgIf();
UChar HeaderType();
- UInt32 Bar();
+ UInt32 Bar(UInt32 bar_in);
public:
- void EnableMmio();
- void BecomeBusMaster(); // for PCI-DMA, PC-DMA does not need that.
+ void EnableMmio(UInt32 bar_in);
+ void BecomeBusMaster(UInt32 bar_in); // for PCI-DMA, PC-DMA does not need that.
UShort Vendor();