Add ATA PIO IRQ handler, documentation
Still WIP, doesn't look like IRQ handler works yet.
diff --git a/src/kernel/Jmk b/src/kernel/Jmk
index 8beb214..2e842a1 100644
--- a/src/kernel/Jmk
+++ b/src/kernel/Jmk
@@ -53,9 +53,9 @@
task_api.o \
faults.o \
lib(ext2) \
+ lib(ide) \
lib(ata_pio) \
- lib(pci) \
- lib(ide)
+ lib(pci)
type(custom_link)
diff --git a/src/kernel/dri/ata_pio/ata_pio.c b/src/kernel/dri/ata_pio/ata_pio.c
index cf55b51..cd426ef 100644
--- a/src/kernel/dri/ata_pio/ata_pio.c
+++ b/src/kernel/dri/ata_pio/ata_pio.c
@@ -2,6 +2,7 @@
#include <io.h>
#include <log.h>
+#include <pic.h>
/* TODO: Rewrite all of this to work with dri_ide in the case of multiple
* devices */
@@ -51,7 +52,7 @@
ata_pio_wait_bsy();
}
-void ata_pio_write_sectors(uint lba, uchar num_sectors, void *buffer)
+void ata_pio_write_sectors(uint lba, uchar num_sectors, ushort *buffer)
{
ata_pio_wait_bsy();
@@ -60,8 +61,10 @@
ata_pio_wait_bsy();
- asm volatile("rep outsw" :: "c"(num_sectors * 256), "d"(ATA_PORT_DATA),
- "S"(buffer));
+ for (int i = 0; i < (num_sectors * 256); i++)
+ {
+ outw(ATA_PORT_DATA, buffer[i]);
+ }
}
static void print_buffer()
@@ -89,3 +92,53 @@
// ata_pio_read_sectors(test_buffer, 0, 1);
// print_buffer();
}
+
+void ata_pio_handle_irq(struct registers *regs)
+{
+ // TODO: check that this IRQ came from the hard drive
+
+ // TODO: use a lock and inform the scheduler that the thread waiting for
+ // this can stop sleeping
+
+ // Acknowledge the IRQ
+ uchar status = inw(ATA_PORT_STATUS);
+
+ kprintf(DEBUG "ATA PIO IRQ received %d (0x%x)\n", status, status);
+}
+
+void init_ata_pio()
+{
+ add_interrupt_handler(46, ata_pio_handle_irq);
+
+/*
+ // TODO: Consider adding this back.
+
+ // 0xA0 for master, 0xB0 for slave
+ outb(ATA_PORT_DRIVE_SEL, 0xA0);
+
+ outb(ATA_PORT_LBA_LOW, 0);
+ outb(ATA_PORT_LBA_MID, 0);
+ outb(ATA_PORT_LBA_HIGH, 0);
+
+ outb(ATA_PORT_CMD, ATA_CMD_IDENTIFY);
+
+ if (inb(ATA_PORT_STATUS))
+ {
+ kprintf(OKAY "ATA drive exists\n");
+
+ // Wait until either DRQ or ERR is set
+ uchar status;
+ while ((status = inb(ATA_PORT_STATUS)) & (ATA_DRQ | ATA_ERR))
+ {
+ if (status & ATA_ERR)
+ {
+
+ }
+ }
+ }
+ else
+ {
+ kprintf(ERROR "ATA drive does not exist\n");
+ }
+*/
+}
diff --git a/src/kernel/dri/fs/ext2/ext2.c b/src/kernel/dri/fs/ext2/ext2.c
index d0dd3bd..3d7b1bc 100644
--- a/src/kernel/dri/fs/ext2/ext2.c
+++ b/src/kernel/dri/fs/ext2/ext2.c
@@ -1,5 +1,5 @@
-#include <dri/fs/ext2/ext2.h>
#include <dri/ata_pio/ata_pio.h>
+#include <dri/fs/ext2/ext2.h>
#include <kint.h>
#include <log.h>
@@ -12,11 +12,56 @@
return *sb;
}
+uint ext2_num_block_groups(struct ext2_superblock *sb)
+{
+ // This is a mildly janky way of rounding up
+ uint a = (sb->total_blocks - 1) / (sb->blocks_per_block_group + 1);
+ uint b = (sb->total_inodes - 1) / (sb->inodes_per_block_group + 1);
+
+ if (a == b)
+ {
+ return a;
+ }
+ else
+ {
+ kprintf(ERROR "EXT2 cannot find number of block groups, %d and %d "
+ "should equal.\n",
+ a, b);
+ kpanic("Corrupted filesystem");
+ }
+}
+
+uint ext2_block_size(struct ext2_superblock *sb)
+{
+ return 1024 << sb->block_size_shift;
+}
+
+void ext2_load_block_group_descriptor_table(struct ext2_superblock *sb,
+ uint num_block_groups)
+{
+ /**
+ * The BGDT (not to be confused with the GDT) is located the block after the
+ * superblock. On any block size EXCEPT 1024 (the minimum, remember that the
+ * block size is specified by X where 1024 << X is the real size) this is
+ * the second block (0-indexed, so 1). On 1024 this is the third block.
+ */
+ uint bgdt_block = 1;
+ uint block_size = ext2_block_size(sb);
+
+ if (block_size == 1024)
+ bgdt_block = 2;
+
+ kprintf(DEBUG "BGDT block = %d block size = %d\n", bgdt_block, block_size);
+}
+
void ext2_mount(struct fs_node *where)
{
struct ext2_superblock sb = ext2_read_superblock();
- kprintf(INFO "EXT2 magic = 0x%x\n", sb.signature);
+ kprintf(DEBUG "EXT2 magic = 0x%x\n", sb.signature);
+
+ uint num_block_groups = ext2_num_block_groups(&sb);
+ ext2_load_block_group_descriptor_table(&sb, num_block_groups);
}
bool ext2_valid_filesystem()
@@ -24,4 +69,4 @@
struct ext2_superblock sb = ext2_read_superblock();
return sb.signature == EXT2_SIGNATURE;
-}
\ No newline at end of file
+}
diff --git a/src/kernel/dri/ide/ide.c b/src/kernel/dri/ide/ide.c
index 0025970..de4144c 100644
--- a/src/kernel/dri/ide/ide.c
+++ b/src/kernel/dri/ide/ide.c
@@ -1,59 +1,65 @@
-#include <dri/ide/ide.h>
-#include <task.h>
#include <alloc.h>
+#include <dri/ata_pio/ata_pio.h>
+#include <dri/ide/ide.h>
#include <log.h>
+#include <task.h>
struct ide_thread_data
{
- struct pci_device dev;
- uchar bus, slot, func;
+ struct pci_device dev;
+ uchar bus, slot, func;
};
bool ide_supports(struct pci_device *dev)
{
- return dev->class == 1 && dev->subclass == 1;
+ return dev->class == 1 && dev->subclass == 1;
}
void ide_print_device(struct ide_device *dev)
{
- kprintf(INFO "<ide-device dma=%b>", dev->supports_dma);
+ kprintf(INFO "<ide-device dma=%b>\n", dev->supports_dma);
}
void ide_thread(struct ide_thread_data *data)
{
- kprintf(DEBUG "IDE driver thread starting: device=0x%x\n", data->dev.device_id);
+ struct ide_device dev;
- struct ide_device dev;
+ uchar p = data->dev.prog_if;
+ dev.channel_mode[0] = p & 1;
+ dev.channel_mode_modifiable[0] = p & (1 << 1);
+ dev.channel_mode[1] = p & (1 << 2);
+ dev.channel_mode_modifiable[1] = p & (1 << 3);
+ dev.supports_dma = p & (1 << 7);
- uchar p = data->dev.prog_if;
- dev.channel_mode[0] = p & 1;
- dev.channel_mode_modifiable[0] = p & (1 << 1);
- dev.channel_mode[1] = p & (1 << 2);
- dev.channel_mode_modifiable[1] = p & (1 << 3);
- dev.supports_dma = p & (1 << 7);
+ ide_print_device(&dev);
- ide_print_device(&dev);
+ // TODO: pass ATA PIO driver information about the IDE device (i.e. what
+ // ports to use)
+ init_ata_pio();
+
+ kprintf(OKAY "Set up ATA PIO\n");
+
+ free(data);
}
void ide_init(struct pci_device dev, uchar bus, uchar slot, uchar func)
{
- struct ide_thread_data *data = malloc(sizeof(struct ide_thread_data));
- data->dev = dev;
- data->bus = bus;
- data->slot = slot;
- data->func = func;
+ struct ide_thread_data *data = malloc(sizeof(struct ide_thread_data));
+ data->dev = dev;
+ data->bus = bus;
+ data->slot = slot;
+ data->func = func;
- spawn_thread(TASK_FUNCTION(ide_thread), data);
+ ide_thread(data);
}
void ide_register()
{
- struct pci_device_driver dri =
- {
- .supports = ide_supports,
- .init = ide_init,
- .generic_name = "IDE Controller",
- };
+ struct pci_device_driver dri = {
+ .supports = ide_supports,
+ .init = ide_init,
+ .generic_name = "IDE Controller",
+ };
- pci_register_device_driver(dri);
+ pci_register_device_driver(dri);
}
diff --git a/src/kernel/io.c b/src/kernel/io.c
index c53ef17..0ba13ae 100644
--- a/src/kernel/io.c
+++ b/src/kernel/io.c
@@ -26,22 +26,32 @@
ushort inw(ushort port)
{
ushort ret;
- asm volatile("inw %1, %0" : "=a"(ret) : "dN"(port));
+ asm("inw %1, %0" : "=a"(ret) : "dN"(port));
return ret;
}
void outl(ushort port, uint val)
{
- asm volatile("outl %1, %0" : : "dN"(port), "a"(val));
+ asm("outl %1, %0" : : "dN"(port), "a"(val));
}
uint inl(ushort port)
{
uint ret;
- asm volatile("inl %1, %0" : "=a"(ret) : "dN"(port));
+ asm("inl %1, %0" : "=a"(ret) : "dN"(port));
return ret;
}
+void outw(ushort port, ushort val)
+{
+ asm("outw %1, %0" :: "dN"(port), "a"(val));
+}
+
+void __attribute__((noinline)) nop()
+{
+ asm("nop");
+}
+
void *memset(void *s, int c, size_t n)
{
for (size_t i = 0; i < n; i++)
diff --git a/src/kernel/kbd.h b/src/kernel/kbd.h
index 98d6fd7..805d4ab 100644
--- a/src/kernel/kbd.h
+++ b/src/kernel/kbd.h
@@ -2,15 +2,24 @@
#include "kint.h"
+/**
+ * A scan code -> keyboard char mapping
+ */
struct kbd_scan_codes
{
bool ascii;
int symbol;
+ /**
+ * Uppercase version of symbol
+ */
int up_symbol;
uchar prefix;
bool brk;
};
+/**
+ * Non-char keyboard keys, assigned values above 7-bit ascii range (>128)
+ */
enum kbd_keys
{
FIRST_KBD_KEY = 129,
diff --git a/src/kernel/main.c b/src/kernel/main.c
index 04dc9a7..098d37b 100644
--- a/src/kernel/main.c
+++ b/src/kernel/main.c
@@ -84,7 +84,7 @@
pci_load();
- kprintf(OKAY "Loaded PCI devices\n");
+ kprintf(OKAY "Loaded PCI device drivers\n");
#ifdef TEST_THREADS
spawn_thread(other_thread, NULL);
@@ -101,13 +101,13 @@
test_ata_pio();
#endif
-#ifdef TEST_EXT2
if (ext2_valid_filesystem())
{
- kprintf(INFO "Mounting EXT2 to /\n");
- ext2_mount(&root);
+ kprintf(OKAY "EXT2 filesystem is valid, again = %b\n", ext2_valid_filesystem());
+
+ //kprintf(INFO "Mounting EXT2 to /\n");
+ //ext2_mount(&root);
}
-#endif
while (true)
asm("hlt");
diff --git a/src/kernel/pic.c b/src/kernel/pic.c
index 5d33213..e4ed88c 100644
--- a/src/kernel/pic.c
+++ b/src/kernel/pic.c
@@ -51,6 +51,7 @@
void pic_remap()
{
+ // I don't remember what this does.
outb(0x20, 0x11);
outb(0xA0, 0x11);
outb(0x21, 0x20);
diff --git a/src/kernel/pic.h b/src/kernel/pic.h
deleted file mode 100644
index de11f3f..0000000
--- a/src/kernel/pic.h
+++ /dev/null
@@ -1,20 +0,0 @@
-#pragma once
-
-#include "kint.h"
-#include "registers.h"
-
-#define PIC1 0x20
-#define PIC2 0xa0
-#define PIC1_COMMAND PIC1
-#define PIC1_DATA (PIC1 + 1)
-#define PIC2_COMMAND PIC2
-#define PIC2_DATA (PIC2 + 1)
-
-#define PIC_EOI 0x20 // End of input
-
-#define IRQ_TO_INT(irq) ((irq) + 32)
-
-void pic_send_eoi(uchar interrupt);
-void add_interrupt_handler(uchar interrupt, void (*handler)(struct registers *));
-
-void pic_remap();