kernel源码(七)设置8259A

1 8259A芯片

外部引脚和内部结构

     

 

 

 IR0-IR7:中断源

IRR:中断请求寄存器,8位,每一位对应一个中断请求,某一位置1表示对应有中断请求

IMR:中断屏蔽寄存器,8位,每一位对应一个中断,某一位置1表示屏蔽某个中断源(比如IR3被屏蔽,则CPU将不会收到IR3的中断请求)

PR判优电路:中断请求冲IRR过来后,如果IRR有多个位置1,则这里判断优先级,先处理哪个中断

ISR:内部服务寄存器,经过PR判优电路,最高优先级的请求被送到ISR中,保存正在服务的中断请求

INT:连接CPU的中断输入端

/INTA:CPU请求中断后的结果回送到这里

ICW:初始化命令字寄存器,共4个,ICW1-ICW4,每一个寄存器都是8位

OCW:写入操作命令字寄存器,共3个,OCW1-OCW3,每一个寄存器都是8位

 

8259A工作过程:

当系统通电后,首先应对8259A初始化,也就是由CPU执行一段程序,向8259A写入若干控制字,指定它的工作方式。初始化完成后,8259A就准备好了,随时可以接受外设的中断请求信号,当外设发出请求后,8259A对外部中断请求的处理过程如下:
1. 哪条IR线上的数据有效,IRR相应位置就置1。
2. 8259A由INT引脚向CPU发INTR信号。
3. CPU完成当前指令后,用/INTR信号响应,告诉8259A收到了中断请求。
4. 8259A接收到CPU发出的第一个/INTA脉冲后,把最高优先权的ISR置1,并使相应的IRR复位0。
5. 第二个中断响应周期中,CPU再输出一个/INTA脉冲,这时8259A就把刚才选定的中断源所对应的8位中断类型码放到数据总线上,CPU读取该中断类型码并乘以4,就是中断服务子程序在中断向量表中的入口地址。找到执行。
6. 若8259A工作在自动中断结束AEOI方式,在第二个/INTA脉冲结束时,把中断源所对应的ISR中相应位复位。对于非自动中断结束方式,则由CPU在中断服务子程序结束时向8259A写入EOI命令,才能使ISR中的相应位复位

2 8259A和CPU的连接方式

 

 

 

 

 

 

3 setup.s

上一篇我们讲解了setup.s。但是对8259A的设置代码,我们一笔带过,这里我们再看一下这一段代码

in和out指令是专门用于累加器ax的指令。out指令表示通过外部设备的I/O端口号发送数据到外设。这里的端口号指的是内存地址,Linux给8259A设置的内存地址是0x20,,0x21和0xA0,0xA1

8259A规定0x20和0xA0:我们通过这两个端口写入ICW1,OCW2,OCW3并能够读取IRR和ISR。0xA0和0xA1:我们通过这两个端口写入ICW2,ICW3,ICW4并能够读写IMR寄存器。

! well, that went ok, I hope. Now we have to reprogram the interrupts :-(
! we put them right after the intel-reserved hardware interrupts, at
! int 0x20-0x2F. There they won't mess up anything. Sadly IBM really
! messed this up with the original PC, and they haven't been able to
! rectify it afterwards. Thus the bios puts interrupts at 0x08-0x0f,
! which is used for the internal hardware interrupts as well. We just
! have to reprogram the 8259's, and it isn't fun.

    mov    al,#0x11        ! initialization sequence
    out    #0x20,al        ! send it to 8259A-1,通过端口号发送数据0x11到8259A-1,用于设置ICW1,这里我们发送的是00010001,对照代码下面的图片我们可以知道其意思。
    .word    0x00eb,0x00eb        ! 和jmp $+2, jmp $+2指令作用相同,这里直接使用机器码。$表示当前指令位置,jmp无条件转移,即转移到当前指令+2的位置,作用是延时两条指令的时间,给IO端口一个反应时间
    out    #0xA0,al        ! and to 8259A-2,设置从芯片的ICW1,也设置为00010001.表示中断请求是边沿触发、多片8259A级联并且需要发送ICW4
    .word    0x00eb,0x00eb
    mov    al,#0x20        ! start of hardware int's (0x20)
    out    #0x21,al !初始化ICW2为0010 0000,参考下面3.2小节说明,可知我么这里设置了IR0~IR7的中断号
    .word    0x00eb,0x00eb
    mov    al,#0x28        ! start of hardware int's 2 (0x28)
    out    #0xA1,al !初始化从片的ICW2,也就是设置从片的中断号高5位
    .word    0x00eb,0x00eb
    mov    al,#0x04        ! 8259-1 is master
    out    #0x21,al !初始化主片ICW3,设置为0000 0100
    .word    0x00eb,0x00eb
    mov    al,#0x02        ! 8259-2 is slave
    out    #0xA1,al !初始化从片ICW3,设置为0000 0010
    .word    0x00eb,0x00eb
    mov    al,#0x01        ! 8086 mode for both
    out    #0x21,al !初始化主片ICW4,设置为0000 0001
    .word    0x00eb,0x00eb
    out    #0xA1,al !初始化从片ICW4,设置为0000 0001
    .word    0x00eb,0x00eb
    mov    al,#0xFF        ! 设置OCW1寄存器,该寄存器用于设置IMR以屏蔽中断。这里设置为1111 1111表示全屏蔽,待外部设备准备好后会开启。
    out    #0x21,al
    .word    0x00eb,0x00eb
    out    #0xA1,al !设置从片OCW1,屏蔽所有中断

 

3.1 初始化ICW1

(参考https://blog.csdn.net/longintchar/article/details/79439466):

 

 

3.2 初始化ICW2 

 

Linux-0.11 系统把主片的 ICW2 设置为 0x20,表示主片中断请求0~7级对应的中断号是 0x20~0x27;把从片的 ICW2 设置成 0x28,表示从片中断请求8~15级对应的中断号是 0x28~0x2f

3 初始化ICW3

 

 4 初始化ICW4

 

 Linux-0.11内核送往8259A主芯片和从芯片的 ICW4 命令字的值均为 0x01。表示 8259A 芯片被设置成普通全嵌套、非缓冲、非自动结束中断方式,并且用于 8086 及其兼容系统。

 5 初始化OCW1

OCW1 用于对 8259A 中中断屏蔽寄存器 IMR 进行读/写操作。

 

posted @ 2022-03-05 18:32  zhenjingcool  阅读(608)  评论(0编辑  收藏  举报