x58添加uefi_在看UEFI CODE

efi code里面有关于init 8259的code,也就是legacy8259protocol的实作

对8259的编程,我们是对其相应端口发送ICW(初始化命令字)来完成的,

总共需要发送4个ICW,而且必须按次序发送,这里提一下8259a编程的一些东西,2片8259a级连,一个为主片,一个为从片,从片的INT端口与主片的IRQ2相连,主片的访问端口为0x20和0x21,从片为0xa和0xa1

在legacy bios中IRQ0-IRQ7被分配了0x8-0xf的中断矢量(中断号),

IRQ-8-IRQF

被分配为0x70-0x78,这也可以看做是实模式下是这样来分的,但当cpu转到保护模式的时候,中断号0x8-0xf都被cpu用来处理错误了,所以我们必须从新对8259进行编程,设置中断号的起始地址,

EFI_LEGACY_8259_PROTOCOL 中的SetVectorBase就是干这种事情的,

从字面的意思也可以看出来,“设置中断矢量的基地址”

在EFI BIOS中我们将master interrupt base 设置为0x58,slave interr

base设置为0x70,linux中我们是将master interrupt base设置0xf0,slave设置为0xf8

设置这些base address的时候,我们就要对8259进行编程,也就是要发四个ICW了

EFI_STATUS SetVectorBase(

IN

EFI_LEGACY_8259_PROTOCOL *This,

IN UINT8

MasterBase,

IN UINT8

SlaveBase

)

{

//8259 Master

if (MasterBase != gMasterBase)

{

IoWrite8(0x20,ICW1); //Start

8259 Master Initialization.

IoWrite8(0x21,MasterBase); //Set

Interrupt Offset

IoWrite8(0x21,ICW3_M); //Set

Slave IRQ.

IoWrite8(0x21,ICW4); //Set

8259 mode. See ICW4 comments with #define.

gMasterBase = MasterBase;

}

//8259 Slave

if (SlaveBase != gSlaveBase)

{

IoWrite8(0xa0,ICW1); //Start

8259 Slave Initialization.

IoWrite8(0xa1,SlaveBase); //Set

Interrupt Offset

IoWrite8(0xa1,ICW3_S); //Set

Slave IRQ.

IoWrite8(0xa1,ICW4); //Set

8259 mode. See ICW4 comments with #define.

gSlaveBase = SlaveBase;

}

return EFI_SUCCESS;

}

ICW1:发送到0x20(主片)及0xa0(从片)端口

7 6 5 4 3 2 1 0

0 0 0 1 M 0 C I

I 位:若置位,表示ICW4 会被发送。(ICW4 等下解释)

C 位:若清零,表示工作在级联环境下。

M 位:指出中断请求的电平触发模式,在PC 机中,它应当被置零,表示采用“边沿触发模

式”。

ICW2:发送到0x21(主片)及0xa1(从片)端口

7 6 5 4 3 2 1 0

A7 A6 A5 A4 A3 0 0 0

ICW2 用来指示出IRQ0 使用的中断号是什么,因为最后三位均是零,因此要求IRQ0 的中

断号必须是8,的倍数,这又是一个很巧妙的设计。因为IRQ1 的中断号就是IRQ0 的中断

号+1,IRQ2 的中断号就是IRQ0 的中断号+2,……,IRQ7 的中断号就是IRQ0 的中断号+1,

刚好填满一个8 个的中断向量号空间。

ICW3:发送到0x21(主片)及0xa1(从片)端口

ICW3 只有在级联工作的时候才会被发送,它主要用来建立两处PIC 之间的连接,对于主片

与从片,它结构是不一样的。

(主片结构:)

7 6 5 4 3 2 1 0

IRQ7 IRQ6 IRQ5 IRQ4 IRQ3 IRQ2 IRQ1 IRQ0

上面,如果相应的位被置1,则相应的IRQ 线就被用于与从片连接,若清零则表示被连接到

外围设备。

(从片结构:)

7 6 5 4 3 2 1 0

0 0 0 0 0 IRQ

IRQ 位指出了是主片的哪一个IRQ 连到了从片,这需要同主片上发送的上面的主片结构字

