5.1 概述

本章将通过AM79C97X网络通信芯片的例子来说明网卡的驱动原理。该通信芯片不仅具有网络通信功能,而且还建有PCI接口控制管理功能。在操作系统通过对AM79C97X的PCI接口的自动配置为该设备分配内存资源和IO资源,这些内存资源和IO资源将是CPU控制AM79C97X网络通信芯片的主要的主要通道。

表4.1列出了AM79C97X芯片的PCI配置寄存器。在配置寄存器的10h地址记录了该PCI设备对IO资源的要求:32字节;在配置寄存器的14h地址记录了该PCI设备对内存资源的需求:32字节。其实这两个地址所映射的内容是一样的,即CPU控制AM79C97X芯片的主要接口。一般来说既有IO接口又有内存接口的情况下,首先选用内存接口,因为内存接口访问速度要远高于IO接口。

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.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设备(或插槽)的IDSEL引脚区分不同设备的配置空间。

PCI总线配置空间是容量为256字节并具有特定记录结构的一个地址空间。该空间分为头标区和设备相关区两部分,在每个区中,设备只设置必须的和与之相关的寄存器,一个设备的配置空间不仅在系统自举时可以访问,在其他时间也可以访问。

头标区的长度为64字节,偏移地址从00H到3FH,该区中的各个域用来识别各自不同的设备,并使设备能以一般的方法控制。每个设备都必须按照该区的格式和规定进行设置,而配置空间的其余192字节可以因设备而异。

通过系统配置软件,可以进行PCI总线的系统配置。进行配置时,是通过配置空间头标区中的寄存器来实现的,这些寄存器的具体格式与具体的设备有关,但必须遵守一些共同的规则。

图4.1为PCI配置空间头标区的结构图:

4.2 PCI配置驱动程序的结构

前面已经说过,PCI设备是一种接口标准,所有PCI设备都要服从这个标准,因此对于操作系统来说,无需为每个设备都单独编写一套驱动程序,而只需要写出一套符合PCI规范的驱动程序就能够满足操作系统配置PCI接口的要求了。从这个意义上来说,PCI接口驱动程序的结构相对要简单一些。

PCI总线驱动主要为上层软件提供两方面的接口,一方面用于系统内PCI设备接口的自动配置,另一方面则是用于系统内PCI设备接口的手工配置。对自动配置来说,它提供了一个自动配置函数,通过调用该函数完成了系统内所有需要自动配置的PCI接口的自动配置,并建立一个专门的数据结构来保存系统中所有自动配置设备的必要的信息;而对于手工配置来说,它也提供了手工配置的一系列操作函数。鉴于目前大多数的设备都采用自动配置的情况,本节只分析自动配置驱动程序结构。

图4.2描述了PCI接口驱动程序的结构。

VxWorks PCI Interface Device Driver Structure

图4.2 PCI接口驱动程序的结构下面将针对图中的各个函数进行详细说明。

4.2.1 基本配置函数库pciConfigLib

该函数库主要提供了一些PCI配置空间访问的一些基本的方法,通过这些底层的访问方法,函数库pciAutoConfigLib就可以完成系统内PCI接口的自动配置。本节还是通过最基本的函数分析研究函数库peiConfigLib提供给上层的基本的访问控制方法。

3.4 中断驱动程序的动态分析

3.4.1 中断驱动程序的初始化

中断驱动程序结构比较简单,因此该驱动的构建过程也比较简单,几个函数库都是静态构建的,唯一需要动态创建的就是中断控制芯片的初始化。

在函数sysHwInit()中调用了函数sysIntInitPIC ()完成了中断控制芯片的初始化,并指定intEoiGet = sysIntEoiGet。此后就可以正常使用中断驱动了。如图3.7。

VxWorks Interrupt Routine

图3.7 中断控制器的初始化过程

3.4.2 中断驱动程序的应用

中断驱动程序为上层应用程序提供了通用的函数接口,这些函数接口如表3.2所示。注意有些函数如sysLib中的sysIntInitPIC虽然属于提供给上层的函数,但是他的上层用户只有sysLib库的sysHwInit函数,因此不作为为上层应用软件提供的接口。

表格 3.2 中断驱动程序提供的通用函数接口

VxWorks Interrupt Routine

注意:控制CPU屏蔽中断和控制中断控制器屏蔽中断的作用是不同的,前者可以控制的中断范围更大,只要是可屏蔽中断都能完成;而后置控制的范围则较小,只有链接到中断控制器的外围中断才是可以屏蔽的。