summaryrefslogtreecommitdiffhomepage
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
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>
-rw-r--r--dev/modules/AHCI/AHCI.hxx6
-rw-r--r--dev/zba/amd64-efi.make8
-rw-r--r--dev/zba/src/HEL/AMD64/BootATA.cxx2
-rw-r--r--dev/zba/src/HEL/AMD64/BootMain.cxx3
-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
8 files changed, 117 insertions, 37 deletions
diff --git a/dev/modules/AHCI/AHCI.hxx b/dev/modules/AHCI/AHCI.hxx
index 084322bb..a48a8c38 100644
--- a/dev/modules/AHCI/AHCI.hxx
+++ b/dev/modules/AHCI/AHCI.hxx
@@ -261,10 +261,10 @@ typedef struct HbaMem final
Kernel::UInt32 Cap2; // 0x24, Host capabilities extended
Kernel::UInt32 Bohc; // 0x28, BIOS/OS handoff control and status
- Kernel::UInt16 Resv0;
- Kernel::UInt32 Resv2;
+ Kernel::UInt8 Resv0[0xA0 - 0x2C];
+ Kernel::UInt8 Vendor[0x100 - 0xA0];
- HbaPort Ports[1]; // 1 ~ 32, 32 is the max ahci devices per controller.
+ HbaPort Ports[32]; // 1 ~ 32, 32 is the max ahci devices per controller.
} HbaMem;
typedef struct HbaCmdHeader final
diff --git a/dev/zba/amd64-efi.make b/dev/zba/amd64-efi.make
index d28c81f1..9ebc8972 100644
--- a/dev/zba/amd64-efi.make
+++ b/dev/zba/amd64-efi.make
@@ -30,13 +30,11 @@ IMG_2=epm-slave.img
IMG_3=epm-master-2.img
EMU_FLAGS=-net none -smp 4 -m 8G -M q35 \
- -bios $(BIOS) -device piix3-ide,id=ide \
- -drive id=disk,file=$(IMG),format=raw,if=none \
- -device ide-hd,drive=disk,bus=ide.0 -drive \
+ -bios $(BIOS) -drive \
file=fat:rw:src/Root/,index=2,format=raw \
- -drive id=disk_2,file=$(IMG_2),if=none \
+ -drive id=disk_2,file=$(IMG),if=none \
-device ahci,id=ahci \
- -device ide-hd,drive=disk_2,bus=ahci.0 -d int
+ -device ide-hd,drive=disk_2,bus=ahci.0 -serial stdio
LD_FLAGS=-e Main --subsystem=10
diff --git a/dev/zba/src/HEL/AMD64/BootATA.cxx b/dev/zba/src/HEL/AMD64/BootATA.cxx
index b975da1a..6561c150 100644
--- a/dev/zba/src/HEL/AMD64/BootATA.cxx
+++ b/dev/zba/src/HEL/AMD64/BootATA.cxx
@@ -83,7 +83,7 @@ ATAInit_Retry:
if (statRdy & ATA_SR_ERR)
{
writer.Write(
- L"NEWOSLDR: ATA: Select error, not an IDE based hard-drive.\r");
+ L"NEWOSLDR: ATA: error, not an IDE based hard-drive.\r");
return false;
}
diff --git a/dev/zba/src/HEL/AMD64/BootMain.cxx b/dev/zba/src/HEL/AMD64/BootMain.cxx
index 113f2d40..6010d21b 100644
--- a/dev/zba/src/HEL/AMD64/BootMain.cxx
+++ b/dev/zba/src/HEL/AMD64/BootMain.cxx
@@ -164,6 +164,7 @@ EFI_EXTERN_C EFI_API Int32 Main(EfiHandlePtr ImageHandle,
// format the disk.
// ---------------------------------------------------- //
+#ifdef __AHCI__
if (!partition_factory.IsPartitionValid())
{
Boot::BDiskFormatFactory<BootDeviceATA>::BFileDescriptor root;
@@ -176,10 +177,12 @@ EFI_EXTERN_C EFI_API Int32 Main(EfiHandlePtr ImageHandle,
rt_reset_hardware();
}
+#endif
BS->GetMemoryMap(&size_struct_ptr, struct_ptr, &map_key, &sz_desc, &rev_desc);
struct_ptr = new EfiMemoryDescriptor[sz_desc];
+
BS->GetMemoryMap(&size_struct_ptr, struct_ptr, &map_key, &sz_desc, &rev_desc);
auto cDefaultMemoryMap = 0; // Grab any usable entries.
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();