]> Zhao Yanbai Git Server - kernel.git/commitdiff
IO APIC接管键盘中断
authoracevest <zhaoyanbai@126.com>
Fri, 2 Jan 2026 13:53:55 +0000 (21:53 +0800)
committeracevest <zhaoyanbai@126.com>
Fri, 2 Jan 2026 13:53:55 +0000 (21:53 +0800)
include/irq.h
kernel/apic.c
kernel/irq.c
kernel/setup.c
kernel/system.c
qemu.sh

index 8554286f061265932fd72ab07e6bd036f3f53340..299327098dfdb177cb4ffc7a1e02d9d02a230aa5 100644 (file)
@@ -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
index 206d138e7ffad315a9415fc6aeb92702c94f29ec..90b13d22be99c97bb177da2bcd8cb5ffebd9c06f 100644 (file)
@@ -15,7 +15,7 @@
 #include <pci.h>
 #include <ioremap.h>
 #include <io.h>
-#include <i8259.h>
+#include <irq.h>
 
 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,
+};
index 101f64067a26e4e742ad2876df6dfe93a72f6ba6..4137ad5078981e9dcae57be94ba711fb45a16663 100644 (file)
@@ -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;
+}
index ffb4b3e32886be601f87cbb8d228111c95f8af6c..093821e14f676b4748784fd0656bbefd375566a1 100644 (file)
@@ -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();
index 14bdfd8f5d57dfe50803c6db26af9873b904b948..447d482f48671ee3c58949be2141b7c39788fb86 100644 (file)
@@ -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 455675e67345fcf03d0953f209ccb67eb497dacc..efa0e87091504a87b7c5e40165bc22f2de4e62e3 100755 (executable)
--- 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 \