summaryrefslogtreecommitdiffhomepage
path: root/dev/Kernel/HALKit/AMD64/Storage
diff options
context:
space:
mode:
authorAmlal El Mahrouss <amlal.elmahrouss@icloud.com>2025-02-12 17:38:32 +0100
committerAmlal El Mahrouss <amlal.elmahrouss@icloud.com>2025-02-12 17:38:32 +0100
commit989893d2ac4086b1c89869c258bc138793a7ea8e (patch)
tree03a6162ceb63f1a3cb3aa30b7b9868c1e68bbd52 /dev/Kernel/HALKit/AMD64/Storage
parent52f882514384c6be00752be0dca9bd511db9d450 (diff)
ADD: AHCI driver is almost done..., Paging API tweaks.
Signed-off-by: Amlal El Mahrouss <amlal.elmahrouss@icloud.com>
Diffstat (limited to 'dev/Kernel/HALKit/AMD64/Storage')
-rw-r--r--dev/Kernel/HALKit/AMD64/Storage/SATA.cc102
1 files changed, 65 insertions, 37 deletions
diff --git a/dev/Kernel/HALKit/AMD64/Storage/SATA.cc b/dev/Kernel/HALKit/AMD64/Storage/SATA.cc
index 7764b55b..b37de7e5 100644
--- a/dev/Kernel/HALKit/AMD64/Storage/SATA.cc
+++ b/dev/Kernel/HALKit/AMD64/Storage/SATA.cc
@@ -15,6 +15,7 @@
*
*/
+#include "KernelKit/DebugOutput.h"
#include <KernelKit/UserProcessScheduler.h>
#include <KernelKit/LPC.h>
@@ -28,11 +29,11 @@
#define kHBAErrTaskFile (1 << 30)
#define kHBACmdGhc (1 << 31)
-#define kHBACmdAE (1 << 0)
-#define kHBAPxCmdST 0x0001
-#define kHBAPxCmdFre 0x0010
-#define kHBAPxCmdFR 0x4000
-#define kHBAPxCmdCR 0x8000
+#define kHBACmdAE (0x80000000)
+#define kHBAPxCmdST (0x0001)
+#define kHBAPxCmdFre (0x0010)
+#define kHBAPxCmdFR (0x4000)
+#define kHBAPxCmdCR (0x8000)
#define kSATALBAMode (1 << 6)
@@ -46,9 +47,10 @@
#define kSATABar5 (0x24)
STATIC Kernel::PCI::Device kPCIDevice;
-STATIC HbaMem* kSATAPort = nullptr;
+STATIC HbaMem* kSATA = nullptr;
STATIC Kernel::SizeT kSATAPortIdx = 0UL;
STATIC Kernel::Lba kCurrentDiskSectorCount = 0UL;
+STATIC Kernel::Char kCurrentDiskModel[50] = {"UNKNOWN SATA DRIVE"};
template <BOOL Write, BOOL CommandOrCTRL, BOOL Identify>
static Kernel::Void drvi_std_input_output(Kernel::UInt64 lba, Kernel::UInt8* buffer, Kernel::SizeT sector_sz, Kernel::SizeT size_buffer) noexcept;
@@ -61,18 +63,28 @@ static Kernel::Void drvi_calculate_disk_geometry() noexcept
{
kCurrentDiskSectorCount = 0UL;
- Kernel::UInt8 identify_data[kib_cast(4)] = {};
+ Kernel::UInt8 identify_data[512] = {};
- drvi_std_input_output<NO, NO, YES>(0, identify_data, 0, kib_cast(4));
+ drvi_std_input_output<NO, NO, YES>(0, identify_data, 0, 512);
kCurrentDiskSectorCount = (identify_data[61] << 16) | identify_data[60];
+ for (int i = 0; i < 20; i++)
+ {
+ kCurrentDiskModel[i * 2] = identify_data[27 + i] >> 8;
+ kCurrentDiskModel[i * 2 + 1] = identify_data[27 + i] & 0xFF;
+ }
+
+ kCurrentDiskModel[40] = '\0';
+
+ kout << "Drive Model: " << kCurrentDiskModel << endl;
+
kout << "Disk Size: " << Kernel::number(drv_get_size()) << endl;
kout << "Highest Disk LBA: " << Kernel::number(kCurrentDiskSectorCount) << endl;
}
/// @brief Initializes an AHCI disk.
-/// @param PortsImplemented the amount of kSATAPort that have been detected.
+/// @param PortsImplemented the amount of kSATA that have been detected.
/// @return if the disk was successfully initialized or not.
Kernel::Boolean drv_std_init(Kernel::UInt16& PortsImplemented)
{
@@ -110,14 +122,33 @@ Kernel::Boolean drv_std_init(Kernel::UInt16& PortsImplemented)
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 && det == 3 && ipm == 1)
+ HAL::mm_map_page(mem_ahci, mem_ahci, HAL::kMMFlagsWr);
+
+ kout << "Virtddr: " << hex_number((UIntPtr)mem_ahci) << endl;
+ kout << "PhysAddr: " << hex_number((UIntPtr)HAL::hal_get_phys_address(mem_ahci)) << endl;
+
+ if (mem_ahci->Ports[ahci_index].Sig == kSATASignature && det == 3 && ipm == 1 &&
+ (mem_ahci->Ports[ahci_index].Ssts & 0xF))
{
kout << "Port is implemented as SATA.\r";
kSATAPortIdx = ahci_index;
- kSATAPort = mem_ahci;
+ kSATA = mem_ahci;
+
+ kSATA->Ports[kSATAPortIdx].Cmd &= ~(kHBAPxCmdST | kHBAPxCmdFre); // Disable command and FIS reception
+
+ while (kSATA->Ports[kSATAPortIdx].Cmd & kHBAPxCmdCR)
+ ; // Wait for controller to stop
- kSATAPort->Ghc |= kHBACmdAE;
+ kSATA->Ports[kSATAPortIdx].Serr = 0xFFFFFFFF; // Clear errors
+ kSATA->Ports[kSATAPortIdx].Is = 0xFFFFFFFF; // Clear interrupts
+
+ kSATA->Ports[kSATAPortIdx].Cmd |= kHBAPxCmdFre; // Re-enable FIS reception
+ kSATA->Ports[kSATAPortIdx].Cmd |= kHBAPxCmdST; // Start command engine
+
+ kSATA->Ghc |= kHBACmdAE; // Enable AHCI mode
+
+ HAL::rt_wait_400ns();
drvi_calculate_disk_geometry();
@@ -153,33 +184,34 @@ static Kernel::Int32 drvi_find_cmd_slot(HbaPort* port) noexcept
{
Kernel::UInt32 slots = port->Ci;
- for (Kernel::Int32 i = 0; i < (kSATAPortCnt); i++)
+ for (Kernel::Int32 i = 0; i < kSATAPortCnt; i++)
{
- if ((slots & 1) == 0)
+ if ((slots & i) == 0)
return i;
slots >>= 1;
}
- return 0;
+ return -1;
}
template <BOOL Write, BOOL CommandOrCTRL, BOOL Identify>
static Kernel::Void drvi_std_input_output(Kernel::UInt64 lba, Kernel::UInt8* buffer, Kernel::SizeT sector_sz, Kernel::SizeT size_buffer) noexcept
{
- auto slot = 0L;
-
- slot = drvi_find_cmd_slot(&kSATAPort->Ports[kSATAPortIdx]);
+ const Kernel::SizeT slot = drvi_find_cmd_slot(&kSATA->Ports[kSATAPortIdx]);
if (slot == -1)
return;
if (size_buffer > mib_cast(4))
- Kernel::ke_panic(RUNTIME_CHECK_FAILED, "AHCI only supports < 4mb DMA transfers.");
+ Kernel::ke_panic(RUNTIME_CHECK_FAILED, "AHCI only supports < 4mb DMA transfers per PRD.");
+
+ if (!Write)
+ Kernel::rt_set_memory(buffer, 0, size_buffer);
- HbaCmdHeader* command_header = ((HbaCmdHeader*)((Kernel::UInt64)(kSATAPort->Ports[kSATAPortIdx].Clbu) | kSATAPort->Ports[kSATAPortIdx].Clb)) + slot;
+ HbaCmdHeader* command_header = ((HbaCmdHeader*)((Kernel::UInt64)(kSATA->Ports[kSATAPortIdx].Clb)));
- MUST_PASS(command_header);
+ TRY([&command_header]() -> BOOL { return command_header != nullptr; });
command_header->Cfl = sizeof(FisRegH2D) / sizeof(Kernel::UInt32);
command_header->Write = Write;
@@ -187,24 +219,19 @@ static Kernel::Void drvi_std_input_output(Kernel::UInt64 lba, Kernel::UInt8* buf
command_header->Atapi = 0;
command_header->Prefetchable = 1;
- HbaCmdTbl* command_table = new HbaCmdTbl();
+ HbaCmdTbl* command_table = ((HbaCmdTbl*)((Kernel::UInt64)(command_header->Ctba)));
Kernel::rt_set_memory(command_table, 0, sizeof(HbaCmdTbl));
MUST_PASS(command_table);
- auto phys_dma_buf = Kernel::HAL::hal_get_phys_address(buffer);
+ auto phys_dma_buf = Kernel::HAL::hal_get_phys_address((Kernel::VoidPtr)buffer);
command_table->Prdt[0].Dba = ((Kernel::UInt32)(Kernel::UInt64)phys_dma_buf & 0xFFFFFFFF);
command_table->Prdt[0].Dbau = (((Kernel::UInt64)phys_dma_buf << 32));
command_table->Prdt[0].Dbc = ((size_buffer)-1);
command_table->Prdt[0].IE = 1;
- auto phys_dma_tbl = Kernel::HAL::hal_get_phys_address(command_table);
-
- command_header->Ctba = ((Kernel::UInt32)(Kernel::UInt64)phys_dma_tbl & 0xFFFFFFFF);
- command_header->Ctbau = ((Kernel::UInt32)((Kernel::UInt64)phys_dma_tbl << 32));
-
FisRegH2D* h2d_fis = (FisRegH2D*)((Kernel::UInt64)&command_table->Cfis);
h2d_fis->FisType = kFISTypeRegH2D;
@@ -228,25 +255,26 @@ static Kernel::Void drvi_std_input_output(Kernel::UInt64 lba, Kernel::UInt8* buf
h2d_fis->CountLow = sector_sz & 0xFF;
h2d_fis->CountHigh = (sector_sz >> 8) & 0xFF;
- if (kSATAPort->Is & kHBAErrTaskFile)
+ if (kSATA->Is & kHBAErrTaskFile)
Kernel::ke_panic(RUNTIME_CHECK_BAD_BEHAVIOR, "AHCI Read disk failure, faulty component.");
- kSATAPort->Ports[kSATAPortIdx].Ci = (1 << slot);
+ while (kSATA->Ports[kSATAPortIdx].Cmd & (kHBAPxCmdCR | kHBAPxCmdFR))
+ ; // Ensure controller is idle
+
+ kSATA->Ports[kSATAPortIdx].Cmd |= kHBAPxCmdFre;
+ kSATA->Ports[kSATAPortIdx].Ci = (1 << slot);
while (YES)
{
- if (kSATAPort->Ports[kSATAPortIdx].Ci == 0)
+ if (kSATA->Ports[kSATAPortIdx].Ci == 0)
break;
- kout << "PxCI: " << Kernel::hex_number(kSATAPort->Ports[kSATAPortIdx].Ci) << endl;
- kout << "PxCMD: " << Kernel::hex_number(kSATAPort->Ports[kSATAPortIdx].Cmd) << endl;
+ kout << "PxCI: " << Kernel::hex_number(kSATA->Ports[kSATAPortIdx].Ci) << endl;
+ kout << "PxCMD: " << Kernel::hex_number(kSATA->Ports[kSATAPortIdx].Cmd) << endl;
- if (kSATAPort->Is & kHBAErrTaskFile)
+ if (kSATA->Is & kHBAErrTaskFile)
Kernel::ke_panic(RUNTIME_CHECK_BAD_BEHAVIOR, "AHCI Read disk failure, faulty component.");
}
-
- delete command_table;
- command_table = nullptr;
}
/***