summaryrefslogtreecommitdiffstats
path: root/isys/pci
diff options
context:
space:
mode:
Diffstat (limited to 'isys/pci')
-rw-r--r--isys/pci/pciprobe.c79
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++)