Annotation of embedaddon/pciutils/ls-kernel.c, revision 1.1.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>