1 PCI配置空间
1.1 BAR大小的确定
Linux kernel读取PCI BARn表示的内存长度时,先直接读取BARn的值,这个就是地址,然后再向BARn写入0xffff,ffff,再读取BARn的值就是需要的内存长度(忽略bit3到bit0的处理),但是此时由于BARn的值已经变成长度了,所以还需要将第一步读取出来的地址再写回BARn。
- 如果可操作的最低位为bit12,那么BAR可申请的最小地址空间大小为4KB(2^12)
- 如果可操作的最低位为bit20,则该BAR可申请的最小地址空间大小为1MB(2^20)
1.2 Linux pcibios_init
x86 BIOS专门提供了针对PCI总线的操作,这些操作里就包括了总线枚举的整个过程,Linux kernel中的宏CONFIG_PCI_BIOS。在系统加电以后自检时,就会完成对PCI总线的枚举,之后Linux对PCI配置空间的访问都是通过BIOS调用的形式进行,提供有这些功能和服务的BIOS就称之为PCI BIOS 。需要注意的是Linux x86_64是不采用PCI BIOS访问PCI配置空间的,而是内核实现了直接访问PCI配置空间的函数(CONFIG_PCI_DIRECT)。
pcibios_init()的第一个功能是在内存中找到BIOS程序的代码(参考函数pci_find_bios),然后将调用BIOS例程的读写PCI配置空间的代码封装成函数赋值给pci_ops。
pci_ops里面的函数指针都是用来读写PCI配置空间的,把要读写的值和设备号告诉这些函数,在这些函数中调用了BIOS例程,并把这些值当作参数传给BIOS例程,BIOS再根据设备号和要读写的值来进行操作。所以Linux x86驱动程序中pci_read_config_byte()最终调用的是pci_bios_read_config_byte()。
zcat /proc/config.gz | grep PCI
2 PCI9054三种工作模式
M模式:直接为Motorola公司的MPC850和MPC860准备的非复用接口
C模式:地址、数据线不复用
J模式:地址数据线复用
Figure 2-1 PCI 9054 Internal Block Diagram
3 PCIBAR地址解析
BAR0:Memory映射;存放PCI9054中的Local Configuration Registers、Runtime Registers和DMA Registers在PCI总线中的地址映射
BAR1:IO映射;存放PCI9054中的Local Configuration Registers、Runtime Registers和DMA Registers在PCI总线中的地址映射
BAR2:BAR2 + offset = LAS0BA + offset;其中LAS0BA为Local Address Space 0/1 Base Address的缩写
BAR3:BAR3 + offset = LAS1BA + offset
如果主机要访问BAR2和BAR3,需要设置位于BAR0空间的LAS0BA和LAS1BA的bit0为1
4 Local寄存器访问
MCU拉低CCS#片选,MCU访问的地址符合:片选BASE + offset
5 DMA
5.1 DMA
DMA模式传输外接FIFO的数据:FIFO本身没有地址,在调用P9054DMAReadWriteBlock()等函数时Local地址的设置,利用PCI9054 的Local地址线的高位通过组合逻辑电路产生一个信号去控制FIFO上的允许信号,而低位地址线可以不接,这样只有在设定的地址范围内才会选中FIFO进行操作,这就等于产生了一个“片选”信号。
5.2 showcase
PLX9056 for Fulcrum Microsystems switch FM2112.
6 开发工具
Juno WinDriver:可以自动生成inf文件和驱动框架
PlxMon
7 Abbreviations
FM2112: Fulcrum Microsystems switch IC, was acquired by Intel in July, 2011