x86架构——8259A中断控制器

说明

8259A中断控制器,如名字所说,是用来处理中断的。

它有如下的特性:

1. 单片支持8个中断,可多片扩展,最多扩展到64个中断;

2. 可编程的中断模式;

3. 可配置中断屏蔽;

4. 中断分优先级;

8259A是一款非常老的芯片,适配8086/8088芯片,目前基本上不再使用。

因此本文是属于考古文,新程序员请在古董程序员陪同下阅读...

本文参考自《8259A PROGRAMMABLE INTERRUPT CONTROLLER》以及EDK代码。

 

8259A的逻辑框图

下图是8259A的逻辑框图:

x86架构——8259A中断控制器_第1张图片

由于软件上不需要关注过多硬件方面的内容,所以这里只是简单介绍各个引脚以及功能模块。

 

引脚信息

1. IRQ1-IRQ7:这是中断引脚,连接外部设备;

2. D0-D7:数据传输通道,8259A会通过它与系统交换控制字,状态字,中断向量等信息;

3. CAS0-CAS2:级联额外的8259控制器以扩展中断,由于是3位,所以最多能够连接8个额外的8259A控制器;

4. CS:片选信号,低有效,此时RD/WR选通;

5. INT:与CPU的中断引脚连接,用于触发CPU中断;

6. INTA:用于通知8259A上传中断向量信息;

7. A0:跟CS/WR/RD一起使用,用来区分CPU发过来的命令的意义,它跟CPU的A0地址线相连,后续初始化8259A的时候会具体说明。

8. WR:低有效,此时CPU可以向8259A发送控制字;

9. RD:低有效,此时8259A向CPU发送状态字或中断信息。

 

模块信息

中断请求寄存器(IRR):当中断进来之后,对应的中断请求寄存器位会被置位;

中断服务寄存器(ISR):中断寄存器中对应的置位表示当前中断正在处理;

优先级处理器:当多个中断同时触发时,判断那个中断会被优先处理;

中断掩码寄存器:用于屏蔽某些中断,使其不被触发;

 

中断流程

1. 一个或多个中断从IRQ0-7中送入(中断线拉高),对应IRR被置位;

2. 8259A评估这些中断,如果有需要通过INT发送中断给CPU;

3. CPU收到INT之后,发送INTA给8259A;

4. 收到INTA之后,优先级最高的中断对应的ISR位被置位,对应的IRR被复位;

5. CPU再次发送INTA,8259A释放地址线并传输8位中断向量给CPU:

x86架构——8259A中断控制器_第2张图片

这里的中断向量低三位是可变的,高五位不同的片选配置不同,但是是固定的,需要通过ICW2来配置。

6. 中断结束,之后如果是在AEOI模式,ISR对应位会被复位,否者直到收到EOI命令,ISR对应位才会被复位。

 

8259A编程

8259A的编程包括两类,一种是初始化命令字(ICW),用于初始化控制器;另一种是操作命令字(OCW),用于设置模式(初始化之后配置,任何时候都可以修改)。

 

ICW

8259A的初始化需要使用若干个ICW,x86平台下通过特定IO口写入这些ICW来初始化8259控制器。

ICW1在A0=0,D4=1的情况下使用,它启动8259A的自动初始化。

ICW1中还包括其它的配置位,具体如下:

x86架构——8259A中断控制器_第3张图片

ICW1之后是配置ICW2:

x86架构——8259A中断控制器_第4张图片

T7-T3是8259A传输给CPU的中断向量的高5位。

之后是ICW3,它在主片和从片中的配置不同:

x86架构——8259A中断控制器_第5张图片

最后是ICW4,它需要根据ICW1中的某个位来确定是否需要配置:

x86架构——8259A中断控制器_第6张图片

之前提到的AEOI的配置就在这里。

下面是配置的流程:

x86架构——8259A中断控制器_第7张图片

对于级联的情况,我们需要配置其中的每一片。

