17 #include <epicsThread.h> 18 #include <epicsMutex.h> 20 #include <epicsStdio.h> 22 #define epicsExportSharedSymbols 28 # define CONTAINER(ptr, structure, member) ({ \ 29 const __typeof(((structure*)0)->member) *_ptr = (ptr); \ 30 (structure*)((char*)_ptr - offsetof(structure, member)); \ 33 # define CONTAINER(ptr, structure, member) \ 34 ((structure*)((char*)(ptr) - offsetof(structure, member))) 38 #if defined(vxWorks) && !defined(_WRS_VXWORKS_MAJOR) 40 #define strdup(x) ({char*s=malloc(strlen(x)+1);s?strcpy(s,x):s;}) 45 #define strtok_r strtok_s 50 static ELLLIST pciDrivers;
54 static epicsMutexId pciDriversLock;
55 static epicsThreadOnceId devPCIReg_once = EPICS_THREAD_ONCE_INIT;
57 static epicsThreadOnceId devPCIInit_once = EPICS_THREAD_ONCE_INIT;
58 static int devPCIInit_result = 42;
63 void regInit(
void* junk)
66 pciDriversLock = epicsMutexMustCreate();
75 if (!drv->
name)
return 1;
77 if(drvsize!=
sizeof(*drv)) {
78 fprintf(stderr,
"devLibPCIRegisterDriver() fails with inconsistent PCI OS struct sizes.\n" 79 "expect %lu but given %lu\n" 80 "Please do a clean rebuild of devLib2 and any code with custom PCI OS structs\n",
81 (
unsigned long)
sizeof(*drv),
82 (
unsigned long)drvsize);
83 return S_dev_internal;
86 epicsThreadOnce(&devPCIReg_once, ®Init, NULL);
88 epicsMutexMustLock(pciDriversLock);
90 for(cur=ellFirst(&pciDrivers); cur; cur=ellNext(cur)) {
92 if (strcmp(drv->
name, other->
name)==0) {
93 fprintf(stderr,
"Failed to register PCI bus driver: name already taken\n");
99 ellAdd(&pciDrivers, &drv->
node);
101 epicsMutexUnlock(pciDriversLock);
115 epicsThreadOnce(&devPCIReg_once, ®Init, NULL);
117 epicsMutexMustLock(pciDriversLock);
120 epicsMutexUnlock(pciDriversLock);
121 fprintf(stderr,
"PCI bus driver already selected. Can't change selection\n");
125 for(cur=ellFirst(&pciDrivers); cur; cur=ellNext(cur)) {
127 if (strcmp(drv->
name, use)==0) {
129 epicsMutexUnlock(pciDriversLock);
133 epicsMutexUnlock(pciDriversLock);
134 fprintf(stderr,
"PCI bus driver '%s' not found\n",use);
140 const char* ret=NULL;
142 epicsThreadOnce(&devPCIReg_once, ®Init, NULL);
144 epicsMutexMustLock(pciDriversLock);
146 ret = pdevLibPCI->
name;
147 epicsMutexUnlock(pciDriversLock);
156 if(
devPCIDebug>1) printf(
" mismatch device %x %x\n",
160 if(
devPCIDebug>1) printf(
" mismatch vendor %x %x\n",
164 if(
devPCIDebug>1) printf(
" mismatch subdevice %x %x\n",
168 if(
devPCIDebug>1) printf(
" mismatch subvendor %x %x\n",
172 if(
devPCIDebug>1) printf(
" mismatch class %x %x\n",
176 if(
devPCIDebug>1) printf(
" mismatch revision %x %x\n",
187 void devInit(
void* junk)
190 epicsThreadOnce(&devPCIReg_once, ®Init, NULL);
191 epicsMutexMustLock(pciDriversLock);
193 epicsMutexUnlock(pciDriversLock);
194 devPCIInit_result = S_dev_internal;
197 epicsMutexUnlock(pciDriversLock);
200 devPCIInit_result = (*pdevLibPCI->
pDevInit)();
202 devPCIInit_result = 0;
207 epicsThreadOnce(&devPCIInit_once, &devInit, NULL); \ 208 if (devPCIInit_result) return devPCIInit_result; \ 221 if(!idlist || !searchfn)
222 return S_dev_badArgument;
226 return (*pdevLibPCI->
pDevPCIFind)(idlist,searchfn,arg,opt);
276 memset(&find, 0,
sizeof(find));
279 return S_dev_badArgument;
289 fprintf(stderr,
"Notice: devPCIFindSpec() expect B:D.F in hex\n");
296 char *save, *alloc, *tok;
298 alloc = strdup(spec);
299 if(!alloc)
return S_dev_noMemory;
301 for(tok = strtok_r(alloc,
" ", &save);
303 tok=strtok_r(NULL,
" ", &save))
305 unsigned dom, bus, dev, func=0;
307 if(sscanf(tok,
"%x:%x:%x.%x", &dom, &bus, &dev, &func)>=3) {
314 }
else if(sscanf(tok,
"%x:%x.%x", &bus, &dev, &func)>=2) {
321 }
else if(sscanf(tok,
"slot=%10s", find.
slot)==1) {
322 if(strlen(find.
slot)==10)
323 fprintf(stderr,
"Slot label '%s' truncated?\n", find.
slot);
326 }
else if(sscanf(tok,
"instance=%u", &dom)==1) {
327 find.
stopat = dom==0 ? 0 : dom-1;
329 }
else if(sscanf(tok,
"inst=%u", &dom)==1) {
330 find.
stopat = dom==0 ? 0 : dom-1;
332 }
else if(strchr(tok,
'=')!=NULL) {
333 fprintf(stderr,
"Ignoring unknown spec '%s'\n", tok);
336 fprintf(stderr,
"Error: invalid spec '%s'\n", tok);
337 err = S_dev_badArgument;
349 fprintf(stderr,
" Match BDF %x:%x:%x.%x\n",
352 fprintf(stderr,
" Match slot %s\n", find.
slot);
353 fprintf(stderr,
" Instance %u\n", find.
stopat);
366 return S_dev_noDevice;
390 return S_dev_badArgument;
392 memset(&find, 0,
sizeof(find));
410 return S_dev_noDevice;
434 volatile void **ppLocalAddr,
441 return S_dev_badArgument;
458 return S_dev_badArgument;
465 void (*pFunction)(
void *),
473 (curdev,pFunction,parameter,opt);
478 void (*pFunction)(
void *),
485 (curdev,pFunction,parameter);
518 printf(
"Matched %d devices\n", info.
matched);
536 printf(
"No match\n");
545 printf(
"PCI %04x:%02x:%02x.%x IRQ %u\n" 546 " vendor:device %04x:%04x rev %02x\n",
551 printf(
" subved:subdev %04x:%04x\n" 557 printf(
" slot: %s\n", dev->
slot);
558 if (dev->
driver) printf(
" driver %s\n",
566 if ((*pdevLibPCI->
pDevPCIBarLen)(dev, i, &len) == 0 && len > 0)
569 if (len >= 1024) { len >>= 10; u =
"k"; }
570 if (len >= 1024) { len >>= 10; u =
"M"; }
571 if (len >= 1024) { len >>= 10; u =
"G"; }
573 printf(
" BAR %u %s-bit %s%s %3u %sB\n",i,
590 return S_dev_badArgument;
592 return S_dev_badFunction;
605 return checkCfgAccess(dev, offset, pResult,
RD_08);
611 return checkCfgAccess(dev, offset, pResult,
RD_16);
617 return checkCfgAccess(dev, offset, pResult,
RD_32);
623 return checkCfgAccess(dev, offset, &value,
WR_08);
629 return checkCfgAccess(dev, offset, &value,
WR_16);
635 return checkCfgAccess(dev, offset, &value,
WR_32);
643 return S_dev_badFunction;
652 return S_dev_badFunction;
658 static const iocshArg devPCIShowArg0 = {
"verbosity level",iocshArgInt};
659 static const iocshArg devPCIShowArg1 = {
"PCI Vendor ID (0=any)",iocshArgInt};
660 static const iocshArg devPCIShowArg2 = {
"PCI Device ID (0=any)",iocshArgInt};
661 static const iocshArg devPCIShowArg3 = {
"exact (1=treat 0 as 0)",iocshArgInt};
662 static const iocshArg *
const devPCIShowArgs[4] =
663 {&devPCIShowArg0,&devPCIShowArg1,&devPCIShowArg2,&devPCIShowArg3};
664 static const iocshFuncDef devPCIShowFuncDef =
665 {
"devPCIShow",4,devPCIShowArgs};
666 static void devPCIShowCallFunc(
const iocshArgBuf *args)
668 devPCIShow(args[0].ival,args[1].ival,args[2].ival,args[3].ival);
671 static const iocshArg devLibPCIUseArg0 = {
"verbosity level",iocshArgString};
672 static const iocshArg *
const devLibPCIUseArgs[1] =
674 static const iocshFuncDef devLibPCIUseFuncDef =
675 {
"devLibPCIUse",1,devLibPCIUseArgs};
676 static void devLibPCIUseCallFunc(
const iocshArgBuf *args)
681 #include <epicsExport.h> 684 void devLibPCIIOCSH()
686 iocshRegister(&devPCIShowFuncDef,devPCIShowCallFunc);
687 iocshRegister(&devLibPCIUseFuncDef,devLibPCIUseCallFunc);
#define DEVPCI_END
The last item in a list of PCI IDS.
#define DEVPCI_ANY_REVISION
int(* devPCISearchFn)(void *ptr, const epicsPCIDevice *dev)
PCI search callback prototype.
#define DEVPCI_ANY_SUBVENDOR
int devPCIEnableInterrupt(const epicsPCIDevice *dev)
Enable interrupts at the device.
const char * devLibPCIDriverName()
int devPCIConnectInterrupt(const epicsPCIDevice *curdev, void(*pFunction)(void *), void *parameter, unsigned int opt)
Request interrupts for device.
int(* pDevPCISwitchInterrupt)(const epicsPCIDevice *id, int level)
int devPCIConfigWrite32(const epicsPCIDevice *dev, unsigned offset, epicsUInt32 value)
Write (32-bit) dword from configuration space.
int devPCIDisableInterrupt(const epicsPCIDevice *dev)
Enable interrupts at the device.
int devLibPCIMatch(const epicsPCIID *match, const epicsPCIID *dev)
#define DEVPCI_DEVICE_VENDOR(dev, vend)
int devPCIConfigWrite16(const epicsPCIDevice *dev, unsigned offset, epicsUInt16 value)
Write (16-bit) word from configuration space.
int devPCIConfigRead8(const epicsPCIDevice *dev, unsigned offset, epicsUInt8 *pResult)
Read byte from configuration space.
#define PCIBARCOUNT
The maximum number of base address registers (BARs).
#define CONTAINER(ptr, structure, member)
const epicsPCIDevice * found
int devPCIToLocalAddr(const epicsPCIDevice *curdev, unsigned int bar, volatile void **ppLocalAddr, unsigned int opt)
Get pointer to PCI BAR.
void devPCIShowDevice(int lvl, const epicsPCIDevice *dev)
#define DEVPCI_ANY_VENDOR
int devLibPCIRegisterDriver2(devLibPCI *drv, size_t drvsize)
#define CFG_ACC_WIDTH(mode)
int(* pDevPCIConfigAccess)(const epicsPCIDevice *id, unsigned offset, void *pArg, devPCIAccessMode mode)
void devPCIShowMatch(int lvl, const char *spec, int vendor, int device)
int devPCIConfigRead16(const epicsPCIDevice *dev, unsigned offset, epicsUInt16 *pResult)
Read (16-bit) word from configuration space.
int(* pDevPCIDisconnectInterrupt)(const epicsPCIDevice *id, void(*pFunction)(void *), void *parameter)
int devPCIFindDBDF(const epicsPCIID *idlist, unsigned int domain, unsigned int b, unsigned int d, unsigned int f, const epicsPCIDevice **found, unsigned int opt)
PCI bus probe.
int(* pDevPCIToLocalAddr)(const epicsPCIDevice *dev, unsigned int bar, volatile void **a, unsigned int o)
int devPCIFindSpec(const epicsPCIID *idlist, const char *spec, const epicsPCIDevice **found, unsigned int opt)
PCI bus search by specification string.
int devPCIDisconnectInterrupt(const epicsPCIDevice *curdev, void(*pFunction)(void *), void *parameter)
Stop receiving interrupts.
int devPCIConfigWrite8(const epicsPCIDevice *dev, unsigned offset, epicsUInt8 value)
Write byte to configuration space.
int(* pDevPCIFind)(const epicsPCIID *ids, devPCISearchFn searchfn, void *arg, unsigned int o)
#define DEVPCI_ANY_SUBDEVICE
epicsExportAddress(int, devPCIDebug)
int devPCIFindBDF(const epicsPCIID *idlist, unsigned int b, unsigned int d, unsigned int f, const epicsPCIDevice **found, unsigned int opt)
int devLibPCIUse(const char *use)
Select driver implementation. Pick driver implementation by name, or NULL to use default. If no selection is made then the default will be used if available.
epicsShareFunc const char * devPCIDeviceClassToString(int classId)
Translate class id to string.
#define DEVPCI_ANY_DEVICE
int(* pDevPCIConnectInterrupt)(const epicsPCIDevice *id, void(*pFunction)(void *), void *parameter, unsigned int opt)
void devPCIShow(int lvl, int vendor, int device, int exact)
int devPCIBarLen(const epicsPCIDevice *curdev, unsigned int bar, epicsUInt32 *len)
Find the size of a BAR.
epicsPCIID id
Exact ID of device.
int devPCIConfigRead32(const epicsPCIDevice *dev, unsigned offset, epicsUInt32 *pResult)
Read (32-bit) dword from configuration space.
int devPCIFindCB(const epicsPCIID *idlist, devPCISearchFn searchfn, void *arg, unsigned int opt)
PCI bus search w/ callback.
epicsExportRegistrar(devLibPCIIOCSH)
int(* pDevPCIBarLen)(const epicsPCIDevice *dev, unsigned int bar, epicsUInt32 *len)