早期的硬盘 IDE(Integrated Device Electronics)的读取方式比较复杂,需要分别指定 CHS (cylinder / head / sector,即柱面 / 磁头 / 扇区);后来的磁盘都支持 LBA(Logical Block Addressing,逻辑块寻址)模式,所有扇区都统一编号,只需指出扇区号即可完成访问。
下面介绍在 LBA 的模式下的 PIO(program IO)来实现对磁盘的读取操作。主板有两个 IDE 通道,每个通道可挂载两个硬盘。访问第一个通道的第一个硬盘的扇区使用 IO 地址寄存器(0x1f0~0x1f7);访问第二个硬盘使用的是(0x1f8~0x1ff)。访问第二个通道的硬盘分别使用(0x170-0x177)和(0x178-0x17f)。我们以第一个通道的第一个硬盘为例,说明 IO 端口寄存器的作用(注意选取本通道的主/从硬盘由第六个寄存器决定):
对照上述定义,我们查看系统启动时载入内核的代码,从 readsect() 函数中可以看出 0x1f2
标识读入一个扇区,0x1f3~0x1f5
给出的是 LBA 的第 0~23 位,0x1f6 为 0xE0(0x1110-0000)标识 LBA 模式访问第一个 IDE 控制器上的第一块(编号为 0)的硬盘, 且 LBA 的第 24~27 位为 0x0000。然后才通过 outb(0x1F7, 0x20)
发出 0x20 的读命令,并通过 waitdisk() 等待磁盘空闲,最后通过 insl(0x1F0, dst, SECTSIZE/4)
读入整个扇区的数据,由于一次读入四字节,因此使用 SECTSIZE/4 次 IO 操作。
注意,IDE 驱动程序中并没有使用 DMA 方式,有兴趣的读者可以将代码修改为支持 DMA 方式以提升系统效率,IDE 相关实现代码在 ide.c。