好的,以下是通过直接访问硬盘 I/O 端口进行硬盘控制的详细完整内容,包括 I/O 端口结构表、寄存器的作用及使用方法,以及具体的操作步骤。这将帮助您理解如何在不使用 BIOS 中断的情况下进行硬盘的低级读写操作。
硬盘 I/O 端口结构表(主 IDE 通道)
硬盘控制器在主 IDE 通道上拥有一组固定的 I/O 端口,用于实现硬盘的底层操作。以下是这些端口的详细结构。
端口地址 | 寄存器名称 | 位宽 | 读/写 | 作用描述 |
---|---|---|---|---|
0x1F0 |
数据寄存器 | 16 位 | 读/写 | 用于数据传输,每次传输 16 位(2 字节)。 |
0x1F1 |
错误/特征寄存器 | 8 位 | 读/写 | 读模式下为错误寄存器,写模式下为特征寄存器,配置硬盘操作特性。 |
0x1F2 |
扇区计数寄存器 | 8 位 | 读/写 | 指定要读/写的扇区数量。0 表示 256 个扇区。 |
0x1F3 |
LBA 地址低 8 位 | 8 位 | 读/写 | 指定 LBA 地址的低 8 位。 |
0x1F4 |
LBA 地址中间 8 位 | 8 位 | 读/写 | 指定 LBA 地址的中间 8 位。 |
0x1F5 |
LBA 地址高 8 位 | 8 位 | 读/写 | 指定 LBA 地址的高 8 位。 |
0x1F6 |
驱动器/头寄存器 | 8 位 | 读/写 | 用于选择驱动器和磁头,以及 LBA 地址的 24-27 位。 |
0x1F7 |
命令/状态寄存器 | 8 位 | 读/写 | 读模式下为状态寄存器,写模式下为命令寄存器。 |
辅助控制端口
端口地址 | 寄存器名称 | 位宽 | 读/写 | 作用描述 |
---|---|---|---|---|
0x3F6 |
驱动器控制寄存器 | 8 位 | 写 | 控制硬盘的复位、禁用中断等操作。 |
0x3F6 |
驱动器地址寄存器 | 8 位 | 读 | 读取当前驱动器状态。 |
各寄存器的功能说明
数据寄存器(
0x1F0
):- 用于硬盘和 CPU 之间的数据传输,读操作时从此端口读取数据,写操作时将数据写入此端口。
错误/特征寄存器(
0x1F1
):- 读模式:显示上次命令的错误信息,包括坏块(BB)、命令被中止(ABRT)等。
- 写模式:配置硬盘特性,指定一些操作参数。
扇区计数寄存器(
0x1F2
):- 用于指定本次读/写操作的扇区数量。写入
0
表示操作 256 个扇区。
- 用于指定本次读/写操作的扇区数量。写入
LBA 地址寄存器(
0x1F3
-0x1F5
):- 用于指定要访问的 LBA 地址,分别为低 8 位、中 8 位和高 8 位。
驱动器/头寄存器(
0x1F6
):- 位 6:设置为
1
表示使用 LBA 模式。 - 位 5:选择驱动器,0 表示主盘,1 表示从盘。
- 位 0-3:存放 LBA 地址的 24-27 位。
- 位 6:设置为
命令/状态寄存器(
0x1F7
):- 读模式:提供硬盘状态信息,包括忙碌(BSY)、数据请求(DRQ)等状态。
- 写模式:用于发送命令给硬盘,例如
0x20
表示读命令,0x30
表示写命令。
辅助控制端口(
0x3F6
):- 控制硬盘的复位、中断禁用等操作。
硬盘读写操作步骤
通过 I/O 端口控制硬盘的操作主要包括读和写两个步骤,以下是这两个操作的详细流程:
读取扇区操作
- 等待硬盘空闲:读取
0x1F7
状态寄存器的BSY
位,等待该位清零,表示硬盘空闲。 - 指定扇区数量:将要读取的扇区数写入
0x1F2
扇区计数寄存器。 - 设置 LBA 地址:依次向
0x1F3
、0x1F4
和0x1F5
写入 LBA 地址的低、中、高字节,将 LBA 的高 4 位写入0x1F6
驱动器/头寄存器。 - 选择驱动器并发出读命令:在
0x1F7
中写入0x20
(读命令)。 - 等待数据准备:读取
0x1F7
中的DRQ
位,等待该位被置位,表示数据准备就绪。 - 读取数据:从
0x1F0
数据寄存器读取数据,每次读取 2 字节(16 位),直到读取完指定的扇区数。
示例代码:读取一个扇区
以下是汇编代码示例,从硬盘读取一个扇区数据到指定内存位置:
mov dx, 0x1F6 ; 设置驱动器和头
mov al, 0xE0 ; LBA 模式,选择主盘
out dx, al
mov dx, 0x1F2 ; 设置扇区计数
mov al, 1 ; 读取一个扇区
out dx, al
mov dx, 0x1F3 ; 设置 LBA 低字节
mov al, LBA_low ; LBA 地址的低 8 位
out dx, al
mov dx, 0x1F4 ; 设置 LBA 中字节
mov al, LBA_mid ; LBA 地址的中 8 位
out dx, al
mov dx, 0x1F5 ; 设置 LBA 高字节
mov al, LBA_high ; LBA 地址的高 8 位
out dx, al
mov dx, 0x1F7 ; 写入读命令
mov al, 0x20 ; 读命令
out dx, al
.wait_drq:
in al, dx ; 检查 DRQ 位
test al, 0x08 ; 检查 DRQ 位
jz .wait_drq ; 如果 DRQ 未置位,等待
mov dx, 0x1F0 ; 读取数据
in ax, dx ; 从数据端口读取 16 位
写入扇区操作
- 等待硬盘空闲:读取
0x1F7
,检查BSY
位是否清零。 - 指定扇区数量:将要写入的扇区数写入
0x1F2
。 - 设置 LBA 地址:依次向
0x1F3
、0x1F4
和0x1F5
写入 LBA 地址,将 LBA 的高 4 位写入0x1F6
。 - 选择驱动器并发出写命令:向
0x1F7
写入0x30
(写命令)。 - 等待数据请求:读取
0x1F7
中的DRQ
位,等待数据请求信号。 - 写入数据:向
0x1F0
数据寄存器写入数据,每次写入 2 字节,直到写入完指定的扇区数。
总结
通过直接访问硬盘 I/O 端口,可以在不调用 BIOS 中断的情况下
直接进行硬盘控制。主要的寄存器包括数据传输、错误检测、扇区计数和地址控制等。读写操作依赖于状态寄存器的 BSY
和 DRQ
位来同步硬盘的状态。掌握这些步骤后,可以在操作系统开发或嵌入式系统中灵活地实现硬盘的底层读写操作。