static int fill_cache(epicsUInt16 dev,epicsUInt16 vend) { ELLNODE *cur; const dev_vend_entry *current; dev_vend_entry *next; for(cur=ellFirst(&dev_vend_cache); cur; cur=ellNext(cur)){ current=CONTAINER(cur,const dev_vend_entry,node); /* If one device is found then all must be in cache */ if( current->device==dev && current->vendor==vend ) return 0; } next=malloc(sizeof(dev_vend_entry)); if(!next) return S_dev_noMemory; next->device=dev; next->vendor=vend; if( sharedDevPCIFind(dev,vend,&devices) ){ free(next); return S_dev_addressNotFound; } /* Prepend */ ellInsert(&dev_vend_cache, NULL, &next->node); return 0; }
/* * devInsertAddress() */ static void devInsertAddress( ELLLIST *pRangeList, rangeItem *pNewRange) { rangeItem *pBefore; rangeItem *pAfter; epicsMutexMustLock(addrListLock); pAfter = (rangeItem *) ellFirst (pRangeList); while (pAfter) { if (pNewRange->end < pAfter->begin) { break; } pAfter = (rangeItem *) ellNext (&pAfter->node); } if (pAfter) { pBefore = (rangeItem *) ellPrevious (&pAfter->node); ellInsert (pRangeList, &pBefore->node, &pNewRange->node); } else { ellAdd (pRangeList, &pNewRange->node); } epicsMutexUnlock(addrListLock); }
static void inputOpenFile(inputData *pinputData,char *filename) { ELLLIST *ppathList = &pinputData->pathList; pathNode *ppathNode = 0; inputFile *pinputFile; char *fullname = 0; FILE *fp = 0; if(!filename) { fp = stdin; } else if((ellCount(ppathList)==0) || strchr(filename,'/')){ fp = fopen(filename,"r"); } else { ppathNode = (pathNode *)ellFirst(ppathList); while(ppathNode) { fullname = calloc(strlen(filename)+strlen(ppathNode->directory) +2, sizeof(char)); strcpy(fullname,ppathNode->directory); strcat(fullname,"/"); strcat(fullname,filename); fp = fopen(fullname,"r"); if(fp) break; free((void *)fullname); ppathNode = (pathNode *)ellNext(&ppathNode->node); } } if(!fp) { fprintf(stderr,"Could not open %s\n",filename); inputErrPrint((void *)pinputData); exit(1); } pinputFile = calloc(1,sizeof(inputFile)); if(ppathNode) { pinputFile->filename = calloc(1,strlen(fullname)+1); strcpy(pinputFile->filename,fullname); free((void *)fullname); } else if(filename) { pinputFile->filename = calloc(1,strlen(filename)+1); strcpy(pinputFile->filename,filename); } else { pinputFile->filename = calloc(1,strlen("stdin")+1); strcpy(pinputFile->filename,"stdin"); } pinputFile->fp = fp; ellInsert(&pinputData->inputFileList,0,&pinputFile->node); }
static void insertProvider(gtProvider *ptp, ELLLIST *plist, epicsMutexId lock) { gtProvider *ptpref; epicsMutexMustLock(lock); for (ptpref = (gtProvider *)ellFirst(plist); ptpref; ptpref = (gtProvider *)ellNext(&ptpref->node)) { if (ptpref->priority > ptp->priority) break; } if (ptpref) { /* Found a provider below the new one */ ptpref = (gtProvider *)ellPrevious(&ptpref->node); ellInsert(plist, &ptpref->node, &ptp->node); } else { ellAdd(plist, &ptp->node); } epicsMutexUnlock(lock); }
static void dbMenuBody(void) { dbMenu *pnewMenu; dbMenu *pMenu; int nChoice; int i; GPHENTRY *pgphentry; if(duplicate) { duplicate = FALSE; return; } pnewMenu = (dbMenu *)popFirstTemp(); pnewMenu->nChoice = nChoice = ellCount(&tempList)/2; pnewMenu->papChoiceName = dbCalloc(pnewMenu->nChoice,sizeof(char *)); pnewMenu->papChoiceValue = dbCalloc(pnewMenu->nChoice,sizeof(char *)); for(i=0; i<nChoice; i++) { pnewMenu->papChoiceName[i] = (char *)popFirstTemp(); pnewMenu->papChoiceValue[i] = (char *)popFirstTemp(); } if(ellCount(&tempList)) yyerrorAbort("dbMenuBody: tempList not empty"); /* Add menu in sorted order */ pMenu = (dbMenu *)ellFirst(&pdbbase->menuList); while(pMenu && strcmp(pMenu->name,pnewMenu->name) >0 ) pMenu = (dbMenu *)ellNext(&pMenu->node); if(pMenu) ellInsert(&pdbbase->menuList,ellPrevious(&pMenu->node),&pnewMenu->node); else ellAdd(&pdbbase->menuList,&pnewMenu->node); pgphentry = gphAdd(pdbbase->pgpHash,pnewMenu->name,&pdbbase->menuList); if(!pgphentry) { yyerrorAbort("gphAdd failed"); } else { pgphentry->userPvt = pnewMenu; } }
static void addToList(struct dbCommon *precord, scan_list *psl) { scan_element *pse, *ptemp; epicsMutexMustLock(psl->lock); pse = precord->spvt; if (pse == NULL) { pse = dbCalloc(1, sizeof(scan_element)); precord->spvt = pse; pse->precord = precord; } pse->pscan_list = psl; ptemp = (scan_element *)ellFirst(&psl->list); while (ptemp) { if (ptemp->precord->phas > precord->phas) { ellInsert(&psl->list, ellPrevious(&ptemp->node), &pse->node); break; } ptemp = (scan_element *)ellNext(&ptemp->node); } if (ptemp == NULL) ellAdd(&psl->list, (void *)pse); psl->modified = TRUE; epicsMutexUnlock(psl->lock); }
/* * devInstallAddr() */ static long devInstallAddr ( rangeItem *pRange, /* item on the free list to be split */ const char *pOwnerName, epicsAddressType addrType, size_t base, size_t size, volatile void **ppPhysicalAddress) { volatile void *pPhysicalAddress; rangeItem *pNewRange; size_t reqEnd = base + (size-1); long status; /* * does it start below the specified block */ if (base < pRange->begin) { return S_dev_badArgument; } /* * does it end above the specified block */ if (reqEnd > pRange->end) { return S_dev_badArgument; } /* * always map through the virtual os in case the memory * management is set up there */ status = (*pdevLibVME->pDevMapAddr) (addrType, 0, base, size, &pPhysicalAddress); if (status) { errPrintf (status, __FILE__, __LINE__, "%s base=0X%X size = 0X%X", epicsAddressTypeName[addrType], (unsigned int)base, (unsigned int)size); return status; } /* * set the callers variable if the pointer is supplied */ if (ppPhysicalAddress) { *ppPhysicalAddress = pPhysicalAddress; } /* * does it start at the beginning of the block */ if (pRange->begin == base) { if (pRange->end == reqEnd) { epicsMutexMustLock(addrListLock); ellDelete(&addrFree[addrType], &pRange->node); epicsMutexUnlock(addrListLock); free ((void *)pRange); } else { pRange->begin = base + size; } } /* * does it end at the end of the block */ else if (pRange->end == reqEnd) { pRange->end = base-1; } /* * otherwise split the item on the free list */ else { pNewRange = (rangeItem *) calloc (1, sizeof(*pRange)); if(!pNewRange){ return S_dev_noMemory; } pNewRange->begin = base + size; pNewRange->end = pRange->end; pNewRange->pOwnerName = "<fragmented block>"; pNewRange->pPhysical = NULL; pRange->end = base - 1; /* * add the node after the old item on the free list * (blocks end up ordered by address) */ epicsMutexMustLock(addrListLock); ellInsert(&addrFree[addrType], &pRange->node, &pNewRange->node); epicsMutexUnlock(addrListLock); } /* * allocate a new address range entry and add it to * the list */ pNewRange = (rangeItem *)calloc (1, sizeof(*pRange)); if (!pNewRange) { return S_dev_noMemory; } pNewRange->begin = base; pNewRange->end = reqEnd; pNewRange->pOwnerName = pOwnerName; pNewRange->pPhysical = pPhysicalAddress; devInsertAddress (&addrAlloc[addrType], pNewRange); return SUCCESS; }
/* * Process breakpoint * Returns a zero if dbProcess() is to execute * record support, a one if dbProcess() is to * skip over record support. See dbProcess(). * * 1. See if there is at least a breakpoint set somewhere * in precord's lockset. If not, return immediately. * 2. Check the disable flag. * 3. Add entry points to the queue for future stepping and * schedule new entrypoints for the continuation task. * 4. Check the pact flag. * 5. Check to see if there is a breakpoint set in a record, and * if so, turn on stepping mode. * 6. If stepping mode is set, stop and report the breakpoint. */ int epicsShareAPI dbBkpt(dbCommon *precord) { struct LS_LIST *pnode; struct EP_LIST *pqe; /* * It is crucial that operations in dbBkpt() execute * in the correct order or certain features in the * breakpoint handler will not work as expected. */ /* * Take and give a semaphore to check for breakpoints * every time a record is processed. Slow. Thank * goodness breakpoint checking is turned off during * normal operation. */ epicsMutexMustLock(bkpt_stack_sem); FIND_LOCKSET(precord, pnode); epicsMutexUnlock(bkpt_stack_sem); if (pnode == NULL) { /* no breakpoints in precord's lockset */ return(0); } /* Check disable flag */ dbGetLink(&(precord->sdis),DBR_SHORT,&(precord->disa),0,0); if (precord->disa == precord->disv) { /* * Do not process breakpoints if the record is disabled, * but allow disable alarms. Alarms will be raised * in dbProcess() because returning 0 allows dbProcess() * to continue. However processing will be prevented * because disa and disv will be examined again in * dbProcess(). Note that checking for pact will occur * before checking for disa and disv in dbProcess(). */ return(0); } /* * Queue entry points for future stepping. The taskid comparison * is used to determine if the source of processing is the * continuation task or an external source. If it is an external * source, queue its execution, but dump out of dbProcess without * calling record support. */ if (pnode->taskid && (epicsThreadGetIdSelf() != pnode->taskid)) { /* CONTINUE TASK CANNOT ENTER HERE */ /* * Add an entry point to queue, if it does * not already exist. */ FIND_QUEUE_ENTRY(&pnode->ep_queue, pqe, precord); if (pqe == NULL) { pqe = (struct EP_LIST *) malloc(sizeof(struct EP_LIST)); if (pqe == NULL) return(1); pqe->entrypoint = precord; pqe->count = 1; epicsTimeGetCurrent(&pqe->time); pqe->sched = 0; #ifdef BKPT_DIAG printf(" BKPT> Adding entrypoint %s to queue\n", precord->name); #endif /* * Take semaphore, wait on continuation task */ epicsMutexMustLock(bkpt_stack_sem); /* Add entry to queue */ ellAdd(&pnode->ep_queue, (ELLNODE *)pqe); epicsMutexUnlock(bkpt_stack_sem); } else { if (pqe->count < MAX_EP_COUNT) pqe->count++; } /* check pact */ if (! precord->pact) { /* schedule if pact not set */ pqe->sched = 1; /* * Release the semaphore, letting the continuation * task begin execution of the new entrypoint. */ epicsEventSignal(pnode->ex_sem); } return(1); } /* * Don't mess with breakpoints if pact set! Skip * over rest of dbProcess() since we don't want * alarms going off. The pact flag is checked * AFTER entry point queuing so that the record * timing feature will work properly. */ if (precord->pact) return(1); /* Turn on stepping mode if a breakpoint is found */ if (precord->bkpt & BKPT_ON_MASK) { pnode->step = 1; #ifdef BKPT_DIAG printf(" BKPT> Bkpt detected: %s\n", precord->name); #endif } /* * If we are currently stepping through the lockset, * suspend task. */ if (pnode->step) { printf("\n BKPT> Stopped at: %s within Entrypoint: %s\n-> ", precord->name, pnode->current_ep->name); pnode->precord = precord; /* Move current lockset to top of stack */ ellDelete(&lset_stack, (ELLNODE *)pnode); ellInsert(&lset_stack, NULL, (ELLNODE *)pnode); /* * Unlock database while the task suspends itself. This * is done so that dbb() dbd() dbc() dbs() may be used * when the task is suspended. Scan tasks that also * use the scan lock feature will not be hung during * a breakpoint, so that records in other locksets will * continue to be processed. Cross your fingers, this * might actually work ! */ epicsMutexUnlock(bkpt_stack_sem); dbScanUnlock(precord); epicsThreadSuspendSelf(); dbScanLock(precord); epicsMutexMustLock(bkpt_stack_sem); } return(0); }
void seq566set(int id, int ch, int nsamp, int ord, int prio, int stop) { xy566 *card=get566(id); ELLNODE *node, *prev; seqent *ent; if(card->fail) return; if(!card){ printf("Invalid ID\n"); card->fail=1; return; } if(ch<0 || ch>card->nchan){ printf("Invalid channel (0->%d)\n",card->nchan-1); card->fail=1; return; } if(nsamp<1 || nsamp>256){ /* This is just a first pass to catch the * obviously impossible. * The actual max number of samples will depend * on what other channels are used */ printf("Invalid number of samples\n"); card->fail=1; return; } if(stop<0 || stop>nsamp){ printf("Stop sample must be between 0 and %u\n",nsamp); card->fail=1; return; } if(ord<0 || ord >= card->nchan){ printf("Invalid order (1->%d)\n",card->nchan); card->fail=1; return; } if(prio<1 || prio >= card->nchan){ printf("Invalid priority (1->%d)\n",card->nchan); card->fail=1; return; } /* Search to see that the rules are followed */ for(node=ellFirst(&card->seq_ctor), prev=NULL; node; prev=node, node=ellNext(node) ){ ent=node2seqent(node); if(ent->channel==ch){ printf("Channel %d already used\n",ch); card->fail=1; return; }else if(ent->order == ord && ent->priority == prio){ printf("Order %d and prio %d are already used by channel %u\n", ord,prio,(unsigned)ent->channel); card->fail=1; return; }else if(ent->order == ord && ent->nsamples != nsamp){ printf("Order %d must have size %u\n", ord,(unsigned)ent->nsamples); card->fail=1; return; } } /* find location for insertion which maintains * sorted order */ for(node=ellFirst(&card->seq_ctor), prev=NULL; node; prev=node, node=ellNext(node) ){ ent=node2seqent(node); if(ent->order > ord) break; else if(ent->order == ord && ent->priority > prio) break; } /* node and/or prev may be NULL if this * entry is to be placed at the start * of the list */ ent=malloc(sizeof(seqent)); if(!ent){ printf("Out of memory\n"); card->fail=1; return; } ent->channel=ch; ent->nsamples=nsamp; ent->order=ord; ent->priority=prio; ent->stop=stop; /* Inserts between prev and node */ ellInsert(&card->seq_ctor, prev, &ent->node); }
static int sharedDevPCIFind(epicsUInt16 dev,epicsUInt16 vend,ELLLIST* store) { int N, ret=0, err; int b, d, f, region; /* Read config space */ uint8_t val8; uint16_t val16; UINT32 val32; for(N=0; ; N++){ osdPCIDevice *next=calloc(1,sizeof(osdPCIDevice)); if(!next) return S_dev_noMemory; err=pci_find_device(vend,dev,N, &b, &d, &f); if(err){ /* No more */ if(N==0 && devPCIDebug>=1) errlogPrintf("sharedDevPCIFind: found no vendor:device with %04x:%04x\n",vend,dev); free(next); break; } next->dev.bus=b; next->dev.device=d; next->dev.function=f; if(devPCIDebug>=1) errlogPrintf("sharedDevPCIFind found %d.%d.%d\n",b,d,f); pci_read_config_word(b,d,f,PCI_DEVICE_ID, &val16); next->dev.id.device=val16; pci_read_config_word(b,d,f,PCI_VENDOR_ID, &val16); next->dev.id.vendor=val16; pci_read_config_word(b,d,f,PCI_SUBSYSTEM_ID, &val16); next->dev.id.sub_device=val16; pci_read_config_word(b,d,f,PCI_SUBSYSTEM_VENDOR_ID, &val16); next->dev.id.sub_vendor=val16; pci_read_config_dword(b,d,f,PCI_CLASS_REVISION, &val32); next->dev.id.revision=val32&0xff; next->dev.id.pci_class=val32>>8; for(region=0;region<PCIBARCOUNT;region++){ pci_read_config_dword(b,d,f,PCI_BASE_ADDRESS(region), &val32); next->dev.bar[region].ioport=(val32 & PCI_BASE_ADDRESS_SPACE)==PCI_BASE_ADDRESS_SPACE_IO; if(next->dev.bar[region].ioport){ /* This BAR is I/O ports */ next->dev.bar[region].below1M=0; next->dev.bar[region].addr64=0; next->base[region]=(volatile void*)( val32 & PCI_BASE_ADDRESS_IO_MASK ); next->len[region]=0; }else{ /* This BAR is memory mapped */ next->dev.bar[region].below1M=!!(val32&PCI_BASE_ADDRESS_MEM_TYPE_1M); next->dev.bar[region].addr64=!!(val32&PCI_BASE_ADDRESS_MEM_TYPE_64); next->base[region]=(volatile void*)( val32 & PCI_BASE_ADDRESS_MEM_MASK ); next->len[region]=0; } } pci_read_config_dword(b,d,f,PCI_ROM_ADDRESS, &val32); next->erom=(volatile void*)(val32 & PCI_ROM_ADDRESS_MASK); pci_read_config_byte(b,d,f,PCI_INTERRUPT_LINE, &val8); next->dev.irq=val8; if(devPCIDebug>=1) errlogPrintf(" as pri %04x:%04x sub %04x:%04x cls %06x\n", next->dev.id.vendor, next->dev.id.device, next->dev.id.sub_vendor, next->dev.id.sub_device, next->dev.id.pci_class); ellInsert(store,NULL,&next->node); } return ret; }
static void dbBreakBody(void) { brkTable *pnewbrkTable; brkInt *paBrkInt; brkTable *pbrkTable; int number, down=0; int i; GPHENTRY *pgphentry; if (duplicate) { duplicate = FALSE; return; } pnewbrkTable = (brkTable *)popFirstTemp(); number = ellCount(&tempList); if (number % 2) { yyerrorAbort("breaktable: Raw value missing"); return; } number /= 2; if (number < 2) { yyerrorAbort("breaktable: Must have at least two points!"); return; } pnewbrkTable->number = number; pnewbrkTable->paBrkInt = paBrkInt = dbCalloc(number, sizeof(brkInt)); for (i=0; i<number; i++) { char *str; str = (char *)popFirstTemp(); epicsScanDouble(str, &paBrkInt[i].raw); free(str); str = (char *)popFirstTemp(); epicsScanDouble(str, &paBrkInt[i].eng); free(str); } /* Compute slopes */ for (i=0; i<number-1; i++) { double slope = (paBrkInt[i+1].eng - paBrkInt[i].eng)/ (paBrkInt[i+1].raw - paBrkInt[i].raw); if (!dbBptNotMonotonic && slope == 0) { yyerrorAbort("breaktable slope is zero"); return; } if (i == 0) { down = (slope < 0); } else if (!dbBptNotMonotonic && down != (slope < 0)) { yyerrorAbort("breaktable slope changes sign"); return; } paBrkInt[i].slope = slope; } /* Continue with last slope beyond the final point */ paBrkInt[number-1].slope = paBrkInt[number-2].slope; /* Add brkTable in sorted order */ pbrkTable = (brkTable *)ellFirst(&pdbbase->bptList); while (pbrkTable) { if (strcmp(pbrkTable->name, pnewbrkTable->name) > 0) { ellInsert(&pdbbase->bptList, ellPrevious((ELLNODE *)pbrkTable), (ELLNODE *)pnewbrkTable); break; } pbrkTable = (brkTable *)ellNext(&pbrkTable->node); } if (!pbrkTable) ellAdd(&pdbbase->bptList, &pnewbrkTable->node); pgphentry = gphAdd(pdbbase->pgpHash,pnewbrkTable->name,&pdbbase->bptList); if (!pgphentry) { yyerrorAbort("dbBreakBody: gphAdd failed"); return; } pgphentry->userPvt = pnewbrkTable; }
static int linuxDevPCIInit(void) { DIR* sysfsPci_dir=NULL; struct dirent* dir; int i; osdPCIDevice *osd=NULL; pciLock = epicsMutexMustCreate(); int host_is_first = 0; pagesize=sysconf(_SC_PAGESIZE); if (pagesize==-1) { perror("Failed to get pagesize"); goto fail; } sysfsPci_dir = opendir("/sys/bus/pci/devices"); if (!sysfsPci_dir){ fprintf(stderr, "Could not open /sys/bus/pci/devices!\n"); goto fail; } while ((dir=readdir(sysfsPci_dir))) { char* filename; FILE* file; int fail=0; int match; unsigned long long int start,stop,flags; char dname[80]; if (!dir->d_name || dir->d_name[0]=='.') continue; /* Skip invalid entries */ osd=calloc(1, sizeof(osdPCIDevice)); if (!osd) { errMessage(S_dev_noMemory, "Out of memory"); goto fail; } osd->fd=-1; osd->cfd = -1; for ( i=0; i<sizeof(osd->rfd)/sizeof(osd->rfd[0]); i++ ) osd->rfd[i] = -1; osd->dev.slot = DEVPCI_NO_SLOT; match = sscanf(dir->d_name,"%x:%x:%x.%x", &osd->dev.domain,&osd->dev.bus,&osd->dev.device,&osd->dev.function); if (match != 4){ fprintf(stderr, "Could not decode PCI device directory %s\n", dir->d_name); } osd->dev.id.vendor=read_sysfs(&fail, BUSBASE "vendor", osd->dev.domain, osd->dev.bus, osd->dev.device, osd->dev.function); osd->dev.id.device=read_sysfs(&fail, BUSBASE "device", osd->dev.domain, osd->dev.bus, osd->dev.device, osd->dev.function); osd->dev.id.sub_vendor=read_sysfs(&fail, BUSBASE "subsystem_vendor", osd->dev.domain, osd->dev.bus, osd->dev.device, osd->dev.function); osd->dev.id.sub_device=read_sysfs(&fail, BUSBASE "subsystem_device", osd->dev.domain, osd->dev.bus, osd->dev.device, osd->dev.function); osd->dev.id.pci_class=read_sysfs(&fail, BUSBASE "class", osd->dev.domain, osd->dev.bus, osd->dev.device, osd->dev.function); osd->dev.irq=read_sysfs(&fail, BUSBASE "irq", osd->dev.domain, osd->dev.bus, osd->dev.device, osd->dev.function); osd->dev.id.revision=0; if (fail) { fprintf(stderr, "Warning: Failed to read some attributes of PCI device %04x:%02x:%02x.%x\n" " This may cause some searches to fail\n", osd->dev.domain, osd->dev.bus, osd->dev.device, osd->dev.function); fail=0; } if(devPCIDebug>=1) { fprintf(stderr, "linuxDevPCIInit found %04x:%02x:%02x.%x\n", osd->dev.domain, osd->dev.bus, osd->dev.device, osd->dev.function); fprintf(stderr, " as pri %04x:%04x sub %04x:%04x cls %06x\n", osd->dev.id.vendor, osd->dev.id.device, osd->dev.id.sub_vendor, osd->dev.id.sub_device, osd->dev.id.pci_class); } /* Read BAR info */ /* Base address */ filename = allocPrintf(BUSBASE "resource", osd->dev.domain, osd->dev.bus, osd->dev.device, osd->dev.function); if (!filename) { errMessage(S_dev_noMemory, "Out of memory"); goto fail; } file=fopen(filename, "r"); if (!file) { fprintf(stderr, "Could not open resource file %s!\n", filename); free(filename); continue; } for (i=0; i<PCIBARCOUNT; i++) { /* read 6 BARs */ match = fscanf(file, "0x%16llx 0x%16llx 0x%16llx\n", &start, &stop, &flags); if (match != 3) { fprintf(stderr, "Could not parse line %i of %s\n", i+1, filename); continue; } osd->dev.bar[i].ioport = (flags & PCI_BASE_ADDRESS_SPACE)==PCI_BASE_ADDRESS_SPACE_IO; osd->dev.bar[i].below1M = !!(flags&PCI_BASE_ADDRESS_MEM_TYPE_1M); osd->dev.bar[i].addr64 = !!(flags&PCI_BASE_ADDRESS_MEM_TYPE_64); osd->displayBAR[i] = start; /* offset from start of page to start of BAR */ osd->offset[i] = osd->displayBAR[i]&(pagesize-1); /* region length */ osd->len[i] = (start || stop ) ? (stop - start + 1) : 0; } /* rom */ match = fscanf(file, "%llx %llx %llx\n", &start, &stop, &flags); if (match != 3) { fprintf(stderr, "Could not parse line %i of %s\n", i+1, filename); start = 0; stop = 0; } osd->displayErom = start; osd->eromlen = (start || stop ) ? (stop - start + 1) : 0; fclose(file); free(filename); /* driver name */ filename = allocPrintf(BUSBASE "driver", osd->dev.domain, osd->dev.bus, osd->dev.device, osd->dev.function); if (!filename) { errMessage(S_dev_noMemory, "Out of memory"); goto fail; } memset (dname, 0, sizeof(dname)); if (readlink(filename, dname, sizeof(dname)-1) != -1) osd->dev.driver = epicsStrDup(basename(dname)); free(filename); osd->devLock = epicsMutexMustCreate(); if (!ellCount(&devices)) { host_is_first = (osd->dev.bus == 0 && osd->dev.device == 0); } ellInsert(&devices,host_is_first?ellLast(&devices):NULL,&osd->node); osd=NULL; } if (sysfsPci_dir) closedir(sysfsPci_dir); sysfsPci_dir = opendir(linuxslotsdir); if (sysfsPci_dir){ while ((dir=readdir(sysfsPci_dir))) { unsigned dom, B, D; char *fullname; FILE *fp; if (!dir->d_name || dir->d_name[0]=='.') continue; /* Skip invalid entries */ if(devPCIDebug>4) fprintf(stderr, "examine /slots entry '%s'\n", dir->d_name); fullname = allocPrintf("%s/%s/address", linuxslotsdir, dir->d_name); if(!fullname) continue; if(devPCIDebug>3) fprintf(stderr, "found '%s'\n", fullname); if((fp=fopen(fullname, "r"))!=NULL) { if(fscanf(fp, "%x:%x:%x", &dom, &B, &D)==3) { ELLNODE *cur; if(devPCIDebug>2) fprintf(stderr, "found slot %s with %04u:%02u:%02u.*\n", dir->d_name, dom, B, D); for(cur=ellFirst(&devices); cur; cur=ellNext(cur)) { osdPCIDevice *osd = CONTAINER(cur, osdPCIDevice, node); if(osd->dev.domain!=dom || osd->dev.bus!=B || osd->dev.device!=D) continue; if(osd->dev.slot==DEVPCI_NO_SLOT) { osd->dev.slot = strdup(dir->d_name); // return NULL would mean slot remains unlabeled } else { fprintf(stderr, "Duplicate slot address for %s\n", dir->d_name); } } } fclose(fp); } free(fullname); } closedir(sysfsPci_dir); } else if(devPCIDebug>0) { fprintf(stderr, "/sys does not provide PCI slots listing\n"); } return 0; fail: if (sysfsPci_dir) closedir(sysfsPci_dir); epicsMutexDestroy(pciLock); return S_dev_badInit; }