一致。

ICW4:发送到0x21(主片)及0xa1(从片)端口

7 6 5 4 3 2 1 0

0 0 0 0 0 0 EOI 80x86

80x86 位:若置位表示工作在80x86 架构下。

EOI 位:若置位表示自动结束,在PC 上这位需要被清零。

在EFI BIOS code中的定义为

#define

ICW1 0x11

#define

ICW3_M 1<<2

#define

ICW3_S 2

#define

ICW4 1

与上面的说明是一致的

EFI_LEGACY_8259_PROTOCOL中SetMode这个function,是设置现在的8259处于实模式还是处于保护模式下,要中断屏蔽那些IRQ,中断触发的方式是什么样的(边沿还是水平)

其中这个会用到2个全局变量

UINT16 gIrqMask[2] =

{0xffff,0xffff}; UINT16 gIrqTrigger[2] =

{0,0}; 一个是控制中断屏蔽regisgter的,一个是控制中断触发的方式,数组为2,一个用于real

mode,一个用于protect mode

看一下setmode的函数实作

EFI_STATUS SetMode(

IN

EFI_LEGACY_8259_PROTOCOL *This,

IN

EFI_8259_MODE Mode,

IN UINT16

*Mask

OPTIONAL,

IN

UINT16 *EdgeLevel OPTIONAL

)

{

if (Mode >= Efi8259MaxMode) return

EFI_INVALID_PARAMETER;

gMode = Mode;

if (Mask) gIrqMask[Mode] = *Mask;

if (EdgeLevel) gIrqTrigger[Mode] =

*EdgeLevel;

ProgramIrqMaskTrigger();

return EFI_SUCCESS;

}

可以猜想 ProgramIrqMaskTrigger()就是操作8259

register的函数

VOID ProgramIrqMaskTrigger()

{

IoWrite8(0x21,(UINT8)gIrqMask[gMode]);

IoWrite8(0xa1,(UINT8)(gIrqMask[gMode]>>8));

//

// 4d0 can not be accessed as by IoWrite16, we

have to split

//

IoWrite8(0x4d0,(UINT8)gIrqTrigger[gMode]);

IoWrite8(0x4d1,(UINT8)(gIrqTrigger[gMode]>>8));

}

其中

IoWrite8(0x21,(UINT8)gIrqMask[gMode]);

IoWrite8(0xa1,(UINT8)(gIrqMask[gMode]>>8));

为操作8259a OCW命令register

OCW1:中断屏蔽,发送到0x21(主片)或0xa1(从片)端口

7 6 5 4 3 2 1 0

IRQ7 IRQ6 IRQ5 IRQ4 IRQ3 IRQ2 IRQ1 IRQ0

如果相应的位置1,则表示屏蔽相应的IRQ 请求。

EFI_LEGACY_8259_PROTOCOL中GetMask和SetMask,也是操作mask和trigger的,原理和以上相同

GetVector字面意思,得到中断号,也就是上面说的我们设置IRQ0对应的中断号为0x58,我们现在要得到这个0x58,就靠这个函数了,无非就是倒过来运算而已

Master的IRQ对应得中断好号为IRQ+masterbase

Slave上的IRQ为IRQ+slavebase-8 而已

EnableIRQ() DisableIRQ()这些函数的都是操作OCW1

GetInterruptLine()为读配置空间,得到IRQ编号

EndOfInterrupt()在中断处理函数里面发送EOI命令

如果 EOI 被设为自动的,那么ISR 中的位总是被清零的(在EOI 被置位的情况下,8259A

只要向CPU 发送了中断号就会将ISR 中的相应位清零),也就是如果有中断来,芯片就会马

上再向CPU 发出中断请求,即使CPU 正在处理IRQ0 的中断,CPU 并不知道谁的优先级高,

它只会简单的响应8259A 送来的中断,因此,这种情况下低优先级的中断就可能会中断高

优先级的中断服务程序。所以在PC 中,我们总是将EOI 位清零,而在中断服务程序结束的

时候才发送EOI 消息。

注意一点,发EOI命令的时候,先发送给从片,再发送给主片

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值