summaryrefslogtreecommitdiffstats
path: root/pci.c
diff options
context:
space:
mode:
authorGwenolé Beauchesne <gbeauchesne@mandriva.org>2006-01-05 15:38:33 +0000
committerGwenolé Beauchesne <gbeauchesne@mandriva.org>2006-01-05 15:38:33 +0000
commit9b9696674a63f3004b51bb2c5320db21bc61f281 (patch)
tree02452b44477ee615886de2904cfd68df25fc8337 /pci.c
parent0daa780a0651f9c078dbfafd0a7c3ff593fbe317 (diff)
downloadldetect-9b9696674a63f3004b51bb2c5320db21bc61f281.tar
ldetect-9b9696674a63f3004b51bb2c5320db21bc61f281.tar.gz
ldetect-9b9696674a63f3004b51bb2c5320db21bc61f281.tar.bz2
ldetect-9b9696674a63f3004b51bb2c5320db21bc61f281.tar.xz
ldetect-9b9696674a63f3004b51bb2c5320db21bc61f281.zip
add support for pci domains
Diffstat (limited to 'pci.c')
-rw-r--r--pci.c52
1 files changed, 50 insertions, 2 deletions
diff --git a/pci.c b/pci.c
index 1ecbeeb..830efa7 100644
--- a/pci.c
+++ b/pci.c
@@ -7,11 +7,44 @@
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
+#include <dirent.h>
#include "common.h"
static char *proc_pci_path_default = "/proc/bus/pci/devices";
char *proc_pci_path = NULL;
+#define MAX_PCI_DOMAINS 256
+static int pci_domains[MAX_PCI_DOMAINS] = { 0, };
+
+static int probe_domains(void)
+{
+ static int n_pci_domains = -1;
+ if (n_pci_domains == -1) {
+ int i;
+ DIR *dir;
+ for (i = 0; i < MAX_PCI_DOMAINS; i++)
+ pci_domains[i] = 0;
+ if ((dir = opendir("/proc/bus/pci")) != NULL) {
+ struct dirent *dent;
+ while ((dent = readdir(dir)) != NULL) {
+ int domain, bus, ret;
+ ret = sscanf(dent->d_name, "%x:%x", &domain, &bus);
+ if (ret == 2) {
+ if (domain < MAX_PCI_DOMAINS)
+ pci_domains[domain] = 1;
+ }
+ }
+ closedir(dir);
+ n_pci_domains = 0;
+ for (i = 0; i < MAX_PCI_DOMAINS; i++) {
+ if (pci_domains[i])
+ pci_domains[n_pci_domains++] = i;
+ }
+ }
+ }
+ return n_pci_domains;
+}
+
extern struct pciusb_entries pci_probe(void) {
FILE *f; int devf;
char buf[BUF_SIZE];
@@ -19,7 +52,10 @@ extern struct pciusb_entries pci_probe(void) {
unsigned short devbusfn;
unsigned int id;
struct pciusb_entries r;
- char file[25];
+ char file[32];
+ int n_pci_domains;
+
+ n_pci_domains = probe_domains();
r.nb = 0;
if (!(f = fopen(proc_pci_path ? proc_pci_path : proc_pci_path_default, "r"))) {
@@ -49,8 +85,20 @@ extern struct pciusb_entries pci_probe(void) {
e->pci_device = (devbusfn & 0xff) >> 3;
e->pci_function = (devbusfn & 0xff) & 0x07;
snprintf(file, sizeof(file), "/proc/bus/pci/%02x/%02x.%d", e->pci_bus, e->pci_device, e->pci_function);
- if ((devf = open(file, O_RDONLY)) == -1)
+ if ((devf = open(file, O_RDONLY)) == -1) {
+ /* try with pci domains */
+ int found = 0;
+ if (n_pci_domains) {
+ int i;
+ for (i = 0; !found && i < n_pci_domains; i++) {
+ snprintf(file, sizeof(file), "/proc/bus/pci/%04x:%02x/%02x.%d", pci_domains[i], e->pci_bus, e->pci_device, e->pci_function);
+ if ((devf = open(file, O_RDONLY)) >= 0)
+ found = 1;
+ }
+ }
+ if (!found)
continue;
+ }
read(devf, &buf, 0x30); /* these files're 256 bytes but we only need first 48 bytes*/
e->class_ = bufi[0x5];
e->subvendor = bufi[0x16];