From 635ed1be4216f7de8fb98c0827c8ba5fe13a031e Mon Sep 17 00:00:00 2001
From: Able <abl3theabove@gmail.com>
Date: Wed, 4 Dec 2024 04:21:24 -0600
Subject: [PATCH] theoretically works but is broken in practice :(

---
 repbuild/src/main.rs                       |   3 +-
 sysdata/programs/diskio_driver/src/main.hb | 126 +++++++++++----------
 sysdata/programs/diskio_driver/src/regs.hb |  23 ++++
 3 files changed, 93 insertions(+), 59 deletions(-)
 create mode 100644 sysdata/programs/diskio_driver/src/regs.hb

diff --git a/repbuild/src/main.rs b/repbuild/src/main.rs
index d361cbc..31600c4 100644
--- a/repbuild/src/main.rs
+++ b/repbuild/src/main.rs
@@ -90,7 +90,7 @@ fn main() -> Result<(), Error> {
                 } else if arg == "avx2" {
                     target = Target::X86_64Avx2;
                 } else if arg == "--ktest" {
-                    tests = true; 
+                    tests = true;
                 } else {
                     return Err(report!(Error::InvalidSubCom));
                 }
@@ -510,7 +510,6 @@ fn run(release: bool, target: Target, do_accel: bool) -> Result<(), Error> {
     }
 }
 
