summaryrefslogtreecommitdiffstats
path: root/isys/pci/pciprobe.c
diff options
context:
space:
mode:
authorBill Nottingham <notting@redhat.com>1999-07-01 15:45:41 +0000
committerBill Nottingham <notting@redhat.com>1999-07-01 15:45:41 +0000
commit350484a64a9f23af061cf361b250073573fa2b1c (patch)
tree05fe6dbbcabf1081b5439d3859a49c0265b72524 /isys/pci/pciprobe.c
parent5f1f6ac61790616230c86102d75cd0f675dbc750 (diff)
downloadanaconda-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.c184
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