File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / pciutils / ls-kernel.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Fri Feb 17 15:18:43 2012 UTC (12 years, 4 months ago) by misho
Branches: pciutils, MAIN
CVS tags: v3_1_9, HEAD
pciutils

    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>