diff options
Diffstat (limited to 'dev/Kernel/HALKit/AMD64/Storage')
| -rw-r--r-- | dev/Kernel/HALKit/AMD64/Storage/AHCI.cxx | 67 | ||||
| -rw-r--r-- | dev/Kernel/HALKit/AMD64/Storage/ATA-DMA.cxx | 38 | ||||
| -rw-r--r-- | dev/Kernel/HALKit/AMD64/Storage/ATA-PIO.cxx | 199 |
3 files changed, 304 insertions, 0 deletions
diff --git a/dev/Kernel/HALKit/AMD64/Storage/AHCI.cxx b/dev/Kernel/HALKit/AMD64/Storage/AHCI.cxx new file mode 100644 index 00000000..0974c240 --- /dev/null +++ b/dev/Kernel/HALKit/AMD64/Storage/AHCI.cxx @@ -0,0 +1,67 @@ +/* ------------------------------------------- + + Copyright ZKA Technologies. + +------------------------------------------- */ + +/** + * @file AHCI.cxx + * @author Amlal El Mahrouss (amlalelmahrouss@icloud.com) + * @brief AHCI driver. + * @version 0.1 + * @date 2024-02-02 + * + * @copyright Copyright (c) ZKA Technologies + * + */ + +#include <Modules/AHCI/AHCI.hxx> +#include <KernelKit/PCI/Iterator.hxx> + +#ifdef __AHCI__ +enum +{ + kSATAProgIfAHCI = 0x01, + kSATASubClass = 0x06 +}; + +static Kernel::PCI::Device kAhciDevice; + +/// @brief Initializes an AHCI disk. +/// @param PortsImplemented the amount of port that have been detected. +/// @return +Kernel::Boolean drv_std_init(Kernel::UInt16& PortsImplemented) +{ + using namespace Kernel; + + PCI::Iterator iterator(Types::PciDeviceKind::MassStorageController); + for (SizeT devIndex = 0; devIndex < NEWOS_BUS_COUNT; ++devIndex) + { + if (iterator[devIndex].Leak().Subclass() == kSATASubClass && + iterator[devIndex].Leak().ProgIf() == kSATAProgIfAHCI) + { + iterator[devIndex].Leak().EnableMmio(); /// enable the memory i/o for this ahci device. + kAhciDevice = iterator[devIndex].Leak(); /// and then leak the reference. + + kcout << "newoskrnl: [PCI] Found AHCI controller.\r"; + + return true; + } + } + + return false; +} + +Kernel::Boolean drv_std_detected(Kernel::Void) +{ + return kAhciDevice.DeviceId() != 0xFFFF; +} + +Kernel::Void drv_std_read(Kernel::UInt64 Lba, Kernel::Char* Buf, Kernel::SizeT SectorSz, Kernel::SizeT Size) +{ +} + +Kernel::Void drv_std_write(Kernel::UInt64 Lba, Kernel::Char* Buf, Kernel::SizeT SectorSz, Kernel::SizeT Size) +{ +} +#endif // __AHCI__ diff --git a/dev/Kernel/HALKit/AMD64/Storage/ATA-DMA.cxx b/dev/Kernel/HALKit/AMD64/Storage/ATA-DMA.cxx new file mode 100644 index 00000000..49d10a7e --- /dev/null +++ b/dev/Kernel/HALKit/AMD64/Storage/ATA-DMA.cxx @@ -0,0 +1,38 @@ +/* ------------------------------------------- + + Copyright ZKA Technologies. + +------------------------------------------- */ + +/** + * @file ATA-DMA.cxx + * @author Amlal El Mahrouss (amlalelmahrouss@icloud.com) + * @brief ATA driver (DMA mode). + * @version 0.1 + * @date 2024-02-02 + * + * @copyright Copyright (c) ZKA Technologies + * + */ + +#include <StorageKit/PRDT.hxx> + +#include <Modules/ATA/ATA.hxx> +#include <ArchKit/ArchKit.hxx> + +using namespace Kernel; + +EXTERN_C Int32 kPRDTTransferStatus; +STATIC PRDT kPRDT; + +#ifdef __ATA_DMA__ + +#ifdef __ATA_PIO__ +#error !!! You cant have both PIO and DMA enabled! !!! +#endif /* ifdef __ATA_PIO__ */ + +#ifdef __AHCI__ +#error !!! You cant have both ATA and AHCI enabled! !!! +#endif /* ifdef __AHCI__ */ + +#endif /* ifdef __ATA_DMA__ */ diff --git a/dev/Kernel/HALKit/AMD64/Storage/ATA-PIO.cxx b/dev/Kernel/HALKit/AMD64/Storage/ATA-PIO.cxx new file mode 100644 index 00000000..c1cdd013 --- /dev/null +++ b/dev/Kernel/HALKit/AMD64/Storage/ATA-PIO.cxx @@ -0,0 +1,199 @@ +/* ------------------------------------------- + + Copyright ZKA Technologies. + +------------------------------------------- */ + +/** + * @file ATA-PIO.cxx + * @author Amlal El Mahrouss (amlalelmahrouss@icloud.com) + * @brief ATA driver (PIO mode). + * @version 0.1 + * @date 2024-02-02 + * + * @copyright Copyright (c) ZKA Technologies + * + */ + +#include <Modules/ATA/ATA.hxx> +#include <ArchKit/ArchKit.hxx> + +#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 < 4; i++) + In8(IO + ATA_REG_STATUS); + +ATAWaitForIO_Retry: + auto statRdy = In8(IO + ATA_REG_STATUS); + + if ((statRdy & ATA_SR_BSY)) + goto ATAWaitForIO_Retry; + +ATAWaitForIO_Retry2: + statRdy = 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) + Out8(Bus + ATA_REG_HDDEVSEL, ATA_PRIMARY_SEL); + else + Out8(Bus + ATA_REG_HDDEVSEL, ATA_SECONDARY_SEL); +} + +Boolean drv_std_init(UInt16 Bus, UInt8 Drive, UInt16& OutBus, UInt8& OutMaster) +{ + UInt16 IO = Bus; + + drv_std_select(IO); + + Kernel::kcout << "newoskrnl: Initializing drive...\r"; + +ATAInit_Retry: + // Bus init, NEIN bit. + Out8(IO + ATA_REG_NEIN, 1); + + // identify until it's good + + auto statRdy = In8(IO + ATA_REG_STATUS); + + if (statRdy & ATA_SR_ERR) + { + Kernel::kcout << "newoskrnl: Failing drive...\r"; + + return false; + } + + if ((statRdy & ATA_SR_BSY)) + { + kcout << "Retrying..."; + goto ATAInit_Retry; + } + + 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] = 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; + + Kernel::kcout << "newoskrnl: Create ATA module.\r"; + + return true; +} + +Void drv_std_read(UInt64 Lba, UInt16 IO, UInt8 Master, Char* Buf, SizeT SectorSz, SizeT Size) +{ + UInt8 Command = ((!Master) ? 0xE0 : 0xF0); + + Lba /= SectorSz; + + drv_std_wait_io(IO); + drv_std_select(IO); + + Out8(IO + ATA_REG_HDDEVSEL, (Command) | (((Lba) >> 24) & 0x0F)); + + /// Compute sector count. + Out8(IO + ATA_REG_SEC_COUNT0, SectorSz / (SectorSz / 2)); + + Out8(IO + ATA_REG_LBA0, (Lba)); + Out8(IO + ATA_REG_LBA1, (Lba) >> 8); + Out8(IO + ATA_REG_LBA2, (Lba) >> 16); + + 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] = In16(IO + ATA_REG_DATA); + drv_std_wait_io(IO); + } + + drv_std_wait_io(IO); +} + +Void drv_std_write(UInt64 Lba, UInt16 IO, UInt8 Master, Char* Buf, SizeT SectorSz, SizeT Size) +{ + UInt8 Command = ((!Master) ? 0xE0 : 0xF0); + + Lba /= SectorSz; + + drv_std_wait_io(IO); + drv_std_select(IO); + + /// Compute sector count. + Out8(IO + ATA_REG_HDDEVSEL, (Command) | (((Lba) >> 24) & 0x0F)); + + Out8(IO + ATA_REG_SEC_COUNT0, SectorSz / (SectorSz / 2)); + + Out8(IO + ATA_REG_LBA0, (Lba)); + Out8(IO + ATA_REG_LBA1, (Lba) >> 8); + Out8(IO + ATA_REG_LBA2, (Lba) >> 16); + + 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); + 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_std_get_sector_count() +{ + return (kATAData[61] << 16) | kATAData[60]; +} + +/// @brief Get the drive size. +Kernel::SizeT drv_std_get_drv_size() +{ + return drv_std_get_sector_count() * kATASectorSize; +} + +#endif /* ifdef __ATA_PIO__ */ |
