diff options
| author | Amlal El Mahrouss <amlal.elmahrouss@icloud.com> | 2025-02-08 08:43:57 +0100 |
|---|---|---|
| committer | Amlal El Mahrouss <amlal.elmahrouss@icloud.com> | 2025-02-08 08:43:57 +0100 |
| commit | 7a260f76e9c05d84e59ffd7270ed8a65d08a4790 (patch) | |
| tree | 9ed4dc0486713e8b9bd293f7da77f739847ec61d /dev | |
| parent | ea0fd7c03e98231d88ad201c1ef7a15f2445bb92 (diff) | |
ADD: Tweaks and improvements on the Operating System.
Signed-off-by: Amlal El Mahrouss <amlal.elmahrouss@icloud.com>
Diffstat (limited to 'dev')
| -rw-r--r-- | dev/Boot/amd64-desktop.make | 11 | ||||
| -rw-r--r-- | dev/Kernel/HALKit/AMD64/Storage/DMA.cc (renamed from dev/Kernel/HALKit/AMD64/Storage/ATA.cc) | 91 | ||||
| -rw-r--r-- | dev/Kernel/HALKit/AMD64/Storage/PIO.cc | 189 | ||||
| -rw-r--r-- | dev/Kernel/HALKit/AMD64/Storage/SATA.cc | 13 | ||||
| -rw-r--r-- | dev/Kernel/src/DriveMgr.cc | 2 | ||||
| -rw-r--r-- | dev/Mod/AHCI/AHCI.h | 10 |
6 files changed, 251 insertions, 65 deletions
diff --git a/dev/Boot/amd64-desktop.make b/dev/Boot/amd64-desktop.make index e2b73c99..46eb8fc2 100644 --- a/dev/Boot/amd64-desktop.make +++ b/dev/Boot/amd64-desktop.make @@ -84,10 +84,17 @@ compile-amd64: run-efi-amd64-ahci: $(EMU) $(EMU_FLAGS) -M q35 -hda $(IMG) -s -S -.PHONY: run-efi-amd64-ata -run-efi-amd64-ata: +.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 + +.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 +.PHONY: run-efi-amd64-ata +run-efi-amd64-ata: run-efi-amd64-ata-dma + # img_2 is the rescue disk. img is the bootable disk, as provided by the Zeta specs. .PHONY: epm-img epm-img: diff --git a/dev/Kernel/HALKit/AMD64/Storage/ATA.cc b/dev/Kernel/HALKit/AMD64/Storage/DMA.cc index 25143a6d..6fa98a24 100644 --- a/dev/Kernel/HALKit/AMD64/Storage/ATA.cc +++ b/dev/Kernel/HALKit/AMD64/Storage/DMA.cc @@ -18,7 +18,7 @@ #include <Mod/ATA/ATA.h> #include <ArchKit/ArchKit.h> -#if defined(__ATA_PIO__) || defined(__ATA_DMA__) +#if defined(__ATA_DMA__) #define kATADataLen 256 @@ -37,18 +37,18 @@ Boolean drv_std_wait_io(UInt16 IO) rt_in8(IO + ATA_REG_STATUS); ATAWaitForIO_Retry: - auto rdy = rt_in8(IO + ATA_REG_STATUS); + auto statRdy = rt_in8(IO + ATA_REG_STATUS); - if ((rdy & ATA_SR_BSY)) + if ((statRdy & ATA_SR_BSY)) goto ATAWaitForIO_Retry; ATAWaitForIO_Retry2: - rdy = rt_in8(IO + ATA_REG_STATUS); + statRdy = rt_in8(IO + ATA_REG_STATUS); - if (rdy & ATA_SR_ERR) + if (statRdy & ATA_SR_ERR) return false; - if (!(rdy & ATA_SR_DRDY)) + if (!(statRdy & ATA_SR_DRDY)) goto ATAWaitForIO_Retry2; return true; @@ -64,45 +64,44 @@ Void drv_std_select(UInt16 Bus) Boolean drv_std_init(UInt16 Bus, UInt8 Drive, UInt16& OutBus, UInt8& OutMaster) { + if (drv_std_detected()) + return true; + UInt16 IO = Bus; + drv_std_select(IO); + // Bus init, NEIN bit. rt_out8(IO + ATA_REG_NEIN, 1); - // Step 1: Wait until drive is not busy - int timeout = 100000; - while ((rt_in8(IO + ATA_REG_STATUS) & ATA_SR_BSY) && --timeout) - ; - if (!timeout) + // identify until it's good. +ATAInit_Retry: + auto statRdy = rt_in8(IO + ATA_REG_STATUS); + + if (statRdy & ATA_SR_ERR) { - kout << "Timeout waiting for drive to become ready...\r"; return false; } - // Step 2: Send IDENTIFY command + if ((statRdy & ATA_SR_BSY)) + goto ATAInit_Retry; + rt_out8(IO + ATA_REG_COMMAND, ATA_CMD_IDENTIFY); - // Step 3: Wait for the drive to be ready (not busy) - drv_std_wait_io(IO); + /// fetch serial info + /// model, speed, number of sectors... - // Step 4: Check for errors - UInt8 status = rt_in8(IO + ATA_REG_STATUS); - if (status & ATA_SR_ERR) - { - kout << "ATA Error, aborting...\r"; - return false; - } + drv_std_wait_io(IO); - // Step 5: Read IDENTIFY DEVICE response - for (SizeT indexData = 0UL; indexData < kATADataLen; ++indexData) + for (SizeT indexData = 0ul; indexData < kATADataLen; ++indexData) { - kATAData[indexData] = rt_in16(IO + ATA_REG_DATA); + kATAData[indexData] = Kernel::HAL::rt_in16(IO + ATA_REG_DATA); } - // Step 6: Set OutBus & OutMaster correctly OutBus = (Bus == ATA_PRIMARY_IO) ? ATA_PRIMARY_IO : ATA_SECONDARY_IO; - OutMaster = (Drive == ATA_MASTER) ? ATA_MASTER : ATA_SLAVE; + OutMaster = (Bus == ATA_PRIMARY_IO) ? ATA_MASTER : ATA_SLAVE; + return true; #ifdef __ATA_DMA__ // Step 7: Check if the drive supports DMA if (!(kATAData[63] & (1 << 8)) || !(kATAData[88] & 0xFF)) @@ -162,20 +161,10 @@ Void drv_std_read(UInt64 Lba, UInt16 IO, UInt8 Master, Char* Buf, SizeT SectorSz rt_out8(IO + ATA_REG_LBA2, (Lba) >> 16); rt_out8(IO + ATA_REG_LBA3, (Lba) >> 24); -#ifdef __ATA_PIO__ - rt_out8(ATA_REG_COMMAND, ATA_CMD_READ_PIO); - - for (SizeT IndexOff = 0; IndexOff < Size; ++IndexOff) - { - drv_std_wait_io(IO); - rt_out16(IO + ATA_REG_DATA, Buf[IndexOff]); - drv_std_wait_io(IO); - } -#else if (Size > kib_cast(64)) ke_panic(RUNTIME_CHECK_FAILED, "ATA-DMA only supports < 64kb DMA transfers."); - Details::PRD* prd = (Details::PRD*)mib_cast(4); + Details::PRD* prd = new Details::PRD(); prd->mAddress = (UInt32)(UIntPtr)Buf; prd->mByteCount = Size; prd->mFlags = 0x8000; @@ -187,8 +176,10 @@ Void drv_std_read(UInt64 Lba, UInt16 IO, UInt8 Master, Char* Buf, SizeT SectorSz while (rt_in8(ATA_REG_STATUS) & 0x01) ; - rt_out8(IO + 0x00, 0x00); // Start DMA engine -#endif // __ATA_PIO__ + rt_out8(IO + 0x00, 0x00); // Stop DMA engine + + delete prd; + prd = nullptr; } Void drv_std_write(UInt64 Lba, UInt16 IO, UInt8 Master, Char* Buf, SizeT SectorSz, SizeT Size) @@ -208,20 +199,10 @@ Void drv_std_write(UInt64 Lba, UInt16 IO, UInt8 Master, Char* Buf, SizeT SectorS rt_out8(IO + ATA_REG_LBA2, (Lba) >> 16); rt_out8(IO + ATA_REG_LBA3, (Lba) >> 24); -#ifdef __ATA_PIO__ - rt_out8(ATA_REG_COMMAND, ATA_CMD_WRITE_PIO); - - for (SizeT IndexOff = 0; IndexOff < Size; ++IndexOff) - { - drv_std_wait_io(IO); - rt_out16(IO + ATA_REG_DATA, Buf[IndexOff]); - drv_std_wait_io(IO); - } -#else if (Size > kib_cast(64)) ke_panic(RUNTIME_CHECK_FAILED, "ATA-DMA only supports < 64kb DMA transfers."); - Details::PRD* prd = (Details::PRD*)mib_cast(4); + Details::PRD* prd = new Details::PRD(); prd->mAddress = (UInt32)(UIntPtr)Buf; prd->mByteCount = Size; prd->mFlags = 0x8000; @@ -234,8 +215,10 @@ Void drv_std_write(UInt64 Lba, UInt16 IO, UInt8 Master, Char* Buf, SizeT SectorS while (rt_in8(ATA_REG_STATUS) & 0x01) ; - rt_out8(IO + 0x00, 0x00); // Start DMA engine -#endif // __ATA_PIO__ + rt_out8(IO + 0x00, 0x00); // Stop DMA engine + + delete prd; + prd = nullptr; } /// @brief is ATA detected? @@ -258,4 +241,4 @@ Kernel::SizeT drv_get_size() return (drv_get_sector_count()) * kATASectorSize; } -#endif /* ifdef __ATA_PIO__ */ +#endif /* ifdef __ATA_DMA__ */ diff --git a/dev/Kernel/HALKit/AMD64/Storage/PIO.cc b/dev/Kernel/HALKit/AMD64/Storage/PIO.cc new file mode 100644 index 00000000..3f1286b6 --- /dev/null +++ b/dev/Kernel/HALKit/AMD64/Storage/PIO.cc @@ -0,0 +1,189 @@ +/* ------------------------------------------- + + Copyright (C) 2024-2025, Amlal EL Mahrouss, all rights reserved. + +------------------------------------------- */ + +/** + * @file ATA-PIO.cc + * @author Amlal EL Mahrouss (amlalelmahrouss@icloud.com) + * @brief ATA driver (PIO mode). + * @version 0.1 + * @date 2024-02-02 + * + * @copyright Copyright (c) Amlal EL Mahrouss + * + */ + +#include <Mod/ATA/ATA.h> +#include <ArchKit/ArchKit.h> + +#ifdef __ATA_PIO__ + +using namespace Kernel; +using namespace Kernel::HAL; + +/// bugs: 0 + +#define kATADataLen 256 + +STATIC Boolean kATADetected = false; +STATIC Int32 kATADeviceType = kATADeviceCount; +STATIC Char kATAData[kATADataLen] = {0}; + +Boolean drv_std_wait_io(UInt16 IO) +{ + for (int i = 0; i < 400; i++) + rt_in8(IO + ATA_REG_STATUS); + +ATAWaitForIO_Retry: + auto statRdy = rt_in8(IO + ATA_REG_STATUS); + + if ((statRdy & ATA_SR_BSY)) + goto ATAWaitForIO_Retry; + +ATAWaitForIO_Retry2: + statRdy = rt_in8(IO + ATA_REG_STATUS); + + if (statRdy & ATA_SR_ERR) + return false; + + if (!(statRdy & ATA_SR_DRDY)) + goto ATAWaitForIO_Retry2; + + return true; +} + +Void drv_std_select(UInt16 Bus) +{ + if (Bus == ATA_PRIMARY_IO) + rt_out8(Bus + ATA_REG_HDDEVSEL, ATA_PRIMARY_SEL); + else + rt_out8(Bus + ATA_REG_HDDEVSEL, ATA_SECONDARY_SEL); +} + +Boolean drv_std_init(UInt16 Bus, UInt8 Drive, UInt16& OutBus, UInt8& OutMaster) +{ + if (drv_std_detected()) + return true; + + UInt16 IO = Bus; + + drv_std_select(IO); + + // Bus init, NEIN bit. + rt_out8(IO + ATA_REG_NEIN, 1); + + // identify until it's good. +ATAInit_Retry: + auto statRdy = rt_in8(IO + ATA_REG_STATUS); + + if (statRdy & ATA_SR_ERR) + { + return false; + } + + if ((statRdy & ATA_SR_BSY)) + goto ATAInit_Retry; + + rt_out8(IO + ATA_REG_COMMAND, ATA_CMD_IDENTIFY); + + /// fetch serial info + /// model, speed, number of sectors... + + drv_std_wait_io(IO); + + for (SizeT indexData = 0ul; indexData < kATADataLen; ++indexData) + { + kATAData[indexData] = Kernel::HAL::rt_in16(IO + ATA_REG_DATA); + } + + OutBus = (Bus == ATA_PRIMARY_IO) ? ATA_PRIMARY_IO : ATA_SECONDARY_IO; + OutMaster = (Bus == ATA_PRIMARY_IO) ? ATA_MASTER : ATA_SLAVE; + + return true; +} + +Void drv_std_read(UInt64 Lba, UInt16 IO, UInt8 Master, Char* Buf, SizeT SectorSz, SizeT Size) +{ + Lba /= SectorSz; + + UInt8 Command = ((!Master) ? 0xE0 : 0xF0); + + drv_std_wait_io(IO); + drv_std_select(IO); + + rt_out8(IO + ATA_REG_HDDEVSEL, (Command) | (((Lba) >> 24) & 0x0F)); + + rt_out8(IO + ATA_REG_SEC_COUNT0, ((Size + SectorSz) / SectorSz)); + + rt_out8(IO + ATA_REG_LBA0, (Lba)&0xFF); + rt_out8(IO + ATA_REG_LBA1, (Lba) >> 8); + rt_out8(IO + ATA_REG_LBA2, (Lba) >> 16); + rt_out8(IO + ATA_REG_LBA3, (Lba) >> 24); + + rt_out8(IO + ATA_REG_COMMAND, ATA_CMD_READ_PIO); + + drv_std_wait_io(IO); + + for (SizeT IndexOff = 0; IndexOff < Size; ++IndexOff) + { + drv_std_wait_io(IO); + Buf[IndexOff] = Kernel::HAL::rt_in16(IO + ATA_REG_DATA); + drv_std_wait_io(IO); + } +} + +Void drv_std_write(UInt64 Lba, UInt16 IO, UInt8 Master, Char* Buf, SizeT SectorSz, SizeT Size) +{ + Lba /= SectorSz; + + UInt8 Command = ((!Master) ? 0xE0 : 0xF0); + + drv_std_wait_io(IO); + drv_std_select(IO); + + rt_out8(IO + ATA_REG_HDDEVSEL, (Command) | (((Lba) >> 24) & 0x0F)); + + rt_out8(IO + ATA_REG_SEC_COUNT0, ((Size + (SectorSz)) / SectorSz)); + + rt_out8(IO + ATA_REG_LBA0, (Lba)&0xFF); + rt_out8(IO + ATA_REG_LBA1, (Lba) >> 8); + rt_out8(IO + ATA_REG_LBA2, (Lba) >> 16); + rt_out8(IO + ATA_REG_LBA3, (Lba) >> 24); + + rt_out8(IO + ATA_REG_COMMAND, ATA_CMD_WRITE_PIO); + + drv_std_wait_io(IO); + + for (SizeT IndexOff = 0; IndexOff < Size; ++IndexOff) + { + drv_std_wait_io(IO); + rt_out16(IO + ATA_REG_DATA, Buf[IndexOff]); + drv_std_wait_io(IO); + } + + drv_std_wait_io(IO); +} + +/// @brief is ATA detected? +Boolean drv_std_detected(Void) +{ + return kATADetected; +} + +/*** + @brief Getter, gets the number of sectors inside the drive. + */ +Kernel::SizeT drv_get_sector_count() +{ + return (kATAData[61] << 16) | kATAData[60]; +} + +/// @brief Get the drive size. +Kernel::SizeT drv_get_size() +{ + return (drv_get_sector_count()) * kATASectorSize; +} + +#endif /* ifdef __ATA_PIO__ */ diff --git a/dev/Kernel/HALKit/AMD64/Storage/SATA.cc b/dev/Kernel/HALKit/AMD64/Storage/SATA.cc index 26391340..00ef8767 100644 --- a/dev/Kernel/HALKit/AMD64/Storage/SATA.cc +++ b/dev/Kernel/HALKit/AMD64/Storage/SATA.cc @@ -184,8 +184,13 @@ static Kernel::Void drv_std_input_output(Kernel::UInt64 lba, Kernel::UInt8* buff if (slot == -1) return; + if (size_buffer > mib_cast(4)) + Kernel::ke_panic(RUNTIME_CHECK_FAILED, "AHCI only supports < 4mb DMA transfers."); + HbaCmdHeader* command_header = ((HbaCmdHeader*)((Kernel::UInt64)kSATAPort->Ports[kSATAPortIdx].Clb + kSATAPort->Ports[kSATAPortIdx].Clbu)); + command_header += slot; + Kernel::rt_set_memory(reinterpret_cast<Kernel::VoidPtr>(command_header), 0, sizeof(HbaCmdHeader)); MUST_PASS(command_header); @@ -200,10 +205,10 @@ static Kernel::Void drv_std_input_output(Kernel::UInt64 lba, Kernel::UInt8* buff MUST_PASS(command_table); - command_table->Prdt[0].Dba = ((Kernel::UInt32)(Kernel::UInt64)Kernel::HAL::hal_get_phys_address(buffer)); - command_table->Prdt[0].Dbau = (((Kernel::UInt64)Kernel::HAL::hal_get_phys_address(buffer) >> 32)); - command_table->Prdt[0].Dbc = ((size_buffer)-1); - command_table->Prdt[0].InterruptBit = 1; + command_table->Prdt[0].Dba = ((Kernel::UInt32)(Kernel::UInt64)Kernel::HAL::hal_get_phys_address(buffer)); + command_table->Prdt[0].Dbau = (((Kernel::UInt64)Kernel::HAL::hal_get_phys_address(buffer) >> 32)); + command_table->Prdt[0].Dbc = ((size_buffer)-1); + command_table->Prdt[0].IE = 1; command_header->Ctba = ((Kernel::UInt32)(Kernel::UInt64)command_table); command_header->Ctbau = ((Kernel::UInt32)((Kernel::UInt64)command_table >> 32)); diff --git a/dev/Kernel/src/DriveMgr.cc b/dev/Kernel/src/DriveMgr.cc index 7230f112..f7215346 100644 --- a/dev/Kernel/src/DriveMgr.cc +++ b/dev/Kernel/src/DriveMgr.cc @@ -162,6 +162,8 @@ namespace Kernel trait.fInit(trait.fPacket); + kout << "Reading EPM block...\r"; + trait.fInput(trait.fPacket); if (rt_string_cmp(((BOOT_BLOCK_STRUCT*)trait.fPacket.fPacketContent)->Magic, kEPMMagic, kEPMMagicLength) == 0) diff --git a/dev/Mod/AHCI/AHCI.h b/dev/Mod/AHCI/AHCI.h index 43fe4f0b..05f75391 100644 --- a/dev/Mod/AHCI/AHCI.h +++ b/dev/Mod/AHCI/AHCI.h @@ -91,7 +91,7 @@ typedef struct FisRegD2H final Kernel::UInt8 PortMul : 4; // Port multiplier Kernel::UInt8 Reserved0 : 2; // Reserved - Kernel::UInt8 InterruptBit : 1; // Interrupt bit + Kernel::UInt8 IE : 1; // Interrupt bit Kernel::UInt8 Reserved1 : 1; // Reserved Kernel::UInt8 Status; // Status register @@ -140,7 +140,7 @@ typedef struct FisPioSetup final Kernel::UInt8 PortMul : 4; // Port multiplier Kernel::UInt8 Reserved0 : 1; // Reserved Kernel::UInt8 DTD : 1; // Data transfer direction, 1 - device to host - Kernel::UInt8 InterruptBit : 1; // Interrupt bit + Kernel::UInt8 IE : 1; // Interrupt bit Kernel::UInt8 Reserved1 : 1; Kernel::UInt8 Status; // Status register @@ -177,7 +177,7 @@ typedef struct FisDmaSetup final Kernel::UInt8 PortMul : 4; // Port multiplier Kernel::UInt8 Reserved0 : 1; // Reserved Kernel::UInt8 DTD : 1; // Data transfer direction, 1 - device to host - Kernel::UInt8 InterruptBit : 1; // Interrupt bit + Kernel::UInt8 IE : 1; // Interrupt bit Kernel::UInt8 AutoEnable : 1; // Auto-activate. Specifies if DMA Activate FIS is needed Kernel::UInt8 Reserved1[2]; // Reserved @@ -207,7 +207,7 @@ typedef struct FisDevBits final Kernel::UInt8 Reserved0 : 5; // Reserved Kernel::UInt8 R0 : 1; - Kernel::UInt8 InterruptBit : 1; + Kernel::UInt8 IE : 1; Kernel::UInt8 N : 1; Kernel::UInt8 StatusLow : 3; @@ -320,7 +320,7 @@ typedef struct HbaPrdtEntry final // DW3 Kernel::UInt32 Dbc : 22; // Byte count, 4M max Kernel::UInt32 Reserved1 : 9; // Reserved - Kernel::UInt32 InterruptBit : 1; // Interrupt on completion + Kernel::UInt32 IE : 1; // Interrupt on completion } HbaPrdtEntry; typedef struct HbaCmdTbl final |
