From: acevest Date: Fri, 2 Jan 2026 13:53:55 +0000 (+0800) Subject: IO APIC接管键盘中断 X-Git-Url: http://repos.zhaoyanbai.com/Mou_128.png?a=commitdiff_plain;h=afe8b89930b56c8b2fafe6213d0127f260a39034;p=kernel.git IO APIC接管键盘中断 --- diff --git a/include/irq.h b/include/irq.h index 8554286..2993270 100644 --- a/include/irq.h +++ b/include/irq.h @@ -90,4 +90,6 @@ void exit_critical_zone(); #define IRQ_CASCADE 0x02 #define IRQ_DISK 0x0E +void irq_set_chip(unsigned int irq, irq_chip_t* chip); + #endif //_IRQ_H diff --git a/kernel/apic.c b/kernel/apic.c index 206d138..90b13d2 100644 --- a/kernel/apic.c +++ b/kernel/apic.c @@ -15,7 +15,7 @@ #include #include #include -#include +#include static inline uint32_t apic_offset_to_msr(uint32_t offset) { return 0x800 + (offset >> 4); @@ -304,6 +304,8 @@ void ioapic_init() { // 打开键盘中断 ioapic_rte_write(IOAPIC_RTE(1), 0x21); + extern irq_chip_t ioapic_chip; + irq_set_chip(0x01, &ioapic_chip); } void disable_i8259(); @@ -353,9 +355,27 @@ void init_apic() { // IOAPIC重定向到LAPIC // 8259A被禁用或掩码 -// irq_chip_t apic_chip = { -// .name = "APIC", -// .enable = enable_apic_irq, -// .disable = disable_apic_irq, -// .ack = ack_apic_irq, -// }; +int enable_ioapic_irq(unsigned int irq) { + uint64_t rte = ioapic_rte_read(irq); + rte &= ~IOAPIC_RTE_MASK; + ioapic_rte_write(irq, rte); + return 0; +} + +int disable_ioapic_irq(unsigned int irq) { + uint64_t rte = ioapic_rte_read(irq); + rte |= IOAPIC_RTE_MASK; + ioapic_rte_write(irq, rte); + return 0; +} + +void ack_ioapic_irq(unsigned int irq) { + system.lapic->write(LAPIC_EOI, 0); +} + +irq_chip_t ioapic_chip = { + .name = "IO-APIC", + .enable = enable_ioapic_irq, + .disable = disable_ioapic_irq, + .ack = ack_ioapic_irq, +}; diff --git a/kernel/irq.c b/kernel/irq.c index 101f640..4137ad5 100644 --- a/kernel/irq.c +++ b/kernel/irq.c @@ -42,6 +42,7 @@ __attribute__((regparm(1))) void irq_handler(pt_regs_t* regs) { panic("invalid irq %d\n", irq); } +#if 0 assert(1 == irq); uint8_t b = inb(0x60); printk("irq %d b %02x\n", irq, b); @@ -50,8 +51,8 @@ __attribute__((regparm(1))) void irq_handler(pt_regs_t* regs) { // vaddr_t apic_virt_base_addr = fixid_to_vaddr(FIX_LAPIC_BASE); // apic_virt_base_addr += 0xB0; // *((volatile uint32_t*)apic_virt_base_addr) = 0x0; - -#if 1 +#endif +#if 0 // 检查IMCR outb(0x22, 0x70); uint8_t imcr = inb(0x23); @@ -81,10 +82,6 @@ __attribute__((regparm(1))) void irq_handler(pt_regs_t* regs) { assert(reenter <= 1); // TODO 判断打断的是否是内核态代码 - - // 屏蔽当前中断 - // p->chip->disable(irq); - #if 0 if (0x00 == irq) { if ((clk_irq_cnt++ & 0xFU) != 0) { @@ -101,14 +98,10 @@ __attribute__((regparm(1))) void irq_handler(pt_regs_t* regs) { action = action->next; } - // 解除屏蔽当前中断 - // p->chip->enable(irq); - // 代表当前中断程序打断了前一个中断程序的“开中断处理的底半部分逻辑” // 即前一个中断处理尚未完全完成 assert(irq_disabled()); - // 发送EOI p->chip->ack(irq); if (reenter != 0) { @@ -341,3 +334,9 @@ void enter_critical_zone() { void exit_critical_zone() { irq_restore(__critical_zone_eflags); } + +void irq_set_chip(unsigned int irq, irq_chip_t* chip) { + assert(irq < NR_IRQS); + assert(chip != NULL); + irq_desc[irq].chip = chip; +} diff --git a/kernel/setup.c b/kernel/setup.c index ffb4b3e..093821e 100644 --- a/kernel/setup.c +++ b/kernel/setup.c @@ -86,14 +86,6 @@ void setup_kernel() { init_mm(); init_buffer(); -#if 1 - void init_acpi(); - init_acpi(); -#endif -#if 1 - void init_apic(); - init_apic(); -#endif void init_mount(); init_mount(); @@ -135,6 +127,15 @@ void setup_kernel() { setup_i8254(100); setup_irqs(); +#if 1 + void init_acpi(); + init_acpi(); +#endif +#if 1 + void init_apic(); + init_apic(); +#endif + #if !DISABLE_IDE void ide_init(); ide_init(); diff --git a/kernel/system.c b/kernel/system.c index 14bdfd8..447d482 100644 --- a/kernel/system.c +++ b/kernel/system.c @@ -124,7 +124,7 @@ void setup_irqs() { irq_desc[i] = no_irq_desc; if (i < 16) { - irq_desc[i].chip = &i8259_chip; + irq_set_chip(i, &i8259_chip); } } diff --git a/qemu.sh b/qemu.sh index 455675e..efa0e87 100755 --- a/qemu.sh +++ b/qemu.sh @@ -22,6 +22,7 @@ qemu-system-i386 \ -m 3100\ -smp 2 \ -cpu qemu32,+x2apic \ + -machine q35 \ -serial tcp::6666,server,nowait \ -drive file=hd.img,format=raw,index=0,media=disk \ -drive file=kernel.iso,index=1,media=cdrom \