hello world
分类: 嵌入式
2018-04-16 11:21:07
原文地址:vxworks驱动开发原理——PCI驱动(1) 作者:哭泣的土地
PCI接口是一种DMA接口,通过DMA接口,CPU和外设能够进行内存的共享,这样CPU访问外设时只需要访问计算机系统的内存就可以了,这样做的一个重要的目的就是增加外部设备的自主性,在外部设备工作时可以不需要CPU的参与,从而省下了宝贵的CPU资源,而当CPU需要访问外部数据时,直接对相应内存的访问就可以完成,这样也增加了CPU与外部设备的数据交换的速度。因为以上的原因,PCI接口得以大量应用。
另一方面,PCI接口只是一种接口标准,通过这个接口标准可以完成数据的快速访问,但是PCI接口并不是一个完整的外部设备,而只是外部设备和CPU通信的一个接口标准而已,以后我们分析的PCI网卡,USB总线控制器等等这些设备除了PCI总线的驱动之外,还需要自己特殊的驱动。
本章不准备过多描述PCI规范的内容,只针对与PCI总线软件紧密相关的的接口配置部分做个简单描述,如果有兴趣的话可以参考相关的资料,如《PCI Local Bus Specification》。
PCI总线采用了即插即用协议,即在系统建立时由操作系统按照各设备的要求统一分配资源,资源分配的信息由系统写入各PCI设备的配置空间寄存器,并在操作系统内部备份。各PCI设备有其独自的配置空间,硬件设计者通过设置PCI设备(或插槽)的ISDEL引脚区分不同设备的配置空间。
PCI总线配置空间是容量为256字节并具有特定记录结构的一个地址空间。该空间分为头标区和设备相关区两部分,在每个区中,设备只设置必须的和与之相关的寄存器,一个设备的配置空间不仅在系统自举时可以访问,在其他时间也可以访问。
头标区的长度为64字节,偏移地址从00H到3FH,该区中的各个域用来识别各自不同的设备,并使设备能以一般的方法控制。每个设备都必须按照该区的格式和规定进行设置,而配置空间的其余192字节可以因设备而异。
通过系统配置软件,可以进行PCI总线的系统配置。进行配置时,是通过配置空间头标区中的寄存器来实现的,这些寄存器的具体格式与具体的设备有关,但必须遵守一些共同的规则。
图4.1为PCI配置空间头标区的结构图:
图 4.1 PCI设备配置空间头表区结构
下面以PCI网卡配置芯片AM79C97X为例对配置空间头标区各个控制状态字做个简单说明。表4.1为AM79C97X网卡控制芯片PCI配置空间头表区的寄存器设置。
表格 4.1 AM79C97X网卡配置芯片中PCI配置空间头表区的寄存器设置
地址 |
寄存器名 |
长度(byte) |
读写 |
am79c97x芯片 的相应设置 |
00h |
Vendor ID |
2 |
RO |
1022h |
02h |
Device ID |
2 |
RO |
2000h |
04h |
Command |
2 |
RW |
0000h |
06h |
Status |
2 |
RW |
0280 |
08h |
Revision ID |
1 |
RO |
10h |
09h |
Programming interface |
1 |
RO |
00h |
0Ah |
Sub-Class |
1 |
RO |
00h |
0Bh |
Base-Class |
2 |
RO |
02h |
0Ch |
Cache Line Size |
1 |
RW |
|
0Dh |
Latency Time |
1 |
RW |
00h |
0Eh |
Header Type |
1 |
RO |
00h |
10h |
Reserved |
1 |
RO |
00h |
10h |
Base |
4 |
RW |
0000 0001h |
14h |
Base |
4 |
RW |
0000 0000h |
18h |
Base |
4 |
RO |
保留,00h |
1Ch |
Base |
4 |
RO |
保留,00h |
20h |
Base |
4 |
RO |
保留,00h |
24h |
Base |
4 |
RO |
保留,00h |
28h |
Cardbus CIS Pointer |
4 |
RO |
保留,00h |
2Ch |
Subsystem vendor ID |
2 |
RO |
00h |
2Eh |
Subsystem ID |
2 |
RO |
00h |
30h |
Expansion ROM Base Address |
4 |
RW |
0000 0000h |
34h |
Capabilities Pointer |
1 |
RO |
00h |
35h |
Reserved |
3 |
RO |
00h |
38h |
Reserved |
4 |
RO |
00h |
3Ch |
Interrupt Line |
1 |
RW |
00h |
3Dh |
Interrupt Pin |
1 |
RO |
01h |
3Eh |
MIN_GNT |
1 |
RO |
06h |
3Fh |
MAX_LAT |
1 |
RO |
FF |
在分析PCI设备配置空间之前,首先需要弄清楚几个概念:
PCI存储空间不同于PCI配置空间。PCI存储空间是作为计算机系统和PCI设备通信的通道,该通道使得计算机可以直接像访问内存或者IO端口一样访问PCI设备,包括该设备的特殊功能寄存器,以及用做数据缓冲和存储区域。
PCI存储空间分为内存空间和I/O空间两类,它们独立寻址,并使用不同的总线操作命令进行访问。MEMORY空间适用于设备功能寄存器较多或数据流量较大的场合,例如网口芯片、PCI-PCI 桥等。I/O空间适用于设备功能寄存器较少或数据流量较小的场合,例如串口芯片、LED控制寄存器等。但在地址空间比较充裕的条件下,也有把范围较小的存储区放入MEMORY空间的做法,因为与I/O空间的访问相比,内存空间的访问速度要快得多。
配置寄存器组中会有一个或多个基址寄存器BAR(Base Address Register),用于保存存储空间的指针。BAR中可读不可写的位数决定了该存储空间的大小,BAR的最低位是只读位,它定义了BAR的空间属性。当BAR描述的是内存存储空间时,该位读回为0;当BAR描述的是I/O存储空间时,该位读回为1。由于BAR的这一属性,使得PCI设备占用的存储区域是放在内存空间,还是放在I/O空间,完全由设备制造商决定,用户无法修改。
单个设备/功能的PCI内存空间的容量可选取16byte~2Gbyte,但为了减少参与地址译码的地址线数量,PCI规范建议MEMORY空间分配不小于4Kbyte;单个设备/功能的PCI I/O空间的容量可选取4byte~256byte ,不允许超过256byte。
映射到I/O空间的基地址寄存器总是32位,其中位0恒为1(由硬件实现),位1为保留位,其余各位用来把设备映射到I/0空间。
映射到存储空间的基地址寄存器可以是32位,也可以是64位。其中位0通过硬件设置使其恒为0。而位2和位1用来表示映射类型:00表示基地址寄存器宽32位,可以映射到32位空间的任何位置;01表示映射基地址寄存器宽32位,但只能映射到32位空间的低1MB范围内;10表示基地址寄存器宽64位,可以映射到64位表示的存储器空间的任何位置;11为保留编码。
在配置空间中,从偏移地址10H开始,为基址寄存器分配了6个双字单元的位置。第一个基址寄存器总是在10H处,第二个基址寄存器要根据第一个的长度来决定它的偏移地址,可能是14H或18H。依此类推,后面的基址寄存器的偏移地址都要由前面寄存器的大小来决定。设备根据需要设置基址寄存器的类型及个数。
设备通过设定可读写的高位数值来向操作系统指示所需资源空间的大小。比如,某设备需要64K字节的内存空间,可以将配置空间的某基地址寄存器的高16位设成可读写的,而将低16位置为0(只可读)。操作系统在建立时,先向所有位写1,实际上只有高16位被接受而被置成了1,低16位仍为0.这样操作系统读取该寄存器时,返回值为FFFF0000h,据此操作系统可以断定其需要的空间大小是64K字节,然后分配一段空闲的内存空间并向该寄存器的高16位填写其地址。