forked from StevenBaby/onix
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
0836a23
commit 3b96094
Showing
6 changed files
with
137 additions
and
14 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
# 硬盘异步 PIO | ||
|
||
由于同步状态检测,消耗了大量的 CPU 资源,所以可以使用异步的方式来等待硬盘驱动器。给驱动器发送完读写命令后,进程可以进入阻塞态,当驱动器完成一个扇区的操作 (读/写) 时,会发送中断,可以在中断中恢复进程到就绪态,继续执行。 | ||
|
||
--- | ||
|
||
## 中断 | ||
|
||
注意:当命令以错误结束时,它不会生成 IRQ。每秒检查几次备用状态寄存器是明智的,以查看是否设置了 ERR 位。否则,直到命令超时您才会知道。 | ||
|
||
--- | ||
|
||
## 处理中断 | ||
|
||
在早期,IRQ 的唯一目的是通知 IRQ 处理程序驱动器已经准备好发送或接受数据。我们的期望是 IRQ 处理程序本身将立即对下一个数据块执行基于 PIO 的数据传输。现在事情没那么简单了。总线上的一个或两个驱动器可能处于 DMA 模式,或者数据块大小不是 256 个 16 位值。此外,现在更强调以尽可能快的速度从 IRQ 处理程序例程中返回。所以问题是:IRQ处理程序需要做的最小操作集是什么? | ||
|
||
如果您正在使用 IRQ 共享,您将需要检查 PCI 总线主状态字节,以验证 IRQ 来自磁盘。如果是这样,就需要读取常规状态寄存器一次,以使磁盘清除其中断标志。如果状态寄存器中的 ERR 位被设置(位 0,值 = 1),您可能想从错误 IO 端口(主总线上 0x1F1)读取并保存 **错误详细信息** 值。 | ||
|
||
如果传输是一个 READ DMA 操作,则必须从总线主状态寄存器读取值。因为 IRQ 处理程序可能不知道操作是否是 DMA 操作,所以在所有 IRQ 之后 (如果总线是由 PCI 控制器控制的,几乎肯定是这样),您可能会检查 Busmaster Status 字节。如果该字节设置了 ERR 位(位 1,值 = 2),您可能希望将当前值保存在磁盘的 LBA IO 端口中,它们可以告诉您驱动器上哪个扇区生成了错误。您还需要清除错误位,方法是向其写入一个 2。 | ||
|
||
您还需要向两个 PIC 发送 EOI (0x20),以清除它们的中断标志。然后,您需要设置一个标志来“解除”驱动程序,并让它知道发生了另一个 IRQ ——这样驱动程序就可以进行任何必要的数据传输。 | ||
|
||
注意:如果你仍然处于单请求模式,并且只在 PIO 模式下轮询常规状态寄存器,那么 IRQ 处理器需要做的唯一一件事就是向 PCI 发送 EOI。您甚至可能想要设置控制寄存器的 nIEN 位,以尝试完全关闭磁盘 IRQ。 | ||
|
||
--- | ||
|
||
## 轮询状态 VS 中断 | ||
|
||
当驱动发出 PIO 读写命令时,需要等待驱动准备好后才能传输数据。有两种方法可以知道驱动器何时准备好接收数据。当它就绪时,驱动器将发送一个 IRQ。或者,驱动程序可以轮询其中一个状态端口(常规或备用状态)。 | ||
|
||
轮询有两个优点: | ||
|
||
- 轮询的响应速度比 IRQ 快 | ||
- 轮询的逻辑比等待 IRQ 简单得多 | ||
|
||
还有一个巨大的缺点: | ||
|
||
- 在多任务环境中,轮询会耗尽所有CPU时间 | ||
- 但是,在单请求模式下,这不是问题(CPU 没有更好的事情可做),所以轮询是一件好事 | ||
|
||
如何轮询(等待驱动器准备传输数据): | ||
|
||
- 读取常规状态端口,直到第 7 位(BSY,值= 0x80)清除,和第 3 位(DRQ,值= 8)设置 | ||
- 或直到第 0 位(ERR,值= 1) 或 第 5 位(DF,值= 0x20)设置。 | ||
- 如果两个错误位都没有设置,那么设备就已经准备好了 | ||
|
||
--- | ||
|
||
## 抢占/防止中断触发 | ||
|
||
如果驱动程序在向驱动器发送命令后读取了常规状态端口,则 **响应** IRQ 可能永远不会发生 | ||
|
||
如果您想要接收 IRQs,那么总是读取 **备用状态端口**,而不是常规状态端口。但有时 IRQ 只是浪费资源,让它们消失可能是一个好主意。 | ||
|
||
防止 ATA IRQs 发生的更完整的方法是在特定选定驱动器的控制寄存器中设置 nIEN 位。这应该会阻止总线上的驱动器发送任何 IRQs,直到你再次清除该位。 | ||
|
||
然而,它可能并不总是有效,一些程序员报告了 nIEN 运行时的问题。当 nIEN 是总线上的选定驱动器时,驱动器只响应新写入的 nIEN 值。 | ||
|
||
也就是说,如果选择了一个驱动器,并且您设置了 nIEN,然后选择带有驱动器选择寄存器的另一个驱动器,然后清除 nIEN ——然后第一个驱动器应该永远“记住”它被告知不要发送 irq ——直到您再次选择它,并在控制寄存器中写入一个 0 到 nIEN 位。 | ||
|
||
### 读写多块 | ||
|
||
在多任务 PIO 模式下,尝试减少 IRQ 数量的一种方法是使用 READ MULTIPLE (0xC4) 和 WRITE MULTIPLE (0xC5) 命令。这 | ||
|
||
些命令使驱动器缓冲区的扇区“块”,并且每个块只发送一个 IRQ,而不是每个扇区发送一个 IRQ。参考 IDENTIFY 命令的 uint16_t 47 和 59 来确定一个块中扇区的数量。您还可以尝试使用 SET MULTIPLE MODE (0xC6) 命令来更改每个块的扇区。 | ||
|
||
注意:总的来说,PIO 模式是一种慢速传输方式。在实际工作条件下,几乎任何驱动器都应该由 DMA 驱动器控制,而不应该使用 PIO。试图通过抢占 IRQ(或任何其他方法)来加快 PIO 模式的速度基本上是在浪费时间和精力。但是,400MB 或更小的 ATA 驱动器可能不支持多字 DMA 模式0。如果您希望支持这种大小的驱动器,那么在 PIO 模式驱动程序上花点功夫可能是值得的。 | ||
|
||
## 参考文献 | ||
|
||
- <https://wiki.osdev.org/PCI_IDE_Controller> | ||
- Information Technology - AT Attachment - 8 ATA/ATAPI Command Set (ATA8-ACS) | ||
- <https://wiki.osdev.org/ATA_PIO_Mode> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters