【发布时间】:2021-04-09 08:13:45
【问题描述】:
IDE PATA 接口:0x1F7 寄存器在读取时用作状态寄存器,在写入时用作命令寄存器。
但是,如果我首先编写一个命令(即 0x20 )来告诉设备我想向它写入一些东西,那么下一条指令我会读取 reg 以查找状态。是否有可能该 reg 上的位仍然是 0x20 而不是我想要的状态位?
【问题讨论】:
IDE PATA 接口:0x1F7 寄存器在读取时用作状态寄存器,在写入时用作命令寄存器。
但是,如果我首先编写一个命令(即 0x20 )来告诉设备我想向它写入一些东西,那么下一条指令我会读取 reg 以查找状态。是否有可能该 reg 上的位仍然是 0x20 而不是我想要的状态位?
【问题讨论】:
虽然端口地址相同,但内部有两个寄存器,一个命令寄存器和一个状态寄存器。一条输出指令写入命令寄存器,一条输入指令从状态寄存器读取。
【讨论】:
I/O 端口不像一个普通的内存位置。读写是独立的事务;一个不能开始,直到前一个完成。 (这也是编程 IO 如此缓慢的部分原因)。此外,正如@rcgldr 解释的那样,在这种情况下,两个寄存器恰好共享相同的端口号,但由于一个是只读的,另一个是只写的,因此它们可以通过“方向”消除歧义。
事实上,每次读取都保证是单独可见的:例如从同一个 IO 端口重复读取可以为您提供来自硬件缓冲区的数据。 (事实上,这就是 PIO 而不是 DMA 在读取数据响应读取请求时的工作方式。)因此,从同一个寄存器中的每次读取都会产生副作用,并且必须在设计硬件时考虑到这一点。
这种单独事务的东西甚至也适用于不可缓存内存(物理地址空间)中的 MMIO 寄存器,而不仅仅是 IO 地址空间(可通过 in / out 指令访问) - 将其映射为不可缓存可确保CPU 不会在内部进行存储-> 负载转发。但是对于in/out 指令,这绝对不会发生。 (MMIO 与 in/out 不同,它确实允许一些流水线操作,但每个 CPU 写入和读取都保证对硬件单独可见。)
【讨论】: