发现pci设备

pci设备驱动开发,首先是要发现pci设备,从中获得pci设备的配置空间,并从中得到基本基本的资源信息。

首先进行pci设备查找的函数为:

STATUS pciFindDevice



int vendorId,

int deviceId,

int index,

int *pBusNo,

int *pDeviceNo,

int *pFuncNo


函数中的参数从命名来看都很好理解,注意第三个参数 ‘index’,这是在系统中有多个pci设备时我们需要从0开始查找,知道查找到我们想要驱动设备(第一个参数vendorId和第二个参数deviceId相同的设备)。

从参数列表中我们可以看到,后面三个参数都是指针类型,这三个参数就是唯一标识该pci设备的资源参数,也是我们在查找pci设备的时候需要获得该设备空间中的pci设备资源。

根据上面的说明我们可以写出这样的代码来查找pci设备:

int pciBus, pciDevice, pciFunc;

int found = 0;

int i;

for (i=0; i<DEV_MAX_NUM; i++) {

if (pciFindDevice(VENDOR_ID,DEVICE_ID,i,&pciBus,&pciDevice,&pciFunc)

== OK) {

found = TRUE;

printf("pci device found!\n");

break;

}

}


注:一定要保证VENDOR_ID,DEVICE_ID的正确性。可以将设备上电之后通过pciDeviceShow命令来查看系统中pci设备的详细信息。为了安全起见最好,打印设备已经找到的信息。如上例,如果找不到函数应该立刻返回。代码中的found就是用来预防找不到设备的情况。

当查找到对应的设备之后,我们需要获取该设备配置空间的基本资源。

  DRV_CTRL * pDrvCtrl;

pDrvCtrl = calloc(1, sizeof(DRV_CTRL));

pDrvCtrl->pciBus = pciBus;

pDrvCtrl->pciDevice = pciDevice;

pDrvCtrl->pciFunc = pciFunc;


第一句是为该设备分配内存空间,其中DRV_CTRL的定义见“WindRiver驱动开发基础”这篇文章。

要访问pci设备空间有专门的访问控制函数,这里我们使用:

pciConfigInLong():从pci配置空间指定位置读取一个字长。

pciConfigInLong



int busNo,

int deviceNo,

int funcNo,

int offset,

UINT32 *pData


注:最后一个参数用于存放都会的数据

通过pciConfigInLong()函数我们需要获取下面的几个信息:IO地址,PCI设备地址,中断号。并且需要映射内存,使能I/O

代码如下:

   UINT32 membaseCsr;

UINT32 iobaseCsr;

UINT8 irq;

pciConfigInLong(pDrvCtrl->pciBus, pDrvCtrl->pciDevice, pDrvCtrl->pciFunc,PCI_CFG_BASE_ADDRESS_0, &iobaseCsr);

pciConfigInLong(pDrvCtrl->pciBus, pDrvCtrl->pciDevice, pDrvCtrl->pciFunc,PCI_CFG_BASE_ADDRESS_1, &membaseCsr);

pciConfigInByte(pDrvCtrl->pciBus, pDrvCtrl->pciDevice, pDrvCtrl->pciFunc,PCI_CFG_DEV_INT_LINE, &irq);

pciConfigOutWord(pciBus, pciDevice, pciFunc, PCI_CFG_COMMAND,CI_CMD_IO_ENABLE | PCI_CMD_MEM_ENABLE | PCI_CMD_MASTER_ENABLE);

membaseCsr &=PCI_MEMBASE_MASK;
iobaseCsr &=PCI_IOBASE_MASK;

pDrvCtrl->membase = membaseCsr;

pDrvCtrl->iobase = iobaseCsr;

pDrvCtrl->created = 0;

pDrvCtrl->irq = irq;

/*为了便于后面使用IO地址将IO地址专门保存本起来*/

ioaddr = iobaseCsr;

至此pci设备的发现,设备空间的资源获取就完成,接下来的任务是创建设备,注册设备,与硬件通信等。

还需要注意的是WindRiver中不允许'//'类型的代码注释,如上面代码中的注释只能使用'/**/'。

make it simple, make it happen
原文地址:https://www.cnblogs.com/zhuyp1015/p/2373950.html