summaryrefslogtreecommitdiffhomepage
path: root/dev/Kernel/HALKit/AMD64/Storage
diff options
context:
space:
mode:
Diffstat (limited to 'dev/Kernel/HALKit/AMD64/Storage')
-rw-r--r--dev/Kernel/HALKit/AMD64/Storage/AHCI.cxx67
-rw-r--r--dev/Kernel/HALKit/AMD64/Storage/ATA-DMA.cxx38
-rw-r--r--dev/Kernel/HALKit/AMD64/Storage/ATA-PIO.cxx199
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__ */