简介
看到一个链接,讲到了一些IO的概念,感觉还不错。
访问IO设备的方式
主机对I/O设备进行访问的目标是I/O设备的寄存器或者内存。常见的I/O设备都只提供寄存器供主机访问,对于低速外设这样的模式是足够的,但是对于需要大量、高速数据交互的外设(如显卡、网卡),就需要主机能够直接访问外设的内存了。现代计算机提供了两种方式来访问I/O设备,它们分别是PMIO和MMIO。
PMIO
端口映射I/O(Port-mapped I/O)。将I/O设备独立看待,并使用CPU提供的专用I/O指令(如X86架构的in和out)访问。端口映射I/O,又叫做被隔离的I/O(isolated I/O),它提供了一个专门用于I/O设备“注册”的地址空间,该地址空间被称为I/O地址空间,最大寻址范围为64K。
为了使I/O地址空间与内存地址空间隔离,要么在CPU物理接口上增加一个I/O引脚,要么增加一条专用的I/O总线。因此,并不是所有的平台都支持PMIO,常见的ARM平台就不支持PMIO。支持PMIO的CPU通常具有专门执行I/O操作的指令,例如在Intel-X86架构的CPU中,I/O指令是in和out,这两个指令可以读/写1、2、4个字节(outb, outw, outl)从内存到I/O接口上。
由于I/O地址空间比较小,因此I/O设备一般只在其中“注册”自己的寄存器,之后系统可以通过PMIO对它们进行访问。
MMIO
内存映射I/O(Memory-mapped I/O)。将I/O设备看作内存的一部分,不使用单独的I/O指令,而是使用内存读写指令访问。MMIO是应用得最为广泛的一种I/O方式,由于内存地址空间远大于I/O地址空间,I/O设备可以在内存地址空间上暴露自己的内存或者寄存器,以供主机进行访问。在MMIO中,物理内存和I/O设备共享内存地址空间,注意,这里的内存地址空间实际指的是内存的物理地址空间。比如从网上找到的一份HI3519AV100的用户手册,在地址空间映射这里,可以发现,从0x40000000才是DDR的起始地址。但是访问前面的各种硬件寄存器,也是直接用操作内存的方式来访问的。
当CPU访问某个虚拟内存地址时,该虚拟地址首先转换为一个物理地址,对该物理地址的访问,会通过南北桥(现在被合并为I/O桥)的路由机制被定向到物理内存或者I/O设备上。因此,用于访问内存的CPU指令也可用于访问I/O设备,并且在内存(的物理)地址空间上,需要给I/O设备预留一个地址区域,该地址区域不能给物理内存使用。
最近在学习PCIe,关于MMIO,还有两种,一种是Non-Prefetchable MMIO,一种是Prefetchable MMIO。
Prefetchable MMIO
可预取内存空间。将MMIO的一个区域设置为可预取的,允许CPU提前获取该区域中的数据,以预测请求者在不久的将来可能需要比实际请求更多的数据。对数据进行这种小规模缓存是安全的,因为读取数据不会改变目标设备上的任何状态信息。也就是说,读取位置的行为没有副作用,比如某些配置寄存器或者说是逻辑上读取之后就会被清空的数据寄存器是不可以用这种配置的。
Non-Prefetchable MMIO
非预取内存空间。将MMIO的一个区域设置为非预取的,就象FIFO地址影射到内存地址,读取数据以后会引起FIFO指针的改变.另外还象一些中断状态I/O影射到内存,读取这个内存后,可能会清除中断标志等等,所以CPU不可缓存这个内存地址,就要用这种配置。