【问题标题】:Setting up IRQ mapping设置 IRQ 映射
【发布时间】:2010-09-21 22:20:21
【问题描述】:

我正在关注几个教程和参考资料,以尝试设置我的内核。我在一个根本没有解释它的教程中遇到了一些不熟悉的代码。这是我被告知将16 IRQs (0-15)映射到ISR位置32-47的代码:

void irq_remap(void)
{
    outportb(0x20, 0x11);
    outportb(0xA0, 0x11);
    outportb(0x21, 0x20);
    outportb(0xA1, 0x28);
    outportb(0x21, 0x04);
    outportb(0xA1, 0x02);
    outportb(0x21, 0x01);
    outportb(0xA1, 0x01);
    outportb(0x21, 0x0);
    outportb(0xA1, 0x0);
}

outportb()的代码如下,但我已经很清楚它的作用了:

void outPortB(unsigned short port, unsigned char data)
{
    __asm__ __volatile__ ("outb %1, %0" : : "dN" (port), "a" (data));
}

我应该提到这是在保护模式下的 x86 架构上。此源代码工作正常,我理解它的作用,但我不明白它是如何做到的。有人可以向我解释这里发生了什么,以便在我需要对此进行扩展时,我会知道我在做什么?

【问题讨论】:

    标签: assembly x86 kernel osdev irq


    【解决方案1】:

    outb 和类似的,写入硬件 IO 端口。基本上,与设备通信有 2 个主要选项。您可以将设备映射到内存或 IO 端口。

    至于这段代码的工作原理,我会为你评论:

    ICW 代表“Initialization Commands Words”

    outportb(0x20, 0x11); /* write ICW1 to PICM, we are gonna write commands to PICM */
    outportb(0xA0, 0x11); /* write ICW1 to PICS, we are gonna write commands to PICS */
    
    outportb(0x21, 0x20); /* remap PICM to 0x20 (32 decimal) */
    outportb(0xA1, 0x28); /* remap PICS to 0x28 (40 decimal) */
    
    outportb(0x21, 0x04); /* IRQ2 -> connection to slave */ 
    outportb(0xA1, 0x02);
    
    outportb(0x21, 0x01); /* write ICW4 to PICM, we are gonna write commands to PICM */
    outportb(0xA1, 0x01); /* write ICW4 to PICS, we are gonna write commands to PICS */
    
    outportb(0x21, 0x0); /* enable all IRQs on PICM */
    outportb(0xA1, 0x0); /* enable all IRQs on PICS */
    

    希望对你有帮助

    欢迎来到 OS 开发者的世界 :) 我还建议您访问:http://forum.osdev.org/,对于新的爱好 OS 开发者来说,这是一个非常宝贵的资源。

    【讨论】:

    • 哇,这正是我所需要的。谢谢大家!
    【解决方案2】:

    简单的答案是,在保护模式下,第一个可编程中断控制器使用的中断是保护模式异常,这意味着它们必须重新映射。

    满意的答案是只有第一个PIC 需要重新映射(第二个的重新映射只是为了方便,因为它从int 70h 开始)。 这是原始 AT BIOS 的引述。

    INTA00    equ  020h        ; 8259 port
    INTA01    equ  021h        ; 8259 port
    INTB00    equ  0A0h        ; 2nd 8259
    INTB01    equ  0A1h
    INT_TYPE  equ  070h        ; start of 8259 interrupt table location
    
    ;---------------------------------------------------------
    ;    re-initialize the 8259 interrupt #1 controller chip :
    ;---------------------------------------------------------
      mov  al, 11h             ; icw1 - edge, master, icw4
      out  INTA00,al
      jmp  $+2                 ; wait state for i/o
      mov  al, 8               ; setup icw2 - int type 8 (8-f)
      out  INTA01, al
      jmp  $+2
      mov  al, 4               ; setup icw3 - master lv 2
      out  INTA01, al
      jmp  $+2
      mov  al, 1               ; setup icw4 - master, 8086 mode
      out  INTA01, al
      jmp  $+2
      mov  al, 0FFh            ; mask all ints. off
      out  INTA01, al          ; (video routine enables interrupts)
    ;---------------------------------------------------------
    ;    re-initialize the 8259 interrupt #2 controller chip  :
    ;---------------------------------------------------------
      mov  al, 11h             ; icw1 - edge, slave icw4
      out  INTB00, al
      jmp  $+2
      mov  al, INT_TYPE        ; setup icw2 - int type 70 (70-7f)
      out  INTB01, al
      mov  al, 2               ; setup icw3 - slave lv 2
      jmp  $+2
      out  INTB01, al
      jmp  $+2
      mov  al, 1               ; setup icw4 - 8086 mode, slave
      out  INTB01, al
      jmp  $+2
      mov  al, 0FFh            ; mask all ints. off
      out  INTB01, al
    ;--------------------------------------------------------------------------------
    

    技术参考 AT BIOS (c) 1984 IBM

    注意:

    jmp $+2 ; wait state for i/o 在当前 PC 上不是必需的。

    icw1 清除中断屏蔽寄存器,从而启用该 PIC 上的中断。

    8259A 芯片早已不复存在,但仍然使用编程接口。 8259A Programmable Interrupt Controller

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-11-27
      • 1970-01-01
      • 2023-01-05
      • 1970-01-01
      • 1970-01-01
      • 2013-10-08
      相关资源
      最近更新 更多