Annotation of embedaddon/pciutils/ls-kernel.c, revision 1.1
1.1 ! misho 1: /*
! 2: * The PCI Utilities -- Show Kernel Drivers
! 3: *
! 4: * Copyright (c) 1997--2008 Martin Mares <mj@ucw.cz>
! 5: *
! 6: * Can be freely distributed and used under the terms of the GNU GPL.
! 7: */
! 8:
! 9: #include <stdio.h>
! 10: #include <string.h>
! 11: #include <unistd.h>
! 12:
! 13: #include "lspci.h"
! 14:
! 15: #ifdef PCI_OS_LINUX
! 16:
! 17: #include <sys/utsname.h>
! 18:
! 19: struct pcimap_entry {
! 20: struct pcimap_entry *next;
! 21: unsigned int vendor, device;
! 22: unsigned int subvendor, subdevice;
! 23: unsigned int class, class_mask;
! 24: char module[1];
! 25: };
! 26:
! 27: static struct pcimap_entry *pcimap_head;
! 28:
! 29: static void
! 30: load_pcimap(void)
! 31: {
! 32: static int tried_pcimap;
! 33: struct utsname uts;
! 34: char *name, line[1024];
! 35: FILE *f;
! 36:
! 37: if (tried_pcimap)
! 38: return;
! 39: tried_pcimap = 1;
! 40:
! 41: if (name = opt_pcimap)
! 42: {
! 43: f = fopen(name, "r");
! 44: if (!f)
! 45: die("Cannot open pcimap file %s: %m", name);
! 46: }
! 47: else
! 48: {
! 49: if (uname(&uts) < 0)
! 50: die("uname() failed: %m");
! 51: name = alloca(64 + strlen(uts.release));
! 52: sprintf(name, "/lib/modules/%s/modules.pcimap", uts.release);
! 53: f = fopen(name, "r");
! 54: if (!f)
! 55: return;
! 56: }
! 57:
! 58: while (fgets(line, sizeof(line), f))
! 59: {
! 60: char *c = strchr(line, '\n');
! 61: struct pcimap_entry *e;
! 62:
! 63: if (!c)
! 64: die("Unterminated or too long line in %s", name);
! 65: *c = 0;
! 66: if (!line[0] || line[0] == '#')
! 67: continue;
! 68:
! 69: c = line;
! 70: while (*c && *c != ' ' && *c != '\t')
! 71: c++;
! 72: if (!*c)
! 73: continue; /* FIXME: Emit warnings! */
! 74: *c++ = 0;
! 75:
! 76: e = xmalloc(sizeof(*e) + strlen(line));
! 77: if (sscanf(c, "%i%i%i%i%i%i",
! 78: &e->vendor, &e->device,
! 79: &e->subvendor, &e->subdevice,
! 80: &e->class, &e->class_mask) != 6)
! 81: continue;
! 82: e->next = pcimap_head;
! 83: pcimap_head = e;
! 84: strcpy(e->module, line);
! 85: }
! 86: fclose(f);
! 87: }
! 88:
! 89: static int
! 90: match_pcimap(struct device *d, struct pcimap_entry *e)
! 91: {
! 92: struct pci_dev *dev = d->dev;
! 93: unsigned int class = get_conf_long(d, PCI_REVISION_ID) >> 8;
! 94: word subv, subd;
! 95:
! 96: #define MATCH(x, y) ((y) > 0xffff || (x) == (y))
! 97: get_subid(d, &subv, &subd);
! 98: return
! 99: MATCH(dev->vendor_id, e->vendor) &&
! 100: MATCH(dev->device_id, e->device) &&
! 101: MATCH(subv, e->subvendor) &&
! 102: MATCH(subd, e->subdevice) &&
! 103: (class & e->class_mask) == e->class;
! 104: #undef MATCH
! 105: }
! 106:
! 107: #define DRIVER_BUF_SIZE 1024
! 108:
! 109: static char *
! 110: find_driver(struct device *d, char *buf)
! 111: {
! 112: struct pci_dev *dev = d->dev;
! 113: char name[1024], *drv, *base;
! 114: int n;
! 115:
! 116: if (dev->access->method != PCI_ACCESS_SYS_BUS_PCI)
! 117: return NULL;
! 118:
! 119: base = pci_get_param(dev->access, "sysfs.path");
! 120: if (!base || !base[0])
! 121: return NULL;
! 122:
! 123: n = snprintf(name, sizeof(name), "%s/devices/%04x:%02x:%02x.%d/driver",
! 124: base, dev->domain, dev->bus, dev->dev, dev->func);
! 125: if (n < 0 || n >= (int)sizeof(name))
! 126: die("show_driver: sysfs device name too long, why?");
! 127:
! 128: n = readlink(name, buf, DRIVER_BUF_SIZE);
! 129: if (n < 0)
! 130: return NULL;
! 131: if (n >= DRIVER_BUF_SIZE)
! 132: return "<name-too-long>";
! 133: buf[n] = 0;
! 134:
! 135: if (drv = strrchr(buf, '/'))
! 136: return drv+1;
! 137: else
! 138: return buf;
! 139: }
! 140:
! 141: void
! 142: show_kernel(struct device *d)
! 143: {
! 144: char buf[DRIVER_BUF_SIZE];
! 145: char *driver;
! 146: struct pcimap_entry *e, *last = NULL;
! 147:
! 148: if (driver = find_driver(d, buf))
! 149: printf("\tKernel driver in use: %s\n", driver);
! 150:
! 151: load_pcimap();
! 152: for (e=pcimap_head; e; e=e->next)
! 153: if (match_pcimap(d, e) && (!last || strcmp(last->module, e->module)))
! 154: {
! 155: printf("%s %s", (last ? "," : "\tKernel modules:"), e->module);
! 156: last = e;
! 157: }
! 158: if (last)
! 159: putchar('\n');
! 160: }
! 161:
! 162: void
! 163: show_kernel_machine(struct device *d)
! 164: {
! 165: char buf[DRIVER_BUF_SIZE];
! 166: char *driver;
! 167: struct pcimap_entry *e, *last = NULL;
! 168:
! 169: if (driver = find_driver(d, buf))
! 170: printf("Driver:\t%s\n", driver);
! 171:
! 172: load_pcimap();
! 173: for (e=pcimap_head; e; e=e->next)
! 174: if (match_pcimap(d, e) && (!last || strcmp(last->module, e->module)))
! 175: {
! 176: printf("Module:\t%s\n", e->module);
! 177: last = e;
! 178: }
! 179: }
! 180:
! 181: #else
! 182:
! 183: void
! 184: show_kernel(struct device *d UNUSED)
! 185: {
! 186: }
! 187:
! 188: void
! 189: show_kernel_machine(struct device *d UNUSED)
! 190: {
! 191: }
! 192:
! 193: #endif
! 194:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>