diff --git a/kernel/arch/acpi.c b/kernel/arch/acpi.c index 441fb57..ed6bf3b 100644 --- a/kernel/arch/acpi.c +++ b/kernel/arch/acpi.c @@ -4,6 +4,7 @@ #include #include #include +#include RSDP_st *find_rsdp() { @@ -87,6 +88,7 @@ void parse_MADT(SDT_header *header) break; case 2: // Interrupt Source Override debug_info("ACPI - Interrupt source override %x->%x\n", f->ISO.irq, f->ISO.interrupt); + irq_map[f->ISO.irq] = f->ISO.interrupt; break; default: break; diff --git a/kernel/boot/kmain.c b/kernel/boot/kmain.c index 9adfacd..aa6efa6 100644 --- a/kernel/boot/kmain.c +++ b/kernel/boot/kmain.c @@ -35,6 +35,7 @@ int kmain(uint64_t multiboot_magic, void *multiboot_data) pic_init(); acpi_init(); apic_init(); + ioapic_init(); process_t *p1 = process_spawn(0); diff --git a/kernel/include/apic.h b/kernel/include/apic.h index f72c284..e79a64e 100644 --- a/kernel/include/apic.h +++ b/kernel/include/apic.h @@ -9,3 +9,8 @@ void apic_ack(); #define APIC_INT_TYPE_FIXED 0x0 #define APIC_INT_TYPE_INIT 0x5 #define APIC_INT_TYPE_STARTUP 0x6 + + +void ioapic_init(); +void ioapic_mask(uint8_t irq); +void ioapic_unmask(uint8_t irq); diff --git a/kernel/include/int.h b/kernel/include/int.h index 608177a..16d7d14 100644 --- a/kernel/include/int.h +++ b/kernel/include/int.h @@ -87,14 +87,12 @@ struct idtr } __attribute__ ((packed)); void pic_init(); -void pic_ack(uint8_t irq); -void pic_mask(uint8_t irq); -void pic_unmask(uint8_t irq); +extern unsigned int irq_map[24]; #define IRQ_INT(irq) (INT_IRQ0 + irq) -#define IRQ(irq) (irq) -#define IRQ_MASK(irq) pic_mask(irq) -#define IRQ_UNMASK(irq) pic_unmask(irq) -#define IRQ_ACK(irq) pic_ack(irq) +#define IRQ(irq) (irq_map[irq]) +#define IRQ_MASK(irq) ioapic_mask(IRQ(irq)) +#define IRQ_UNMASK(irq) ioapic_unmask(IRQ(irq)) +#define IRQ_ACK(irq) apic_ack(IRQ(irq)) #define IRQ_TIMER 0 #define IRQ_KEYBOARD 1 diff --git a/kernel/interrupts/apic.c b/kernel/interrupts/apic.c index 213c316..e47528a 100644 --- a/kernel/interrupts/apic.c +++ b/kernel/interrupts/apic.c @@ -49,9 +49,6 @@ void apic_init() // Make sure the APIC base addres is mapped in kernel memory vmm_set_page(0, (uintptr_t)P2V(APIC_BASE), APIC_BASE, PAGE_PRESENT | PAGE_WRITE); - debug_info("APIC - ID: %x\n", APIC(R_ID)); - debug_info("APIC - Version: %x\n", APIC(R_VERSION)); - uint8_t id = APIC(R_ID) >> 24; if(id <= 0) APIC(R_LDR) = 1 << (24 + id); diff --git a/kernel/interrupts/ioapic.c b/kernel/interrupts/ioapic.c new file mode 100644 index 0000000..44dc1ba --- /dev/null +++ b/kernel/interrupts/ioapic.c @@ -0,0 +1,91 @@ +#include +#include +#include + +#define IOAPIC_BASE 0xFEC00000 + +#define IOAPIC_DEST_PHYSICAL 0x0 +#define IOAPIC_DEST_LOGICAL 0x8 +#define IOAPIC_DELIVERY_FIXED 0x0 +#define IOAPIC_DELIVERY_LOWEST 0x1 + + +volatile uint32_t *ioregsel = (void *)P2V(IOAPIC_BASE); +volatile uint32_t *iowin = (void *)P2V(IOAPIC_BASE + 0x10); + +uint32_t ioapic_read(uint32_t reg) +{ + // Read value from APIC register + *ioregsel = reg; + return *iowin; +} +void ioapic_write(uint32_t reg, uint32_t value) +{ + // Read value from APIC register + *ioregsel = reg; + *iowin = value; +} + +struct ioapic_redirection +{ + union + { + struct + { + uint32_t data[2]; + }__attribute__((packed)); + struct + { + uint8_t vector; + uint8_t mode; + uint8_t mask; + uint32_t reserved; + uint8_t target; + }__attribute__((packed)); + }; +}; + +void ioapic_readv(uint8_t irq, struct ioapic_redirection *v) +{ + v->data[0] = ioapic_read(0x10 + 2*irq); + v->data[1] = ioapic_read(0x11 + 2*irq); +} +void ioapic_writev(uint8_t irq, struct ioapic_redirection *v) +{ + ioapic_write(0x10 + 2*irq, v->data[0]); + ioapic_write(0x11 + 2*irq, v->data[1]); +} + +void ioapic_route(uint8_t irq, uint8_t mode, uint8_t target, uint8_t vector) +{ + struct ioapic_redirection v; + ioapic_readv(irq, &v); + v.target = target; + v.vector = vector; + v.mode = mode; + ioapic_writev(irq, &v); +} + +void ioapic_mask(uint8_t irq) +{ + struct ioapic_redirection v; + ioapic_readv(irq, &v); + v.mask |= 1; + ioapic_writev(irq, &v); +} +void ioapic_unmask(uint8_t irq) +{ + struct ioapic_redirection v; + ioapic_readv(irq, &v); + v.mask &= 0xFE; + ioapic_writev(irq, &v); +} + +void ioapic_init() +{ + vmm_set_page(0, (uintptr_t)P2V(IOAPIC_BASE), IOAPIC_BASE, PAGE_PRESENT | PAGE_WRITE); + for(int i = 0; i < 24; i++) + ioapic_route(i, IOAPIC_DEST_LOGICAL | IOAPIC_DELIVERY_LOWEST, 0xFF, INT_IRQ0+i); + + IRQ_UNMASK(IRQ_KEYBOARD); +} diff --git a/kernel/interrupts/pic.c b/kernel/interrupts/pic.c index 85629f4..9dda293 100644 --- a/kernel/interrupts/pic.c +++ b/kernel/interrupts/pic.c @@ -13,6 +13,7 @@ #define PIC_CMD_8086 0x01 #define PIC_CMD_EOI 0x20 +unsigned int irq_map[] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23}; void pic_init() { @@ -37,29 +38,3 @@ void pic_init() outb(MPIC_DATA, 0xFF); outb(SPIC_DATA, 0xFF); } - -void pic_ack(uint8_t irq) -{ - if(irq >= 8) - outb(SPIC_CMD, PIC_CMD_EOI); - outb(MPIC_CMD, PIC_CMD_EOI); -} - -void pic_mask(uint8_t irq) -{ - if(irq >= 8) - { - outb(SPIC_DATA, inb(SPIC_DATA) | 1 << (irq-8)); - } else { - outb(MPIC_DATA, inb(MPIC_DATA) | 1 << irq); - } -} -void pic_unmask(uint8_t irq) -{ - if(irq >= 8) - { - outb(SPIC_DATA, inb(SPIC_DATA) & ~(1 << (irq-8))); - } else { - outb(MPIC_DATA, inb(MPIC_DATA) & ~(1 << irq)); - } -}