Add preliminary ATA PIO driver
diff --git a/include/kernel/dri/ata_pio/ata_pio.h b/include/kernel/dri/ata_pio/ata_pio.h
new file mode 100644
index 0000000..acd7667
--- /dev/null
+++ b/include/kernel/dri/ata_pio/ata_pio.h
@@ -0,0 +1,46 @@
+#pragma once
+
+#include <kint.h>
+
+/**
+ * ATA PIO Driver for Bluejay. This should be replaced by a proper
+ * ATAPI driver later on, but for now this will do. It is going to
+ * be horribly slow by virtue of having to pass all data through
+ * in() and out().
+ */
+
+// status codes
+enum
+{
+	ATA_BSY = 0x80, // Busy
+	ATA_RDY = 0x40, // Ready for command
+	ATA_DRQ = 0x08, // Ready for data
+	ATA_DF = 0x20,
+	ATA_ERR = 0x01, // Error code placed in error register
+};
+
+// IO ports
+enum
+{
+	ATA_PORT_CMD = 0x1f7,
+	ATA_PORT_DATA = 0x1f0,
+	ATA_PORT_DRIVE_SEL = 0x1f6,
+	ATA_PORT_SECTOR_COUNT = 0x1f2,
+	ATA_PORT_LBA_LOW,
+	ATA_PORT_LBA_MID,
+	ATA_PORT_LBA_HIGH,
+};
+
+// Commands
+enum
+{
+	ATA_CMD_READ = 0x20,
+	ATA_CMD_WRITE = 0x30,
+};
+
+void ata_pio_wait_bsy();
+void ata_pio_wait_drq();
+void ata_pio_read_sectors(uchar *buffer, uint lba, uchar num_sectors);
+void ata_pio_write_sectors(uint lba, uchar num_sectors, uchar *buffer);
+
+void test_ata_pio();
diff --git a/src/kernel/io.h b/include/kernel/io.h
similarity index 100%
rename from src/kernel/io.h
rename to include/kernel/io.h
diff --git a/src/kernel/kint.h b/include/kernel/kint.h
similarity index 100%
rename from src/kernel/kint.h
rename to include/kernel/kint.h
diff --git a/src/kernel/log.h b/include/kernel/log.h
similarity index 100%
rename from src/kernel/log.h
rename to include/kernel/log.h
diff --git a/src/kernel/registers.h b/include/kernel/registers.h
similarity index 100%
rename from src/kernel/registers.h
rename to include/kernel/registers.h
diff --git a/src/kernel/Jmk b/src/kernel/Jmk
index e1dc457..4133349 100644
--- a/src/kernel/Jmk
+++ b/src/kernel/Jmk
@@ -11,6 +11,9 @@
 archetype(asm)
 
 depends(initrd, $(ROOT)/boot/initrd, initrd.img)
+depends(ata_pio, dri/ata_pio, ata_pio.a)
+
+CFLAGS += -I $(ROOT)/include/kernel
 
 LDFLAGS += -Tlink.ld -melf_i386
 ASMFLAGS += -felf -Fdwarf
@@ -37,7 +40,8 @@
 			vfs_initrd.o \
 			syscall.o \
 			task.o \
-			task_api.o
+			task_api.o \
+			lib(ata_pio)
 
 type(custom_link)
 
diff --git a/src/kernel/dri/ata_pio/Jmk b/src/kernel/dri/ata_pio/Jmk
new file mode 100644
index 0000000..b2fa318
--- /dev/null
+++ b/src/kernel/dri/ata_pio/Jmk
@@ -0,0 +1,17 @@
+init(ata_pio, ata_pio.a)
+
+preset(freestanding)
+preset(optimize)
+preset(debug)
+preset(32)
+preset(warn)
+
+CFLAGS += -I $(ROOT)/include/kernel
+
+archetype(c)
+
+OBJECTS = ata_pio.o
+
+type(static_lib)
+
+finish
diff --git a/src/kernel/dri/ata_pio/ata_pio.c b/src/kernel/dri/ata_pio/ata_pio.c
new file mode 100644
index 0000000..a8ec300
--- /dev/null
+++ b/src/kernel/dri/ata_pio/ata_pio.c
@@ -0,0 +1,70 @@
+#include <dri/ata_pio/ata_pio.h>
+
+#include <io.h>
+#include <log.h>
+
+static uchar test_buffer[256 * 4];
+
+void ata_pio_wait_bsy()
+{
+	while (inb(ATA_PORT_CMD) & ATA_BSY)
+	{}
+}
+
+void ata_pio_wait_drq()
+{
+	while (!(inb(ATA_PORT_CMD) & ATA_RDY))
+	{}
+}
+
+static void ata_pio_send_init(uint lba, uchar num_sectors)
+{
+	outb(ATA_PORT_DRIVE_SEL, 0xe0 | (lba >> 24));
+	outb(ATA_PORT_SECTOR_COUNT, num_sectors);
+	outb(ATA_PORT_LBA_LOW, lba & 0xff);
+	outb(ATA_PORT_LBA_MID, (lba >> 8) & 0xff);
+	outb(ATA_PORT_LBA_HIGH, (lba >> 16) & 0xff);
+}
+
+void ata_pio_read_sectors(uchar *buffer, uint lba, uchar num_sectors)
+{
+	ata_pio_wait_bsy();
+
+	ata_pio_send_init(lba, num_sectors);
+	outb(ATA_PORT_CMD, ATA_CMD_READ);
+
+	for (int i = 0; i < num_sectors; i++)
+	{
+		ata_pio_wait_bsy();
+		ata_pio_wait_drq();
+
+		for (int j = 0; j < 256; j++)
+			buffer[i * 256 + j] = inb(ATA_PORT_DATA);
+	}
+}
+
+void ata_pio_write_sectors(uint lba, uchar num_sectors, uchar *buffer)
+{
+	ata_pio_wait_bsy();
+
+	ata_pio_send_init(lba, num_sectors);
+	outb(ATA_PORT_CMD, ATA_CMD_WRITE);
+
+	for (int i = 0; i < num_sectors; i++)
+	{
+		ata_pio_wait_bsy();
+		ata_pio_wait_drq();
+
+		for (int j = 0; j < 256; j++)
+			outb(ATA_PORT_DATA, buffer[i * 256 + j]);
+	}
+}
+
+void test_ata_pio()
+{
+	kprintf("Going to ata_pio_read_sectors\n");
+	ata_pio_read_sectors(test_buffer, 0, 4);
+
+	for (int i = 0; i < 256 * 4; i += 64)
+		kprintf("Byte %d = %d\n", test_buffer[i]);
+}
diff --git a/src/kernel/main.c b/src/kernel/main.c
index 355ce9f..2ee8192 100644
--- a/src/kernel/main.c
+++ b/src/kernel/main.c
@@ -10,6 +10,7 @@
 #include "vfs.h"
 #include "vfs_initrd.h"
 #include "vga.h"
+#include <dri/ata_pio/ata_pio.h>
 
 void greet()
 {
@@ -76,15 +77,13 @@
 	init_tasks();
 	kprintf("\ndone initializing tasks\n");
 
+#ifdef TEST_THREADS
 	spawn_thread(other_thread, NULL);
 
 	greet();
+#endif
 
-	asm volatile("cli");
-
-	switch_task();
-
-	kprintf("Switched task, this should have done nothing.\n");
+	test_ata_pio();
 
 	while (true)
 		asm volatile("hlt");