为什么我们在初始化 PIC(8259) 时将 ICW 1 分配给端口 0x20 而将其他 ICWS 分配给端口 0x21?

why do we give ICW 1 to port 0x20 but other ICWS to port 0x21 when initializing a PIC(8259)?

我正在写一个键盘设备 driver.While 配置 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);

inout一起使用的端口号放置在地址总线中,使该总线的线路连接到设备。
设备没有连接到端口,端口是发送给所有设备的数字。
在配置良好的系统中,只有单个设备对地址总线上的给定数字(端口)做出反应。
当然,这是总线模型的简化视图,从功能的角度来看,这就是 PC/XT 和 ISA 总线的工作方式。


8259A 的 CS 引脚必须处于低电平才能激活芯片。通过一些逻辑门,只有当地址总线具有一定范围的值时,才能使该引脚有效。
例如,为了简洁起见,假设地址总线是 8 位宽,如果地址线 A7 - A4 被“与”在一起形成 CS,那么 8259A 将响应范围 0xf0 - 0xff。
简而言之,从计算 CS 的函数的输入中排除一些地址行会创建 8259A 响应的地址范围。
特别是,排除从 A0 到 An 的行会形成一个大小为 2n 的连续范围,其起始地址的低 n 位已清除。

8259A 只有两个寄存器,所以我们需要一个大小为 2 的范围,或者等效地 n 等于 1。
因此,A7 - A1 用于计算 CS。请注意,某些体系结构可能具有 别名,IIRC 这在 ISA 总线扩展期间也存在。
如果地址线可以由 CPU 驱动,但它既未连接到计算 CS 的块,也未连接到设备,则会发生混叠。

不用于 CS 的地址线必须用于 select 设备内部的寄存器(如果不是全部使用,就会出现别名)。
由于 8259A 只有两个寄存器,我们希望这两个寄存器之间有一个引脚 select。
事实上,这就是 A0 引脚的作用:

A0 ADDRESS LINE: This pin acts in conjunction with the CS, WR, and RD pins. It is used by the 8259A to decipher various Command Words the CPU writes and status the CPU wishes to read. It is typically connected to the CPU A0 address line (A1 for 8086, 8088).

通过使 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---|_________|

为什么 ICW1 转到 0x20 而其他 ICW 转到 0x21

嗯,正确答案是:因为数据表中确实如此。
我的解释是 0x21 端口用于 read/write 屏蔽寄存器,因为所有 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。