我目前正在阅读Linux设备驱动程序一书,发现了从I/O内存读取的功能:
要从I/O内存中读取,请使用以下操作之一:
unsigned int ioread8(void *addr);
unsigned int ioread16(void *addr);
unsigned int ioread32(void *addr);
如果必须向给定的I/O内存地址读取或写入一系列值,则可以使用函数的重复版本:
void ioread8_rep(void *addr, void *buf, unsigned long count);
void ioread16_rep(void *addr, void *buf, unsigned long count);
void ioread32_rep(void *addr, void *buf, unsigned long count);
这些函数从给定的buf
向给定的addr
读取或写入count
值。注意,CCD_ 10以正在写入的数据的大小来表示;ioread32_rep
从buf
开始读取count
的32位值。
我在驱动程序代码中使用了ioread64()
和iowrite64()
,用于读取和写入内存映射IO寄存器(8字节(。iowrite64()
可以工作,但iowrite64()
函数永远不会返回,我的虚拟机(QEMU(冻结了——我所能做的就是重新启动。我使用GDB进行远程调试,但没有显示错误消息。通过检查主机上的dmesg,也没有显示错误消息。有关详细信息,请参阅此问题。
由于我找不到ioread64()
失败的原因,我想我可以使用ioread32_rep()
。
通过搜索内核驱动程序代码,我注意到ioread32_rep()
的大多数用例都是设备中的一些缓冲区(例如,那些处理流数据的网络设备(。如果我可以用ioread32_rep()
代替ioread64()
,只读取一个8字节的内存映射寄存器,那合适吗?
任何想法都将不胜感激。
ioread32_rep(addr,buf,2(替换ioread64((?
在旧的8088 CPU上,ioread16(n)
的作用与ioread8(n)
和ioread8(n+1)
大致相同。
出于这个原因,我怀疑当使用32位总线连接硬件时,ioread64(n)
与64位计算机上的ioread32(n)
和ioread32(n+4)
的作用大致相同。
然而,ioread32_rep(n,buffer,2)
将执行ioread32(n)
(而不是(n+4)
(两次。
如果使用64位总线连接实际硬件,则根本无法使用ioread32
来模拟ioread64
发送的电信号。它是否接受两条ioread32
指令而不是一条ioread64
指令取决于硬件。
一些设备甚至可以在多次呼叫ioread32
和呼叫ioread32_rep
之间进行区分。
QEMU
我不知道QEMU,但我知道VMware(另一种虚拟机软件(有时确实区分了ioread32
和ioread32_rep
。
和我的虚拟机(QEMU(冻结
如果您以不允许的方式访问某些I/O寄存器,实际硬件也可能冻结-我在访问PCI寄存器时已经看到了这一点。
您确定使用iowrite64
可以访问相应的地址吗?