4.2.3 PCI中断处理函数库pciIntLib
在库文件src\dev\pci\pciIntLib.c中描述了PCI设备的中断处理方法。这个函数库并不是在PCI自动配置的时候调用,因为这时候各PCI设备的中断处理函数还不明确,只能是作为具体PCI设备初始化的时候调用该函数库从而完成该中断向量初始化功能。
根据PCI规范,PCI设备function的中断可以连接到4个IRQ中断的一个,对系统的PCI总线来说,所有设备中断都将连接在这4根IRQ上,因此当一个PCI中断IRQ信号到来时,系统并不知道具体是那个PCI function发生了中断,它必须调用系统中所有中断号为IRQ的function,这也就是中断处理函数pciInt要做的工作。
当CPU发现了一个PCI总线上的中断,它并不知道到底是那个设备中断的,为了处理的方便,系统构造了一个数组pciIntList,这个数组中一共有4个元素,分别对应于IRQ的4个中断。每个元素就是一个链表头,该链表中链接的是系统中所有中断IRQ号为function的中断处理函数。图4.9表示pciIntList[0]链表对应的数据结构。
图4.9 pciIntList[0]链表对应的数据结构
1. pciIntLibInit()函数
图4.10 pciIntLibInit初始化的数据结构
2. VOID pciInt
(
int irq
)
运行pciIntList[irq]链上的各个元素中的函数。参见图4.9。
3. STATUS pciIntConnect
(
VOIDFUNCPTR *vector,
VOIDFUNCPTR routine,
int parameter
)
如图4.9的结构,给定了vector,找到相应的pciIntList[irq]链表,将参数指定的中断处理函数插入到pciIntList[irq]链表中去,如果之前pciIntList[irq]链表为空则需要调用函数intConnect将pciInt安装在相应的中断向量位置,以后每次需要在链表中增加相应的中断处理函数即可。
4. STATUS pciIntDisconnect
(
VOIDFUNCPTR *vector, /* interrupt vector to attach to */
VOIDFUNCPTR routine /* routine to be called */
)
pciIntConnect函数的逆过程。从pciIntList[irq]链表中删除routine函数,此时如果pciIntList[irq]为空,则unbind该pciInt(irq)函数。
5. pciIntDisconnect2()函数
和函数pciIntConnect相同,只是不光是查找函数,还要查找参数,必须是函数和参数都相同才能够删除。
4.2.4 PCI总线配置函数库
在vxWorks系统中的函数库config/templatex86/sysBusPci.c是提供给用户进行pci总线及设备配置参数的一个入口,它负责设置PCI的配置参数设置并调用自动配置函数。
1. LOCAL STATUS sysPciAutoConfigInclude
(
PCI_SYSTEM *pSys,
PCI_LOC *pciLoc,
UINT devVend
)
该函数列举出不支持自动配置的设备,返回ERROR。对于自动支持的设备则返回OK。
用户可以通过对这个函数进行定制以确定那些设备需要自动配置,那些不需要。默认都需要自动配置。
2. LOCAL UCHAR sysPciAutoConfigIntAsgn
(
PCI_SYSTEM * pSys,
PCI_LOC * pFunc,
UCHAR intPin
)
这个函数的作用是由用户定义指定PCI设备IRQ号的函数。
它主要是来自一个数组intLine,intLine是一个16×4的阵列,其中每一行对应的是一个设备号(0~15),每一列则是对应的是function对应的4个中断输出线INTA、INTB、INTC、INTD,这个是需要用户定义的。
注意:PCI设备的Int pin配置寄存器是只读的,也就是说是PCI设备在出厂的时候就已经确定的。不过它们并不是直接连接到计算机系统的IRQn上,而是通过PCI总线连接到IRQn上的,通过硬件连接及int pin配置寄存器的就可以控制function中断连接到一个指定的IRQ上。
3. void sysPciAutoConfig (void)
初始化配置参数PCI_SYSTEM sysParams,并调用函数pciAutoConfig()进行自动配置。该函数被函数中sysHwInit所调用,从而完成了PCI总线的自动配置。
4.3 PCI总线配置过程
在文件config/pcpentium/sysLib.c中,函数sysHwInit()揭示了PCI的初始化配置过程:首先,函数sysHwInit()调用了pciConfigLibInit (PCI_MECHANISM_1, PCI_CONFIG_ADDR, PCI_CONFIG_DATA, NONE),它定义了PCI配置空间的访问方法。
然后调用函数sysPciIntInit (),它对PCI中断的数据结构进行了初始化。
然后是调用函数sysPciAutoConfig(),用于初始化配置参数PCI_SYSTEM sysParams,并调用数pciAutoConfig()进行自动配置。图4.11为PCI自动配置过程。
从本章的分析可以看出,PCI接口驱动的核心就是根据每个PCI设备的去求为其分配特定的IO或内存资源,利用DMA来实现CPU和外部设备之间的快速通信。关于PCI接口设备驱动的例子,将在后面的章节中结合网卡驱动和USB控制器驱动进行详细分析,其中也包括PCI设备的中断的设置。
图4.11 PCI总线的初始化配置过程