struct pci_access *a = d->access;
int fd, n;
char namebuf[OBJNAMELEN];
- void (*warn)(char *msg, ...) = (mandatory ? a->error : a->warning);
sysfs_obj_name(d, object, namebuf);
fd = open(namebuf, O_RDONLY);
if (fd < 0)
{
if (mandatory || errno != ENOENT)
- warn("Cannot open %s: %s", namebuf, strerror(errno));
+ a->warning("Cannot open %s: %s", namebuf, strerror(errno));
return 0;
}
n = read(fd, buf, OBJBUFSIZE);
close(fd);
if (n < 0)
{
- warn("Error reading %s: %s", namebuf, strerror(read_errno));
+ a->warning("Error reading %s: %s", namebuf, strerror(read_errno));
return 0;
}
if (n >= OBJBUFSIZE)
{
- warn("Value in %s too long", namebuf);
+ a->warning("Value in %s too long", namebuf);
return 0;
}
buf[n] = 0;
struct pci_access *a = d->access;
char namebuf[OBJNAMELEN], buf[256];
struct { pciaddr_t flags, base_addr, size; } lines[10];
- int have_bar_bases, have_rom_base, have_bridge_bases;
+ int have_bar_bases = 0, have_rom_base = 0, have_bridge_bases = 0;
FILE *file;
int i;
- have_bar_bases = have_rom_base = have_bridge_bases = 0;
sysfs_obj_name(d, "resource", namebuf);
file = fopen(namebuf, "r");
if (!file)
- a->error("Cannot open %s: %s", namebuf, strerror(errno));
- for (i = 0; i < 7+6+4+1; i++)
+ a->warning("Cannot open %s: %s", namebuf, strerror(errno));
+ else
{
- unsigned long long start, end, size, flags;
- if (!fgets(buf, sizeof(buf), file))
- break;
- if (sscanf(buf, "%llx %llx %llx", &start, &end, &flags) != 3)
- a->error("Syntax error in %s", namebuf);
- if (end > start)
- size = end - start + 1;
- else
- size = 0;
- if (i < 6)
+ for (i = 0; i < 7+6+4+1; i++)
{
- d->flags[i] = flags;
- flags &= PCI_ADDR_FLAG_MASK;
- d->base_addr[i] = start | flags;
- d->size[i] = size;
- have_bar_bases = 1;
+ unsigned long long start, end, size, flags;
+ if (!fgets(buf, sizeof(buf), file))
+ break;
+ if (sscanf(buf, "%llx %llx %llx", &start, &end, &flags) != 3)
+ {
+ fclose(file);
+ a->error("Syntax error in %s", namebuf);
+ }
+ if (end > start)
+ size = end - start + 1;
+ else
+ size = 0;
+ if (i < 6)
+ {
+ d->flags[i] = flags;
+ flags &= PCI_ADDR_FLAG_MASK;
+ d->base_addr[i] = start | flags;
+ d->size[i] = size;
+ have_bar_bases = 1;
+ }
+ else if (i == 6)
+ {
+ d->rom_flags = flags;
+ flags &= PCI_ADDR_FLAG_MASK;
+ d->rom_base_addr = start | flags;
+ d->rom_size = size;
+ have_rom_base = 1;
+ }
+ else if (i < 7+6+4)
+ {
+ /*
+ * If kernel was compiled without CONFIG_PCI_IOV option then after
+ * the ROM line for configured bridge device (that which had set
+ * subordinary bus number to non-zero value) are four additional lines
+ * which describe resources behind bridge. For PCI-to-PCI bridges they
+ * are: IO, MEM, PREFMEM and empty. For CardBus bridges they are: IO0,
+ * IO1, MEM0 and MEM1. For unconfigured bridges and other devices
+ * there is no additional line after the ROM line. If kernel was
+ * compiled with CONFIG_PCI_IOV option then after the ROM line and
+ * before the first bridge resource line are six additional lines
+ * which describe IOV resources. Read all remaining lines in resource
+ * file and based on the number of remaining lines (0, 4, 6, 10) parse
+ * resources behind bridge.
+ */
+ lines[i-7].flags = flags;
+ lines[i-7].base_addr = start;
+ lines[i-7].size = size;
+ }
}
- else if (i == 6)
+ if (i == 7+4 || i == 7+6+4)
{
- d->rom_flags = flags;
- flags &= PCI_ADDR_FLAG_MASK;
- d->rom_base_addr = start | flags;
- d->rom_size = size;
- have_rom_base = 1;
+ int offset = (i == 7+6+4) ? 6 : 0;
+ for (i = 0; i < 4; i++)
+ {
+ d->bridge_flags[i] = lines[offset+i].flags;
+ d->bridge_base_addr[i] = lines[offset+i].base_addr;
+ d->bridge_size[i] = lines[offset+i].size;
+ }
+ have_bridge_bases = 1;
}
- else if (i < 7+6+4)
- {
- /*
- * If kernel was compiled without CONFIG_PCI_IOV option then after
- * the ROM line for configured bridge device (that which had set
- * subordinary bus number to non-zero value) are four additional lines
- * which describe resources behind bridge. For PCI-to-PCI bridges they
- * are: IO, MEM, PREFMEM and empty. For CardBus bridges they are: IO0,
- * IO1, MEM0 and MEM1. For unconfigured bridges and other devices
- * there is no additional line after the ROM line. If kernel was
- * compiled with CONFIG_PCI_IOV option then after the ROM line and
- * before the first bridge resource line are six additional lines
- * which describe IOV resources. Read all remaining lines in resource
- * file and based on the number of remaining lines (0, 4, 6, 10) parse
- * resources behind bridge.
- */
- lines[i-7].flags = flags;
- lines[i-7].base_addr = start;
- lines[i-7].size = size;
- }
- }
- if (i == 7+4 || i == 7+6+4)
- {
- int offset = (i == 7+6+4) ? 6 : 0;
- for (i = 0; i < 4; i++)
- {
- d->bridge_flags[i] = lines[offset+i].flags;
- d->bridge_base_addr[i] = lines[offset+i].base_addr;
- d->bridge_size[i] = lines[offset+i].size;
- }
- have_bridge_bases = 1;
+ fclose(file);
}
- fclose(file);
+
if (!have_bar_bases)
clear_fill(d, PCI_FILL_BASES | PCI_FILL_SIZES | PCI_FILL_IO_FLAGS);
if (!have_rom_base)
*/
if (want_fill(d, flags, PCI_FILL_IDENT))
{
- d->vendor_id = sysfs_get_value(d, "vendor", 1);
- d->device_id = sysfs_get_value(d, "device", 1);
+ /*
+ * Reading of vendor/device ID may fail in case of hot unplug.
+ * At this point, it is too late to pretend that the device has
+ * never existed, so return FFFF:FFFF as its ID.
+ */
+ d->vendor_id = sysfs_get_value(d, "vendor", 1) & 0xffff;
+ d->device_id = sysfs_get_value(d, "device", 1) & 0xffff;
}
want_class = want_fill(d, flags, PCI_FILL_CLASS);
want_class_ext = want_fill(d, flags, PCI_FILL_CLASS_EXT);
if (want_class || want_class_ext)
{
- value = sysfs_get_value(d, "class", 1);
+ value = sysfs_get_value(d, "class", 1) & 0xffff;
if (want_class)
d->device_class = value >> 8;
if (want_class_ext)