在上面的两节中,我们讨论了两个设备如何通过总线传输数据和如何决定哪个总线设备控制总线传输数据。也就是说,我们已经知道了总线中如何确定总线的控制者(总线主设备,或者启动方),我们还知道了在确认了总线主设备和总线从设备(目标设备)之后如何通过总线进行数据传输,那么剩下的问题是如何确认总线从设备呢?答案是通过寻址。
寻址即总线传输过程中根据目标地址确认总线交易目标设备的过程,对于包括ISA和PCI在内的大多数总线,寻址都是由目标设备完成的。以PCI总线为例,在总线交易的地址段,总线交易的启动方会在把总线交易命令放在C/引线上的同时将总线交易的目标地址驱动到总线的地址线上。由于PCI总线的共享特性,挂接在PCI总线上的所有PCI设备都能够接收到这些总线交易命令和目标地址,这些设备将分析总线交易命令及目标地址,判断该地址是否落在设备的地址空间之中。如果该地址属于设备的地址范围,则这个设备将以信号予以响应,从而完成寻址的过程。
那么,一个设备如何判断某个地址是否属于其地址范围呢?首先,每个总线标准都会定义一系列的地址空间。例如,ISA总线定义了存储器空间和I/O空间两个互相独立的地址空间,PCI总线则比ISA总线更多定义了一个配置地址空间,用以实现对设备的自动配置。其次,总线控制信号或总线命令中指出本次总线传输使用哪个地址空间,例如ISA总线对不同空间的访问通过、I、、W等信号来区分。PCI总线则通过不同的总线命令来区分总线交易寻址目标属于哪个地址空间,比如I/O读命令所涉及的一定是I/O空间,而存储器写命令所涉及的地址空间则一定是存储器空间。最后,每个总线设备中要保存一个地址列表,其中包括本设备在各地址空间中占用的地址范围。从寻址判断方便出发,这个地址范围一般包括2n个字节,从而使得寻址的判断过程可以通过一个简单的高位地址相等比较或者译码器译码来实现。
在上述叙述中,我们讨论了在一条总线上如何进行寻址,但是当代的微型计算机为了应对速度各异的外围设备而广泛采用了分层总线的结构,即使用总线桥将多个不同速度的总线桥接到一起,从而满足不同速度的外围设备的需要。这时系统总线上的寻址过程就要比单一总线的时候复杂得多。以通过PCI-ISA桥桥接到ISA总线的PCI总线上的寻址为例,PCI总线提供了一种被称作“负向译码”(Subtractive Decode)的寻址方式。负向译码的基本思想是将总线上的某个设备视为“缺省设备”,当其他总线设备都拒绝响应总线请求时,该“缺省设备”响应这个总线请求,并进行进一步的寻址操作。很显然这个“缺省设备”应当是用于桥接总线的总线桥(PCI-ISA桥)。具体做法是,PCI-ISA桥在一个PCI交易周期开始后对总线上的信号进行监听,当经过了4个时钟周期依然没有其他设备响应总线请求的时候,PCI-ISA桥就启动负向译码,在第五和第六个时钟周期通过信号响应总线交易的启动方。与此同时总线桥会将目标地址的低位(存储器访问的低24位或I/O访问的低14位)转送到ISA总线上,并将PCI总线命令加以译码,形成ISA总线的驱动信号,以启动一次ISA总线传输。
对于设备占用的地址空间,总线协议一般不会有太多的限制,一个设备可以在所有的地址空间中都占用一定范围的地址,也可以根据其需要只在一个或几个地址空间中占用一些地址区间,这些地址区间可以连续,也可以分布在地址空间的不同位置。对于这些地址区间,关键的限制就是不能有多个设备占用同一地址空间里面的同一段地址区间,以免造成多个设备同时响应一个总线交易请求而发生冲突。除此之外,某些总线对设备占用地址空间的对齐机制还有一定的要求,如PCI就要求一个总线设备占用的地址区间必须是2n个字节,并且只能被定位到形如XXX…XX0…00~XXX…XX1…11的地址范围之中。
在总线中,除了I/O空间、存储器空间之外,某些总线设备还要使用到中断请求和DMA请求,这些需要分配给设备的I/O空间、存储器空间、中断请求、DMA请求被统称为“资源”(我们在Windows的“设备管理器”里面看到的“资源”指的就是这个资源)。给总线上的各设备分配资源,使得总线上各设备能够在一起正常运行的过程被称作总线的配置。
在早期的ISA总线中,总线是以手工的方式进行配置的。一方面,主板上内置的各种ISA设备在安装前就已经被仔细地配置,以保证其分配的资源不会出现冲突。另一方面,要安装在ISA总线插槽上的各种设备必须以某种方式进行手工的资源分配。在最早的ISA扩展卡上,这种配置一般是通过设置一组跳线或者开关实现,后来,跳线或开关被程序所取代。在那个时代,为微型计算机增加一块ISA扩展卡是一件需要专业技术的事情,操作者必须非常小心地对这张新加入的ISA扩展卡进行配置,从而避开所有已占用的资源,保证其正常运行,而这通常需要多次改变跳线或开关的试验。有些时候,运气不好的操作者还必须修改其他ISA扩展卡占用的资源,以空出合适的资源来容纳新的ISA扩展卡,而这些都需要比较多的专业知识和经验。
随着微型计算机技术的发展,即插即用(Plug and play,PnP)技术开始出现在EISA和MCA总线之上,其中一个重要功能就是自动的硬件资源分配,即根据设备的说明自动为设备分配需要的各种硬件资源,包括存储器地址空间、I/O地址空间、中断请求和DMA请求,而无需用户再手工分配这些资源。即插即用技术后来扩展到了ISA总线上,试图借此摆脱ISA设备配置的困难。但是,由于先天不足,ISA PnP存在一系列的缺陷,使得ISA PnP的配置成功率比较低,无法满足人们的要求。
为了避免ISA总线所面临的种种问题,PCI总线在设计之初就把自动配置作为一个重要的设计目标。为了实现自动配置,PCI在ISA的存储器空间、I/O空间之外增加了一个“配置空间”,用于实现PCI设备的自动配置。PCI设备的自动配置是一个相当复杂的过程,由于篇幅的原因本书仅对PCI总线的自动配置进行比较简单的探讨。
为了实现PCI设备的自动配置,在每个PCI设备中都设有一组PCI配置寄存器,这些配置寄存器就组成了PCI总线的配置空间。当PCI卡刚加电时,卡上只有配置空间是可被访问的,而且配置空间的访问也不能通过简单的存储器或I/O等CPU指令直接进行,因而PCI卡开始不能由驱动或用户程序访问,这与ISA卡有本质的区别。PCI设备配置的过程大致分为三个步骤:1.读取设备功能说明与配置需求;2.计算每个设备应该的配置;3.将配置结果写入到各设备的配置寄存器中,完成设备配置过程。
从功能上来讲,PCI配置寄存器必须提供两方面的能力:1.通过配置读将PCI设备相关说明和配置需求提供给系统;2.通过配置写为PCI设备分配各种资源。PCI配置空间保存着该卡工作所需的所有信息。如厂家、卡功能、资源要求、处理能力、功能模块数量、主控卡能力等。
图7-45给出了PCI配置寄存器的主要内容,下面分类简要介绍。
图7-45 PCI配置寄存器
(1)PCI信息
PCI卡的所有信息都是由配置空间给出的,因而,通过读取配置空间相应的位置,即可了解此卡的相关信息,这些信息是PCI卡设计者所必须实现的。这些信息包括:
●制造商标识(Vendor ID):由PCI组织机构给厂家的唯一编码,其中子系统制造商标识(Subsystem Vendor ID)也是由该组织给出的。
●设备标识(Device ID):由这个产品对该卡的设备命名的编号,其中也可命名为子系统标识(Subsystem ID)。由制造商标识(Vendor ID)和设备标识(Device ID)等确定了每一种产品只有一个唯一编码。这一编码是以后驱动程序或应用程序找到该设备的唯一凭证。
●分类码(Class Code):代表该卡设备功能的分类码,如网卡、硬盘卡、解压卡、声卡等,它们都可对应到一个唯一的编码。
(2)存储器空间配置
在某些PCI卡内部建有存储器功能,或有以存储器编址的寄存器和I/O空间,为能使驱动程序和应用程序访问这些存储器或寄存器,需要申请一段PCI空间的存储区域。存储空间的大小由PCI设备指定,分配的位置则由总线控制器统一安排并写入到PCI设备的配置寄存器之中。
配置空间中的基地址寄存器(Base Address Registers)是专用于申请空间的,它可以使PCI设备最多可以申请6段32位地址区域的空间,或3段64位地地区域的空间,即最多6个CPU的地址。每个基地址寄存器具有如图7-46所示结构。
图7-46 PCI基地址配置寄存器(存储器)
其中位0要用硬件方法使其恒为0(接地)。而位2和位1两位用来表示映射类型,具体如表7-3所示。
表7-3 基地址配置寄存器映射类型
至于位3,若数据是可预取的,就应将它置为1,否则清0。第4~31位(或63位)为可读写的寄存器内容,实现时具体有多少位可读写,代表了所申请的存储器空间的大小。例如一个设备需要256个字节的存储空间,那么它在设计基地址寄存器(Base Address Regis-ters)时,从第4~7位不用实现写,读出时为0即可。此时PCI控制器通过如下方式确定设备所需存储空间的大小并分配一个区域给设备。
●写全1到该寄存器。
●读出该寄存器,确定它从高位开始的1的数量,计算出空间的大小,如上述中读出24个为1的位,则为32-24=8即256空间。
●综合所有设备与主板的空间分配,确定一个以申请大小为基础的对齐的地址(即低位全为0)
●将这个地址回写到该寄存器中,其位数正好与所实现的位数相同。
此后PCI设备就可通过这个寄存器的内容与PCI总线的地址进行比较,来确定是否对其占用的存储区域进行访问。
(3)I/O空间配置(www.xing528.com)
I/O空间的申请和存储器复用6个基地址寄存器(Base Address Registers)所不同的是I/O空间申请时采用图7-47所示格式。
图7-47 PCI基地址配置寄存器(I/O空间)
除此之外,I/O空间的寄存设计的及配置过程与存储器完全一样,不同之处是用于I/O空间的基地址寄存器位0必须为1,以区分于用于存储器空间的基地址寄存器。另外,虽然Intel系列CPU仅支持16位I/O地址,但作为与处理器无关的PCI设备,地址译码(比较)时应仍保持32位的I/O空间访问。
(4)扩展ROM空间配置
有些PCI设备,尤其是那些准备用于PC结构扩展板上的设备,需要EPROM作为扩展ROM。为此,在配置空间偏移地址30H处开始定义了四个字节的寄存器,用来处理这个扩展ROM的基地址和大小(见图7-48)。
图7-48 扩展ROM基地址寄存器
该寄存器和32位基地址寄存器相比,除了位的编码和用途不同之外,其他功能完全相似。它的高21位对应于扩展ROM基地址的高21位。一个设备实际实现的位数取决于该设备要求多大的地址空间。例如,一个设备要求它的扩展ROM映射到64 KB存储区域时,它就应该实现此寄存器的高16位,其他5位用硬件方法使它们恒为0。凡是支持扩展ROM的设备必须实现这个寄存器。
与设备无关的配置软件通过对扩展ROM基址寄存器的地址位上写入全“1”,然后再读回以确定设备要求多大的地址范围。所有的无关位上都返回0,从而有效地指出了地址边界,也就知道了设备要求的这一块地址空间的大小。一个设备要求的地址空间范围不能超过16 MB。
这个寄存器的位0用来控制相应的设备是否能够接受对其扩展ROM的访问。当该位为0时,禁止访问设备的扩展ROM地址空间。当该位为1时,允许将本寄存器的其他位作为参数进行地址译码。命令寄存器中的存储器空间位优先于扩展ROM的使能位,但是,如果存储器空间位和扩展ROM的使能位同时为1时,设备就必须响应对其扩展ROM的访问。扩展ROM的使能位在复位后应该为0。
(5)中断资源申请
中断资源的申请是通过中断引脚(Interrupt Pin)和中断线(Interrupt Line)来完成的。配置空间的中断引脚(Interrupt Pin)为只读,反映出所要申请的中断要求。
求中断资0:不要求中断资源
1:要求中断,并且中断线接在INTA
2:要求中断,并且中断线接在INTB
3:要求中断,并且中断线接在INTC
4:要求中断,并且中断线接在INTD
PCI总线上有4条中断线INTA、INTB、INTC、INTD,PCI设备的中断线接到哪一条上从该寄存器反映出来。总线控制器在读取这个寄存器内容后,将分配的中断号回送到中断线(Interrupt Line)寄存器中,其中0~15为有效的中断号,255为未分配到,16~254保留,这样,驱动程序就可通过读取中断线(Interrupt Line)的内容得到所分配的中断号,作出相应的编程。
(6)多功能卡
当一块PCI卡上设计不止一个功能时,就要指定为多功能卡,而且每个功能都要有一个自己的配置空间,因此每个功能可以是不同的设备标识(Device ID)及功能类型、存储器和I/O地址空间及中断资源,配置空间中的头类型(Header Type)可用于指明是单功能或多功能卡,头类型(Header Type)的第7位为1时代表多能卡,访问配置空间时,有3位地址用于指定功能号,因此每块卡最多可以支持8个功能部件。由于PCI总线上只有4条中断线,因而多功能卡最多仅能有4个中断源。
在PCI配置的过程中,PCI控制器需要读写系统中连接的所有PCI设备的配置寄存器,这是通过PCI配置读/配置写总线命令完成的。在PCI配置读/配置写命令发送的同时,PCI总线的控制器还必须发送一组地址信号和片选信号,以指定被访问的PCI设备和访问目标在配置寄存器堆中的偏移。根据目标设备的不同连接位置,PCI规定了两种不同类型的PCI配置地址格式(见图7-49)。
图7-49 PCI配置地址格式
其中类型0用于访问直接连接到主PCI总线(即与处理机直接连接的PCI总线,该总线被命名为总线0)的PCI设备,类型1被用于访问连接到通过PCI-PCI桥与主PCI总线连接的其他PCI总线上的PCI设备。类型1的配置地址会被PCI-PCI桥解码,根据其中的总线号选择合适的目标总线,并根据设备号选择该总线上的合适设备,最终在目标PCI总线上形成类型0地址驱动目标PCI设备。在PCI设备接收到配置地址时,功能号被用于在多功能PCI设备中进行功能选择,而第7~第2位的寄存器编号则被用于给出目标寄存器在配置寄存器堆中的偏移。
但是,类型0的PCI配置地址中并没有指明被访问的设备号,那么如何确定是哪个PCI设备被访问呢?答案是使用IDSEL信号。PCI总线标准规定所有PCI设备必须支持IDSEL信号,用于在配置阶段对设备进行片选。在PCI配置读/配置写总线交易中,PCI设备的片选不像其他总线交易周期那样来自于对目标地址的译码结果,而是由IDSEL信号决定。
虽然PCI总线规范并没有规定PCI设备的IDSEL信号应该如何产生,但是在当前PCI总线的实现中,各PCI设备的IDSEL信号通常通过一个电阻连接到被保留的高位地址线上,每个设备连接到不同的地址线(如AD31、AD20等,见图7-50)。这样,总线控制器就可以通过将被保留的这些高位地址线依次置1的方式来遍历总线上连接的所有设备,从而完成整个PCI配置过程了。
图7-50 IDSEL信号的连接
由于处理器并不支持对PCI配置空间的直接访问,系统必须提供某种机制来将PCI配置空间的访问映射到CPU对I/O空间的访问之中。目前常用的有两种形式,一是固定端口法,即使用两个双字I/O地址(0CF8H和0CFCH)作为配置地址与配置数据寄存器,先向配置地址寄存器写入要访问的配置目标地址,再从配置数据寄存器实现配置数据的读写。Host-PCI桥(即将CPU连接到PCI总线上的桥接设备)将把这两次I/O操作映射成为PCI配置读/配置写总线交易,从而完成PCI总线配置的读写。这种做法通过使用两个双字I/O地址的读写完成PCI总线的配置操作,是当前推荐的做法。
另外一种常见的做法是将PCI配置空间映射到一段I/O空间中(一般是C000H~CFFFH),这种做法占用I/O空间比较大,主要是为了向后兼容而提供。
可能读者已经注意到,我们一直没有提到PCI Express总线中如何对设备进行寻址与配置。在ISA和PCI总线中,由于其共享总线结构,总线交易的启动方将目标设备的地址放置到总线的地址线上即可以将其广播给所有的总线设备,再由总线设备自己来判定该目标设备是否落在自己的地址空间中,从而实现对目标设备的寻址。PCI Express总线取消了共享总线结构,这就意味着启动方无法将目标设备的地址广播给所有设备,只能通过其他的方法来实现目标设备的寻址,而这个过程依赖于PCI Express交换设备的通道控制功能。用一句比较形象的话来比喻,就是互联PCI Express设备的交换器能够“记住”那些地址属于哪个设备和怎样把数据包传送到这个设备,这样就不需要像ISA和PCI总线那样通过广播目标地址来进行寻址了。同时,PCI Express总线继承了PCI总线的配置功能,并保持和PCI总线在软件层上的兼容,也就是说,PCI Express使用和PCI相同的原理和配置方法来实现PCI Ex-press总线设备的配置功能。
免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。