Upload files to "drivers"

This commit is contained in:
2025-05-20 20:37:45 -05:00
parent 21daf4b745
commit a1fedd379b
5 changed files with 405 additions and 0 deletions

34
drivers/gdt.c Normal file
View File

@ -0,0 +1,34 @@
#include <gdt.h>
#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;
}

173
drivers/ide.c Normal file
View File

@ -0,0 +1,173 @@
#include <stdio.h>
#include <port_io.h>
#include <drivers/ide.h>
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;
}

110
drivers/idt.c Normal file
View File

@ -0,0 +1,110 @@
#include <string.h>
#include <idt.h>
#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);
}

29
drivers/isr.c Normal file
View File

@ -0,0 +1,29 @@
#include <stdio.h>
#include <isr.h>
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);
}
}

59
drivers/pci.c Normal file
View File

@ -0,0 +1,59 @@
#include <stdint.h>
#include <stddef.h>
#include <drivers/pci.h>
#include <port_io.h>
#include <stdio.h>
#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.
}
}
}
}
}