diff options
author | Bill Nottingham <notting@redhat.com> | 1999-07-01 15:45:41 +0000 |
---|---|---|
committer | Bill Nottingham <notting@redhat.com> | 1999-07-01 15:45:41 +0000 |
commit | 350484a64a9f23af061cf361b250073573fa2b1c (patch) | |
tree | 05fe6dbbcabf1081b5439d3859a49c0265b72524 /isys/pci/pciprobe.c | |
parent | 5f1f6ac61790616230c86102d75cd0f675dbc750 (diff) | |
download | anaconda-350484a64a9f23af061cf361b250073573fa2b1c.tar.gz anaconda-350484a64a9f23af061cf361b250073573fa2b1c.tar.xz anaconda-350484a64a9f23af061cf361b250073573fa2b1c.zip |
makefile changes
Diffstat (limited to 'isys/pci/pciprobe.c')
-rw-r--r-- | isys/pci/pciprobe.c | 184 |
1 files changed, 184 insertions, 0 deletions
diff --git a/isys/pci/pciprobe.c b/isys/pci/pciprobe.c new file mode 100644 index 000000000..0a85285ad --- /dev/null +++ b/isys/pci/pciprobe.c @@ -0,0 +1,184 @@ +#include <ctype.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include <sys/stat.h> + +#include <pci/pci.h> + + +struct pciDevice { + unsigned int vendor, device, type; + char * driver; + char * desc; +}; + +struct pciDevice * pciDeviceList = NULL; +static int numPciDevices = 0; +static struct pci_access *pacc=NULL; + +static int devCmp(const void * a, const void * b) { + const struct pciDevice * one = a; + const struct pciDevice * two = b; + int x=0,y=0; + + x = (one->vendor - two->vendor); + y = (one->device - two->device); + if (x) + return x; + else + return y; +} + +int buildDriverList(const char * fn) { + int fd; + struct stat sb; + char * buf; + int numDrivers; + char * start; + struct pciDevice * nextDevice; + char module[5000]; + + fd = open(fn, O_RDONLY); + if (fd < 0) return -1; + + fstat(fd, &sb); + buf = alloca(sb.st_size + 1); + read(fd, buf, sb.st_size); + buf[sb.st_size] = '\0'; + close(fd); + + /* upper bound */ + numDrivers = 1; + start = buf; + while ((start = strchr(start, '\n'))) { + numDrivers++; + start++; + } + + pciDeviceList = realloc(pciDeviceList, sizeof(*pciDeviceList) * + (numPciDevices + numDrivers)); + nextDevice = pciDeviceList + numPciDevices; + + start = buf; + while (start && *start) { + while (isspace(*start)) start++; + if (*start != '#' && *start != '\n') { + if (sscanf(start, "%x %x %s", &nextDevice->vendor, + &nextDevice->device, module ) == 3) { + int x; + numPciDevices++; + nextDevice->driver = strdup(module); + x=strchr(start,'\n')-strchr(start,'"')-2; + if (x>0) { + nextDevice->desc = calloc(x,sizeof(char)); + nextDevice->desc = strncpy(nextDevice->desc,strchr(start,'"')+1,x); + } + nextDevice++; + } + } + + start = strchr(start, '\n'); + if (start) start++; + } + + qsort(pciDeviceList, numPciDevices, sizeof(*pciDeviceList), devCmp); + + return 0; +} + +struct pciDevice * pciGetDeviceInfo(unsigned int vend, unsigned int dev) { + struct pciDevice *searchDev, key; + + key.vendor = vend; + key.device = dev; + + searchDev = bsearch(&key,pciDeviceList,numPciDevices, + sizeof(struct pciDevice), devCmp); + if (!searchDev) { + char *namebuf=calloc(128,sizeof(char *)); + searchDev = malloc(sizeof(struct pciDevice)); + searchDev->vendor = vend; + searchDev->device = dev; + searchDev->driver = strdup("unknown"); + searchDev->desc = calloc(128, sizeof(char)); + namebuf=pci_lookup_name(pacc,namebuf,128, + PCI_LOOKUP_VENDOR, searchDev->vendor,0); + if ((strtol(namebuf, (char **)NULL, 16)) == searchDev->vendor) { + snprintf(searchDev->desc,128, + "Unknown vendor unknown device: %04x:%04x", + searchDev->vendor, searchDev->device); + } else { + snprintf(searchDev->desc,128, + "%s unknown device: %04x:%04x", + namebuf, searchDev->vendor, searchDev->device); + } + } + return searchDev; +} + +struct pciDevice ** probePci(unsigned int type, int all) { + struct pciDevice **devices=NULL; + struct pci_dev *p; + int numDevices=0; + + pacc = pci_alloc(); + if (!pacc) return NULL; + pci_init(pacc); + pci_scan_bus(pacc); + for (p = pacc->devices; p; p=p->next) { + byte config[256]; + int x=64; + struct pciDevice *dev; + + memset(config,256,0); + pci_read_block(p, 0, config, x); + if (x<128 && (config[PCI_HEADER_TYPE] & 0x7f) == PCI_HEADER_TYPE_CARDBUS) { + pci_read_block(p, 0, config+64, 64); + x=128; + } + dev = pciGetDeviceInfo(p->vendor_id,p->device_id); + dev->type = config[PCI_CLASS_DEVICE+1] << 8 | config[PCI_CLASS_DEVICE]; + if (all || (strcmp(dev->driver,"unknown") && strcmp(dev->driver,"ignore"))) { + if (!type || (type<0xff && (type==dev->type>>8)) + || (type==dev->type)) { + if (!numDevices) { + devices = malloc(sizeof(struct pciDevice *)); + } else { + devices = realloc(devices,(numDevices+1)*sizeof(struct pciDevice *)); + } + devices[numDevices] = dev; + numDevices++; + } + } + } + pci_cleanup(pacc); + if (devices) { + devices = realloc(devices,(numDevices+1)*sizeof(struct pciDevice *)); + devices[numDevices] = NULL; + } + return devices; +} + +#ifdef TESTING +int main(int argc, char **argv) { + struct pciDevice **list,*dev; + int x=0; + + if (buildDriverList("pcitable")) { + perror("error reading pci table"); + exit(0); + } + list = probePci(0,1); + if (list) + while ((dev=list[x])) { + printf("%04x %04x %s (%s)\n",dev->vendor,dev->device, + dev->desc, dev->driver); + x++; + } + exit(0); +} +#endif |