我正在编写一个键盘设备驱动程序。将PIC ICW1配置为端口0x20,将其他ICWS配置为端口0x21,但我不明白为什么我们有两个端口以及它们如何连接到8259芯片上的引脚? >
我已经阅读了手册,但仍然无法理解它与x86处理器上的端口的确切连接方式。
outb(0x20, 0x11); /* send ICW1 */
outb(0xA0, 0x11);
/* send ICW2 */
outb(0x20 + 1, pic1); /* remap */
outb(0xA0 + 1, pic2); /* pics */
/* send ICW3 */
outb(0x20 + 1, 4); /* IRQ2 -> connection to slave */
outb(0xA0 + 1, 2);
/* send ICW4 */
outb(0x20 + 1, 0x01);
outb(0xA0 + 1, 0x01);
答案 0 :(得分:3)
与in
和out
一起使用的端口号位于地址总线中,构成该总线的线已连接到设备。
设备未连接到端口,而是端口是发送到所有设备的号码。
在配置良好的系统中,只有单个设备会对放置在地址总线上的给定编号(端口)做出反应。
当然,这是总线模型的简化视图,从功能的角度来看,这就是PC / XT和ISA总线的工作方式。
8259A的CS引脚必须为低电平才能激活芯片。通过一些逻辑门,仅当地址总线具有一定范围的值时,才可以使该引脚有效。
例如,为了简短起见,假设地址总线为8位宽,如果将地址线A7-A4进行AND运算以形成CS,则8259A将响应范围0xf0-0xff。
简而言之,从计算CS的函数的输入中排除一些地址线,即可创建8259A响应的地址范围。
特别是,排除从A0到An的行,会形成一个连续的大小为2 n 的范围,该范围的起始地址清除了较低的 n 位。
8259A只有两个寄存器,因此我们需要一个大小为2的范围,或者等效地 n 等于1。
因此,A7-A1用于计算CS。请注意,某些架构可能具有 aliasing ,IIRC在ISA总线扩展期间也存在。
如果地址线可以由CPU驱动,但它既未连接到计算CS的块,也未连接到设备,则会发生混淆。
未用于CS的地址线必须用于选择设备内部的寄存器(如果未全部使用,则会发生别名)。
由于8259A只有两个寄存器,因此我们希望在这两个寄存器中选择一个引脚。
实际上,这就是A0引脚的作用:
A0地址线:此引脚与CS,WR和 RD引脚。 8259A使用它来解密各种命令字 CPU写入和CPU希望读取的状态。通常是 连接到CPU A0地址线(用于8086、8088的A1)。
通过使A7-A1线仅在其值(二进制)0010_000时将CS驱动为高电平,并且通过将CPU A0线连接到A0引脚,我们使8259A响应地址0x20和0x21。
____
----A7----O| \ _________
----A7----O| \ | |
----A6----O| )-----CS---| |
... | / | |
----A1----O|____/ | 8259A |
| |
----D7------------------D7---| |
... | |
----D0------------------D0---| |
| |
----A0------------------A0---|_________|
好吧,正确的答案是:因为数据表也是如此。
我的解释是0x21端口用于读/写屏蔽寄存器,因为所有8位都用于8259A的8条IRQ线,因此可写到该端口的所有256个可能值已经有些含义了。
端口0x21后面的逻辑无法确定写入的字节是ICW还是OCW,因此端口0x21无法用于发送ICW1。
要触发ICW1,位4必须为1。这意味着,每当写入端口0x20时位4为1,8259A都会检测到ICW1并进入初始化序列。
由于ICW2和ICW3(对于主机)需要8个位的所有 (包括第4位),因此无法将其发送到端口0x20。
因此ICW2和ICW3必须转到端口0x21。
最后,ICW4也使用了D4,但可以重新设计为不使用它,但是由于前两个ICW使用的是端口0x21,所以它也用于ICW4。
会有所不同吗?当然是。也许有一个命令寄存器和一个数据寄存器(以及掩码寄存器访问权限),但显然在当时该解决方案更易于实现。
它具有较少的端口来解码,并且可能具有较短的DFA以处理设备状态(不过我没有检查)。
我不知道为什么对于8086/8系统,是将地址线A1连接到引脚A0。