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>