⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lspci.c

📁 linux下的pci设备浏览工具
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *	The PCI Utilities -- List All PCI Devices * *	Copyright (c) 1997--2008 Martin Mares <mj@ucw.cz> * *	Can be freely distributed and used under the terms of the GNU GPL. */#include <stdio.h>#include <string.h>#include <stdlib.h>#include <stdarg.h>#include <unistd.h>#include "lspci.h"/* Options */int verbose;				/* Show detailed information */static int opt_hex;			/* Show contents of config space as hexadecimal numbers */struct pci_filter filter;		/* Device filter */static int opt_tree;			/* Show bus tree */static int opt_machine;			/* Generate machine-readable output */static int opt_map_mode;		/* Bus mapping mode enabled */static int opt_domains;			/* Show domain numbers (0=disabled, 1=auto-detected, 2=requested) */static int opt_kernel;			/* Show kernel drivers */static int opt_query_dns;		/* Query the DNS (0=disabled, 1=enabled, 2=refresh cache) */static int opt_query_all;		/* Query the DNS for all entries */char *opt_pcimap;			/* Override path to Linux modules.pcimap */const char program_name[] = "lspci";static char options[] = "nvbxs:d:ti:mgp:qkMDQ" GENERIC_OPTIONS ;static char help_msg[] ="Usage: lspci [<switches>]\n""\n""Basic display modes:\n""-mm\t\tProduce machine-readable output (single -m for an obsolete format)\n""-t\t\tShow bus tree\n""\n""Display options:\n""-v\t\tBe verbose (-vv for very verbose)\n"#ifdef PCI_OS_LINUX"-k\t\tShow kernel drivers handling each device\n"#endif"-x\t\tShow hex-dump of the standard part of the config space\n""-xxx\t\tShow hex-dump of the whole config space (dangerous; root only)\n""-xxxx\t\tShow hex-dump of the 4096-byte extended config space (root only)\n""-b\t\tBus-centric view (addresses and IRQ's as seen by the bus)\n""-D\t\tAlways show domain numbers\n""\n""Resolving of device ID's to names:\n""-n\t\tShow numeric ID's\n""-nn\t\tShow both textual and numeric ID's (names & numbers)\n"#ifdef PCI_USE_DNS"-q\t\tQuery the PCI ID database for unknown ID's via DNS\n""-qq\t\tAs above, but re-query locally cached entries\n""-Q\t\tQuery the PCI ID database for all ID's via DNS\n"#endif"\n""Selection of devices:\n""-s [[[[<domain>]:]<bus>]:][<slot>][.[<func>]]\tShow only devices in selected slots\n""-d [<vendor>]:[<device>]\t\t\tShow only devices with specified ID's\n""\n""Other options:\n""-i <file>\tUse specified ID database instead of %s\n"#ifdef PCI_OS_LINUX"-p <file>\tLook up kernel modules in a given file instead of default modules.pcimap\n"#endif"-M\t\tEnable `bus mapping' mode (dangerous; root only)\n""\n""PCI access options:\n"GENERIC_HELP;/*** Our view of the PCI bus ***/struct pci_access *pacc;struct device *first_dev;static int seen_errors;intconfig_fetch(struct device *d, unsigned int pos, unsigned int len){  unsigned int end = pos+len;  int result;  while (pos < d->config_bufsize && len && d->present[pos])    pos++, len--;  while (pos+len <= d->config_bufsize && len && d->present[pos+len-1])    len--;  if (!len)    return 1;  if (end > d->config_bufsize)    {      int orig_size = d->config_bufsize;      while (end > d->config_bufsize)	d->config_bufsize *= 2;      d->config = xrealloc(d->config, d->config_bufsize);      d->present = xrealloc(d->present, d->config_bufsize);      memset(d->present + orig_size, 0, d->config_bufsize - orig_size);    }  result = pci_read_block(d->dev, pos, d->config + pos, len);  if (result)    memset(d->present + pos, 1, len);  return result;}struct device *scan_device(struct pci_dev *p){  struct device *d;  if (p->domain && !opt_domains)    opt_domains = 1;  if (!pci_filter_match(&filter, p))    return NULL;  d = xmalloc(sizeof(struct device));  memset(d, 0, sizeof(*d));  d->dev = p;  d->config_cached = d->config_bufsize = 64;  d->config = xmalloc(64);  d->present = xmalloc(64);  memset(d->present, 1, 64);  if (!pci_read_block(p, 0, d->config, 64))    {      fprintf(stderr, "lspci: Unable to read the standard configuration space header of device %04x:%02x:%02x.%d\n",	      p->domain, p->bus, p->dev, p->func);      seen_errors++;      return NULL;    }  if ((d->config[PCI_HEADER_TYPE] & 0x7f) == PCI_HEADER_TYPE_CARDBUS)    {      /* For cardbus bridges, we need to fetch 64 bytes more to get the       * full standard header... */      if (config_fetch(d, 64, 64))	d->config_cached += 64;    }  pci_setup_cache(p, d->config, d->config_cached);  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);  return d;}static voidscan_devices(void){  struct device *d;  struct pci_dev *p;  pci_scan_bus(pacc);  for (p=pacc->devices; p; p=p->next)    if (d = scan_device(p))      {	d->next = first_dev;	first_dev = d;      }}/*** Config space accesses ***/static voidcheck_conf_range(struct device *d, unsigned int pos, unsigned int len){  while (len)    if (!d->present[pos])      die("Internal bug: Accessing non-read configuration byte at position %x", pos);    else      pos++, len--;}byteget_conf_byte(struct device *d, unsigned int pos){  check_conf_range(d, pos, 1);  return d->config[pos];}wordget_conf_word(struct device *d, unsigned int pos){  check_conf_range(d, pos, 2);  return d->config[pos] | (d->config[pos+1] << 8);}u32get_conf_long(struct device *d, unsigned int pos){  check_conf_range(d, pos, 4);  return d->config[pos] |    (d->config[pos+1] << 8) |    (d->config[pos+2] << 16) |    (d->config[pos+3] << 24);}/*** Sorting ***/static intcompare_them(const void *A, const void *B){  const struct pci_dev *a = (*(const struct device **)A)->dev;  const struct pci_dev *b = (*(const struct device **)B)->dev;  if (a->domain < b->domain)    return -1;  if (a->domain > b->domain)    return 1;  if (a->bus < b->bus)    return -1;  if (a->bus > b->bus)    return 1;  if (a->dev < b->dev)    return -1;  if (a->dev > b->dev)    return 1;  if (a->func < b->func)    return -1;  if (a->func > b->func)    return 1;  return 0;}static voidsort_them(void){  struct device **index, **h, **last_dev;  int cnt;  struct device *d;  cnt = 0;  for (d=first_dev; d; d=d->next)    cnt++;  h = index = alloca(sizeof(struct device *) * cnt);  for (d=first_dev; d; d=d->next)    *h++ = d;  qsort(index, cnt, sizeof(struct device *), compare_them);  last_dev = &first_dev;  h = index;  while (cnt--)    {      *last_dev = *h;      last_dev = &(*h)->next;      h++;    }  *last_dev = NULL;}/*** Normal output ***/static voidshow_slot_name(struct device *d){  struct pci_dev *p = d->dev;  if (!opt_machine ? opt_domains : (p->domain || opt_domains >= 2))    printf("%04x:", p->domain);  printf("%02x:%02x.%d", p->bus, p->dev, p->func);}voidget_subid(struct device *d, word *subvp, word *subdp){  byte htype = get_conf_byte(d, PCI_HEADER_TYPE) & 0x7f;  if (htype == PCI_HEADER_TYPE_NORMAL)    {      *subvp = get_conf_word(d, PCI_SUBSYSTEM_VENDOR_ID);      *subdp = get_conf_word(d, PCI_SUBSYSTEM_ID);    }  else if (htype == PCI_HEADER_TYPE_CARDBUS && d->config_cached >= 128)    {      *subvp = get_conf_word(d, PCI_CB_SUBSYSTEM_VENDOR_ID);      *subdp = get_conf_word(d, PCI_CB_SUBSYSTEM_ID);    }  else    *subvp = *subdp = 0xffff;}static voidshow_terse(struct device *d){	  int c;  struct pci_dev *p = d->dev;  char classbuf[128], devbuf[128];  show_slot_name(d);  printf(" %s: %s",	 pci_lookup_name(pacc, classbuf, sizeof(classbuf),			 PCI_LOOKUP_CLASS,			 p->device_class),	 pci_lookup_name(pacc, devbuf, sizeof(devbuf),			 PCI_LOOKUP_VENDOR | PCI_LOOKUP_DEVICE,			 p->vendor_id, p->device_id));  if (c = get_conf_byte(d, PCI_REVISION_ID))    printf(" (rev %02x)", c);  if (verbose)    {      char *x;      c = get_conf_byte(d, PCI_CLASS_PROG);      x = pci_lookup_name(pacc, devbuf, sizeof(devbuf),			  PCI_LOOKUP_PROGIF | PCI_LOOKUP_NO_NUMBERS,			  p->device_class, c);      if (c || x)	{	  printf(" (prog-if %02x", c);	  if (x)	    printf(" [%s]", x);	  putchar(')');	}    }  putchar('\n');  if (verbose || opt_kernel)    {      word subsys_v, subsys_d;      char ssnamebuf[256];      get_subid(d, &subsys_v, &subsys_d);      if (subsys_v && subsys_v != 0xffff)	printf("\tSubsystem: %s\n",		pci_lookup_name(pacc, ssnamebuf, sizeof(ssnamebuf),			PCI_LOOKUP_SUBSYSTEM | PCI_LOOKUP_VENDOR | PCI_LOOKUP_DEVICE,			p->vendor_id, p->device_id, subsys_v, subsys_d));    }}/*** Verbose output ***/static voidshow_size(pciaddr_t x){  if (!x)    return;  printf(" [size=");  if (x < 1024)    printf("%d", (int) x);  else if (x < 1048576)    printf("%dK", (int)(x / 1024));  else if (x < 0x80000000)    printf("%dM", (int)(x / 1048576));  else    printf(PCIADDR_T_FMT, x);  putchar(']');}static voidshow_bases(struct device *d, int cnt){  struct pci_dev *p = d->dev;  word cmd = get_conf_word(d, PCI_COMMAND);  int i;  int virtual = 0;  for (i=0; i<cnt; i++)    {      pciaddr_t pos = p->base_addr[i];      pciaddr_t len = (p->known_fields & PCI_FILL_SIZES) ? p->size[i] : 0;      u32 flg = get_conf_long(d, PCI_BASE_ADDRESS_0 + 4*i);      if (flg == 0xffffffff)	flg = 0;      if (!pos && !flg && !len)	continue;      if (verbose > 1)	printf("\tRegion %d: ", i);      else	putchar('\t');      if (pos && !flg)			/* Reported by the OS, but not by the device */	{	  printf("[virtual] ");	  flg = pos;	  virtual = 1;	}      if (flg & PCI_BASE_ADDRESS_SPACE_IO)	{	  pciaddr_t a = pos & PCI_BASE_ADDRESS_IO_MASK;	  printf("I/O ports at ");	  if (a)	    printf(PCIADDR_PORT_FMT, a);	  else if (flg & PCI_BASE_ADDRESS_IO_MASK)	    printf("<ignored>");	  else	    printf("<unassigned>");	  if (!virtual && !(cmd & PCI_COMMAND_IO))	    printf(" [disabled]");	}      else	{	  int t = flg & PCI_BASE_ADDRESS_MEM_TYPE_MASK;	  pciaddr_t a = pos & PCI_ADDR_MEM_MASK;	  int done = 0;	  u32 z = 0;	  printf("Memory at ");	  if (t == PCI_BASE_ADDRESS_MEM_TYPE_64)	    {	      if (i >= cnt - 1)		{		  printf("<invalid-64bit-slot>");		  done = 1;		}	      else		{		  i++;		  z = get_conf_long(d, PCI_BASE_ADDRESS_0 + 4*i);		}	    }	  if (!done)	    {	      if (a)		printf(PCIADDR_T_FMT, a);	      else		printf(((flg & PCI_BASE_ADDRESS_MEM_MASK) || z) ? "<ignored>" : "<unassigned>");	    }	  printf(" (%s, %sprefetchable)",		 (t == PCI_BASE_ADDRESS_MEM_TYPE_32) ? "32-bit" :		 (t == PCI_BASE_ADDRESS_MEM_TYPE_64) ? "64-bit" :		 (t == PCI_BASE_ADDRESS_MEM_TYPE_1M) ? "low-1M" : "type 3",		 (flg & PCI_BASE_ADDRESS_MEM_PREFETCH) ? "" : "non-");	  if (!virtual && !(cmd & PCI_COMMAND_MEMORY))	    printf(" [disabled]");	}      show_size(len);      putchar('\n');    }}static voidshow_rom(struct device *d, int reg){  struct pci_dev *p = d->dev;  pciaddr_t rom = p->rom_base_addr;  pciaddr_t len = (p->known_fields & PCI_FILL_SIZES) ? p->rom_size : 0;  u32 flg = get_conf_long(d, reg);  word cmd = get_conf_word(d, PCI_COMMAND);  int virtual = 0;  if (!rom && !flg && !len)    return;  putchar('\t');  if ((rom & PCI_ROM_ADDRESS_MASK) && !(flg & PCI_ROM_ADDRESS_MASK))    {      printf("[virtual] ");      flg = rom;      virtual = 1;    }  printf("Expansion ROM at ");  if (rom & PCI_ROM_ADDRESS_MASK)    printf(PCIADDR_T_FMT, rom & PCI_ROM_ADDRESS_MASK);  else if (flg & PCI_ROM_ADDRESS_MASK)    printf("<ignored>");  else    printf("<unassigned>");  if (!(flg & PCI_ROM_ADDRESS_ENABLE))    printf(" [disabled]");  else if (!virtual && !(cmd & PCI_COMMAND_MEMORY))    printf(" [disabled by cmd]");  show_size(len);  putchar('\n');}static voidshow_htype0(struct device *d){  show_bases(d, 6);  show_rom(d, PCI_ROM_ADDRESS);  show_caps(d);}static voidshow_htype1(struct device *d){  u32 io_base = get_conf_byte(d, PCI_IO_BASE);  u32 io_limit = get_conf_byte(d, PCI_IO_LIMIT);  u32 io_type = io_base & PCI_IO_RANGE_TYPE_MASK;  u32 mem_base = get_conf_word(d, PCI_MEMORY_BASE);  u32 mem_limit = get_conf_word(d, PCI_MEMORY_LIMIT);  u32 mem_type = mem_base & PCI_MEMORY_RANGE_TYPE_MASK;  u32 pref_base = get_conf_word(d, PCI_PREF_MEMORY_BASE);  u32 pref_limit = get_conf_word(d, PCI_PREF_MEMORY_LIMIT);  u32 pref_type = pref_base & PCI_PREF_RANGE_TYPE_MASK;  word sec_stat = get_conf_word(d, PCI_SEC_STATUS);  word brc = get_conf_word(d, PCI_BRIDGE_CONTROL);  int verb = verbose > 2;  show_bases(d, 2);  printf("\tBus: primary=%02x, secondary=%02x, subordinate=%02x, sec-latency=%d\n",	 get_conf_byte(d, PCI_PRIMARY_BUS),	 get_conf_byte(d, PCI_SECONDARY_BUS),	 get_conf_byte(d, PCI_SUBORDINATE_BUS),	 get_conf_byte(d, PCI_SEC_LATENCY_TIMER));  if (io_type != (io_limit & PCI_IO_RANGE_TYPE_MASK) ||      (io_type != PCI_IO_RANGE_TYPE_16 && io_type != PCI_IO_RANGE_TYPE_32))    printf("\t!!! Unknown I/O range types %x/%x\n", io_base, io_limit);  else    {      io_base = (io_base & PCI_IO_RANGE_MASK) << 8;      io_limit = (io_limit & PCI_IO_RANGE_MASK) << 8;      if (io_type == PCI_IO_RANGE_TYPE_32)	{	  io_base |= (get_conf_word(d, PCI_IO_BASE_UPPER16) << 16);	  io_limit |= (get_conf_word(d, PCI_IO_LIMIT_UPPER16) << 16);	}      if (io_base <= io_limit || verb)	printf("\tI/O behind bridge: %08x-%08x\n", io_base, io_limit+0xfff);    }  if (mem_type != (mem_limit & PCI_MEMORY_RANGE_TYPE_MASK) ||      mem_type)    printf("\t!!! Unknown memory range types %x/%x\n", mem_base, mem_limit);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -