Maray中对8259A PIC的初始化代码

2019-04-15 13:41发布

学习接口,才发现原来做的很多事情是在对接口在编程:( 捡起到处凑出来的代码看看,唉,其实真的很简单! 重新写了些注释,为后来人铺路~
/**//*
Name:irq.c
Copyright:GPL
Author:Raywill
Date:22-12-06
Description:init,disableandenableinterruptprocedure
*/


#ifndefIRQ1_PORT
#defineIRQ1_PORT
0x21
#defineIRQ2_PORT
0xA1
#endif
/**//*
关于8259A
1.8259A是PC中管理中断的芯片。在实际PC主板中并不能找到8259,
这是因为它被集成到了一个大规模芯片中去了,其可提供的功能于8259等价
作为OSer,我们我们完全可以当做PC中含有8259芯片。

2.8259工作前需要对其初始化,包括
1)中断请求方式的设定(ICW1)
2)中断类型号的设定(ICW2)
3)中断级联方式的设定(ICW3)
4)特定完全嵌套方式(ICW4)

3.PIC端口地址
MasterPICcommand0x20
MasterPICdata0x21
SlavePICcommand0xA0
SlavePICdata0xA1

4.对init_irq()函数中的操作的解释
==========================================
outportb(0x20,0x11);
*)对ICW1编程使用20H号端口(A0=0)
*)11H=00010001B
D7-D5000中断向量地址的A7~A5
D4=1
D30边缘出发输入
D20调用间隔为8
D10级联方式
D01要写ICW4

==========================================

outportb(0x21,irq0_int);
outportb(0xA1,irq8_int);

*)对ICW2编程使用21H号端口(A0=1)
*)irq0_int=20H=00100000B
D7-D300100中断类型号高5位100000=20H
经过这一步后,IR0对应的中断号码为100000B=20H
IR1对应的中断号码为100000B=21H
·······
IR7对应的中断号码为100000B=27H
D2-D0000低三位中断类型号,由硬件IR0~IR7提供
*)irq8_int=28H=00101000B;
D7-D300101中断类型号高5位101000=28H
经过这一步后,IR8对应的中断号码为100000B=28H
IR9对应的中断号码为100000B=29H
·······
IR15对应的中断号码为100000B=2FH
D2-D0000低三位中断类型号,由硬件IR8~IR15提供

==========================================

outportb(0x21,0x04);//对主片(Master)编程
outportb(0xA1,0x02);//对从片(Slave)编程
*)对ICW3编程使用21H号端口(A0=1)
*)只有配置成为级联模式才需要设置ICW3
*)主片和从片的ICW各位表示的含义不同
*)主片
04H=00000010B
1)D7-D000000010INT级联掩码,第二位S1=1表示从片是通过IR1引脚连接到主片的
*)从片
02H=00000010
1)D7-D300000保留不用,全置零
2)D2-D0010表示本从片的INT信号连接到主片的第几个引脚,
010B表示2号引脚,和主片中的04H正好对应

==========================================

outportb(0x21,0x01);
outportb(0xA1,0x01);
*)01H=00000001
D7-D5000强制为0
D40非特殊全嵌套方式
D3-D200非缓冲方式
D10正常EIO(需要在中断末尾加入中断结束命令)
D01MCS8086/88模式

==========================================

5.对上面过程的总结
init_irq主要做了下面几件事:
1)重定向中断向量位置
Thedefault(BIOS-defined)vectoroffsetsare8forMasterPICand0x70forSlavePIC:
Master:IRQ0..7->INT8..0xF(vectoroffset=0x08)
Slave:IRQ8..15->INT0x70..0x77(vectoroffset=0x70)
However,thesedefaultvaluesdon'tsuittheneedsofProtectedModeprogramming:there'sacollisionbetweenIRQs0..7(mappedtoINT8..0xF)andprocessorexceptions(INT0..0x1Farereserved).Consequentlyyouwouldn'tbeabletotellthedifferencebetweenanIRQoransoftwareerror.
2)对级联进行编程,确定工作模式

6.ICW初始化完成后,就可以对PIC发OCW命令字了用来初始化中断屏蔽字
MasterPICdata0x21
SlavePICdata0xA1
Di=1为关i对应中断,Di=0为关闭对应中断
Maray中代码为:
//DisableAllInterruptFirst
outportb(0x21,~0x00);
outportb(0xA1,~0x00);
*/

voidinit_irq()
...{
staticconstunsignedirq0_int
=0x20,irq8_int=0x28;
/**//**/

/**//*InitializationControlWord#1(ICW1)*/
outportb(
0x20,0x11);
outportb(
0xA0,0x11);
/**//*ICW2:
routeIRQs0-7toINTs20h-27h
*/

outportb(
0x21,irq0_int);
/**//*routeIRQs8-15toINTs28h-2Fh*/
outportb(
0xA1,irq8_int);
/**//*ICW3*/
outportb(
0x21,0x04);
outportb(
0xA1,0x02);
/**//*ICW4*/
outportb(
0x21,0x01);
outportb(
0xA1,0x01);
/**//*enableIRQ0(timer)andIRQ1(keyboard)*/
outportb(
0x21,~0x00);/**//*onlykeyboardfortesting*/
outportb(
0xA1,~0x00);

kprintf(
"8259initOK! ");
}


voidenable_irq(intirq)
...{
/**//*twocase:irq<8,irq>=8*/
bytebit=1;

if(irq>(15+IRQ_OFFSET)||irq<(0+IRQ_OFFSET))return;

bit
<<=irq%8;
if(irq<(8+IRQ_OFFSET))...{
outportb(IRQ1_PORT,
~bit&inportb(IRQ1_PORT));
}
else...{
outportb(IRQ2_PORT,
~bit&inportb(IRQ2_PORT));
}

}


voiddisable_irq(intirq)
...{
/**//*twocase:irq<8,irq>=8*/
bytebit=1;

if(irq>(15+IRQ_OFFSET)||irq<(0+IRQ_OFFSET))return;

bit
<<=irq%8;
if(irq<(8+IRQ_OFFSET))...{
outportb(IRQ1_PORT,bit
|inportb(IRQ1_PORT));
}
else...{
outportb(IRQ2_PORT,bit
|inportb(IRQ2_PORT));
}

}