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/include/kernel/io.h b/include/kernel/io.h
new file mode 100644
index 0000000..85f2e8c
--- /dev/null
+++ b/include/kernel/io.h
@@ -0,0 +1,31 @@
+#pragma once
+
+#include "kint.h"
+#include "registers.h"
+
+#define KBD_CMD_PORT 0x64
+#define KBD_DATA_PORT 0x60
+
+struct kbd_scan_code_info
+{
+	bool pressed;
+	bool escape;
+	char key;
+};
+
+extern struct kbd_scan_code_info scan_code_table[0xff];
+
+void outb(ushort port, uchar val);
+uchar inb(ushort port);
+ushort inw(ushort port);
+
+/* Random string.h stuff, TODO: move to own header */
+void *memset(void *s, int c, size_t n);
+void *memcpy(void *dest, const void *src, size_t n);
+void strcpy(char *dest, char *src);
+int strcmp(char *a, char *b);
+uint strlen(char *a);
+
+uchar kbd_scan_code();
+void kbd_handle_input(struct registers *registers);
+void init_kbd();
diff --git a/include/kernel/kint.h b/include/kernel/kint.h
new file mode 100644
index 0000000..f70b22f
--- /dev/null
+++ b/include/kernel/kint.h
@@ -0,0 +1,23 @@
+#pragma once
+
+typedef unsigned char uchar;
+typedef unsigned short ushort;
+typedef unsigned int uint;
+typedef unsigned long ulong;
+
+typedef unsigned long size_t;
+
+typedef _Bool bool;
+
+enum
+{
+	false = 0,
+	true,
+};
+
+#define NULL 0
+#define MIN(a, b) ((a)>(b)?(b):(a))
+#define MAX(a, b) ((a)>(b)?(a):(b))
+
+// Coerce into 1 or 0
+#define BOOL(a) (!(!(a)))
diff --git a/include/kernel/log.h b/include/kernel/log.h
new file mode 100644
index 0000000..fe5dcd9
--- /dev/null
+++ b/include/kernel/log.h
@@ -0,0 +1,12 @@
+#pragma once
+
+#include "kint.h"
+
+void kprintf(const char *format, ...);
+void kassert_int(bool condition, const char *message, const char *file,
+				 const int line);
+
+#define kassert(cond, msg) kassert_int((cond), (msg), __FILE__, __LINE__)
+#define kpanic(msg)                                                            \
+	kassert(false, msg);                                                       \
+	__builtin_unreachable()
diff --git a/include/kernel/registers.h b/include/kernel/registers.h
new file mode 100644
index 0000000..687bd0e
--- /dev/null
+++ b/include/kernel/registers.h
@@ -0,0 +1,11 @@
+#pragma once
+
+#include "kint.h"
+
+struct registers
+{
+	uint ds;
+	uint edi, esi, ebp, esp, ebx, edx, ecx, eax;
+	uint interrupt_number, error_code;
+	uint eip, cs, eflags, useresp, ss;
+};