From a1fedd379b655112682b244cde5aec5e4a698978 Mon Sep 17 00:00:00 2001 From: david-on-debian Date: Tue, 20 May 2025 20:37:45 -0500 Subject: [PATCH] Upload files to "drivers" --- drivers/gdt.c | 34 ++++++++++ drivers/ide.c | 173 ++++++++++++++++++++++++++++++++++++++++++++++++++ drivers/idt.c | 110 ++++++++++++++++++++++++++++++++ drivers/isr.c | 29 +++++++++ drivers/pci.c | 59 +++++++++++++++++ 5 files changed, 405 insertions(+) create mode 100644 drivers/gdt.c create mode 100644 drivers/ide.c create mode 100644 drivers/idt.c create mode 100644 drivers/isr.c create mode 100644 drivers/pci.c diff --git a/drivers/gdt.c b/drivers/gdt.c new file mode 100644 index 0000000..99e06ec --- /dev/null +++ b/drivers/gdt.c @@ -0,0 +1,34 @@ +#include + + +#define GDT_ENTRIES 3 + +struct gdt_entry gdt[GDT_ENTRIES]; +struct gdt_ptr gp; + +extern void gdt_flush(uint32_t); + +void gdt_install() +{ + gp.limit = (sizeof(struct gdt_entry) * GDT_ENTRIES) - 1; + gp.base = (uint32_t)&gdt; + + gdt_set_entry(0, 0, 0, 0, 0); /* Null segment */ + gdt_set_entry(1, 0, 0xFFFFFFFF, 0x9A, 0xCF); /* Code segment */ + gdt_set_entry(2, 0, 0xFFFFFFFF, 0x92, 0xCF); /* Data segment */ + + gdt_flush((uint32_t)&gp); +} + +void gdt_set_entry(int num, uint32_t base, uint32_t limit, uint8_t access, uint8_t gran) +{ + gdt[num].base_low = (base & 0xFFFF); + gdt[num].base_middle = (base >> 16) & 0xFF; + gdt[num].base_high = (base >> 24) & 0xFF; + + gdt[num].limit_low = (limit & 0xFFFF); + gdt[num].granularity = (limit >> 16) & 0x0F; + + gdt[num].granularity |= (gran & 0xF0); + gdt[num].access = access; +} diff --git a/drivers/ide.c b/drivers/ide.c new file mode 100644 index 0000000..f398b6d --- /dev/null +++ b/drivers/ide.c @@ -0,0 +1,173 @@ +#include + +#include + +#include + + +static void io_delay() { + for (int32_t i = 0; i < 1000; i++) { + outb(0x80, 0); + } +} + + +static int32_t ide_wait(uint16_t io, int32_t check_drq) { + for (int32_t i = 0; i < 5000; i++) { // 5000 ms = 5s + uint8_t status = inb(io + ATA_REG_STATUS); + if (!(status & ATA_SR_BSY)) { + if (!check_drq || (status & ATA_SR_DRQ)) + return 0; + } + io_delay(1); + } + return 1; +} + +static int32_t ide_wait_ready(uint16_t io) { + for (int32_t i = 0; i < 100000; i++) { + uint8_t status = inb(io + ATA_REG_STATUS); + if (!(status & ATA_SR_BSY)) return 0; + } + return 1; +} + + + +int32_t ide_identify(uint8_t drive, uint16_t* buffer) { + uint16_t io = ATA_PRIMARY_IO; + uint8_t slave_bit = (drive & 1) << 4; + + ide_wait(io, 0); + outb(io + ATA_REG_HDDEVSEL, 0xA0 | slave_bit); + outb(io + ATA_REG_SECCOUNT0, 0); + outb(io + ATA_REG_LBA0, 0); + outb(io + ATA_REG_LBA1, 0); + outb(io + ATA_REG_LBA2, 0); + outb(io + ATA_REG_COMMAND, 0xEC); // IDENTIFY DEVICE + + uint8_t status = inb(io + ATA_REG_STATUS); + if (status == 0) return -1; // No device + + if (ide_wait(io, 1)) return -2; + + insw(io + ATA_REG_DATA, buffer, 256); // Read 512 bytes + return 0; +} + +void ide_initialize(void) { + outb(ATA_PRIMARY_CTRL, 0x02); // Disable IRQs + + uint16_t identify_buf[256]; + if (ide_identify(0, identify_buf) == 0) { + char model[41]; + for (int i = 0; i < 20; ++i) { + model[i * 2 + 0] = identify_buf[27 + i] >> 8; + model[i * 2 + 1] = identify_buf[27 + i] & 0xFF; + } + model[40] = 0; + printf("Disk model: %s\n", model); + } +} + +int32_t ide_read48(uint8_t drive, uint64_t lba, uint8_t sector_count, void* buffer) { + if (sector_count == 0) return -1; + + uint16_t io = ATA_PRIMARY_IO; + uint8_t slave_bit = (drive & 1) << 4; + + ide_wait(io, 0); // Wait for BSY to clear + + outb(io + ATA_REG_HDDEVSEL, 0xE0 | slave_bit); // Select drive + + // High bytes (use 0xC2 - 0xC6 offsets if you define them separately) + outb(io + 6, (sector_count >> 8) & 0xFF); // Sector Count High + outb(io + 7, (lba >> 40) & 0xFF); // LBA[47:40] + outb(io + 8, (lba >> 32) & 0xFF); // LBA[39:32] + outb(io + 9, (lba >> 24) & 0xFF); // LBA[31:24] + + // Low bytes + outb(io + 2, sector_count & 0xFF); // Sector Count Low + outb(io + 3, (lba >> 0) & 0xFF); // LBA[7:0] + outb(io + 4, (lba >> 8) & 0xFF); // LBA[15:8] + outb(io + 5, (lba >> 16) & 0xFF); // LBA[23:16] + + + outb(io + ATA_REG_COMMAND, ATA_CMD_READ_SECTORS_EXT); + + uint16_t* ptr = (uint16_t*)buffer; + for (int i = 0; i < sector_count; i++) { + if (ide_wait(io, 1)) { + uint8_t status = inb(io + ATA_REG_STATUS); + printf("IDE DRQ wait failed (read), status = 0x%02X\n", status); + return -2; + } + + uint8_t status = inb(io + ATA_REG_STATUS); + if (status & ATA_SR_ERR) return -3; + + insw(io + ATA_REG_DATA, ptr, 256); + ptr += 256; + } + + return 0; +} + + +int32_t ide_write48(uint8_t drive, uint64_t lba, uint8_t sector_count, const void* buffer) { + if (sector_count == 0) return -1; + + uint16_t io = ATA_PRIMARY_IO; + uint8_t slave_bit = (drive & 1) << 4; + + ide_wait(io, 0); // Wait for BSY to clear + + outb(io + ATA_REG_HDDEVSEL, 0xE0 | slave_bit); // Select drive + + // Send high bytes of sector count and LBA first + outb(io + ATA_REG_SECCOUNT0, 0); // Sector count high byte + outb(io + ATA_REG_LBA0, (lba >> 40) & 0xFF); // LBA[47:40] + outb(io + ATA_REG_LBA1, (lba >> 32) & 0xFF); // LBA[39:32] + outb(io + ATA_REG_LBA2, (lba >> 24) & 0xFF); // LBA[31:24] + + // Send low bytes + outb(io + ATA_REG_SECCOUNT0, sector_count); // Sector count low byte + outb(io + ATA_REG_LBA0, (lba >> 0) & 0xFF); // LBA[7:0] + outb(io + ATA_REG_LBA1, (lba >> 8) & 0xFF); // LBA[15:8] + outb(io + ATA_REG_LBA2, (lba >> 16) & 0xFF); // LBA[23:16] + + // Send write command + outb(io + ATA_REG_COMMAND, ATA_CMD_WRITE_SECTORS_EXT); // 0x34 + + const uint16_t* ptr = (const uint16_t*)buffer; + for (int i = 0; i < sector_count; i++) { + if (ide_wait(io, 1)) { + uint8_t status = inb(io + ATA_REG_STATUS); + printf("IDE DRQ wait failed (write), status = 0x%02X\n", status); + return -2; + } + + // Check for drive error + uint8_t status = inb(io + ATA_REG_STATUS); + if (status & ATA_SR_ERR) return -3; + + outsw(io + ATA_REG_DATA, ptr, 256); // 256 words = 512 bytes + inb(io + ATA_REG_STATUS); /* Dummy read */ + ptr += 256; + } + + // Wait for BSY=0 before issuing FLUSH CACHE + if (ide_wait_ready(io)) return -5; + outb(io + ATA_REG_COMMAND, 0xE7); // FLUSH CACHE + if (ide_wait(io, 0)) { + printf("FLUSH CACHE timeout, status=0x%02X\n", inb(io + ATA_REG_STATUS)); + return -4; + } + + + + return 0; +} + + + diff --git a/drivers/idt.c b/drivers/idt.c new file mode 100644 index 0000000..990c3e5 --- /dev/null +++ b/drivers/idt.c @@ -0,0 +1,110 @@ +#include + +#include + +#define IDT_ENTRIES 256 + +struct idt_entry idt[IDT_ENTRIES]; +struct idt_ptr idtp; + +extern void idt_load(uint32_t); + +void idt_install(void) +{ + idtp.limit = sizeof(struct idt_entry) * IDT_ENTRIES - 1; + idtp.base = (uint32_t)&idt; + + memset(&idt, 0, sizeof(struct idt_entry) * IDT_ENTRIES); + + /* Set entries for IRQs/ISRs here using `idt_set_entry(...)` */ + /* Example: idt_set_entry(0, (uint32_t)isr0, 0x08, 0x8E); */ + + idt_load((uint32_t)&idtp); +} + +void idt_set_entry(int num, uint32_t base, uint16_t sel, uint8_t flags) +{ + idt[num].base_low = base & 0xFFFF; + idt[num].base_high = (base >> 16) & 0xFFFF; + + idt[num].sel = sel; + idt[num].always0 = 0; + idt[num].flags = flags; +} + +extern void isr0(); +extern void isr1(); +extern void isr2(); +extern void isr3(); +extern void isr4(); +extern void isr5(); +extern void isr6(); +extern void isr7(); +extern void isr8(); +extern void isr9(); +extern void isr10(); +extern void isr11(); +extern void isr12(); +extern void isr13(); +extern void isr14(); +extern void isr15(); +extern void isr16(); +extern void isr17(); +extern void isr18(); +extern void isr19(); +extern void isr20(); +extern void isr21(); +extern void isr22(); +extern void isr23(); +extern void isr24(); +extern void isr25(); +extern void isr26(); +extern void isr27(); +extern void isr28(); +extern void isr29(); +extern void isr30(); +extern void isr31(); + +extern void isr128(); + + +void idt_install_isrs(void) +{ + idt_set_entry(0, (uint32_t)isr0, 0x08, 0x8E); + idt_set_entry(1, (uint32_t)isr1, 0x08, 0x8E); + idt_set_entry(2, (uint32_t)isr2, 0x08, 0x8E); + idt_set_entry(3, (uint32_t)isr3, 0x08, 0x8E); + idt_set_entry(4, (uint32_t)isr4, 0x08, 0x8E); + idt_set_entry(5, (uint32_t)isr5, 0x08, 0x8E); + idt_set_entry(6, (uint32_t)isr6, 0x08, 0x8E); + idt_set_entry(7, (uint32_t)isr7, 0x08, 0x8E); + idt_set_entry(8, (uint32_t)isr8, 0x08, 0x8E); + idt_set_entry(9, (uint32_t)isr9, 0x08, 0x8E); + idt_set_entry(10, (uint32_t)isr10, 0x08, 0x8E); + idt_set_entry(11, (uint32_t)isr11, 0x08, 0x8E); + idt_set_entry(12, (uint32_t)isr12, 0x08, 0x8E); + idt_set_entry(13, (uint32_t)isr13, 0x08, 0x8E); + idt_set_entry(14, (uint32_t)isr14, 0x08, 0x8E); + idt_set_entry(15, (uint32_t)isr15, 0x08, 0x8E); + idt_set_entry(16, (uint32_t)isr16, 0x08, 0x8E); + idt_set_entry(17, (uint32_t)isr17, 0x08, 0x8E); + idt_set_entry(18, (uint32_t)isr18, 0x08, 0x8E); + idt_set_entry(19, (uint32_t)isr19, 0x08, 0x8E); + idt_set_entry(20, (uint32_t)isr20, 0x08, 0x8E); + idt_set_entry(21, (uint32_t)isr21, 0x08, 0x8E); + idt_set_entry(22, (uint32_t)isr22, 0x08, 0x8E); + idt_set_entry(23, (uint32_t)isr23, 0x08, 0x8E); + idt_set_entry(24, (uint32_t)isr24, 0x08, 0x8E); + idt_set_entry(25, (uint32_t)isr25, 0x08, 0x8E); + idt_set_entry(26, (uint32_t)isr26, 0x08, 0x8E); + idt_set_entry(27, (uint32_t)isr27, 0x08, 0x8E); + idt_set_entry(28, (uint32_t)isr28, 0x08, 0x8E); + idt_set_entry(29, (uint32_t)isr29, 0x08, 0x8E); + idt_set_entry(30, (uint32_t)isr30, 0x08, 0x8E); + idt_set_entry(31, (uint32_t)isr31, 0x08, 0x8E); +} + +void idt_install_syscall(void) +{ + idt_set_entry(128, (uint32_t)isr128, 0x08, 0xEE); +} diff --git a/drivers/isr.c b/drivers/isr.c new file mode 100644 index 0000000..8b26f77 --- /dev/null +++ b/drivers/isr.c @@ -0,0 +1,29 @@ +#include + +#include + + +void isr_handler(regs_t *r) +{ + // Handle faults + if (r->int_no < 32) + { + printf("Received interrupt: %d\n", r->int_no); + // halt or kill task... + } + if (r->int_no == 128) + { + syscall_handler(r); + return; + } +} + +void syscall_handler(regs_t *r) +{ + switch (r->eax) { + case 0: printf("Syscall: Hello world\n"); break; + case 1: printf("Syscall: value = %d\n", r->ebx); break; + default: printf("Unknown syscall %d\n", r->eax); + } +} + diff --git a/drivers/pci.c b/drivers/pci.c new file mode 100644 index 0000000..769c329 --- /dev/null +++ b/drivers/pci.c @@ -0,0 +1,59 @@ +#include +#include + +#include +#include +#include + +#define PCI_CONFIG_ADDRESS 0xCF8 +#define PCI_CONFIG_DATA 0xCFC + +uint32_t pci_config_read(uint8_t bus, uint8_t device, uint8_t function, uint8_t offset) +{ + uint32_t address = 0; + address |= (bus << 16); // Bus number (bits 23-16) + address |= (device << 11); // Device number (bits 15-11) + address |= (function << 8); // Function number (bits 10-8) + address |= (offset & 0xFC); // Register offset (bits 7-0) + address |= (1 << 31); // Enable configuration access + + outl(PCI_CONFIG_ADDRESS, address); // Write address to PCI config space + return inl(PCI_CONFIG_DATA); // Read data from PCI config space +} + +void pci_config_write(uint8_t bus, uint8_t device, uint8_t function, uint8_t offset, uint32_t value) +{ + uint32_t address = 0x80000000 | (bus << 16) | (device << 11) | (function << 8) | (offset & 0xFC); + outl(PCI_CONFIG_ADDRESS, address); // Send the address to PCI config space + outl(PCI_CONFIG_DATA, value); // Write data to PCI config space +} + +void pci_enumerate() +{ + for (uint16_t bus = 0; bus < 256; bus++) // Maximum 256 buses + { + for (uint8_t device = 0; device < 32; device++) // Maximum 32 devices per bus + { + for (uint8_t function = 0; function < 8; function++) // Maximum 8 functions per device + { + uint32_t vendor_id = pci_config_read(bus, device, function, 0x00); + if (vendor_id == 0xFFFFFFFF) continue; // No device present + + uint32_t device_id = pci_config_read(bus, device, function, 0x02); + uint32_t class_code = pci_config_read(bus, device, function, 0x08); + printf("Found PCI device: Vendor ID: 0x%X Device ID: 0x%X Class: 0x%X\n", vendor_id, device_id, class_code); + + printf("0x%X", class_code); + printf(" --- "); + printf("0x%X\n", (class_code >> 8)); + + + if ((class_code >> 8) == 0x0C) { + printf("Found USB controller (Class: 0x%02X)\n", class_code); + // Now, you can initialize and configure the USB controller. + } + + } + } + } +}