2003-12-27 Martin Mares <mj@ucw.cz>
+ * lspci.c: Devices in domains different from 0 have their slot number
+ printed as "<domain>:<bus>:<slot>.<func>".
+
+ * lib/filter.c: Slot filters understand domains.
+
+ * lib/generic.c: Mention the domain in slot numbers in all error messages.
+
+ * lib/internal.h: The #ifdef for Linux <asm/byteorder.h> was wrong.
+
+ * lib/access.c (pci_get_dev): Added support for domains.
+
+ * lib/sysfs.c (sysfs_scan): Read vendor and device ID from the config
+ registers (or to be precise, leave it for the generic parts of the pcilib
+ to do so) instead of reading them from the sysfs. It's faster this way.
+
+ * lspci.c (show_pcix): Don't touch pci_dev->hdrtype, it's an internal
+ variable. Better read it from the config registers (it's cached anyway).
+
+ * lib/sysfs.c (sysfs_scan), lib/proc.c (proc_scan): Don't read the hdrtype.
+ lib/generic.c (pci_generic_fill_info): If hdrtype is -1 (unset), read it.
+ Saves lots of unnecessary file accesses.
+
* lib/pci.h (PCIADDR_PORT_FMT): Use %llx instead of %Lx, because the latter
is not supported by all C libraries.
- names.c: rewrite
- support for domains:
- - pci_get_dev
- - filters
+ - filters: doc and helps
+ - reading of dumps
+ - tree view
+ - map mode
bzero(d, sizeof(*d));
d->access = a;
d->methods = a->methods;
+ d->hdrtype = -1;
if (d->methods->init_dev)
d->methods->init_dev(d);
return d;
}
struct pci_dev *
-pci_get_dev(struct pci_access *a, int bus, int dev, int func)
+pci_get_dev(struct pci_access *a, int domain, int bus, int dev, int func)
{
struct pci_dev *d = pci_alloc_dev(a);
+ d->domain = domain;
d->bus = bus;
d->dev = dev;
d->func = func;
if (len >= 8 && buf[2] == ':' && buf[5] == '.' && buf[7] == ' ' &&
sscanf(buf, "%x:%x.%d ", &bn, &dn, &fn) == 3)
{
- dev = pci_get_dev(a, bn, dn, fn);
+ dev = pci_get_dev(a, 0, bn, dn, fn);
dev->aux = pci_malloc(a, 256);
memset(dev->aux, 0xff, 256);
pci_link_dev(a, dev);
void
pci_filter_init(struct pci_access *a UNUSED, struct pci_filter *f)
{
- f->bus = f->slot = f->func = -1;
+ f->domain = f->bus = f->slot = f->func = -1;
f->vendor = f->device = -1;
}
-/* Slot filter syntax: [[bus]:][slot][.[func]] */
+/* Slot filter syntax: [[[domain]:][bus]:][slot][.[func]] */
char *
pci_filter_parse_slot(struct pci_filter *f, char *str)
{
- char *colon = strchr(str, ':');
+ char *colon = strrchr(str, ':');
char *dot = strchr((colon ? colon + 1 : str), '.');
char *mid = str;
- char *e;
+ char *e, *bus, *colon2;
if (colon)
{
*colon++ = 0;
mid = colon;
- if (str[0] && strcmp(str, "*"))
+ colon2 = strchr(str, ':');
+ if (colon2)
{
- long int x = strtol(str, &e, 16);
+ *colon2++ = 0;
+ bus = colon2;
+ if (str[0] && strcmp(str, "*"))
+ {
+ long int x = strtol(bus, &e, 16);
+ if ((e && *e) || (x < 0 || x > 0xffff))
+ return "Invalid domain number";
+ f->domain = x;
+ }
+ }
+ else
+ bus = str;
+ if (bus[0] && strcmp(bus, "*"))
+ {
+ long int x = strtol(bus, &e, 16);
if ((e && *e) || (x < 0 || x > 0xff))
return "Invalid bus number";
f->bus = x;
int
pci_filter_match(struct pci_filter *f, struct pci_dev *d)
{
- if ((f->bus >= 0 && f->bus != d->bus) ||
+ if ((f->domain >= 0 && f->domain != d->domain) ||
+ (f->bus >= 0 && f->bus != d->bus) ||
(f->slot >= 0 && f->slot != d->dev) ||
(f->func >= 0 && f->func != d->func))
return 0;
pci_generic_scan_bus(a, busmap, pci_read_byte(t, PCI_SECONDARY_BUS));
break;
default:
- a->debug("Device %02x:%02x.%d has unknown header type %02x.\n", d->bus, d->dev, d->func, ht);
+ a->debug("Device %04x:%02x:%02x.%d has unknown header type %02x.\n", d->domain, d->bus, d->dev, d->func, ht);
}
}
}
{
struct pci_access *a = d->access;
+ if ((flags & (PCI_FILL_BASES | PCI_FILL_ROM_BASE)) && d->hdrtype < 0)
+ d->hdrtype = pci_read_byte(d, PCI_HEADER_TYPE);
if (flags & PCI_FILL_IDENT)
{
d->vendor_id = pci_read_word(d, PCI_VENDOR_ID);
if ((x & PCI_BASE_ADDRESS_MEM_TYPE_MASK) == PCI_BASE_ADDRESS_MEM_TYPE_64)
{
if (i >= cnt-1)
- a->warning("%02x:%02x.%d: Invalid 64-bit address seen.", d->bus, d->dev, d->func);
+ a->warning("%04x:%02x:%02x.%d: Invalid 64-bit address seen.", d->domain, d->bus, d->dev, d->func);
else
{
u32 y = pci_read_long(d, PCI_BASE_ADDRESS_0 + (++i)*4);
#else
if (y)
{
- a->warning("%02x:%02x.%d 64-bit device address ignored.", d->bus, d->dev, d->func);
+ a->warning("%04x:%02x:%02x.%d 64-bit device address ignored.", d->domain, d->bus, d->dev, d->func);
d->base_addr[i-1] = 0;
}
#endif
#define inline
#endif
-#ifdef HAVE_PM_LINUX_BYTEORDER_H
+#ifdef HAVE_LINUX_BYTEORDER_H
#include <asm/byteorder.h>
#define cpu_to_le16 __cpu_to_le16
/* Scanning of devices */
void pci_scan_bus(struct pci_access *acc);
-struct pci_dev *pci_get_dev(struct pci_access *acc, int bus, int dev, int func); /* Raw access to specified device */
+struct pci_dev *pci_get_dev(struct pci_access *acc, int domain, int bus, int dev, int func); /* Raw access to specified device */
void pci_free_dev(struct pci_dev *);
/*
struct pci_dev {
struct pci_dev *next; /* Next device in the chain */
- word domain; /* PCI domain (host bridge) */
- byte bus; /* Bus inside domain */
- byte dev, func; /* Device and function */
+ u16 domain; /* PCI domain (host bridge) */
+ byte bus, dev, func; /* Bus inside domain, device and function */
/* These fields are set by pci_fill_info() */
int known_fields; /* Set of info fields already known */
/* Fields used internally: */
struct pci_access *access;
struct pci_methods *methods;
- byte *cache; /* Cached information */
+ byte *cache; /* Cached config registers */
int cache_len;
- int hdrtype; /* Direct methods: header type */
+ int hdrtype; /* Cached header type, -1 if unknown */
void *aux; /* Auxillary data */
};
*/
struct pci_filter {
- int bus, slot, func; /* -1 = ANY */
+ int domain, bus, slot, func; /* -1 = ANY */
int vendor, device;
};
d->func = PCI_FUNC(dfn & 0xff);
d->vendor_id = vend >> 16U;
d->device_id = vend & 0xffff;
- d->hdrtype = pci_read_byte(d, PCI_HEADER_TYPE) & 0x7f;
known = PCI_FILL_IDENT;
if (!a->buscentric)
{
{
if (access(sysfs_name(a), R_OK))
{
- a->debug("Cannot open %s", sysfs_name(a));
+ a->debug("...cannot open %s", sysfs_name(a));
return 0;
}
a->debug("...using %s", sysfs_name(a));
d->bus = bus;
d->dev = dev;
d->func = func;
- d->hdrtype = pci_read_byte(d, PCI_HEADER_TYPE) & 0x7f;
if (!a->buscentric)
{
sysfs_get_resources(d);
+ d->irq = sysfs_get_value(d, "irq");
+ d->known_fields = PCI_FILL_IRQ | PCI_FILL_BASES | PCI_FILL_ROM_BASE | PCI_FILL_SIZES;
+#if 0
+ /*
+ * We prefer reading these from the config registers, it's faster.
+ * However, it would be possible and maybe even useful to hack the kernel
+ * to believe that some device has a different ID. If you do it, just
+ * enable this piece of code. --mj
+ */
d->vendor_id = sysfs_get_value(d, "vendor");
d->device_id = sysfs_get_value(d, "device");
- d->irq = sysfs_get_value(d, "irq");
- d->known_fields = PCI_FILL_IDENT | PCI_FILL_IRQ | PCI_FILL_BASES | PCI_FILL_ROM_BASE | PCI_FILL_SIZES;
+ d->known_fields |= PCI_FILL_IDENT;
+#endif
}
pci_link_dev(a, d);
}
-b\t\tBus-centric view (PCI addresses and IRQ's instead of those seen by the CPU)\n\
-x\t\tShow hex-dump of the standard portion of config space\n\
-xxx\t\tShow hex-dump of the whole config space (dangerous; root only)\n\
--s [[<bus>]:][<slot>][.[<func>]]\tShow only devices in selected slots\n\
+-s [[[[<domain>]:]<bus>]:][<slot>][.[<func>]]\tShow only devices in selected slots\n\
-d [<vendor>]:[<device>]\tShow only selected devices\n\
-t\t\tShow bus tree\n\
-m\t\tProduce machine-readable output\n\
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)
#define FLAG(x,y) ((x & y) ? '+' : '-')
+static void
+show_slot_name(struct device *d)
+{
+ struct pci_dev *p = d->dev;
+
+ if (p->domain)
+ printf("%04x:", p->domain);
+ printf("%02x:%02x.%d", p->bus, p->dev, p->func);
+}
+
static void
show_terse(struct device *d)
{
struct pci_dev *p = d->dev;
byte classbuf[128], devbuf[128];
- printf("%02x:%02x.%x %s: %s",
- p->bus,
- p->dev,
- p->func,
+ show_slot_name(d);
+ printf(" %s: %s",
pci_lookup_name(pacc, classbuf, sizeof(classbuf),
PCI_LOOKUP_CLASS,
get_conf_word(d, PCI_CLASS_DEVICE), 0, 0, 0),
static void
show_pcix(struct device *d, int where)
{
- switch (d->dev->hdrtype)
+ switch (get_conf_byte(d, PCI_HEADER_TYPE) & 0x7f)
{
case PCI_HEADER_TYPE_NORMAL:
show_pcix_nobridge(d, where);
if (verbose)
{
- printf("Device:\t%02x:%02x.%x\n", p->bus, p->dev, p->func);
+ printf("Device:\t");
+ show_slot_name(d);
+ putchar('\n');
printf("Class:\t%s\n",
pci_lookup_name(pacc, classbuf, sizeof(classbuf), PCI_LOOKUP_CLASS, get_conf_word(d, PCI_CLASS_DEVICE), 0, 0, 0));
printf("Vendor:\t%s\n",
}
else
{
- printf("%02x:%02x.%x ", p->bus, p->dev, p->func);
- printf("\"%s\" \"%s\" \"%s\"",
+ show_slot_name(d);
+ printf(" \"%s\" \"%s\" \"%s\"",
pci_lookup_name(pacc, classbuf, sizeof(classbuf), PCI_LOOKUP_CLASS,
get_conf_word(d, PCI_CLASS_DEVICE), 0, 0, 0),
pci_lookup_name(pacc, vendbuf, sizeof(vendbuf), PCI_LOOKUP_VENDOR,
for(func = 0; func < func_limit; func++)
if (filter.func < 0 || filter.func == func)
{
- struct pci_dev *p = pci_get_dev(pacc, bus, dev, func);
+ struct pci_dev *p = pci_get_dev(pacc, 0, bus, dev, func);
u16 vendor = pci_read_word(p, PCI_VENDOR_ID);
if (vendor && vendor != 0xffff)
{
-v\t\tBe verbose\n\
-D\t\tList changes, don't commit them\n"
GENERIC_HELP
-"<device>:\t-s [[<bus>]:][<slot>][.[<func>]]\n"
+"<device>:\t-s [[[<domain>]:][<bus>]:][<slot>][.[<func>]]\n"
"\t|\t-d [<vendor>]:[<device>]\n"
"<reg>:\t\t<number>[.(B|W|L)]\n"
" |\t\t<name>\n"