PCI(Peripheral Component Interconnect)是一种高性能的局部总线,采用高度综合优化的总线结构,保证系统各部件之间的运行可靠,目前广泛应用于各种计算机系统中。PCI总线可同时支持多组外围设备,具有很高的数据传输速率,峰值传输速率可达132MB/s(32位、33MHz)。 目前开发PCI 接口大体有两种方式:一是使用专用的PCI接口芯片,二是使用可编程器件。如果使用厂家提供的专用接口芯片,用户可能只使用到它的部分功能,会造成一定的资源浪费,而且专用芯片价格高,不经济。而使用可编程器件比前者具有以下两个优点:一方面用户可以根据需要设计PCI接口,不会浪费资源;另外一方面用户逻辑和接口部分可以做在同一个器件内,PCI接口和用户逻辑会结合得更紧密。现在已经有越来越多的用户使用可编程器件如FPGA、CPLD 等进行PCI 设备的开发。对可编程器件进行PCI 接口开发的研究具有很强的实际意义。 PCI 接口的实现包括配置空间和数据接口两方面。
PCI 总线配置空间的实现 配置空间 PCI总线定义了3种物理地址空间:存储器地址空间、I/O地址空间和配置地址空间。前两者是普通的计算机系统地址空间,而配置空间是PCI所特有的一种空间。根据PCI 总线规范[1],所有的PCI 设备都必须提供配置空间。定义PCI 配置空间的目的在于:提供一套适当的配置措 施,使之满足现行的和可预见的系统配置机构。配置空间是一长度为256 字节并且有特定记录结构或模型的地址空间,可以在系统自举时访问,也可在其他时间访问。该空间分为首部区和设备有关区两部分。设备在每个区中只须实现必要的和与之相关的寄存器。首部区的长度为64 字节,每个设备都必须支持该区的寄存器分配,这个区包括进行设备识别的唯一标示码,和允许对设备进行控制的若干区域。表1 所示为64 字节首部区的布局情况。
表中颜色较深部分为强制性的首部寄存器,包括供应商代码寄存器、设备代码寄存器、命令寄存器、状态寄存器、修改版本寄存器、类别寄存器和首部类型寄存器。供应商代码由PCI SIG 分配,设备代码由设备制造商分配;设备代码和供应商代码一起用于定位设备指定的驱动程序。命令寄存器用于存放PCI命令;状态寄存器包含PCI 的状态信息。修改版本寄存器包含版本标识号;类别代码寄存器是只读寄存器,用来说明设备的通用功能。首部类型寄存器包含两个字段,D6-D0 位定义配置空间首部区字节10H-13H 的格式,D7 位表示该PCI 设备是多功能还是单功能设备,如果为1表示是多功能设备,反之则是单功能设备。 除了上面所说的强制性首部类型寄存器以外,还有一些寄存器是经常用到的,比如基地址、中断线和中断引脚寄存器等。基地址寄存器提供了一种为设备指定存储空间或I/O空间的机制。操作系统在启动的时候要判断系统中有多少存储器、系统中的I/O 设备需要多少地址空间,然后根据得到的结果,自动配置系统的存储空间和I/O 空间,实现设备无关管理。基地址寄存器中的值有两个含义,一是存储空间或I/O空 间的基地址;二是存放定义空间的长度。它的D31 位用来区分是基地址还是长度,如果为1则是基地址,反之是长度;另外D0位用来区分存 储器空间和I/O空间,如果为1则是I/O空间,反之是存储器空间。 另外如果要实现中断,必须对中断线寄存器和中断引脚寄存器进行设置。中断线寄存器由系统中的所有中断源共同使用,它的值说明设备的中断引脚连接到中断控制器的哪个输入上。中断引脚寄存器说明设备使用PCI总线上的哪一个中断引脚。
为避免地址冲突,PCI总线要求各个设备所占用的地址能够重定位,重定位是由设备的配置空间的基址寄存器实现的,通常情况下,各个设备的基址寄存器总是被BIOS或操作系统分配为不同的基址,从而将各个设备分别映射到不同的地址范围。在需要时,应用程序也可以自行修改基址寄存器中的基址,从而将设备映射到指定的地址范围。
BAR中可读不可写的位数决定了存储空间的大小,同样如果读回空间大小以后,将基地址写回去的时候,改变的也只是高位可写的。举例来说,如果从10h写全f读回fff00001,说明memory空间大小为1M,再往里写的时候同样只能改变高位的3个f,即这个设备的IO基址必然为xxx00001。其中x就是你往里写的。