我目前正在开发一个爱好操作系统,特别是ATA驱动程序。我在使用带有中断的PIO数据输入命令时遇到了一些问题。我正在尝试执行READ MULTIPLE命令,逐块地从驱动器中读取多个扇区,每个块都有一个中断触发。
如果我请求读取4个块(每个块1个扇区)。我希望得到4个中断,每个数据块一个。收到第4个中断后,我可以识别出我已经传输了所有数据并相应地更新了我的请求结构。但是,在VirtualBox中,我发现在传输完最后一个数据块后,我收到了另一个中断(STATUS = 0x50,READY,OVERLAPPED MODE SERVER REQ)。我可以简单地读取STATUS寄存器然后清除它,但我不认为我应该根据规格接收第5个中断。
那么确认ATA设备发出的中断的正确方法是什么?
在此示例中,我发出READ MULTIPLE命令,然后我的ISR执行以下操作:
PIO数据输入命令协议的ATA规范并未指示您需要来读取状态寄存器。由此我假设当我收到中断时,我所要做的就是遵循协议并通过将EOI发送到PIC完成。至于nIEN的设置/清除,在处理VirtualBox时我发现如果我不这样做,我就不会收到任何超过第一个的中断。所以我在进入ISR时设置了nIEN,然后在我离开之前将其清除。我认为这不会有任何影响,但它必须与读/写特定寄存器有关。
答案 0 :(得分:5)
这总是发生在我身上,我发布了一个我一直在努力的问题,但不久之后我就找到了答案。
我参考的ATA-6规范在PIO数据输入部分(9.5)中有这一行:
当处于此状态时,主机应读取设备状态寄存器。
使用ATA时,状态寄存器会产生副作用:它会清除挂起的中断。我知道这一点,但我之前没有正确阅读过这部分内容。它没有提到为什么你应该阅读寄存器,它只是如上所述。
重要的部分是如何使用中断处理程序。在发出PIO数据输入命令后,一旦INTRQ被置位,您只需读取状态寄存器一次以清除中断,然后继续处理中断并正常返回(只是将EOI发送到PIC。)让我困惑的是什么是因为我读到的文档都没有提到这应该如何处理中断(接收INTRQ,读取状态,处理中断。)大多数在线指南只处理轮询IO。
这是低级编程的难点之一,关键细节(例如需要读取ISR中的状态寄存器)经常被浏览过。这个在协议描述中保留为单行。叫我挑剔,但我本来希望更多地强调这一点。