x86模式下通常使用的是主从两片,对应的初始化代码如下:

  //
  // Set vector base for slave PIC
  //
  if (SlaveBase != mSlaveBase) {
    mSlaveBase = SlaveBase;

    //
    // Initialization sequence is needed for setting vector base.
    //

    //
    // Preserve interrtup mask register before initialization sequence
    // because it will be cleared during initialization
    //
    Mask = IoRead8 (LEGACY_8259_MASK_REGISTER_SLAVE);

    //
    // ICW1: cascade mode, ICW4 write required
    //
    IoWrite8 (LEGACY_8259_CONTROL_REGISTER_SLAVE, 0x11);

    //
    // ICW2: new vector base (must be multiple of 8)
    //
    IoWrite8 (LEGACY_8259_MASK_REGISTER_SLAVE, mSlaveBase);

    //
    // ICW3: slave indentification code must be 2
    //
    IoWrite8 (LEGACY_8259_MASK_REGISTER_SLAVE, 0x02);

    //
    // ICW4: fully nested mode, non-buffered mode, normal EOI, IA processor
    //
    IoWrite8 (LEGACY_8259_MASK_REGISTER_SLAVE, 0x01);

    //
    // Restore interrupt mask register
    //
    IoWrite8 (LEGACY_8259_MASK_REGISTER_SLAVE, Mask);
  }

  //
  // Set vector base for master PIC
  //
  if (MasterBase != mMasterBase) {
    mMasterBase = MasterBase;

    //
    // Initialization sequence is needed for setting vector base.
    //

    //
    // Preserve interrtup mask register before initialization sequence
    // because it will be cleared during initialization
    //
    Mask = IoRead8 (LEGACY_8259_MASK_REGISTER_MASTER);

    //
    // ICW1: cascade mode, ICW4 write required
    //
    IoWrite8 (LEGACY_8259_CONTROL_REGISTER_MASTER, 0x11);

    //
    // ICW2: new vector base (must be multiple of 8)
    //
    IoWrite8 (LEGACY_8259_MASK_REGISTER_MASTER, mMasterBase);

    //
    // ICW3: slave PIC is cascaded on IRQ2
    //
    IoWrite8 (LEGACY_8259_MASK_REGISTER_MASTER, 0x04);

    //
    // ICW4: fully nested mode, non-buffered mode, normal EOI, IA processor
    //
    IoWrite8 (LEGACY_8259_MASK_REGISTER_MASTER, 0x01);

    //
    // Restore interrupt mask register
    //
    IoWrite8 (LEGACY_8259_MASK_REGISTER_MASTER, Mask);
  }

主片对应的IO地址是20h/21h,从片对应的地址是A0h/A1h。

这里需要一对寄存器来处理,并且只有低四字节有差(0和1),这跟前面提到的A0管脚相关。

 

OCW

当ICW初始化8259A控制器之后,它就可以正常接收中断。

不过此后我们还是可以通过OCW来配置8259A的模式。

OCW共有三个。

OCW1用于设置中断屏蔽:

x86架构——8259A中断控制器_第8张图片

OCW2用于设置中断模式:

x86架构——8259A中断控制器_第9张图片

OCW3用于设置屏蔽模式:

x86架构——8259A中断控制器_第10张图片

写入OCW的地址不同:

x86架构——8259A中断控制器_第11张图片

OCW需要使用x1h的地址,其它需要使用x0h的地址。

关于OCW的代码,实在在前面的代码中已经设置了OCW1,后面还会设置OCW2:

  IoWrite8 (LEGACY_8259_CONTROL_REGISTER_SLAVE, LEGACY_8259_EOI);
  IoWrite8 (LEGACY_8259_CONTROL_REGISTER_MASTER, LEGACY_8259_EOI);

目前只设置了EOI,即需要通过CPU发送EOI命令,ISR对应位才会复位。

 

IRQ的使用

老的x86设备中不一般使用主从模式两片8259A控制器,组成的中断控制器中有15个中断:

x86架构——8259A中断控制器_第12张图片

这些中断的作用比较固定,在早起IBM的PC-AT设备中,中断的分配如下:

x86架构——8259A中断控制器_第13张图片

即使到现在,所以8259A不再使用,某些设备的中断还是没有改变,比如串口还是会使用到IRQ4,虽然实现的手段已经不同。

 

以上是对8259A中断控制器的介绍。

由于水平有限,某些说明可能存在问题,请见谅。

 

你可能感兴趣的:(x86,8259,x86架构介绍)