diff options
Diffstat (limited to 'isys/pci')
-rw-r--r-- | isys/pci/pciprobe.c | 79 |
1 files changed, 65 insertions, 14 deletions
diff --git a/isys/pci/pciprobe.c b/isys/pci/pciprobe.c index 0f42f0129..dff9f9557 100644 --- a/isys/pci/pciprobe.c +++ b/isys/pci/pciprobe.c @@ -1,26 +1,81 @@ #include <alloca.h> +#include <ctype.h> #include <fcntl.h> +#include <stdio.h> #include <stdlib.h> #include <string.h> +#include <sys/stat.h> #include <unistd.h> struct pciDrivers { - unsigned short manufacturer, device; + unsigned int manufacturer, device; char * driver; }; -#include "driverlist.h" +struct pciDrivers * pciDriverList = NULL; +static int numPciDrivers = 0; -static int numPciDrivers = sizeof(pciDriverList) / sizeof(*pciDriverList); +static int driverCmp(const void * a, const void * b); + +int probePciReadDrivers(const char * fn) { + int fd; + struct stat sb; + char * buf; + int numDrivers; + char * start; + struct pciDrivers * nextDriver; + 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++; + } + + pciDriverList = realloc(pciDriverList, sizeof(*pciDriverList) * + (numPciDrivers + numDrivers)); + nextDriver = pciDriverList + numPciDrivers; + + start = buf; + while (start && *start) { + while (isspace(*start)) start++; + if (*start != '#' && *start != '\n') { + if (sscanf(start, "%x %x %s\n", &nextDriver->manufacturer, + &nextDriver->device, module) == 3) { + numPciDrivers++; + nextDriver++; + nextDriver->driver = strdup(module); + } + } + + start = strchr(start, '\n'); + if (start) start++; + } + + /*qsort(pciDriverList, numPciDrivers, sizeof(*pciDriverList), driverCmp);*/ + + return 0; +} static int driverCmp(const void * a, const void * b) { const struct pciDrivers * one = a; const struct pciDrivers * two = b; if (one->manufacturer < two->manufacturer) return -1; - if (one->manufacturer > two->manufacturer) return -1; + if (one->manufacturer > two->manufacturer) return 1; - if (one->device < two->device) return 1; + if (one->device < two->device) return -1; if (one->device > two->device) return 1; return 0; @@ -33,7 +88,7 @@ char ** probePciDriverList(void) { char * buf, * chptr; int bufSize; int bytes; - int tmp, i; + unsigned int tmp, i; struct pciDrivers needle, * item; fd = open("/proc/bus/pci/devices", O_RDONLY); @@ -44,6 +99,7 @@ char ** probePciDriverList(void) { while ((bytes = read(fd, buf, bufSize)) == bufSize) { bufSize += 1024; buf = realloc(buf, bufSize); + lseek(fd, SEEK_SET, 0); } close(fd); @@ -58,15 +114,10 @@ char ** probePciDriverList(void) { chptr = strchr(chptr, '\n') + 1; needle.manufacturer = tmp >> 16; - needle.device = tmp &0xFFFF; + needle.device = tmp & 0xFFFF; - item = NULL; - for (i = 0; i < numPciDrivers; i++) { - if (!driverCmp(pciDriverList + i, &needle)) { - item = pciDriverList + i; - break; - } - } + item = bsearch(&needle, pciDriverList, numPciDrivers, + sizeof(*pciDriverList), driverCmp); if (item) { for (i = 0; i < driverCount; i++) |