关于x86 I / O端口地址和IN / OUT指令的问题

时间:2019-06-18 20:31:32

标签: assembly x86 cpu-architecture

据我所知,这是PC总线系统的简化视图(它不包括我所知道的桥)。

如图所示: x86 Bus Simplified View

据我所知,现代x86 CPU中的地址空间为65536字节(0000-FFFF)。这些是I / O地址。在x86中,IN和OUT指令用于通过I / O端口与设备进行通信。

考虑到PC(x86 cpus),以下是我的问题:

  1. 是否可以在不使用PCI或任何其他总线的情况下将设备添加到此I / O总线?我的意思是与IN / OUT直接通信。如果是,如何分配I / O地址?他们不冲突吗?

  2. 如果我的CPU支持PCI和I²C(是的话!),CPU如何区分它们的I / O地址?如何知道I / O地址属于PCI还是I²C。

(顺便说一句,我不知道I²C地址是否只是逻辑而不是I / O端口,但这是我也需要回答的另一个问题)

1 个答案:

答案 0 :(得分:6)

  

1)是否可以在不使用PCI或任何其他总线的情况下向该I / O总线添加设备?

理论上;是。但是,对于现代系统而言,没有共享/公共总线(现在是“点对点链接”)。并且内存控制器和PCI主机都与CPU内置在同一芯片中,这意味着(除非您是像Intel这样的CPU供应商的员工),您将不得不处理高速串行链接(快速路径,超传输,PCIe或DMI)并不便宜,也不容易与之交互(换句话说,就像1980年代,您可以使用不错而又慢的ISA总线)。

  

如果是,如何分配I / O地址?他们不冲突吗?

旧版设备使用由历史记录/兼容性分配的固定IO端口。其他所有内容均由一种“ IO端口范围分配器”(内置在固件和/或操作系统中)动态分配,该分配器在PCI配置空间中配置BAR(“基地址范围”寄存器)。有一些(现在已不推荐使用/不存在的)替代方案-由ISA卡上的物理跳线或DIP开关手动分配,ISA的“即插即用”规范在许多设备支持之前已被PCI取代,并且存在于用于动态资源分配的其他类型的总线(MCA和EISA)。当然,大多数现代设备根本不使用IO端口(而是使用内存映射寄存器)。

  

2-)如果我的CPU支持PCI和I²C(是的话!),CPU如何区分它们的I / O地址?如何知道I / O地址属于PCI还是I²C。

对于I²C,可能在某处(在IO端口地址空间或物理地址空间中)有一对寄存器,用于向I²C总线发送字节或从I²C总线接收字节。 I²C总线上的所有内容都将通过这2个寄存器进行访问,而I²C总线上的任何内容都将无法访问I²C总线上没有的任何内容(包括无法访问任何IO端口以及无法访问任何物理端口)。地址)。

大多数情况下(例如以太网,视频,USB等),您都有一个控制器(具有可直接访问CPU的寄存器)来控制CPU无法直接访问的某些内容(LAN,向显示器发出的信号,USB设备插入USB总线,...)。

(简体)示例

我们假设(由于一条out dx,al指令),CPU在共享总线或链接上显示了“ command = WRITE, space = IO port space, address = 0x1234, size = 1 byte, data = 0x56”的消息。该消息可能会被PCI主机控制器截获,后者会查看详细信息(哪个地址空间中的哪个地址),并决定将该消息转发到PCI总线上的“ PCI到LPC桥接器”设备。当“ PCI到LPC桥接器”收到消息时,它可能会查看详细信息(哪个地址空间中的哪个地址),并意识到它对应于I²C总线控制器,并将其转发给I²C总线控制器。 I²C总线控制器可能会对消息进行解码,并在I²C总线上发送字节0x56(来自消息的“数据”部分)。然后,也许正在I²C总线上侦听的设备看到了0x56字节,并通过将字节0x78通过I²C总线发送回I²C总线控制器做出响应,该控制器在其中将值0x78存储在内部缓冲寄存器中。

下一步; (由于一条in al,dx指令,CPU可能会发送另一条消息“ command = READ, space = IO port space, address = 0x1234, size = 1 byte”。该消息将遵循与前一条相同的路径(因为地址和地址空间相同),并最终到达I²C总线控制器。 I²C总线控制器可能会解码该消息,并意识到该消息正在请求从I²C总线控制器的内部缓冲寄存器中读取(该寄存器的值之前为0x78);因此I²C总线控制器会发回消息“ command = READ_REPLY, space = IO port space, address = 0x1234, size = 1 byte, data = 0x78”。此回复消息将返回到CPU(再次使用相同的路径,但方向相反-例如,从PCI到LPC桥,再到PCI主机控制器,再到CPU)。当CPU获得回复时,它可以完成引起回复的原始指令(例如,将al设置为“ READ_reply”消息中的值以完成in al,dx指令)。

这里的意思是,CPU无法将任何东西直接发送到I²C总线上的设备(CPU只能与I²C总线控制器进行通讯);而且I²C总线上的任何设备都不能直接将任何东西发送到CPU(它们也只能与I²C总线控制器通信)。 I²C总线上的任何信息都无需了解IO端口。而且CPU总线/链接上的任何内容都不需要了解I²C总线上的字节。

也; CPU只是发送和接收消息。它不知道将它们发送后会发生什么情况,也不知道如何将“ command = READ”消息按什么转发到哪里,也不知道哪个设备会发回“ command = READ_REPLY”消息。路由主要取决于消息所采用路径中每一步的逻辑。例如,可能将PCI主机控制器配置为将用于0x0000到0x2000范围内的IO端口访问的所有消息转发到PCI总线,并且可以将PCI到LPC桥配置为转发范围为0x1234的IO端口访问的所有消息。到0x1235到I²C总线控制器。