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

    1: /*
    2:  *	The PCI Utilities -- List All PCI Devices
    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 <stdlib.h>
   12: #include <stdarg.h>
   13: 
   14: #include "lspci.h"
   15: 
   16: /* Options */
   17: 
   18: int verbose;				/* Show detailed information */
   19: static int opt_hex;			/* Show contents of config space as hexadecimal numbers */
   20: struct pci_filter filter;		/* Device filter */
   21: static int opt_tree;			/* Show bus tree */
   22: static int opt_machine;			/* Generate machine-readable output */
   23: static int opt_map_mode;		/* Bus mapping mode enabled */
   24: static int opt_domains;			/* Show domain numbers (0=disabled, 1=auto-detected, 2=requested) */
   25: static int opt_kernel;			/* Show kernel drivers */
   26: static int opt_query_dns;		/* Query the DNS (0=disabled, 1=enabled, 2=refresh cache) */
   27: static int opt_query_all;		/* Query the DNS for all entries */
   28: char *opt_pcimap;			/* Override path to Linux modules.pcimap */
   29: 
   30: const char program_name[] = "lspci";
   31: 
   32: static char options[] = "nvbxs:d:ti:mgp:qkMDQ" GENERIC_OPTIONS ;
   33: 
   34: static char help_msg[] =
   35: "Usage: lspci [<switches>]\n"
   36: "\n"
   37: "Basic display modes:\n"
   38: "-mm\t\tProduce machine-readable output (single -m for an obsolete format)\n"
   39: "-t\t\tShow bus tree\n"
   40: "\n"
   41: "Display options:\n"
   42: "-v\t\tBe verbose (-vv for very verbose)\n"
   43: #ifdef PCI_OS_LINUX
   44: "-k\t\tShow kernel drivers handling each device\n"
   45: #endif
   46: "-x\t\tShow hex-dump of the standard part of the config space\n"
   47: "-xxx\t\tShow hex-dump of the whole config space (dangerous; root only)\n"
   48: "-xxxx\t\tShow hex-dump of the 4096-byte extended config space (root only)\n"
   49: "-b\t\tBus-centric view (addresses and IRQ's as seen by the bus)\n"
   50: "-D\t\tAlways show domain numbers\n"
   51: "\n"
   52: "Resolving of device ID's to names:\n"
   53: "-n\t\tShow numeric ID's\n"
   54: "-nn\t\tShow both textual and numeric ID's (names & numbers)\n"
   55: #ifdef PCI_USE_DNS
   56: "-q\t\tQuery the PCI ID database for unknown ID's via DNS\n"
   57: "-qq\t\tAs above, but re-query locally cached entries\n"
   58: "-Q\t\tQuery the PCI ID database for all ID's via DNS\n"
   59: #endif
   60: "\n"
   61: "Selection of devices:\n"
   62: "-s [[[[<domain>]:]<bus>]:][<slot>][.[<func>]]\tShow only devices in selected slots\n"
   63: "-d [<vendor>]:[<device>]\t\t\tShow only devices with specified ID's\n"
   64: "\n"
   65: "Other options:\n"
   66: "-i <file>\tUse specified ID database instead of %s\n"
   67: #ifdef PCI_OS_LINUX
   68: "-p <file>\tLook up kernel modules in a given file instead of default modules.pcimap\n"
   69: #endif
   70: "-M\t\tEnable `bus mapping' mode (dangerous; root only)\n"
   71: "\n"
   72: "PCI access options:\n"
   73: GENERIC_HELP
   74: ;
   75: 
   76: /*** Our view of the PCI bus ***/
   77: 
   78: struct pci_access *pacc;
   79: struct device *first_dev;
   80: static int seen_errors;
   81: 
   82: int
   83: config_fetch(struct device *d, unsigned int pos, unsigned int len)
   84: {
   85:   unsigned int end = pos+len;
   86:   int result;
   87: 
   88:   while (pos < d->config_bufsize && len && d->present[pos])
   89:     pos++, len--;
   90:   while (pos+len <= d->config_bufsize && len && d->present[pos+len-1])
   91:     len--;
   92:   if (!len)
   93:     return 1;
   94: 
   95:   if (end > d->config_bufsize)
   96:     {
   97:       int orig_size = d->config_bufsize;
   98:       while (end > d->config_bufsize)
   99: 	d->config_bufsize *= 2;
  100:       d->config = xrealloc(d->config, d->config_bufsize);
  101:       d->present = xrealloc(d->present, d->config_bufsize);
  102:       memset(d->present + orig_size, 0, d->config_bufsize - orig_size);
  103:     }
  104:   result = pci_read_block(d->dev, pos, d->config + pos, len);
  105:   if (result)
  106:     memset(d->present + pos, 1, len);
  107:   return result;
  108: }
  109: 
  110: struct device *
  111: scan_device(struct pci_dev *p)
  112: {
  113:   struct device *d;
  114: 
  115:   if (p->domain && !opt_domains)
  116:     opt_domains = 1;
  117:   if (!pci_filter_match(&filter, p))
  118:     return NULL;
  119:   d = xmalloc(sizeof(struct device));
  120:   memset(d, 0, sizeof(*d));
  121:   d->dev = p;
  122:   d->config_cached = d->config_bufsize = 64;
  123:   d->config = xmalloc(64);
  124:   d->present = xmalloc(64);
  125:   memset(d->present, 1, 64);
  126:   if (!pci_read_block(p, 0, d->config, 64))
  127:     {
  128:       fprintf(stderr, "lspci: Unable to read the standard configuration space header of device %04x:%02x:%02x.%d\n",
  129: 	      p->domain, p->bus, p->dev, p->func);
  130:       seen_errors++;
  131:       return NULL;
  132:     }
  133:   if ((d->config[PCI_HEADER_TYPE] & 0x7f) == PCI_HEADER_TYPE_CARDBUS)
  134:     {
  135:       /* For cardbus bridges, we need to fetch 64 bytes more to get the
  136:        * full standard header... */
  137:       if (config_fetch(d, 64, 64))
  138: 	d->config_cached += 64;
  139:     }
  140:   pci_setup_cache(p, d->config, d->config_cached);
  141:   pci_fill_info(p, PCI_FILL_IDENT | PCI_FILL_CLASS | PCI_FILL_IRQ | PCI_FILL_BASES | PCI_FILL_ROM_BASE | PCI_FILL_SIZES | PCI_FILL_PHYS_SLOT);
  142:   return d;
  143: }
  144: 
  145: static void
  146: scan_devices(void)
  147: {
  148:   struct device *d;
  149:   struct pci_dev *p;
  150: 
  151:   pci_scan_bus(pacc);
  152:   for (p=pacc->devices; p; p=p->next)
  153:     if (d = scan_device(p))
  154:       {
  155: 	d->next = first_dev;
  156: 	first_dev = d;
  157:       }
  158: }
  159: 
  160: /*** Config space accesses ***/
  161: 
  162: static void
  163: check_conf_range(struct device *d, unsigned int pos, unsigned int len)
  164: {
  165:   while (len)
  166:     if (!d->present[pos])
  167:       die("Internal bug: Accessing non-read configuration byte at position %x", pos);
  168:     else
  169:       pos++, len--;
  170: }
  171: 
  172: byte
  173: get_conf_byte(struct device *d, unsigned int pos)
  174: {
  175:   check_conf_range(d, pos, 1);
  176:   return d->config[pos];
  177: }
  178: 
  179: word
  180: get_conf_word(struct device *d, unsigned int pos)
  181: {
  182:   check_conf_range(d, pos, 2);
  183:   return d->config[pos] | (d->config[pos+1] << 8);
  184: }
  185: 
  186: u32
  187: get_conf_long(struct device *d, unsigned int pos)
  188: {
  189:   check_conf_range(d, pos, 4);
  190:   return d->config[pos] |
  191:     (d->config[pos+1] << 8) |
  192:     (d->config[pos+2] << 16) |
  193:     (d->config[pos+3] << 24);
  194: }
  195: 
  196: /*** Sorting ***/
  197: 
  198: static int
  199: compare_them(const void *A, const void *B)
  200: {
  201:   const struct pci_dev *a = (*(const struct device **)A)->dev;
  202:   const struct pci_dev *b = (*(const struct device **)B)->dev;
  203: 
  204:   if (a->domain < b->domain)
  205:     return -1;
  206:   if (a->domain > b->domain)
  207:     return 1;
  208:   if (a->bus < b->bus)
  209:     return -1;
  210:   if (a->bus > b->bus)
  211:     return 1;
  212:   if (a->dev < b->dev)
  213:     return -1;
  214:   if (a->dev > b->dev)
  215:     return 1;
  216:   if (a->func < b->func)
  217:     return -1;
  218:   if (a->func > b->func)
  219:     return 1;
  220:   return 0;
  221: }
  222: 
  223: static void
  224: sort_them(void)
  225: {
  226:   struct device **index, **h, **last_dev;
  227:   int cnt;
  228:   struct device *d;
  229: 
  230:   cnt = 0;
  231:   for (d=first_dev; d; d=d->next)
  232:     cnt++;
  233:   h = index = alloca(sizeof(struct device *) * cnt);
  234:   for (d=first_dev; d; d=d->next)
  235:     *h++ = d;
  236:   qsort(index, cnt, sizeof(struct device *), compare_them);
  237:   last_dev = &first_dev;
  238:   h = index;
  239:   while (cnt--)
  240:     {
  241:       *last_dev = *h;
  242:       last_dev = &(*h)->next;
  243:       h++;
  244:     }
  245:   *last_dev = NULL;
  246: }
  247: 
  248: /*** Normal output ***/
  249: 
  250: static void
  251: show_slot_name(struct device *d)
  252: {
  253:   struct pci_dev *p = d->dev;
  254: 
  255:   if (!opt_machine ? opt_domains : (p->domain || opt_domains >= 2))
  256:     printf("%04x:", p->domain);
  257:   printf("%02x:%02x.%d", p->bus, p->dev, p->func);
  258: }
  259: 
  260: void
  261: get_subid(struct device *d, word *subvp, word *subdp)
  262: {
  263:   byte htype = get_conf_byte(d, PCI_HEADER_TYPE) & 0x7f;
  264: 
  265:   if (htype == PCI_HEADER_TYPE_NORMAL)
  266:     {
  267:       *subvp = get_conf_word(d, PCI_SUBSYSTEM_VENDOR_ID);
  268:       *subdp = get_conf_word(d, PCI_SUBSYSTEM_ID);
  269:     }
  270:   else if (htype == PCI_HEADER_TYPE_CARDBUS && d->config_cached >= 128)
  271:     {
  272:       *subvp = get_conf_word(d, PCI_CB_SUBSYSTEM_VENDOR_ID);
  273:       *subdp = get_conf_word(d, PCI_CB_SUBSYSTEM_ID);
  274:     }
  275:   else
  276:     *subvp = *subdp = 0xffff;
  277: }
  278: 
  279: static void
  280: show_terse(struct device *d)
  281: {
  282:   int c;
  283:   struct pci_dev *p = d->dev;
  284:   char classbuf[128], devbuf[128];
  285: 
  286:   show_slot_name(d);
  287:   printf(" %s: %s",
  288: 	 pci_lookup_name(pacc, classbuf, sizeof(classbuf),
  289: 			 PCI_LOOKUP_CLASS,
  290: 			 p->device_class),
  291: 	 pci_lookup_name(pacc, devbuf, sizeof(devbuf),
  292: 			 PCI_LOOKUP_VENDOR | PCI_LOOKUP_DEVICE,
  293: 			 p->vendor_id, p->device_id));
  294:   if (c = get_conf_byte(d, PCI_REVISION_ID))
  295:     printf(" (rev %02x)", c);
  296:   if (verbose)
  297:     {
  298:       char *x;
  299:       c = get_conf_byte(d, PCI_CLASS_PROG);
  300:       x = pci_lookup_name(pacc, devbuf, sizeof(devbuf),
  301: 			  PCI_LOOKUP_PROGIF | PCI_LOOKUP_NO_NUMBERS,
  302: 			  p->device_class, c);
  303:       if (c || x)
  304: 	{
  305: 	  printf(" (prog-if %02x", c);
  306: 	  if (x)
  307: 	    printf(" [%s]", x);
  308: 	  putchar(')');
  309: 	}
  310:     }
  311:   putchar('\n');
  312: 
  313:   if (verbose || opt_kernel)
  314:     {
  315:       word subsys_v, subsys_d;
  316:       char ssnamebuf[256];
  317: 
  318:       get_subid(d, &subsys_v, &subsys_d);
  319:       if (subsys_v && subsys_v != 0xffff)
  320: 	printf("\tSubsystem: %s\n",
  321: 		pci_lookup_name(pacc, ssnamebuf, sizeof(ssnamebuf),
  322: 			PCI_LOOKUP_SUBSYSTEM | PCI_LOOKUP_VENDOR | PCI_LOOKUP_DEVICE,
  323: 			p->vendor_id, p->device_id, subsys_v, subsys_d));
  324:     }
  325: }
  326: 
  327: /*** Verbose output ***/
  328: 
  329: static void
  330: show_size(pciaddr_t x)
  331: {
  332:   static const char suffix[][2] = { "", "K", "M", "G", "T" };
  333:   unsigned i;
  334:   if (!x)
  335:     return;
  336:   for (i = 0; i < (sizeof(suffix) / sizeof(*suffix) - 1); i++) {
  337:     if (x < 1024)
  338:       break;
  339:     x /= 1024;
  340:   }
  341:   printf(" [size=%u%s]", (unsigned)x, suffix[i]);
  342: }
  343: 
  344: static void
  345: show_bases(struct device *d, int cnt)
  346: {
  347:   struct pci_dev *p = d->dev;
  348:   word cmd = get_conf_word(d, PCI_COMMAND);
  349:   int i;
  350:   int virtual = 0;
  351: 
  352:   for (i=0; i<cnt; i++)
  353:     {
  354:       pciaddr_t pos = p->base_addr[i];
  355:       pciaddr_t len = (p->known_fields & PCI_FILL_SIZES) ? p->size[i] : 0;
  356:       u32 flg = get_conf_long(d, PCI_BASE_ADDRESS_0 + 4*i);
  357:       if (flg == 0xffffffff)
  358: 	flg = 0;
  359:       if (!pos && !flg && !len)
  360: 	continue;
  361:       if (verbose > 1)
  362: 	printf("\tRegion %d: ", i);
  363:       else
  364: 	putchar('\t');
  365:       if (pos && !flg)			/* Reported by the OS, but not by the device */
  366: 	{
  367: 	  printf("[virtual] ");
  368: 	  flg = pos;
  369: 	  virtual = 1;
  370: 	}
  371:       if (flg & PCI_BASE_ADDRESS_SPACE_IO)
  372: 	{
  373: 	  pciaddr_t a = pos & PCI_BASE_ADDRESS_IO_MASK;
  374: 	  printf("I/O ports at ");
  375: 	  if (a)
  376: 	    printf(PCIADDR_PORT_FMT, a);
  377: 	  else if (flg & PCI_BASE_ADDRESS_IO_MASK)
  378: 	    printf("<ignored>");
  379: 	  else
  380: 	    printf("<unassigned>");
  381: 	  if (!virtual && !(cmd & PCI_COMMAND_IO))
  382: 	    printf(" [disabled]");
  383: 	}
  384:       else
  385: 	{
  386: 	  int t = flg & PCI_BASE_ADDRESS_MEM_TYPE_MASK;
  387: 	  pciaddr_t a = pos & PCI_ADDR_MEM_MASK;
  388: 	  int done = 0;
  389: 	  u32 z = 0;
  390: 
  391: 	  printf("Memory at ");
  392: 	  if (t == PCI_BASE_ADDRESS_MEM_TYPE_64)
  393: 	    {
  394: 	      if (i >= cnt - 1)
  395: 		{
  396: 		  printf("<invalid-64bit-slot>");
  397: 		  done = 1;
  398: 		}
  399: 	      else
  400: 		{
  401: 		  i++;
  402: 		  z = get_conf_long(d, PCI_BASE_ADDRESS_0 + 4*i);
  403: 		}
  404: 	    }
  405: 	  if (!done)
  406: 	    {
  407: 	      if (a)
  408: 		printf(PCIADDR_T_FMT, a);
  409: 	      else
  410: 		printf(((flg & PCI_BASE_ADDRESS_MEM_MASK) || z) ? "<ignored>" : "<unassigned>");
  411: 	    }
  412: 	  printf(" (%s, %sprefetchable)",
  413: 		 (t == PCI_BASE_ADDRESS_MEM_TYPE_32) ? "32-bit" :
  414: 		 (t == PCI_BASE_ADDRESS_MEM_TYPE_64) ? "64-bit" :
  415: 		 (t == PCI_BASE_ADDRESS_MEM_TYPE_1M) ? "low-1M" : "type 3",
  416: 		 (flg & PCI_BASE_ADDRESS_MEM_PREFETCH) ? "" : "non-");
  417: 	  if (!virtual && !(cmd & PCI_COMMAND_MEMORY))
  418: 	    printf(" [disabled]");
  419: 	}
  420:       show_size(len);
  421:       putchar('\n');
  422:     }
  423: }
  424: 
  425: static void
  426: show_rom(struct device *d, int reg)
  427: {
  428:   struct pci_dev *p = d->dev;
  429:   pciaddr_t rom = p->rom_base_addr;
  430:   pciaddr_t len = (p->known_fields & PCI_FILL_SIZES) ? p->rom_size : 0;
  431:   u32 flg = get_conf_long(d, reg);
  432:   word cmd = get_conf_word(d, PCI_COMMAND);
  433:   int virtual = 0;
  434: 
  435:   if (!rom && !flg && !len)
  436:     return;
  437:   putchar('\t');
  438:   if ((rom & PCI_ROM_ADDRESS_MASK) && !(flg & PCI_ROM_ADDRESS_MASK))
  439:     {
  440:       printf("[virtual] ");
  441:       flg = rom;
  442:       virtual = 1;
  443:     }
  444:   printf("Expansion ROM at ");
  445:   if (rom & PCI_ROM_ADDRESS_MASK)
  446:     printf(PCIADDR_T_FMT, rom & PCI_ROM_ADDRESS_MASK);
  447:   else if (flg & PCI_ROM_ADDRESS_MASK)
  448:     printf("<ignored>");
  449:   else
  450:     printf("<unassigned>");
  451:   if (!(flg & PCI_ROM_ADDRESS_ENABLE))
  452:     printf(" [disabled]");
  453:   else if (!virtual && !(cmd & PCI_COMMAND_MEMORY))
  454:     printf(" [disabled by cmd]");
  455:   show_size(len);
  456:   putchar('\n');
  457: }
  458: 
  459: static void
  460: show_htype0(struct device *d)
  461: {
  462:   show_bases(d, 6);
  463:   show_rom(d, PCI_ROM_ADDRESS);
  464:   show_caps(d);
  465: }
  466: 
  467: static void
  468: show_htype1(struct device *d)
  469: {
  470:   u32 io_base = get_conf_byte(d, PCI_IO_BASE);
  471:   u32 io_limit = get_conf_byte(d, PCI_IO_LIMIT);
  472:   u32 io_type = io_base & PCI_IO_RANGE_TYPE_MASK;
  473:   u32 mem_base = get_conf_word(d, PCI_MEMORY_BASE);
  474:   u32 mem_limit = get_conf_word(d, PCI_MEMORY_LIMIT);
  475:   u32 mem_type = mem_base & PCI_MEMORY_RANGE_TYPE_MASK;
  476:   u32 pref_base = get_conf_word(d, PCI_PREF_MEMORY_BASE);
  477:   u32 pref_limit = get_conf_word(d, PCI_PREF_MEMORY_LIMIT);
  478:   u32 pref_type = pref_base & PCI_PREF_RANGE_TYPE_MASK;
  479:   word sec_stat = get_conf_word(d, PCI_SEC_STATUS);
  480:   word brc = get_conf_word(d, PCI_BRIDGE_CONTROL);
  481:   int verb = verbose > 2;
  482: 
  483:   show_bases(d, 2);
  484:   printf("\tBus: primary=%02x, secondary=%02x, subordinate=%02x, sec-latency=%d\n",
  485: 	 get_conf_byte(d, PCI_PRIMARY_BUS),
  486: 	 get_conf_byte(d, PCI_SECONDARY_BUS),
  487: 	 get_conf_byte(d, PCI_SUBORDINATE_BUS),
  488: 	 get_conf_byte(d, PCI_SEC_LATENCY_TIMER));
  489: 
  490:   if (io_type != (io_limit & PCI_IO_RANGE_TYPE_MASK) ||
  491:       (io_type != PCI_IO_RANGE_TYPE_16 && io_type != PCI_IO_RANGE_TYPE_32))
  492:     printf("\t!!! Unknown I/O range types %x/%x\n", io_base, io_limit);
  493:   else
  494:     {
  495:       io_base = (io_base & PCI_IO_RANGE_MASK) << 8;
  496:       io_limit = (io_limit & PCI_IO_RANGE_MASK) << 8;
  497:       if (io_type == PCI_IO_RANGE_TYPE_32)
  498: 	{
  499: 	  io_base |= (get_conf_word(d, PCI_IO_BASE_UPPER16) << 16);
  500: 	  io_limit |= (get_conf_word(d, PCI_IO_LIMIT_UPPER16) << 16);
  501: 	}
  502:       if (io_base <= io_limit || verb)
  503: 	printf("\tI/O behind bridge: %08x-%08x\n", io_base, io_limit+0xfff);
  504:     }
  505: 
  506:   if (mem_type != (mem_limit & PCI_MEMORY_RANGE_TYPE_MASK) ||
  507:       mem_type)
  508:     printf("\t!!! Unknown memory range types %x/%x\n", mem_base, mem_limit);
  509:   else
  510:     {
  511:       mem_base = (mem_base & PCI_MEMORY_RANGE_MASK) << 16;
  512:       mem_limit = (mem_limit & PCI_MEMORY_RANGE_MASK) << 16;
  513:       if (mem_base <= mem_limit || verb)
  514: 	printf("\tMemory behind bridge: %08x-%08x\n", mem_base, mem_limit + 0xfffff);
  515:     }
  516: 
  517:   if (pref_type != (pref_limit & PCI_PREF_RANGE_TYPE_MASK) ||
  518:       (pref_type != PCI_PREF_RANGE_TYPE_32 && pref_type != PCI_PREF_RANGE_TYPE_64))
  519:     printf("\t!!! Unknown prefetchable memory range types %x/%x\n", pref_base, pref_limit);
  520:   else
  521:     {
  522:       pref_base = (pref_base & PCI_PREF_RANGE_MASK) << 16;
  523:       pref_limit = (pref_limit & PCI_PREF_RANGE_MASK) << 16;
  524:       if (pref_base <= pref_limit || verb)
  525: 	{
  526: 	  if (pref_type == PCI_PREF_RANGE_TYPE_32)
  527: 	    printf("\tPrefetchable memory behind bridge: %08x-%08x\n", pref_base, pref_limit + 0xfffff);
  528: 	  else
  529: 	    printf("\tPrefetchable memory behind bridge: %08x%08x-%08x%08x\n",
  530: 		   get_conf_long(d, PCI_PREF_BASE_UPPER32),
  531: 		   pref_base,
  532: 		   get_conf_long(d, PCI_PREF_LIMIT_UPPER32),
  533: 		   pref_limit + 0xfffff);
  534: 	}
  535:     }
  536: 
  537:   if (verbose > 1)
  538:     printf("\tSecondary status: 66MHz%c FastB2B%c ParErr%c DEVSEL=%s >TAbort%c <TAbort%c <MAbort%c <SERR%c <PERR%c\n",
  539: 	     FLAG(sec_stat, PCI_STATUS_66MHZ),
  540: 	     FLAG(sec_stat, PCI_STATUS_FAST_BACK),
  541: 	     FLAG(sec_stat, PCI_STATUS_PARITY),
  542: 	     ((sec_stat & PCI_STATUS_DEVSEL_MASK) == PCI_STATUS_DEVSEL_SLOW) ? "slow" :
  543: 	     ((sec_stat & PCI_STATUS_DEVSEL_MASK) == PCI_STATUS_DEVSEL_MEDIUM) ? "medium" :
  544: 	     ((sec_stat & PCI_STATUS_DEVSEL_MASK) == PCI_STATUS_DEVSEL_FAST) ? "fast" : "??",
  545: 	     FLAG(sec_stat, PCI_STATUS_SIG_TARGET_ABORT),
  546: 	     FLAG(sec_stat, PCI_STATUS_REC_TARGET_ABORT),
  547: 	     FLAG(sec_stat, PCI_STATUS_REC_MASTER_ABORT),
  548: 	     FLAG(sec_stat, PCI_STATUS_SIG_SYSTEM_ERROR),
  549: 	     FLAG(sec_stat, PCI_STATUS_DETECTED_PARITY));
  550: 
  551:   show_rom(d, PCI_ROM_ADDRESS1);
  552: 
  553:   if (verbose > 1)
  554:     {
  555:       printf("\tBridgeCtl: Parity%c SERR%c NoISA%c VGA%c MAbort%c >Reset%c FastB2B%c\n",
  556: 	FLAG(brc, PCI_BRIDGE_CTL_PARITY),
  557: 	FLAG(brc, PCI_BRIDGE_CTL_SERR),
  558: 	FLAG(brc, PCI_BRIDGE_CTL_NO_ISA),
  559: 	FLAG(brc, PCI_BRIDGE_CTL_VGA),
  560: 	FLAG(brc, PCI_BRIDGE_CTL_MASTER_ABORT),
  561: 	FLAG(brc, PCI_BRIDGE_CTL_BUS_RESET),
  562: 	FLAG(brc, PCI_BRIDGE_CTL_FAST_BACK));
  563:       printf("\t\tPriDiscTmr%c SecDiscTmr%c DiscTmrStat%c DiscTmrSERREn%c\n",
  564: 	FLAG(brc, PCI_BRIDGE_CTL_PRI_DISCARD_TIMER),
  565: 	FLAG(brc, PCI_BRIDGE_CTL_SEC_DISCARD_TIMER),
  566: 	FLAG(brc, PCI_BRIDGE_CTL_DISCARD_TIMER_STATUS),
  567: 	FLAG(brc, PCI_BRIDGE_CTL_DISCARD_TIMER_SERR_EN));
  568:     }
  569: 
  570:   show_caps(d);
  571: }
  572: 
  573: static void
  574: show_htype2(struct device *d)
  575: {
  576:   int i;
  577:   word cmd = get_conf_word(d, PCI_COMMAND);
  578:   word brc = get_conf_word(d, PCI_CB_BRIDGE_CONTROL);
  579:   word exca;
  580:   int verb = verbose > 2;
  581: 
  582:   show_bases(d, 1);
  583:   printf("\tBus: primary=%02x, secondary=%02x, subordinate=%02x, sec-latency=%d\n",
  584: 	 get_conf_byte(d, PCI_CB_PRIMARY_BUS),
  585: 	 get_conf_byte(d, PCI_CB_CARD_BUS),
  586: 	 get_conf_byte(d, PCI_CB_SUBORDINATE_BUS),
  587: 	 get_conf_byte(d, PCI_CB_LATENCY_TIMER));
  588:   for (i=0; i<2; i++)
  589:     {
  590:       int p = 8*i;
  591:       u32 base = get_conf_long(d, PCI_CB_MEMORY_BASE_0 + p);
  592:       u32 limit = get_conf_long(d, PCI_CB_MEMORY_LIMIT_0 + p);
  593:       limit = limit + 0xfff;
  594:       if (base <= limit || verb)
  595: 	printf("\tMemory window %d: %08x-%08x%s%s\n", i, base, limit,
  596: 	       (cmd & PCI_COMMAND_MEMORY) ? "" : " [disabled]",
  597: 	       (brc & (PCI_CB_BRIDGE_CTL_PREFETCH_MEM0 << i)) ? " (prefetchable)" : "");
  598:     }
  599:   for (i=0; i<2; i++)
  600:     {
  601:       int p = 8*i;
  602:       u32 base = get_conf_long(d, PCI_CB_IO_BASE_0 + p);
  603:       u32 limit = get_conf_long(d, PCI_CB_IO_LIMIT_0 + p);
  604:       if (!(base & PCI_IO_RANGE_TYPE_32))
  605: 	{
  606: 	  base &= 0xffff;
  607: 	  limit &= 0xffff;
  608: 	}
  609:       base &= PCI_CB_IO_RANGE_MASK;
  610:       limit = (limit & PCI_CB_IO_RANGE_MASK) + 3;
  611:       if (base <= limit || verb)
  612: 	printf("\tI/O window %d: %08x-%08x%s\n", i, base, limit,
  613: 	       (cmd & PCI_COMMAND_IO) ? "" : " [disabled]");
  614:     }
  615: 
  616:   if (get_conf_word(d, PCI_CB_SEC_STATUS) & PCI_STATUS_SIG_SYSTEM_ERROR)
  617:     printf("\tSecondary status: SERR\n");
  618:   if (verbose > 1)
  619:     printf("\tBridgeCtl: Parity%c SERR%c ISA%c VGA%c MAbort%c >Reset%c 16bInt%c PostWrite%c\n",
  620: 	   FLAG(brc, PCI_CB_BRIDGE_CTL_PARITY),
  621: 	   FLAG(brc, PCI_CB_BRIDGE_CTL_SERR),
  622: 	   FLAG(brc, PCI_CB_BRIDGE_CTL_ISA),
  623: 	   FLAG(brc, PCI_CB_BRIDGE_CTL_VGA),
  624: 	   FLAG(brc, PCI_CB_BRIDGE_CTL_MASTER_ABORT),
  625: 	   FLAG(brc, PCI_CB_BRIDGE_CTL_CB_RESET),
  626: 	   FLAG(brc, PCI_CB_BRIDGE_CTL_16BIT_INT),
  627: 	   FLAG(brc, PCI_CB_BRIDGE_CTL_POST_WRITES));
  628: 
  629:   if (d->config_cached < 128)
  630:     {
  631:       printf("\t<access denied to the rest>\n");
  632:       return;
  633:     }
  634: 
  635:   exca = get_conf_word(d, PCI_CB_LEGACY_MODE_BASE);
  636:   if (exca)
  637:     printf("\t16-bit legacy interface ports at %04x\n", exca);
  638: }
  639: 
  640: static void
  641: show_verbose(struct device *d)
  642: {
  643:   struct pci_dev *p = d->dev;
  644:   word status = get_conf_word(d, PCI_STATUS);
  645:   word cmd = get_conf_word(d, PCI_COMMAND);
  646:   word class = p->device_class;
  647:   byte bist = get_conf_byte(d, PCI_BIST);
  648:   byte htype = get_conf_byte(d, PCI_HEADER_TYPE) & 0x7f;
  649:   byte latency = get_conf_byte(d, PCI_LATENCY_TIMER);
  650:   byte cache_line = get_conf_byte(d, PCI_CACHE_LINE_SIZE);
  651:   byte max_lat, min_gnt;
  652:   byte int_pin = get_conf_byte(d, PCI_INTERRUPT_PIN);
  653:   unsigned int irq = p->irq;
  654: 
  655:   show_terse(d);
  656: 
  657:   switch (htype)
  658:     {
  659:     case PCI_HEADER_TYPE_NORMAL:
  660:       if (class == PCI_CLASS_BRIDGE_PCI)
  661: 	printf("\t!!! Invalid class %04x for header type %02x\n", class, htype);
  662:       max_lat = get_conf_byte(d, PCI_MAX_LAT);
  663:       min_gnt = get_conf_byte(d, PCI_MIN_GNT);
  664:       break;
  665:     case PCI_HEADER_TYPE_BRIDGE:
  666:       if ((class >> 8) != PCI_BASE_CLASS_BRIDGE)
  667: 	printf("\t!!! Invalid class %04x for header type %02x\n", class, htype);
  668:       irq = int_pin = min_gnt = max_lat = 0;
  669:       break;
  670:     case PCI_HEADER_TYPE_CARDBUS:
  671:       if ((class >> 8) != PCI_BASE_CLASS_BRIDGE)
  672: 	printf("\t!!! Invalid class %04x for header type %02x\n", class, htype);
  673:       min_gnt = max_lat = 0;
  674:       break;
  675:     default:
  676:       printf("\t!!! Unknown header type %02x\n", htype);
  677:       return;
  678:     }
  679: 
  680:   if (p->phy_slot)
  681:     printf("\tPhysical Slot: %s\n", p->phy_slot);
  682: 
  683:   if (verbose > 1)
  684:     {
  685:       printf("\tControl: I/O%c Mem%c BusMaster%c SpecCycle%c MemWINV%c VGASnoop%c ParErr%c Stepping%c SERR%c FastB2B%c DisINTx%c\n",
  686: 	     FLAG(cmd, PCI_COMMAND_IO),
  687: 	     FLAG(cmd, PCI_COMMAND_MEMORY),
  688: 	     FLAG(cmd, PCI_COMMAND_MASTER),
  689: 	     FLAG(cmd, PCI_COMMAND_SPECIAL),
  690: 	     FLAG(cmd, PCI_COMMAND_INVALIDATE),
  691: 	     FLAG(cmd, PCI_COMMAND_VGA_PALETTE),
  692: 	     FLAG(cmd, PCI_COMMAND_PARITY),
  693: 	     FLAG(cmd, PCI_COMMAND_WAIT),
  694: 	     FLAG(cmd, PCI_COMMAND_SERR),
  695: 	     FLAG(cmd, PCI_COMMAND_FAST_BACK),
  696: 	     FLAG(cmd, PCI_COMMAND_DISABLE_INTx));
  697:       printf("\tStatus: Cap%c 66MHz%c UDF%c FastB2B%c ParErr%c DEVSEL=%s >TAbort%c <TAbort%c <MAbort%c >SERR%c <PERR%c INTx%c\n",
  698: 	     FLAG(status, PCI_STATUS_CAP_LIST),
  699: 	     FLAG(status, PCI_STATUS_66MHZ),
  700: 	     FLAG(status, PCI_STATUS_UDF),
  701: 	     FLAG(status, PCI_STATUS_FAST_BACK),
  702: 	     FLAG(status, PCI_STATUS_PARITY),
  703: 	     ((status & PCI_STATUS_DEVSEL_MASK) == PCI_STATUS_DEVSEL_SLOW) ? "slow" :
  704: 	     ((status & PCI_STATUS_DEVSEL_MASK) == PCI_STATUS_DEVSEL_MEDIUM) ? "medium" :
  705: 	     ((status & PCI_STATUS_DEVSEL_MASK) == PCI_STATUS_DEVSEL_FAST) ? "fast" : "??",
  706: 	     FLAG(status, PCI_STATUS_SIG_TARGET_ABORT),
  707: 	     FLAG(status, PCI_STATUS_REC_TARGET_ABORT),
  708: 	     FLAG(status, PCI_STATUS_REC_MASTER_ABORT),
  709: 	     FLAG(status, PCI_STATUS_SIG_SYSTEM_ERROR),
  710: 	     FLAG(status, PCI_STATUS_DETECTED_PARITY),
  711: 	     FLAG(status, PCI_STATUS_INTx));
  712:       if (cmd & PCI_COMMAND_MASTER)
  713: 	{
  714: 	  printf("\tLatency: %d", latency);
  715: 	  if (min_gnt || max_lat)
  716: 	    {
  717: 	      printf(" (");
  718: 	      if (min_gnt)
  719: 		printf("%dns min", min_gnt*250);
  720: 	      if (min_gnt && max_lat)
  721: 		printf(", ");
  722: 	      if (max_lat)
  723: 		printf("%dns max", max_lat*250);
  724: 	      putchar(')');
  725: 	    }
  726: 	  if (cache_line)
  727: 	    printf(", Cache Line Size: %d bytes", cache_line * 4);
  728: 	  putchar('\n');
  729: 	}
  730:       if (int_pin || irq)
  731: 	printf("\tInterrupt: pin %c routed to IRQ " PCIIRQ_FMT "\n",
  732: 	       (int_pin ? 'A' + int_pin - 1 : '?'), irq);
  733:     }
  734:   else
  735:     {
  736:       printf("\tFlags: ");
  737:       if (cmd & PCI_COMMAND_MASTER)
  738: 	printf("bus master, ");
  739:       if (cmd & PCI_COMMAND_VGA_PALETTE)
  740: 	printf("VGA palette snoop, ");
  741:       if (cmd & PCI_COMMAND_WAIT)
  742: 	printf("stepping, ");
  743:       if (cmd & PCI_COMMAND_FAST_BACK)
  744: 	printf("fast Back2Back, ");
  745:       if (status & PCI_STATUS_66MHZ)
  746: 	printf("66MHz, ");
  747:       if (status & PCI_STATUS_UDF)
  748: 	printf("user-definable features, ");
  749:       printf("%s devsel",
  750: 	     ((status & PCI_STATUS_DEVSEL_MASK) == PCI_STATUS_DEVSEL_SLOW) ? "slow" :
  751: 	     ((status & PCI_STATUS_DEVSEL_MASK) == PCI_STATUS_DEVSEL_MEDIUM) ? "medium" :
  752: 	     ((status & PCI_STATUS_DEVSEL_MASK) == PCI_STATUS_DEVSEL_FAST) ? "fast" : "??");
  753:       if (cmd & PCI_COMMAND_MASTER)
  754: 	printf(", latency %d", latency);
  755:       if (irq)
  756: 	printf(", IRQ " PCIIRQ_FMT, irq);
  757:       putchar('\n');
  758:     }
  759: 
  760:   if (bist & PCI_BIST_CAPABLE)
  761:     {
  762:       if (bist & PCI_BIST_START)
  763: 	printf("\tBIST is running\n");
  764:       else
  765: 	printf("\tBIST result: %02x\n", bist & PCI_BIST_CODE_MASK);
  766:     }
  767: 
  768:   switch (htype)
  769:     {
  770:     case PCI_HEADER_TYPE_NORMAL:
  771:       show_htype0(d);
  772:       break;
  773:     case PCI_HEADER_TYPE_BRIDGE:
  774:       show_htype1(d);
  775:       break;
  776:     case PCI_HEADER_TYPE_CARDBUS:
  777:       show_htype2(d);
  778:       break;
  779:     }
  780: }
  781: 
  782: /*** Machine-readable dumps ***/
  783: 
  784: static void
  785: show_hex_dump(struct device *d)
  786: {
  787:   unsigned int i, cnt;
  788: 
  789:   cnt = d->config_cached;
  790:   if (opt_hex >= 3 && config_fetch(d, cnt, 256-cnt))
  791:     {
  792:       cnt = 256;
  793:       if (opt_hex >= 4 && config_fetch(d, 256, 4096-256))
  794: 	cnt = 4096;
  795:     }
  796: 
  797:   for (i=0; i<cnt; i++)
  798:     {
  799:       if (! (i & 15))
  800: 	printf("%02x:", i);
  801:       printf(" %02x", get_conf_byte(d, i));
  802:       if ((i & 15) == 15)
  803: 	putchar('\n');
  804:     }
  805: }
  806: 
  807: static void
  808: print_shell_escaped(char *c)
  809: {
  810:   printf(" \"");
  811:   while (*c)
  812:     {
  813:       if (*c == '"' || *c == '\\')
  814: 	putchar('\\');
  815:       putchar(*c++);
  816:     }
  817:   putchar('"');
  818: }
  819: 
  820: static void
  821: show_machine(struct device *d)
  822: {
  823:   struct pci_dev *p = d->dev;
  824:   int c;
  825:   word sv_id, sd_id;
  826:   char classbuf[128], vendbuf[128], devbuf[128], svbuf[128], sdbuf[128];
  827: 
  828:   get_subid(d, &sv_id, &sd_id);
  829: 
  830:   if (verbose)
  831:     {
  832:       printf((opt_machine >= 2) ? "Slot:\t" : "Device:\t");
  833:       show_slot_name(d);
  834:       putchar('\n');
  835:       printf("Class:\t%s\n",
  836: 	     pci_lookup_name(pacc, classbuf, sizeof(classbuf), PCI_LOOKUP_CLASS, p->device_class));
  837:       printf("Vendor:\t%s\n",
  838: 	     pci_lookup_name(pacc, vendbuf, sizeof(vendbuf), PCI_LOOKUP_VENDOR, p->vendor_id, p->device_id));
  839:       printf("Device:\t%s\n",
  840: 	     pci_lookup_name(pacc, devbuf, sizeof(devbuf), PCI_LOOKUP_DEVICE, p->vendor_id, p->device_id));
  841:       if (sv_id && sv_id != 0xffff)
  842: 	{
  843: 	  printf("SVendor:\t%s\n",
  844: 		 pci_lookup_name(pacc, svbuf, sizeof(svbuf), PCI_LOOKUP_SUBSYSTEM | PCI_LOOKUP_VENDOR, sv_id));
  845: 	  printf("SDevice:\t%s\n",
  846: 		 pci_lookup_name(pacc, sdbuf, sizeof(sdbuf), PCI_LOOKUP_SUBSYSTEM | PCI_LOOKUP_DEVICE, p->vendor_id, p->device_id, sv_id, sd_id));
  847: 	}
  848:       if (p->phy_slot)
  849: 	printf("PhySlot:\t%s\n", p->phy_slot);
  850:       if (c = get_conf_byte(d, PCI_REVISION_ID))
  851: 	printf("Rev:\t%02x\n", c);
  852:       if (c = get_conf_byte(d, PCI_CLASS_PROG))
  853: 	printf("ProgIf:\t%02x\n", c);
  854:       if (opt_kernel)
  855: 	show_kernel_machine(d);
  856:     }
  857:   else
  858:     {
  859:       show_slot_name(d);
  860:       print_shell_escaped(pci_lookup_name(pacc, classbuf, sizeof(classbuf), PCI_LOOKUP_CLASS, p->device_class));
  861:       print_shell_escaped(pci_lookup_name(pacc, vendbuf, sizeof(vendbuf), PCI_LOOKUP_VENDOR, p->vendor_id, p->device_id));
  862:       print_shell_escaped(pci_lookup_name(pacc, devbuf, sizeof(devbuf), PCI_LOOKUP_DEVICE, p->vendor_id, p->device_id));
  863:       if (c = get_conf_byte(d, PCI_REVISION_ID))
  864: 	printf(" -r%02x", c);
  865:       if (c = get_conf_byte(d, PCI_CLASS_PROG))
  866: 	printf(" -p%02x", c);
  867:       if (sv_id && sv_id != 0xffff)
  868: 	{
  869: 	  print_shell_escaped(pci_lookup_name(pacc, svbuf, sizeof(svbuf), PCI_LOOKUP_SUBSYSTEM | PCI_LOOKUP_VENDOR, sv_id));
  870: 	  print_shell_escaped(pci_lookup_name(pacc, sdbuf, sizeof(sdbuf), PCI_LOOKUP_SUBSYSTEM | PCI_LOOKUP_DEVICE, p->vendor_id, p->device_id, sv_id, sd_id));
  871: 	}
  872:       else
  873: 	printf(" \"\" \"\"");
  874:       putchar('\n');
  875:     }
  876: }
  877: 
  878: /*** Main show function ***/
  879: 
  880: void
  881: show_device(struct device *d)
  882: {
  883:   if (opt_machine)
  884:     show_machine(d);
  885:   else
  886:     {
  887:       if (verbose)
  888: 	show_verbose(d);
  889:       else
  890: 	show_terse(d);
  891:       if (opt_kernel || verbose)
  892: 	show_kernel(d);
  893:     }
  894:   if (opt_hex)
  895:     show_hex_dump(d);
  896:   if (verbose || opt_hex)
  897:     putchar('\n');
  898: }
  899: 
  900: static void
  901: show(void)
  902: {
  903:   struct device *d;
  904: 
  905:   for (d=first_dev; d; d=d->next)
  906:     show_device(d);
  907: }
  908: 
  909: /* Main */
  910: 
  911: int
  912: main(int argc, char **argv)
  913: {
  914:   int i;
  915:   char *msg;
  916: 
  917:   if (argc == 2 && !strcmp(argv[1], "--version"))
  918:     {
  919:       puts("lspci version " PCIUTILS_VERSION);
  920:       return 0;
  921:     }
  922: 
  923:   pacc = pci_alloc();
  924:   pacc->error = die;
  925:   pci_filter_init(pacc, &filter);
  926: 
  927:   while ((i = getopt(argc, argv, options)) != -1)
  928:     switch (i)
  929:       {
  930:       case 'n':
  931: 	pacc->numeric_ids++;
  932: 	break;
  933:       case 'v':
  934: 	verbose++;
  935: 	break;
  936:       case 'b':
  937: 	pacc->buscentric = 1;
  938: 	break;
  939:       case 's':
  940: 	if (msg = pci_filter_parse_slot(&filter, optarg))
  941: 	  die("-s: %s", msg);
  942: 	break;
  943:       case 'd':
  944: 	if (msg = pci_filter_parse_id(&filter, optarg))
  945: 	  die("-d: %s", msg);
  946: 	break;
  947:       case 'x':
  948: 	opt_hex++;
  949: 	break;
  950:       case 't':
  951: 	opt_tree++;
  952: 	break;
  953:       case 'i':
  954:         pci_set_name_list_path(pacc, optarg, 0);
  955: 	break;
  956:       case 'm':
  957: 	opt_machine++;
  958: 	break;
  959:       case 'p':
  960: 	opt_pcimap = optarg;
  961: 	break;
  962: #ifdef PCI_OS_LINUX
  963:       case 'k':
  964: 	opt_kernel++;
  965: 	break;
  966: #endif
  967:       case 'M':
  968: 	opt_map_mode++;
  969: 	break;
  970:       case 'D':
  971: 	opt_domains = 2;
  972: 	break;
  973: #ifdef PCI_USE_DNS
  974:       case 'q':
  975: 	opt_query_dns++;
  976: 	break;
  977:       case 'Q':
  978: 	opt_query_all = 1;
  979: 	break;
  980: #else
  981:       case 'q':
  982:       case 'Q':
  983: 	die("DNS queries are not available in this version");
  984: #endif
  985:       default:
  986: 	if (parse_generic_option(i, pacc, optarg))
  987: 	  break;
  988:       bad:
  989: 	fprintf(stderr, help_msg, pacc->id_file_name);
  990: 	return 1;
  991:       }
  992:   if (optind < argc)
  993:     goto bad;
  994: 
  995:   if (opt_query_dns)
  996:     {
  997:       pacc->id_lookup_mode |= PCI_LOOKUP_NETWORK;
  998:       if (opt_query_dns > 1)
  999: 	pacc->id_lookup_mode |= PCI_LOOKUP_REFRESH_CACHE;
 1000:     }
 1001:   if (opt_query_all)
 1002:     pacc->id_lookup_mode |= PCI_LOOKUP_NETWORK | PCI_LOOKUP_SKIP_LOCAL;
 1003: 
 1004:   pci_init(pacc);
 1005:   if (opt_map_mode)
 1006:     map_the_bus();
 1007:   else
 1008:     {
 1009:       scan_devices();
 1010:       sort_them();
 1011:       if (opt_tree)
 1012: 	show_forest();
 1013:       else
 1014: 	show();
 1015:     }
 1016:   pci_cleanup(pacc);
 1017: 
 1018:   return (seen_errors ? 2 : 0);
 1019: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>