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>