(8)PCI接口的驱动程序和配置空间

日期 2001-11-18
作者 老古 http://www.laogu.com Email:zhangshenggu@vip.163.com
内容

  PCI卡有一个特殊的空间叫配置空间.该空间记录卡的中断,输入输出地址,内存映射,总线速度等一些PCI卡的信息.PCI的配置空间最多256字节,而PCI2.1标准规定的空间只有64字节,就是0x00-0x3F.RTL8019AS支持PCI2.1版本.所以空间只有64字节.超过64字节的空间0x40-0xFF为保留的.
PCI配置空间的读出内容如下:

PCI配置空间地址 读出内容 意义
0x00 0x802910EC DeviceID=8029 VendorID=10EC
0x04 0x02000001  
0x08 0x02000000  
0x0C 0x00000000  
0x10 0x00000001  
0x14 0x00000000  
0x18 0x00000000  
0x1C 0x00000000  
0x20 0x00000000  
0x24 0x00000000  
0x28 0x00000000  
0x2C 0x802910EC  
0x30 0x00000000  
0x34 0x00000000  
0x38 0x00000000  
0x3C 0x0000010F  
0x40--0xFF 0x00000000 保留

PCI卡在复位之后(上电之后),它是处于待机状态的,卡属于禁止状态,就是说它还不能进行I/O或内存地址译码.必须先对它进行配置,才可以开始工作.配置就是对PCI配置空间进行一些读写的操作.
对RTL8029As来说,最重要的有几个配置寄存器,一个是BAR,一个是Command.分别介绍.

BAR:Base Address Register,地址译码寄存器,位于PCI配置空间的10-13H,读出内容如下:

bit 31-5 :BAR31-5,在还没有进行设置之前,读出值是一个不确定的值.
bit 4-2 :IOSIZE只读,为0,表示地址译码的大小为32个地址
bit 1:只读,为0
bit 0:IOIN ,只读,为1 ,表示该地址译码为I/O地址空间的译码.
初始化的时候向该寄存器写入全0就可以了.写入全0之后,网卡的译码地址为:
0x00000000--0x0000001F 译码空间为I/O地址空间.
可以看到网卡的32位的I/O地址译码的高3个字节是0,只有低位字节是需要变化的.
那么在PCI的接口逻辑的设计里,我们可以固定高3个字节的地址为0,然后只变化低位字节的地址.这样可以大大简化接口逻辑.同时也简化单片机对PCI总线的操作.
可以看到网卡的译码地址是I/O空间的地址译码,而没有内存地址的译码.那么对PCI卡进行内存译码的操作和接口是可以省略的.在我的PCI接口逻辑里,为了简化设计,没有进行内存地址寻址的逻辑设计.
我的设计只支持PCI配置空间寻址和I/O地址空间寻址.I/O地址寻址空间也限制在
0x00000000--0x000000FF范围内,最多支持256个I/O地址.而RTL8029AS只用了其中的32个地址.
设置完BAR之后,网卡实际上还没有开始工作. 还需要设置命令寄存器.

命令寄存器中只有最低位是可以写的,其他为只读.需要向该位IOEN写入1, 网卡才开始进行地址译码.

设置完这两个寄存器,网卡就可以开始工作了.开始工作之后,不需要再进行PCI配置空间的读写.
为了简化用户的程序设计,我提供了6个函数用来进行PCI接口的驱动.两个进行PCI配置空间读写的函数:
unsigned long read_config(unsigned char address)
/*PCI 配置寄存器读,地址address必须是4的倍数0,4,8。。。。地址,一次读出4个字节 */
void write_config(unsigned char addr,unsigned char value3,unsigned char value2,unsigned char value1,unsigned char value0)
/*PCI 配置寄存器写,地址addr必须为4的倍数0,4,8。。。。,value3-value0为要写入的值,value3为高位字节,一次要写入4个字节?*/
4个读写网卡寄存器的函数:
unsigned char read_register(unsigned char addr)//读网卡的寄存器

void write_register(unsigned char address_offset,unsigned char value)//写网卡的寄存器

void write_dma_port(unsigned char value)//写网卡的Remote DMA port

unsigned char read_register(unsigned char addr) //读网卡的Remote DMA port
有了这6个函数,对PCI总线的操作就和ISA总线的操作一样了.通过这6个函数,用户可以方便的进行PCI卡的读写,而不需要太多的了解PCI总线的时序.


来源
老古网

欢迎技术探讨和发表评论