From bea589553fa9d33168e42bb83b77591fa8a0cad1 Mon Sep 17 00:00:00 2001 From: Amlal Date: Mon, 17 Feb 2025 20:35:53 +0100 Subject: ADD: Patch CountL and CountH in AHCI driver. Signed-off-by: Amlal --- dev/Boot/amd64-desktop.make | 22 ++- dev/Boot/arm64-desktop.make | 2 +- dev/Boot/arm64-mobile.make | 2 +- dev/Boot/src/HEL/AMD64/BootEFI.cc | 5 + dev/Kernel/HALKit/AMD64/Storage/AHCI.cc | 313 +++++++++++++++++++++++++++++++ dev/Kernel/HALKit/AMD64/Storage/SATA.cc | 318 -------------------------------- 6 files changed, 334 insertions(+), 328 deletions(-) create mode 100644 dev/Kernel/HALKit/AMD64/Storage/AHCI.cc delete mode 100644 dev/Kernel/HALKit/AMD64/Storage/SATA.cc (limited to 'dev') diff --git a/dev/Boot/amd64-desktop.make b/dev/Boot/amd64-desktop.make index bb5deb71..208d6ff6 100644 --- a/dev/Boot/amd64-desktop.make +++ b/dev/Boot/amd64-desktop.make @@ -20,7 +20,7 @@ else EMU=qemu-system-x86_64 -net none endif -ifeq ($(NEWS_MODEL), ) +ifeq ($(NEOS_MODEL), ) NE_MODEL=-DkMachineModel="\"NeOS\"" endif @@ -28,6 +28,8 @@ BIOS=OVMF.fd IMG=epm-master-1.img IMG_2=epm-master-2.img +BOOT=neos.iso + DISK_DRV = ifneq ($(ATA_PIO_SUPPORT), ) @@ -48,14 +50,12 @@ endif ifeq ($(shell uname), Darwin) EMU_FLAGS=-net none -smp 4 -m 8G \ - -bios $(BIOS) -drive \ - file=fat:rw:src/Root/,index=3,format=raw + -bios $(BIOS) -cdrom $(BOOT) -boot d endif ifneq ($(shell uname), Darwin) EMU_FLAGS=-net none -smp 4 -m 8G \ - -bios $(BIOS) -drive \ - file=fat:rw:src/Root/,index=3,format=raw -accel kvm + -bios $(BIOS) -M q35 -cdrom $(BOOT) -boot d -accel kvm endif LD_FLAGS=-e Main --subsystem=10 @@ -92,6 +92,12 @@ all: compile-amd64 $(COPY) ./Mod/SysChk/$(SYSCHK) src/Root/$(SYSCHK) $(COPY) ../LibSCI/$(SCIKIT) src/Root/$(SCIKIT) $(COPY) src/$(BOOTLOADER) src/Root/$(BOOTLOADER) + xorriso -as mkisofs -R -r -J \ + -no-emul-boot -boot-load-size 4 -boot-info-table -hfsplus \ + -apm-block-size 2048 --efi-boot EFI/BOOT/BOOTX64.EFI \ + -efi-boot-part --efi-boot-image --protective-msdos-label \ + src/Root -o $(BOOT) + ifneq ($(DEBUG_SUPPORT), ) DEBUG = -D__DEBUG__ @@ -107,15 +113,15 @@ compile-amd64: .PHONY: run-efi-amd64-ahci run-efi-amd64-ahci: - $(EMU) $(EMU_FLAGS) -M q35 -hdc $(IMG) -s -S -trace ahci_* + $(EMU) $(EMU_FLAGS) -hda $(IMG) -s -S -trace ahci_* -boot menu=on .PHONY: run-efi-amd64-ata-pio run-efi-amd64-ata-pio: - $(EMU) $(EMU_FLAGS) -M q35 -device piix3-ide,id=ide -drive id=disk,file=$(IMG),format=raw,if=none -device ide-hd,drive=disk,bus=ide.0 -s -S + $(EMU) $(EMU_FLAGS) -device piix3-ide,id=ide -drive id=disk,file=$(IMG),format=raw,if=none -device ide-hd,drive=disk,bus=ide.0 -s -S .PHONY: run-efi-amd64-ata-dma run-efi-amd64-ata-dma: - $(EMU) $(EMU_FLAGS) -M q35 -device piix4-ide,id=ide -drive id=disk,file=$(IMG),format=raw,if=none -device ide-hd,drive=disk,bus=ide.0 -s -S + $(EMU) $(EMU_FLAGS) -device piix4-ide,id=ide -drive id=disk,file=$(IMG),format=raw,if=none -device ide-hd,drive=disk,bus=ide.0 -s -S .PHONY: run-efi-amd64-ata run-efi-amd64-ata: run-efi-amd64-ata-dma diff --git a/dev/Boot/arm64-desktop.make b/dev/Boot/arm64-desktop.make index 42aa1f57..5e78868f 100644 --- a/dev/Boot/arm64-desktop.make +++ b/dev/Boot/arm64-desktop.make @@ -18,7 +18,7 @@ else EMU=qemu-system-aarch64 endif -ifeq ($(NEWS_MODEL), ) +ifeq ($(NEOS_MODEL), ) NE_MODEL=-DkMachineModel="\"NeKernel\"" endif diff --git a/dev/Boot/arm64-mobile.make b/dev/Boot/arm64-mobile.make index 853d984a..809ad313 100644 --- a/dev/Boot/arm64-mobile.make +++ b/dev/Boot/arm64-mobile.make @@ -18,7 +18,7 @@ else EMU=qemu-system-aarch64 endif -ifeq ($(NEWS_MODEL), ) +ifeq ($(NEOS_MODEL), ) NE_MODEL=-DkMachineModel="\"NeKernel\"" endif diff --git a/dev/Boot/src/HEL/AMD64/BootEFI.cc b/dev/Boot/src/HEL/AMD64/BootEFI.cc index a8dc5561..b3e03f01 100644 --- a/dev/Boot/src/HEL/AMD64/BootEFI.cc +++ b/dev/Boot/src/HEL/AMD64/BootEFI.cc @@ -201,6 +201,11 @@ EFI_EXTERN_C EFI_API Int32 Main(EfiHandlePtr image_handle, while (BS->AllocatePool(EfiLoaderData, handover_hdr->f_BitMapSize, &handover_hdr->f_BitMapStart) != kEfiOk) { + if (handover_hdr->f_BitMapStart) + { + BS->FreePool(handover_hdr->f_BitMapStart); + handover_hdr->f_BitMapStart = nullptr; + } } handover_hdr->f_FirmwareCustomTables[0] = (VoidPtr)BS; diff --git a/dev/Kernel/HALKit/AMD64/Storage/AHCI.cc b/dev/Kernel/HALKit/AMD64/Storage/AHCI.cc new file mode 100644 index 00000000..49025023 --- /dev/null +++ b/dev/Kernel/HALKit/AMD64/Storage/AHCI.cc @@ -0,0 +1,313 @@ +/* ------------------------------------------- + + Copyright (C) 2024-2025, DeVrije-Aker Corporation, all rights reserved. + +------------------------------------------- */ + +/** + * @file AHCI.cc + * @author Amlal El Mahrouss (amlalelmahrouss@icloud.com) + * @brief AHCI driver. + * @version 0.1 + * @date 2024-02-02 + * + * @Copyright (C) 2024, DeVrije-Aker, all rights reserved. + * + */ + +#include +#include + +#include +#include +#include +#include +#include + +#ifdef __AHCI__ + +#define kHBAErrTaskFile (1 << 30) +#define kHBAPxCmdST 0x0001 +#define kHBAPxCmdFre 0x0010 +#define kHBAPxCmdFR 0x4000 +#define kHBAPxCmdCR 0x8000 + +#define kSataLBAMode (1 << 6) + +#define kAhciSRBsy (0x80) +#define kAhciSRDrq (0x08) + +#define kAhciPortCnt 32 + +enum +{ + kSATAProgIfAHCI = 0x01, + kSATASubClass = 0x06, + kSATABar5 = 0x24, +}; + +STATIC Kernel::PCI::Device kPCIDevice; +STATIC HbaMem* kSATA = nullptr; +STATIC Kernel::SizeT kSATAPortIdx = 0UL; +STATIC Kernel::Lba kCurrentDiskSectorCount = 0UL; + +template +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; + +static Kernel::Void drv_calculate_disk_geometry() noexcept +{ + kCurrentDiskSectorCount = 0UL; + + Kernel::UInt8 identify_data[kib_cast(4)] = {0}; + + drv_std_input_output(0, identify_data, 0, kib_cast(8)); + + kCurrentDiskSectorCount = (identify_data[61] << 16) | identify_data[60]; + + kout << "Disk Size: " << Kernel::number(drv_get_size()) << endl; + kout << "Highest LBA: " << Kernel::number(kCurrentDiskSectorCount) << endl; +} + +/// @brief Initializes an AHCI disk. +/// @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) +{ + using namespace Kernel; + + PCI::Iterator iterator(Types::PciDeviceKind::MassStorageController); + + for (SizeT device_index = 0; device_index < NE_BUS_COUNT; ++device_index) + { + kPCIDevice = iterator[device_index].Leak(); // And then leak the reference. + + // if SATA and then interface is AHCI... + if (kPCIDevice.Subclass() == kSATASubClass && + kPCIDevice.ProgIf() == kSATAProgIfAHCI) + { + 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; + + const Kernel::UInt16 kMaxPortsImplemented = kAhciPortCnt; + const Kernel::UInt32 kSATASignature = 0x00000101; + const Kernel::UInt8 kAhciPresent = 0x03; + const Kernel::UInt8 kAhciIPMActive = 0x01; + + Kernel::Boolean detected = false; + + while (ahci_index < kMaxPortsImplemented) + { + if (ports_implemented) + { + kout << "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) + { + kout << "Port is SATA.\r"; + + kSATAPortIdx = ahci_index; + kSATA = mem_ahci; + + kSATA->Ports[kSATAPortIdx].Cmd &= ~kHBAPxCmdST; + kSATA->Ports[kSATAPortIdx].Cmd &= ~kHBAPxCmdFre; + + while (YES) + { + if (kSATA->Ports[kSATAPortIdx].Cmd & kHBAPxCmdFR) + continue; + if (kSATA->Ports[kSATAPortIdx].Cmd & kHBAPxCmdCR) + continue; + + break; + } + + const auto kAHCIBaseAddress = mib_cast(4); + + kSATA->Ports[kSATAPortIdx].Clb = kAHCIBaseAddress + (kSATAPortIdx << 10); + kSATA->Ports[kSATAPortIdx].Clbu = 0; + + rt_set_memory((VoidPtr)((UIntPtr)kSATA->Ports[kSATAPortIdx].Clb), 0, 1024); + + kSATA->Ports[kSATAPortIdx].Fb = kAHCIBaseAddress + (32 << 10) + (kSATAPortIdx << 8); + kSATA->Ports[kSATAPortIdx].Fbu = 0; + + rt_set_memory((VoidPtr)((UIntPtr)kSATA->Ports[kSATAPortIdx].Fb), 0, 256); + + HbaCmdHeader* cmdheader = (HbaCmdHeader*)((UIntPtr)kSATA->Ports[kSATAPortIdx].Clb); + + for (int i = 0; i < 32; i++) + { + cmdheader[i].Prdtl = 8; + + cmdheader[i].Ctba = kAHCIBaseAddress + (40 << 10) + (kSATAPortIdx << 13) + (i << 8); + cmdheader[i].Ctbau = 0; + + rt_set_memory((VoidPtr)(UIntPtr)cmdheader[i].Ctba, 0, 256); + } + + while (kSATA->Ports[kSATAPortIdx].Cmd & kHBAPxCmdCR) + { + } + + kSATA->Ports[kSATAPortIdx].Cmd |= kHBAPxCmdFre; + kSATA->Ports[kSATAPortIdx].Cmd |= kHBAPxCmdST; + + drv_calculate_disk_geometry(); + + detected = YES; + + break; + } + } + + ports_implemented >>= 1; + ++ahci_index; + } + + return detected; + } + } + + return No; +} + +Kernel::Boolean drv_std_detected(Kernel::Void) +{ + return kPCIDevice.DeviceId() != 0xFFFF; +} + +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); +} + +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); +} + +static Kernel::Int32 drv_find_cmd_slot(HbaPort* port) noexcept +{ + if (port == nullptr) + return -1; + + Kernel::UInt32 slots = (kSATA->Ports[kSATAPortIdx].Sact | kSATA->Ports[kSATAPortIdx].Ci); + + for (Kernel::Int32 i = 0; i < ((kSATA->Cap & 0x1F) + 1); i++) + { + if ((slots & 1) == 0) + return i; + + slots >>= 1; + } + + return -1; +} + +BOOL kAHCICommandIssued = NO; + +template +static Kernel::Void drv_std_input_output(Kernel::UInt64 lba, Kernel::UInt8* buffer, Kernel::SizeT sector_sz, Kernel::SizeT size_buffer) noexcept +{ + kSATA->Ports[kSATAPortIdx].Is = -1; + kSATA->Is = -1; + + auto slot = 0L; + + slot = drv_find_cmd_slot(&kSATA->Ports[kSATAPortIdx]); + + if (slot == -1) + return; + + volatile HbaCmdHeader* command_header = ((volatile HbaCmdHeader*)((Kernel::UInt64)kSATA->Ports[kSATAPortIdx].Clb + kSATA->Ports[kSATAPortIdx].Clbu)); + + command_header += slot; + + MUST_PASS(command_header); + + command_header->Cfl = sizeof(FisRegH2D) / sizeof(Kernel::UInt32); + command_header->Write = Write; + command_header->Prdtl = (size_buffer / 16) + 1; + + volatile HbaCmdTbl* command_table = (volatile HbaCmdTbl*)((Kernel::UInt64)command_header->Ctba + command_header->Ctbau); + + MUST_PASS(command_table); + + auto buffer_phys = buffer; + + for (Kernel::SizeT i = 0; i < (command_header->Prdtl); ++i) + { + command_table->Prdt[i].Dba = ((Kernel::UInt32)(Kernel::UInt64)buffer_phys + (i * 16) & 0xFFFFFFFF); + command_table->Prdt[i].Dbau = (((Kernel::UInt64)(buffer_phys + (i * 16)) >> 32) & 0xFFFFFFFF); + command_table->Prdt[i].Dbc = (16 - 1); + command_table->Prdt[i].Ie = YES; + } + + volatile FisRegH2D* h2d_fis = (volatile FisRegH2D*)((Kernel::UInt64)&command_table->Cfis); + + h2d_fis->FisType = kFISTypeRegH2D; + h2d_fis->CmdOrCtrl = CommandOrCTRL; + h2d_fis->Command = Write ? kAHCICmdWriteDmaEx : kAHCICmdReadDmaEx; + + if (Identify) + h2d_fis->Command = kAHCICmdIdentify; + + h2d_fis->Lba0 = (lba & 0xFF); + h2d_fis->Lba1 = (lba >> 8) & 0xFF; + h2d_fis->Lba2 = (lba >> 16) & 0xFF; + h2d_fis->Lba3 = (lba >> 24) & 0xFF; + h2d_fis->Lba4 = (lba >> 32) & 0xFF; + h2d_fis->Lba5 = (lba >> 40) & 0xFF; + + h2d_fis->Device = kSataLBAMode; + + h2d_fis->CountLow = (size_buffer) & 0xFF; + h2d_fis->CountHigh = (size_buffer >> 8) & 0xFF; + + while ((kSATA->Ports[kSATAPortIdx].Tfd & (kAhciSRBsy | kAhciSRDrq))) + { + kout << "Waiting for slot to be ready\r"; + } + + kSATA->Ports[kSATAPortIdx].Ci = 1 << slot; + kAHCICommandIssued = YES; + + while (kSATA->Ports[kSATAPortIdx].Ci & (1 << slot)) + { + if (kSATA->Is & kHBAErrTaskFile) // check for task file error. + { + Kernel::ke_panic(RUNTIME_CHECK_BAD_BEHAVIOR, "AHCI Read disk failure, faulty component."); + return; + } + } +} + +/*** + @brief Gets the number of sectors inside the drive. + @return Sector size in bytes. + */ +Kernel::SizeT drv_get_sector_count() +{ + return kCurrentDiskSectorCount; +} + +/// @brief Get the drive size. +/// @return Disk size in bytes. +Kernel::SizeT drv_get_size() +{ + return (drv_get_sector_count()) * kAHCISectorSize; +} + +#endif // ifdef __AHCI__ \ No newline at end of file diff --git a/dev/Kernel/HALKit/AMD64/Storage/SATA.cc b/dev/Kernel/HALKit/AMD64/Storage/SATA.cc deleted file mode 100644 index 6651db8c..00000000 --- a/dev/Kernel/HALKit/AMD64/Storage/SATA.cc +++ /dev/null @@ -1,318 +0,0 @@ -/* ------------------------------------------- - - Copyright (C) 2024-2025, DeVrije-Aker Corporation, all rights reserved. - -------------------------------------------- */ - -/** - * @file AHCI.cc - * @author Amlal El Mahrouss (amlalelmahrouss@icloud.com) - * @brief AHCI driver. - * @version 0.1 - * @date 2024-02-02 - * - * @Copyright (C) 2024, DeVrije-Aker, all rights reserved. - * - */ - -#include "HALKit/AMD64/Processor.h" -#include -#include - -#include -#include -#include -#include -#include - -#ifdef __AHCI__ - -#define kHBAErrTaskFile (1 << 30) -#define kHBAPxCmdST 0x0001 -#define kHBAPxCmdFre 0x0010 -#define kHBAPxCmdFR 0x4000 -#define kHBAPxCmdCR 0x8000 - -#define kSataLBAMode (1 << 6) - -#define kAhciSRBsy (0x80) -#define kAhciSRDrq (0x08) - -#define kAhciPortCnt 32 - -enum -{ - kSATAProgIfAHCI = 0x01, - kSATASubClass = 0x06, - kSATABar5 = 0x24, -}; - -STATIC Kernel::PCI::Device kPCIDevice; -STATIC HbaMem* kSATA = nullptr; -STATIC Kernel::SizeT kSATAPortIdx = 0UL; -STATIC Kernel::Lba kCurrentDiskSectorCount = 0UL; - -template -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; - -static Kernel::Void drv_calculate_disk_geometry() noexcept -{ - kCurrentDiskSectorCount = 0UL; - - Kernel::UInt8 identify_data[kib_cast(4)] = {0}; - - drv_std_input_output(0, identify_data, 0, kib_cast(8)); - - kCurrentDiskSectorCount = (identify_data[61] << 16) | identify_data[60]; - - kout << "Disk Size: " << Kernel::number(drv_get_size()) << endl; - kout << "Highest LBA: " << Kernel::number(kCurrentDiskSectorCount) << endl; -} - -/// @brief Initializes an AHCI disk. -/// @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) -{ - using namespace Kernel; - - PCI::Iterator iterator(Types::PciDeviceKind::MassStorageController); - - for (SizeT device_index = 0; device_index < NE_BUS_COUNT; ++device_index) - { - kPCIDevice = iterator[device_index].Leak(); // And then leak the reference. - - // if SATA and then interface is AHCI... - if (kPCIDevice.Subclass() == kSATASubClass && - kPCIDevice.ProgIf() == kSATAProgIfAHCI) - { - 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; - - const Kernel::UInt16 kMaxPortsImplemented = kAhciPortCnt; - const Kernel::UInt32 kSATASignature = 0x00000101; - const Kernel::UInt8 kAhciPresent = 0x03; - const Kernel::UInt8 kAhciIPMActive = 0x01; - - Kernel::Boolean detected = false; - - while (ahci_index < kMaxPortsImplemented) - { - if (ports_implemented) - { - kout << "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) - { - kout << "Port is SATA.\r"; - - kSATAPortIdx = ahci_index; - kSATA = mem_ahci; - - kSATA->Ports[kSATAPortIdx].Cmd &= ~kHBAPxCmdST; - kSATA->Ports[kSATAPortIdx].Cmd &= ~kHBAPxCmdFre; - - while (YES) - { - if (kSATA->Ports[kSATAPortIdx].Cmd & kHBAPxCmdFR) - continue; - if (kSATA->Ports[kSATAPortIdx].Cmd & kHBAPxCmdCR) - continue; - - break; - } - - const auto kAHCIBaseAddress = mib_cast(4); - - kSATA->Ports[kSATAPortIdx].Clb = kAHCIBaseAddress + (kSATAPortIdx << 10); - kSATA->Ports[kSATAPortIdx].Clbu = 0; - - rt_set_memory((VoidPtr)((UIntPtr)kSATA->Ports[kSATAPortIdx].Clb), 0, 1024); - - kSATA->Ports[kSATAPortIdx].Fb = kAHCIBaseAddress + (32 << 10) + (kSATAPortIdx << 8); - kSATA->Ports[kSATAPortIdx].Fbu = 0; - - rt_set_memory((VoidPtr)((UIntPtr)kSATA->Ports[kSATAPortIdx].Fb), 0, 256); - - HbaCmdHeader* cmdheader = (HbaCmdHeader*)((UIntPtr)kSATA->Ports[kSATAPortIdx].Clb); - - for (int i = 0; i < 32; i++) - { - cmdheader[i].Prdtl = 8; - - cmdheader[i].Ctba = kAHCIBaseAddress + (40 << 10) + (kSATAPortIdx << 13) + (i << 8); - cmdheader[i].Ctbau = 0; - - rt_set_memory((VoidPtr)(UIntPtr)cmdheader[i].Ctba, 0, 256); - } - - while (kSATA->Ports[kSATAPortIdx].Cmd & kHBAPxCmdCR) - { - } - - kSATA->Ports[kSATAPortIdx].Cmd |= kHBAPxCmdFre; - kSATA->Ports[kSATAPortIdx].Cmd |= kHBAPxCmdST; - - drv_calculate_disk_geometry(); - - detected = YES; - - break; - } - } - - ports_implemented >>= 1; - ++ahci_index; - } - - return detected; - } - } - - return No; -} - -Kernel::Boolean drv_std_detected(Kernel::Void) -{ - return kPCIDevice.DeviceId() != 0xFFFF; -} - -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); -} - -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); -} - -static Kernel::Int32 drv_find_cmd_slot(HbaPort* port) noexcept -{ - if (port == nullptr) - return -1; - - Kernel::UInt32 slots = (kSATA->Ports[kSATAPortIdx].Sact | kSATA->Ports[kSATAPortIdx].Ci); - - for (Kernel::Int32 i = 0; i < ((kSATA->Cap & 0x1F) + 1); i++) - { - if ((slots & 1) == 0) - return i; - - slots >>= 1; - } - - return -1; -} - -BOOL kAHCICommandIssued = NO; - -template -static Kernel::Void drv_std_input_output(Kernel::UInt64 lba, Kernel::UInt8* buffer, Kernel::SizeT sector_sz, Kernel::SizeT size_buffer) noexcept -{ - kSATA->Ports[kSATAPortIdx].Is = -1; - kSATA->Is = -1; - - auto slot = 0L; - - slot = drv_find_cmd_slot(&kSATA->Ports[kSATAPortIdx]); - - if (slot == -1) - return; - - volatile HbaCmdHeader* command_header = ((volatile HbaCmdHeader*)((Kernel::UInt64)kSATA->Ports[kSATAPortIdx].Clb + kSATA->Ports[kSATAPortIdx].Clbu)); - - command_header += slot; - - MUST_PASS(command_header); - - command_header->Cfl = sizeof(FisRegH2D) / sizeof(Kernel::UInt32); - command_header->Write = Write; - command_header->Prdtl = (size_buffer / kib_cast(8)) / sizeof(HbaPrdtEntry) + 1; - - volatile HbaCmdTbl* command_table = (volatile HbaCmdTbl*)((Kernel::UInt64)command_header->Ctba + command_header->Ctbau); - - MUST_PASS(command_table); - - auto buffer_phys = Kernel::HAL::hal_get_phys_address(buffer); - - for (Kernel::SizeT i = 0; i < (command_header->Prdtl - 1); i++) - { - command_table->Prdt[i].Dba = ((Kernel::UInt32)(Kernel::UInt64)buffer_phys + (i * 16) & 0xFFFFFFFF); - command_table->Prdt[i].Dbau = (((Kernel::UInt64)(buffer_phys + (i * 16)) >> 32) & 0xFFFFFFFF); - command_table->Prdt[i].Dbc = (16 - 1); - command_table->Prdt[i].Ie = YES; - - buffer += 16; - } - - volatile FisRegH2D* h2d_fis = (volatile FisRegH2D*)((Kernel::UInt64)&command_table->Cfis); - - h2d_fis->FisType = kFISTypeRegH2D; - - h2d_fis->CmdOrCtrl = YES; - - h2d_fis->Command = Write ? kAHCICmdWriteDmaEx : kAHCICmdReadDmaEx; - - if (Identify) - h2d_fis->Command = kAHCICmdIdentify; - - h2d_fis->Lba0 = (lba & 0xFF); - h2d_fis->Lba1 = (lba >> 8) & 0xFF; - h2d_fis->Lba2 = (lba >> 16) & 0xFF; - h2d_fis->Lba3 = (lba >> 24) & 0xFF; - h2d_fis->Lba4 = (lba >> 32) & 0xFF; - h2d_fis->Lba5 = (lba >> 40) & 0xFF; - - h2d_fis->Device = kSataLBAMode; - - h2d_fis->CountLow = sector_sz & 0xFF; - h2d_fis->CountHigh = (sector_sz >> 8) & 0xFF; - - while ((kSATA->Ports[kSATAPortIdx].Tfd & (kAhciSRBsy | kAhciSRDrq))) - { - kout << "Waiting for slot to be ready\r"; - } - - kSATA->Ports[kSATAPortIdx].Ci = 1 << slot; - kAHCICommandIssued = YES; - - while (kSATA->Ports[kSATAPortIdx].Ci & (1 << slot)) - { - if (kSATA->Is & kHBAErrTaskFile) // check for task file error. - { - Kernel::ke_panic(RUNTIME_CHECK_BAD_BEHAVIOR, "AHCI Read disk failure, faulty component."); - return; - } - } -} - -/*** - @brief Gets the number of sectors inside the drive. - @return Sector size in bytes. - */ -Kernel::SizeT drv_get_sector_count() -{ - return kCurrentDiskSectorCount; -} - -/// @brief Get the drive size. -/// @return Disk size in bytes. -Kernel::SizeT drv_get_size() -{ - return (drv_get_sector_count()) * kAHCISectorSize; -} - -#endif // ifdef __AHCI__ \ No newline at end of file -- cgit v1.2.3