-
 fn fetch_ovmf(target: Target) -> Result<String, OvmfFetchError> {
     let (ovmf_url, ovmf_path) = match target {
         Target::X86_64 | Target::X86_64Avx2 => (
diff --git a/sysdata/programs/diskio_driver/src/main.hb b/sysdata/programs/diskio_driver/src/main.hb
index 9311c2f..844bf53 100644
--- a/sysdata/programs/diskio_driver/src/main.hb
+++ b/sysdata/programs/diskio_driver/src/main.hb
@@ -1,67 +1,79 @@
-.{memory, buffer, log} := @use("../../../libraries/stn/src/lib.hb")
+.{memory, buffer, log} := @use("../../../libraries/stn/src/lib.hb");
+.{inb, outb} := memory
 
-// Influenced by https://github.com/levex/osdev/blob/master/drivers/ata.c
+regs := @use("regs.hb");
+.{ATA_PRIMARY_COMM_REGSTAT, ATA_PRIMARY_DRIVE_HEAD, ATA_PRIMARY_SECCOUNT, ATA_PRIMARY_LBA_LO, ATA_PRIMARY_LBA_MID, ATA_PRIMARY_LBA_HI, STAT_BSY} := regs
 
-main := fn(): int {
-	// shuts down ableOS
-	// memory.outb(0xF400, 0)
+sloop := fn(): void {
+	idx := 0xFFFFFFF
+	loop {
+		if idx == 0 {
+			break
+		} else {
+			idx -= 1
+		}
+	}
+}
 
-	a := memory.inb(0x4600)
-	b := memory.inb(0x4700)
+identify := fn(): u8 {
+	a := inb(ATA_PRIMARY_COMM_REGSTAT)
+	outb(ATA_PRIMARY_DRIVE_HEAD, 0xA0)
+	log.info("Primary drive head set.\0")
+
+	a = inb(ATA_PRIMARY_COMM_REGSTAT)
+	outb(ATA_PRIMARY_SECCOUNT, 0)
+	a = inb(ATA_PRIMARY_COMM_REGSTAT)
+	outb(ATA_PRIMARY_LBA_LO, 0)
+	a = inb(ATA_PRIMARY_COMM_REGSTAT)
+	outb(ATA_PRIMARY_LBA_MID, 0)
+	a = inb(ATA_PRIMARY_COMM_REGSTAT)
+	outb(ATA_PRIMARY_LBA_HI, 0)
+	a = inb(ATA_PRIMARY_COMM_REGSTAT)
+	outb(ATA_PRIMARY_COMM_REGSTAT, 0xEC)
+	outb(ATA_PRIMARY_COMM_REGSTAT, 0xE7)
+
+	status := inb(ATA_PRIMARY_COMM_REGSTAT)
+	log.info("Waiting for status.\0")
+	loop {
+		if (status & STAT_BSY) == 0 {
+			break
+		} else {
+			sloop()
+		}
+		status = inb(ATA_PRIMARY_COMM_REGSTAT)
+	}
+	log.info("Status got\0")
+	if status == 0 return 0
+
+	log.info("Status indicates presence of a drive. Polling while STAT_BSY... \0")
+	loop {
+		if (status & STAT_BSY) == 0 {
+			break
+		} else {
+			sloop()
+		}
+		status = inb(ATA_PRIMARY_COMM_REGSTAT)
+	}
+
+	mid := inb(ATA_PRIMARY_LBA_MID)
+	hi := inb(ATA_PRIMARY_LBA_HI)
+
+	if (mid | hi) == 0 {
+		log.error("The drive is not ATA. (Who knows what it is.)\0")
+		return 0
+	}
 
-	// c := buffer.search("XNumber\0")
-	ata := ATA.new()
 	return 0
 }
+main := fn(): int {
+	// shuts down ableOS
+	// outb(0xF400, 0)
 
-ATA_PRIMARY := @as(u8, @intcast(0x0))
-ATA_PRIMARY_IO := @as(u8, @intcast(0x1F0))
+	a := inb(0x4600)
+	b := inb(0x4700)
 
-ATA_SECONDARY := @as(u8, @intcast(0x1))
-ATA_SECONDARY_IO := @as(u8, @intcast(0x170))
+	// c := buffer.search("XNumber\0")
+	c := identify()
 
-ATA_REG_HDDEVSEL := @as(u8, @intcast(0x6))
-
-ATA_MASTER := @as(u8, @intcast(0x0))
-IDE := struct {}
-
-ide_select_drive := fn(bus: u8, i: u8): void {
-	if bus == ATA_PRIMARY {
-		if i == ATA_MASTER {
-			log.info("Primary ATA selected\0")
-			memory.outb(ATA_PRIMARY_IO + ATA_REG_HDDEVSEL, 0xA0)
-		} else {
-			memory.outb(ATA_PRIMARY_IO + ATA_REG_HDDEVSEL, 0xB0)
-		}
-	} else {
-		if i == ATA_MASTER {
-			memory.outb(ATA_SECONDARY_IO + ATA_REG_HDDEVSEL, 0xA0)
-		} else {
-			memory.outb(ATA_SECONDARY_IO + ATA_REG_HDDEVSEL, 0xB0)
-		}
-	}
-}
-
-identify := fn(bus: u8, drive: u8): bool {
-	io := 0
-
-	// BUG: Causes qemu to crash
-	ide_select_drive(bus, drive)
-	if bus == ATA_PRIMARY {
-		io = ATA_PRIMARY_IO
-	}
-
-	return true
-}
-
-ata_probe := fn(): void {
-	if identify(ATA_PRIMARY, ATA_MASTER) {
-	}
-}
-
-ATA := struct {
-	new := fn(): void {
-		log.info("Checking for ATA Drives.\0")
-		// ata_probe()
-	}
+	return 0
 }
\ No newline at end of file
diff --git a/sysdata/programs/diskio_driver/src/regs.hb b/sysdata/programs/diskio_driver/src/regs.hb
new file mode 100644
index 0000000..5562d1b
--- /dev/null
+++ b/sysdata/programs/diskio_driver/src/regs.hb
@@ -0,0 +1,23 @@
+$ATA_PRIMARY_DATA := @intcast(0x1F0)
+$ATA_PRIMARY_ERR := @intcast(0x1F1)
+$ATA_PRIMARY_SECCOUNT := @intcast(0x1F2)
+$ATA_PRIMARY_LBA_LO := @intcast(0x1F3)
+$ATA_PRIMARY_LBA_MID := @intcast(0x1F4)
+$ATA_PRIMARY_LBA_HI := @intcast(0x1F5)
+$ATA_PRIMARY_DRIVE_HEAD := @intcast(0x1F6)
+$ATA_PRIMARY_COMM_REGSTAT := @intcast(0x1F7)
+$ATA_PRIMARY_ALTSTAT_DCR := @intcast(0x3F6)
+
+// Indicates an error occurred. Send a new command to clear it
+STAT_ERR := 1 << 0
+// Set when the drive has PIO data to transfer, or is ready to accept PIO data.
+STAT_DRQ := 1 << 3
+// Overlapped Mode Service Request.
+STAT_SRV := 1 << 4
+// Drive Fault Error (does not set ERR).
+STAT_DF := 1 << 5
+// Bit is clear when drive is spun down, or after an error. Set otherwise.
+STAT_RDY := 1 << 6
+// Indicates the drive is preparing to send/receive data (wait for it to clear).
+// In case of 'hang' (it never clears), do a software reset.
+STAT_BSY := 1 << 7
\ No newline at end of file