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

📄 ls-tree.c

📁 linux下的pci设备浏览工具
💻 C
字号:
/* *	The PCI Utilities -- Show Bus Tree * *	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 "lspci.h"struct bridge {  struct bridge *chain;			/* Single-linked list of bridges */  struct bridge *next, *child;		/* Tree of bridges */  struct bus *first_bus;		/* List of buses connected to this bridge */  unsigned int domain;  unsigned int primary, secondary, subordinate;	/* Bus numbers */  struct device *br_dev;};struct bus {  unsigned int domain;  unsigned int number;  struct bus *sibling;  struct device *first_dev, **last_dev;};static struct bridge host_bridge = { NULL, NULL, NULL, NULL, 0, ~0, 0, ~0, NULL };static struct bus *find_bus(struct bridge *b, unsigned int domain, unsigned int n){  struct bus *bus;  for (bus=b->first_bus; bus; bus=bus->sibling)    if (bus->domain == domain && bus->number == n)      break;  return bus;}static struct bus *new_bus(struct bridge *b, unsigned int domain, unsigned int n){  struct bus *bus = xmalloc(sizeof(struct bus));  bus->domain = domain;  bus->number = n;  bus->sibling = b->first_bus;  bus->first_dev = NULL;  bus->last_dev = &bus->first_dev;  b->first_bus = bus;  return bus;}static voidinsert_dev(struct device *d, struct bridge *b){  struct pci_dev *p = d->dev;  struct bus *bus;  if (! (bus = find_bus(b, p->domain, p->bus)))    {      struct bridge *c;      for (c=b->child; c; c=c->next)	if (c->domain == p->domain && c->secondary <= p->bus && p->bus <= c->subordinate)          {            insert_dev(d, c);            return;          }      bus = new_bus(b, p->domain, p->bus);    }  /* Simple insertion at the end _does_ guarantee the correct order as the   * original device list was sorted by (domain, bus, devfn) lexicographically   * and all devices on the new list have the same bus number.   */  *bus->last_dev = d;  bus->last_dev = &d->next;  d->next = NULL;}static voidgrow_tree(void){  struct device *d, *d2;  struct bridge **last_br, *b;  /* Build list of bridges */  last_br = &host_bridge.chain;  for (d=first_dev; d; d=d->next)    {      word class = d->dev->device_class;      byte ht = get_conf_byte(d, PCI_HEADER_TYPE) & 0x7f;      if (class == PCI_CLASS_BRIDGE_PCI &&	  (ht == PCI_HEADER_TYPE_BRIDGE || ht == PCI_HEADER_TYPE_CARDBUS))	{	  b = xmalloc(sizeof(struct bridge));	  b->domain = d->dev->domain;	  if (ht == PCI_HEADER_TYPE_BRIDGE)	    {	      b->primary = get_conf_byte(d, PCI_PRIMARY_BUS);	      b->secondary = get_conf_byte(d, PCI_SECONDARY_BUS);	      b->subordinate = get_conf_byte(d, PCI_SUBORDINATE_BUS);	    }	  else	    {	      b->primary = get_conf_byte(d, PCI_CB_PRIMARY_BUS);	      b->secondary = get_conf_byte(d, PCI_CB_CARD_BUS);	      b->subordinate = get_conf_byte(d, PCI_CB_SUBORDINATE_BUS);	    }	  *last_br = b;	  last_br = &b->chain;	  b->next = b->child = NULL;	  b->first_bus = NULL;	  b->br_dev = d;	}    }  *last_br = NULL;  /* Create a bridge tree */  for (b=&host_bridge; b; b=b->chain)    {      struct bridge *c, *best;      best = NULL;      for (c=&host_bridge; c; c=c->chain)	if (c != b && (c == &host_bridge || b->domain == c->domain) &&	    b->primary >= c->secondary && b->primary <= c->subordinate &&	    (!best || best->subordinate - best->primary > c->subordinate - c->primary))	  best = c;      if (best)	{	  b->next = best->child;	  best->child = b;	}    }  /* Insert secondary bus for each bridge */  for (b=&host_bridge; b; b=b->chain)    if (!find_bus(b, b->domain, b->secondary))      new_bus(b, b->domain, b->secondary);  /* Create bus structs and link devices */  for (d=first_dev; d;)    {      d2 = d->next;      insert_dev(d, &host_bridge);      d = d2;    }}static voidprint_it(char *line, char *p){  *p++ = '\n';  *p = 0;  fputs(line, stdout);  for (p=line; *p; p++)    if (*p == '+' || *p == '|')      *p = '|';    else      *p = ' ';}static void show_tree_bridge(struct bridge *, char *, char *);static voidshow_tree_dev(struct device *d, char *line, char *p){  struct pci_dev *q = d->dev;  struct bridge *b;  char namebuf[256];  p += sprintf(p, "%02x.%x", q->dev, q->func);  for (b=&host_bridge; b; b=b->chain)    if (b->br_dev == d)      {	if (b->secondary == b->subordinate)	  p += sprintf(p, "-[%04x:%02x]-", b->domain, b->secondary);	else	  p += sprintf(p, "-[%04x:%02x-%02x]-", b->domain, b->secondary, b->subordinate);        show_tree_bridge(b, line, p);        return;      }  if (verbose)    p += sprintf(p, "  %s",		 pci_lookup_name(pacc, namebuf, sizeof(namebuf),				 PCI_LOOKUP_VENDOR | PCI_LOOKUP_DEVICE,				 q->vendor_id, q->device_id));  print_it(line, p);}static voidshow_tree_bus(struct bus *b, char *line, char *p){  if (!b->first_dev)    print_it(line, p);  else if (!b->first_dev->next)    {      *p++ = '-';      *p++ = '-';      show_tree_dev(b->first_dev, line, p);    }  else    {      struct device *d = b->first_dev;      while (d->next)	{	  p[0] = '+';	  p[1] = '-';	  show_tree_dev(d, line, p+2);	  d = d->next;	}      p[0] = '\\';      p[1] = '-';      show_tree_dev(d, line, p+2);    }}static voidshow_tree_bridge(struct bridge *b, char *line, char *p){  *p++ = '-';  if (!b->first_bus->sibling)    {      if (b == &host_bridge)        p += sprintf(p, "[%04x:%02x]-", b->domain, b->first_bus->number);      show_tree_bus(b->first_bus, line, p);    }  else    {      struct bus *u = b->first_bus;      char *k;      while (u->sibling)        {          k = p + sprintf(p, "+-[%04x:%02x]-", u->domain, u->number);          show_tree_bus(u, line, k);          u = u->sibling;        }      k = p + sprintf(p, "\\-[%04x:%02x]-", u->domain, u->number);      show_tree_bus(u, line, k);    }}voidshow_forest(void){  char line[256];  grow_tree();  show_tree_bridge(&host_bridge, line, line);}

⌨️ 快捷键说明

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