From 6f98067bc9fb75794c864c5b35a7ee1bf0704c73 Mon Sep 17 00:00:00 2001 From: Amlal Date: Sat, 25 Jan 2025 21:48:56 +0100 Subject: ADD: Better SATA driver, but not fully fixed yet. Signed-off-by: Amlal --- dev/Boot/amd64-desktop.make | 5 +- dev/Boot/src/HEL/AMD64/EFIBootStartup.cc | 2 +- .../HALKit/AMD64/HalCoreInterruptHandlerAMD64.cc | 2 +- dev/Kernel/HALKit/AMD64/Processor.h | 21 ++++ dev/Kernel/HALKit/AMD64/Storage/SATA-DMA.cc | 112 ++++++++++++--------- dev/Mod/AHCI/AHCI.h | 32 +++--- 6 files changed, 109 insertions(+), 65 deletions(-) (limited to 'dev') diff --git a/dev/Boot/amd64-desktop.make b/dev/Boot/amd64-desktop.make index 1aa07a1e..4e817a43 100644 --- a/dev/Boot/amd64-desktop.make +++ b/dev/Boot/amd64-desktop.make @@ -82,7 +82,10 @@ compile-amd64: .PHONY: run-efi-amd64-ahci run-efi-amd64-ahci: - $(EMU) $(EMU_FLAGS) -hda $(IMG) -s -S + $(EMU) $(EMU_FLAGS) -device ahci,id=ahci0 \ + -drive id=disk,file=$(IMG),if=none,format=raw \ + -device ide-hd,drive=disk \ + -s -S .PHONY: run-efi-amd64-ata run-efi-amd64-ata: diff --git a/dev/Boot/src/HEL/AMD64/EFIBootStartup.cc b/dev/Boot/src/HEL/AMD64/EFIBootStartup.cc index 462e59e4..d742b098 100644 --- a/dev/Boot/src/HEL/AMD64/EFIBootStartup.cc +++ b/dev/Boot/src/HEL/AMD64/EFIBootStartup.cc @@ -236,7 +236,7 @@ EFI_EXTERN_C EFI_API Int32 Main(EfiHandlePtr image_handle, const auto kFSName = "SSD"; - partition_factory.Format(kFSName, &root, 1); + // partition_factory.Format(kFSName, &root, 1); fb_init(); diff --git a/dev/Kernel/HALKit/AMD64/HalCoreInterruptHandlerAMD64.cc b/dev/Kernel/HALKit/AMD64/HalCoreInterruptHandlerAMD64.cc index 2c7e043c..c01a46fe 100644 --- a/dev/Kernel/HALKit/AMD64/HalCoreInterruptHandlerAMD64.cc +++ b/dev/Kernel/HALKit/AMD64/HalCoreInterruptHandlerAMD64.cc @@ -7,7 +7,7 @@ #include #include #include -#include +#include STATIC BOOL kIsScheduling = NO; diff --git a/dev/Kernel/HALKit/AMD64/Processor.h b/dev/Kernel/HALKit/AMD64/Processor.h index 0e6dcfff..acdf7e42 100644 --- a/dev/Kernel/HALKit/AMD64/Processor.h +++ b/dev/Kernel/HALKit/AMD64/Processor.h @@ -206,6 +206,27 @@ namespace Kernel::HAL return edx & (1 << 5); } + inline UInt64 hal_get_phys_address(void* virtual_address) + { + UInt64 addr = (UInt64)virtual_address; + UInt64 cr3 = (UInt64)hal_read_cr3(); + + // Extract indices for PML4, PDPT, PD, and PT + UInt64 pml4_idx = (addr >> 39) & 0x1FF; + UInt64 pdpt_idx = (addr >> 30) & 0x1FF; + UInt64 pd_idx = (addr >> 21) & 0x1FF; + UInt64 pt_idx = (addr >> 12) & 0x1FF; + + // Get PML4 Table + UInt64* pml4 = (UInt64*)(cr3 & ~0xFFF); + UInt64* pdpt = (UInt64*)(pml4[pml4_idx] & ~0xFFF); + UInt64* pd = (UInt64*)(pdpt[pdpt_idx] & ~0xFFF); + UInt64* pt = (UInt64*)(pd[pd_idx] & ~0xFFF); + + // Get Physical Address + return (pt[pt_idx] & ~0xFFF) + (addr & 0xFFF); + } + /***********************************************************************************/ /// @brief Get Model specific register inside core. /// @param msr MSR diff --git a/dev/Kernel/HALKit/AMD64/Storage/SATA-DMA.cc b/dev/Kernel/HALKit/AMD64/Storage/SATA-DMA.cc index 74afcde3..a9f2decd 100644 --- a/dev/Kernel/HALKit/AMD64/Storage/SATA-DMA.cc +++ b/dev/Kernel/HALKit/AMD64/Storage/SATA-DMA.cc @@ -15,6 +15,10 @@ * */ +#include "HALKit/AMD64/Processor.h" +#include "KernelKit/DebugOutput.h" +#include "KernelKit/Heap.h" +#include "NewKit/Defines.h" #include #include @@ -62,12 +66,26 @@ static Kernel::Void drv_calculate_disk_geometry() noexcept { kCurrentDiskSectorCount = 0UL; - Kernel::UInt8 identify_data[kib_cast(4)] = {}; + Kernel::UInt8 __attribute__((aligned(4096))) identify_data[kib_cast(4)] = {}; drv_std_input_output(0, identify_data, 0, kib_cast(8)); kCurrentDiskSectorCount = (identify_data[61] << 16) | identify_data[60]; + Kernel::Char model[41]; + + for (int i = 0; i < 40; i += 2) + { + char temp = identify_data[54 + i]; + identify_data[54 + i] = identify_data[54 + i + 1]; + identify_data[54 + i + 1] = temp; + } + + Kernel::rt_copy_memory((Kernel::Char*)(identify_data + 54), model, 40); + model[40] = '\0'; + + kcout << "SATA Model: " << model << "\r"; + kcout << "Disk Size: " << Kernel::number(drv_get_size()) << endl; kcout << "Highest LBA: " << Kernel::number(kCurrentDiskSectorCount) << endl; } @@ -89,11 +107,11 @@ Kernel::Boolean drv_std_init(Kernel::UInt16& PortsImplemented) if (kPCIDevice.Subclass() == kSATASubClass && kPCIDevice.ProgIf() == kSATAProgIfAHCI) { + HbaMem* mem_ahci = (HbaMem*)(kPCIDevice.Bar(0x24) & 0xFFFFFFF0); + 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*)kPCIDevice.Bar(0x24); - Kernel::UInt32 ports_implemented = mem_ahci->Pi; Kernel::UInt16 ahci_index = 0; @@ -113,7 +131,7 @@ 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) + if (mem_ahci->Ports[ahci_index].Sig == kSATASignature && det == 3 && ipm == 1) { kcout << "Port is SATA.\r"; @@ -135,8 +153,7 @@ Kernel::Boolean drv_std_init(Kernel::UInt16& PortsImplemented) const auto kAHCIBaseAddress = mib_cast(4); - kSATAPort->Ports[kSATAPortIdx].Clb = kAHCIBaseAddress + (kSATAPortIdx << 10); - kSATAPort->Ports[kSATAPortIdx].Clbu = 0; + kSATAPort->Ports[kSATAPortIdx].Clb = kAHCIBaseAddress + (kSATAPortIdx << 10); rt_set_memory((VoidPtr)((UIntPtr)kSATAPort->Ports[kSATAPortIdx].Clb), 0, 1024); @@ -151,8 +168,7 @@ Kernel::Boolean drv_std_init(Kernel::UInt16& PortsImplemented) { cmdheader[i].Prdtl = 8; - cmdheader[i].Ctba = kAHCIBaseAddress + (40 << 10) + (kSATAPortIdx << 13) + (i << 8); - cmdheader[i].Ctbau = 0; + cmdheader[i].Ctba = kAHCIBaseAddress + (40 << 10) + (kSATAPortIdx << 13) + (i << 8); rt_set_memory((VoidPtr)(UIntPtr)cmdheader[i].Ctba, 0, 256); } @@ -164,23 +180,22 @@ Kernel::Boolean drv_std_init(Kernel::UInt16& PortsImplemented) kSATAPort->Ports[kSATAPortIdx].Cmd |= kHBAPxCmdFre; kSATAPort->Ports[kSATAPortIdx].Cmd |= kHBAPxCmdST; - drv_calculate_disk_geometry(); + // Enable AHCI Mode FIRST + kSATAPort->Ghc |= (1 >> 31); - detected = YES; + drv_calculate_disk_geometry(); - break; + return YES; } } ports_implemented >>= 1; ++ahci_index; } - - return detected; } } - return No; + return NO; } Kernel::Boolean drv_std_detected(Kernel::Void) @@ -190,12 +205,12 @@ Kernel::Boolean drv_std_detected(Kernel::Void) Kernel::Void drv_std_write(Kernel::UInt64 lba, Kernel::Char* buffer, Kernel::SizeT sector_sz, Kernel::SizeT size_buffer) { - drv_std_input_output(lba, (Kernel::UInt8*)buffer, sector_sz, size_buffer); + drv_std_input_output(lba, (Kernel::UInt8*)buffer, sector_sz, size_buffer / sector_sz); } Kernel::Void drv_std_read(Kernel::UInt64 lba, Kernel::Char* buffer, Kernel::SizeT sector_sz, Kernel::SizeT size_buffer) { - drv_std_input_output(lba, (Kernel::UInt8*)buffer, sector_sz, size_buffer); + drv_std_input_output(lba, (Kernel::UInt8*)buffer, sector_sz, size_buffer / sector_sz); } static Kernel::Int32 drv_find_cmd_slot(HbaPort* port) noexcept @@ -222,8 +237,6 @@ static Kernel::Void drv_std_input_output(Kernel::UInt64 lba, Kernel::UInt8* buff if (!CommandOrCTRL) return; - kSATAPort->Ports[kSATAPortIdx].Is = -1; - auto slot = 0L; slot = drv_find_cmd_slot(&kSATAPort->Ports[kSATAPortIdx]); @@ -231,46 +244,51 @@ static Kernel::Void drv_std_input_output(Kernel::UInt64 lba, Kernel::UInt8* buff if (slot == -1) return; - volatile HbaCmdHeader* command_header = ((volatile HbaCmdHeader*)((Kernel::UInt64)kSATAPort->Ports[kSATAPortIdx].Clb + kSATAPort->Ports[kSATAPortIdx].Clbu)); + kcout << "Reading AHCI disk...\r"; - command_header += slot; + volatile HbaCmdHeader* command_header = ((volatile HbaCmdHeader*)((Kernel::UInt64)kSATAPort->Ports[kSATAPortIdx].Clb + slot * sizeof(HbaCmdHeader))); + + Kernel::rt_set_memory((void*)command_header, 0, sizeof(HbaCmdTbl)); MUST_PASS(command_header); command_header->Cfl = sizeof(FisRegH2D) / sizeof(Kernel::UInt32); command_header->Write = Write; - command_header->Prdtl = (Kernel::UInt16)((size_buffer - 1) >> 4) + 1; + command_header->Prdtl = 1; + command_header->Ctba = (Kernel::UIntPtr)Kernel::mm_new_heap(sizeof(HbaCmdTbl), YES, NO); + + volatile HbaCmdTbl* command_table = (volatile HbaCmdTbl*)((Kernel::UInt64)command_header->Ctba); - volatile HbaCmdTbl* command_table = (volatile HbaCmdTbl*)((Kernel::UInt64)command_header->Ctba + command_header->Ctbau); + Kernel::rt_set_memory((void*)command_table, 0, sizeof(HbaCmdTbl)); MUST_PASS(command_table); - for (Kernel::SizeT i = 0; i < (command_header->Prdtl - 1); i++) - { - command_table->PrdtEntries[i].Dba = ((Kernel::UInt32)(Kernel::UInt64)buffer & 0xFFFFFFFF); - command_table->PrdtEntries[i].Dbau = (((Kernel::UInt64)buffer >> 32) & 0xFFFFFFFF); - command_table->PrdtEntries[i].Dbc = (size_buffer - 1); - command_table->PrdtEntries[i].InterruptBit = YES; + command_table->PrdtEntries->Dba = (Kernel::UInt64)Kernel::HAL::hal_get_phys_address(buffer); + command_table->PrdtEntries->Dbc = (size_buffer * sector_sz) - 1; + command_table->PrdtEntries->InterruptBit = YES; + kcout << "PRDT Entry 0 - Dba: " << Kernel::hex_number(command_table->PrdtEntries->Dba) << endl; + kcout << "PRDT Entry 0 - Dbc: " << Kernel::hex_number(command_table->PrdtEntries->Dbc) << endl; - size_buffer -= 16; - buffer += kib_cast(4); - } + volatile FisRegH2D* h2d_fis = (volatile FisRegH2D*)(command_table->Cfis); - volatile FisRegH2D* h2d_fis = (volatile FisRegH2D*)((Kernel::UInt64)command_table->Cfis); + Kernel::rt_set_memory((void*)h2d_fis, 0, sizeof(FisRegH2D)); h2d_fis->FisType = kFISTypeRegH2D; - h2d_fis->CmdOrCtrl = YES; + h2d_fis->CmdOrCtrl = CommandOrCTRL; h2d_fis->Command = Write ? kAHCICmdWriteDmaEx : kAHCICmdReadDmaEx; if (Identify) h2d_fis->Command = kAHCICmdIdentify; - h2d_fis->Lba0 = lba; - h2d_fis->Lba1 = lba >> 8; - h2d_fis->Lba2 = lba >> 16; - h2d_fis->Lba3 = lba >> 24; + h2d_fis->Lba0 = (Kernel::UInt32)(lba) & 0xFF; + h2d_fis->Lba1 = (Kernel::UInt8)(lba >> 8) & 0xFF; + h2d_fis->Lba2 = (Kernel::UInt8)(lba >> 16) & 0xFF; + + h2d_fis->Lba3 = (Kernel::UInt8)(lba >> 24) & 0xFF; + h2d_fis->Lba4 = (Kernel::UInt8)(lba >> 32) & 0xFF; + h2d_fis->Lba5 = (Kernel::UInt8)(lba >> 40) & 0xFF; h2d_fis->Device = kSataLBAMode; @@ -282,19 +300,23 @@ static Kernel::Void drv_std_input_output(Kernel::UInt64 lba, Kernel::UInt8* buff kcout << "waiting for slot to be ready\r\n"; } - kSATAPort->Is = -1; - kSATAPort->Ports[kSATAPortIdx].Ci |= 1 << slot; + kSATAPort->Ports[kSATAPortIdx].Ci = 1 << slot; while (kSATAPort->Ports[kSATAPortIdx].Ci & (1 << slot)) { - kcout << Kernel::number(slot) << endl; + Kernel::UInt32 tfd = kSATAPort->Ports[kSATAPortIdx].Tfd; + kcout << "AHCI TFD: " << Kernel::number(tfd) << endl; + } - if (kSATAPort->Is & kHBAErrTaskFile) // check for task file error. - { - Kernel::ke_panic(RUNTIME_CHECK_BAD_BEHAVIOR, "AHCI Read disk failure, faulty component."); - return; - } + kcout << "Last Command Sent: " << (int)Kernel::number(h2d_fis->Command) << endl; + + kcout << "LBA 1 First 16 Bytes: "; + for (int i = 0; i < 16; i++) + { + kcout << Kernel::hex_number(buffer[i]); } + + Kernel::mm_delete_heap((Kernel::VoidPtr)command_header->Ctba); } /*** diff --git a/dev/Mod/AHCI/AHCI.h b/dev/Mod/AHCI/AHCI.h index 08846e85..7b50d461 100644 --- a/dev/Mod/AHCI/AHCI.h +++ b/dev/Mod/AHCI/AHCI.h @@ -59,20 +59,21 @@ typedef struct FisRegH2D final Kernel::UInt8 Reserved0 : 3; // Reserved Kernel::UInt8 CmdOrCtrl : 1; // 1: Command, 0: Control - Kernel::UInt8 Command; // Command register - Kernel::UInt8 Featurel; // Feature register, 7:0 + Kernel::UInt8 Command; // Command register + Kernel::UInt8 FeatureLow; // Feature register, 7:0 // DWORD 1 - Kernel::UInt8 Lba0; // LBA low register, 7:0 - Kernel::UInt8 Lba1; // LBA mid register, 15:8 - Kernel::UInt8 Lba2; // LBA high register, 23:16 + Kernel::UInt8 Lba0; // LBA low register, 7:0 + Kernel::UInt8 Lba1; // LBA mid register, 15:8 + Kernel::UInt8 Lba2; + Kernel::UInt8 Device; // Device register - // DWORD 2 - Kernel::UInt8 Lba3; // LBA register, 31:24 - Kernel::UInt8 Lba4; // LBA register, 39:32 - Kernel::UInt8 Lba5; // LBA register, 47:40 - Kernel::UInt8 FeatureHigh; // Feature register, 15:8 + Kernel::UInt8 Lba3; // Feature register, 15:8 + Kernel::UInt8 Lba4; + Kernel::UInt8 Lba5; + + Kernel::UInt8 FeatureHigh; // DWORD 3 Kernel::UInt8 CountLow; // Count register, 7:0 @@ -191,7 +192,7 @@ typedef struct FisDmaSetup final Kernel::UInt32 Rsvd; // More reserved // DWORD 4 - Kernel::UInt32 DmabufOffset; // Byte offset into buffer. First 2 bits must be 0 + Kernel::UInt32 DmaBufOffset; // Byte offset into buffer. First 2 bits must be 0 // DWORD 5 Kernel::UInt32 TransferCount; // Number of bytes to transfer. Bit 0 must be 0 @@ -228,8 +229,7 @@ typedef struct FisDevBits final typedef struct HbaPort final { - Kernel::UInt32 Clb; // 0x00, command list base address, 1K-byte aligned - Kernel::UInt32 Clbu; // 0x04, command list base address upper 32 bits + Kernel::UInt64 Clb; Kernel::UInt32 Fb; // 0x08, FIS base address, 256-byte aligned Kernel::UInt32 Fbu; // 0x0C, FIS base address upper 32 bits Kernel::UInt32 Is; // 0x10, interrupt status @@ -287,8 +287,7 @@ typedef struct HbaCmdHeader final Kernel::UInt16 Prdtl; // Physical region descriptor table length in entries volatile Kernel::UInt32 Prdbc; // Physical region descriptor byte count transferred - Kernel::UInt32 Ctba; // Command table descriptor base address - Kernel::UInt32 Ctbau; // Command table descriptor base address upper 32 bits + Kernel::UInt64 Ctba; // Command table descriptor base address Kernel::UInt32 Reserved1[4]; // Reserved } HbaCmdHeader; @@ -314,8 +313,7 @@ typedef struct HbaFis final typedef struct HbaPrdtEntry final { - Kernel::UInt32 Dba; // Data base address - Kernel::UInt32 Dbau; // Data base address upper 32 bits + Kernel::UInt64 Dba; // Data base address Kernel::UInt32 Reserved0; // Reserved // DW3 Kernel::UInt32 Dbc : 22; // Byte count, 4M max -- cgit v1.2.3