summaryrefslogtreecommitdiffhomepage
path: root/dev/Kernel/HALKit/AMD64
diff options
context:
space:
mode:
authorAmlal El Mahrouss <amlal.elmahrouss@icloud.com>2025-01-05 09:29:00 +0100
committerAmlal El Mahrouss <amlal.elmahrouss@icloud.com>2025-01-05 09:29:00 +0100
commit5903f0c8eca69916c3acffcbe0a20a9af36fdf27 (patch)
tree307f5c3289c3208f613425eb55f04bccd69da8d8 /dev/Kernel/HALKit/AMD64
parent188550e4f26c77e33dcc2a83c4775d17e47dcb39 (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/AMD64')
-rw-r--r--dev/Kernel/HALKit/AMD64/Storage/SATA-DMA.cc170
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;
- }
}
/***