Annotation of embedaddon/pciutils/lspci.c, revision 1.1.1.1

1.1       misho       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>