[从 0 开始写一个操作系统] A20 Gate

A20 Gate

作者:解琛
时间:2020 年 9 月 4 日

关于A20 Gate

激活A20地址线详解

Intel 早期的 8086 CPU 提供了 20 根地址线,可寻址空间范围即 0   2 2 0 0~2^20 0 220 (00000H ~ FFFFFH) 的 1MB 内存空间。

但 8086 的数据处理位宽位 16 位,无法直接寻址 1MB 内存空间,所以 8086 提供了段地址加偏移地址的地址转换机制。

PC 机的寻址结构是 segment:offset,segment 和 offset 都是 16 位的寄存器,最大值是 0ffffh。

换算成物理地址的计算方法是把 segment 左移 4 位,再加上 offset,所以 segment:offset 所能表达的寻址空间最大应为 0ffff0h + 0ffffh = 10ffefh。

前面的 0ffffh 是 segment = 0ffffh 并向左移动 4 位的结果,后面的 0ffffh 是可能的最大 offset。

这个计算出的 10ffefh 是多大呢?大约是 1088KB,就是说,segment:offset 的地址表示能力,超过了 20 位地址线的物理寻址能力。

所以当寻址到超过 1MB 的内存时,会发生“回卷”(不会发生异常)。

下一代的基于 Intel 80286 CPU 的 PC AT 计算机系统提供了 24 根地址线,这样 CPU 的寻址范围变为 2 2 4 = 16 M 2^24=16M 224=16M,同时也提供了保护模式,可以访问到 1MB 以上的内存了,此时如果遇到“寻址超过 1MB”的情况,系统不会再“回卷”了,这就造成了向下不兼容。

为了保持完全的向下兼容性,IBM 决定在 PC AT 计算机系统上加个硬件逻辑,来模仿以上的回绕特征,于是出现了 A20 Gate。

他们的方法就是把 A20 地址线控制和键盘控制器的一个输出进行 AND 操作,这样来控制 A20 地址线的打开(使能)和关闭(屏蔽\禁止)。

一开始时 A20 地址线控制是被屏蔽的(总为 0),直到系统软件通过一定的 IO 操作去打开它。

在实模式下要访问高端内存区,这个开关必须打开。

在保护模式下,由于使用 32 位地址线,如果 A20 恒等于0,那么系统只能访问奇数兆的内存,即只能访问 0-1M、2-3M、4-5M…,这显然是不行的,所以在保护模式下,这个开关也必须打开。

当 A20 地址线控制禁止时,则程序就像在 8086 中运行,1MB 以上的地址是不可访问的。

在保护模式下 A20 地址线控制是要打开的。

为了使能所有地址位的寻址能力,必须向键盘控制器 8042 发送一个命令。

键盘控制器 8042 将会将它的的某个输出引脚的输出置高电平,作为 A20 地址线控制的输入。

一旦设置成功之后,内存将不会再被绕回(memory wrapping),这样我们就可以寻址整个 286 的 16M 内存,或者是寻址 80386 级别机器的所有 4G 内存了。

键盘控制器 8042 的逻辑结构图如下所示。

键盘控制器8042的逻辑结构图

早期的 PC 机,控制键盘有一个单独的单片机 8042,现如今这个芯片已经给集成到了其它大片子中,但其功能和使用方法还是一样。

当 PC 机刚刚出现 A20 Gate 的时候,为节省硬件设计成本等考虑,工程师使用这个 8042 键盘控制器来控制 A20 Gate,但 A20 Gate 与键盘管理没有一点关系。

8042 键盘控制器的 IO 端口是 0x60~0x6f,实际上 IBM PC/AT 使用的只有 0x60 和 0x64 两个端口(0x61、0x62 和 0x63 用于与 XT 兼容目的)。

8042 通过这些端口给键盘控制器或键盘发送命令或读取状态。

输出端口 P2 用于特定目的。

位 0(P20引脚)用于实现 CPU 复位操作,位 1(P21 引脚)用户控制 A20 信号线的开启与否。

系统向输入缓冲(端口 0x64)写入一个字节,即发送一个键盘控制器命令,可以带一个参数。

参数是通过 0x60 端口发送的。 命令的返回值也从端口 0x60 去读。

8042 有 4 个寄存器:

  • 1 个 8-bit 长的 Input buffer,Write-Only;
  • 1 个 8-bit 长的 Output buffer,Read-Only;
  • 1 个 8-bit 长的 Status Register,Read-Only;
  • 1 个 8-bit 长的 Control Register,Read/Write。

有两个端口地址,60h 和 64h,有关对它们的读写操作描述如下:

  • 读 60h 端口,读 output buffer;
  • 写 60h 端口,写 input buffer;
  • 读 64h 端口,读 Status Register;
  • 操作 Control Register。
    • 要向 64h 端口写一个命令(20h 为读命令,60h 为写命令);
    • 根据命令从 60h 端口读出 Control Register 的数据;
    • 或向 60h 端口写入 Control Register 的数据(64h 端口还可以接受许多其它的命令)。

Status Register 的定义(要用 bit 0 和 bit 1):

bitmeaning
0output register (60h) 中有数据
1input register (60h/64h) 有数据
2系统标志(上电复位后被置为0)
3data in input register is command (1) or data (0)
41=keyboard enabled, 0=keyboard disabled (via switch)
51=transmit timeout (data transmit not complete)
61=receive timeout (data transmit not complete)
71=even parity rec’d, 0=odd parity rec’d (should be odd)

8042 还有 3 个内部端口:Input Port、Outport Port 和 Test Port。

这三个端口的操作都是通过向 64h 发送命令,然后在 60h 进行读写的方式完成,其中本文要操作的 A20 Gate 被定义在 Output Port 的 bit 1 上,所以有必要对 Outport Port 的操作及端口定义做一个说明。

  • 读 Output Port:向 64h 发送 0d0h 命令,然后从 60h 读取 Output Port 的内容;
  • 写 Output Port:向 64h 发送 0d1h 命令,然后向 60h 写入 Output Port 的数据;
  • 禁止键盘操作命令:向 64h 发送 0adh;
  • 打开键盘操作命令:向 64h 发送 0aeh。

有了这些命令和知识,就可以实现操作 A20 Gate 来从实模式切换到保护模式了。

理论上讲,我们只要操作 8042 芯片的输出端口(64h)的bit 1,就可以控制 A20 Gate。

实际上,当你准备向 8042 的输入缓冲区里写数据时,可能里面还有其它数据没有处理,所以,我们要首先禁止键盘操作,同时等待数据缓冲区中没有数据以后,才能真正地去操作 8042 打开或者关闭 A20 Gate。

打开 A20 Gate 的具体步骤大致如下:

  1. 等待 8042 Input buffer 为空;
  2. 发送 Write 8042 Output Port (P2)命令到8042 Input buffer;
  3. 等待 8042 Input buffer 为空;
  4. 将 8042 Output Port(P2)得到字节的第 2 位置 1,然后写入 8042 Input buffer。
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

解琛

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值