/*
* The PCI Library -- Generic Direct Access Functions
*
- * Copyright (c) 1997--2000 Martin Mares <mj@ucw.cz>
+ * Copyright (c) 1997--2022 Martin Mares <mj@ucw.cz>
*
* Can be freely distributed and used under the terms of the GNU GPL.
*/
#include "internal.h"
void
-pci_generic_scan_bus(struct pci_access *a, byte *busmap, int bus)
+pci_generic_scan_bus(struct pci_access *a, byte *busmap, int domain, int bus)
{
int dev, multi, ht;
struct pci_dev *t;
}
busmap[bus] = 1;
t = pci_alloc_dev(a);
+ t->domain = domain;
t->bus = bus;
- for(dev=0; dev<32; dev++)
+ for (dev=0; dev<32; dev++)
{
t->dev = dev;
multi = 0;
- for(t->func=0; !t->func || multi && t->func<8; t->func++)
+ for (t->func=0; !t->func || multi && t->func<8; t->func++)
{
u32 vd = pci_read_long(t, PCI_VENDOR_ID);
struct pci_dev *d;
multi = ht & 0x80;
ht &= 0x7f;
d = pci_alloc_dev(a);
+ d->domain = t->domain;
d->bus = t->bus;
d->dev = t->dev;
d->func = t->func;
break;
case PCI_HEADER_TYPE_BRIDGE:
case PCI_HEADER_TYPE_CARDBUS:
- pci_generic_scan_bus(a, busmap, pci_read_byte(t, PCI_SECONDARY_BUS));
+ pci_generic_scan_bus(a, busmap, domain, pci_read_byte(t, PCI_SECONDARY_BUS));
break;
default:
a->debug("Device %04x:%02x:%02x.%d has unknown header type %02x.\n", d->domain, d->bus, d->dev, d->func, ht);
}
void
-pci_generic_scan(struct pci_access *a)
+pci_generic_scan_domain(struct pci_access *a, int domain)
{
byte busmap[256];
- bzero(busmap, sizeof(busmap));
- pci_generic_scan_bus(a, busmap, 0);
+ memset(busmap, 0, sizeof(busmap));
+ pci_generic_scan_bus(a, busmap, domain, 0);
}
-int
-pci_generic_fill_info(struct pci_dev *d, int flags)
+void
+pci_generic_scan(struct pci_access *a)
{
- struct pci_access *a = d->access;
+ pci_generic_scan_domain(a, 0);
+}
- if ((flags & (PCI_FILL_BASES | PCI_FILL_ROM_BASE)) && d->hdrtype < 0)
+static int
+get_hdr_type(struct pci_dev *d)
+{
+ if (d->hdrtype < 0)
d->hdrtype = pci_read_byte(d, PCI_HEADER_TYPE) & 0x7f;
- if (flags & PCI_FILL_IDENT)
+ return d->hdrtype;
+}
+
+void
+pci_generic_fill_info(struct pci_dev *d, unsigned int flags)
+{
+ struct pci_access *a = d->access;
+ struct pci_cap *cap;
+
+ if (want_fill(d, flags, PCI_FILL_IDENT))
{
d->vendor_id = pci_read_word(d, PCI_VENDOR_ID);
d->device_id = pci_read_word(d, PCI_DEVICE_ID);
}
- if (flags & PCI_FILL_IRQ)
+
+ if (want_fill(d, flags, PCI_FILL_CLASS))
+ d->device_class = pci_read_word(d, PCI_CLASS_DEVICE);
+
+ if (want_fill(d, flags, PCI_FILL_CLASS_EXT))
+ {
+ d->prog_if = pci_read_byte(d, PCI_CLASS_PROG);
+ d->rev_id = pci_read_byte(d, PCI_REVISION_ID);
+ }
+
+ if (want_fill(d, flags, PCI_FILL_SUBSYS))
+ {
+ switch (get_hdr_type(d))
+ {
+ case PCI_HEADER_TYPE_NORMAL:
+ d->subsys_vendor_id = pci_read_word(d, PCI_SUBSYSTEM_VENDOR_ID);
+ d->subsys_id = pci_read_word(d, PCI_SUBSYSTEM_ID);
+ break;
+ case PCI_HEADER_TYPE_BRIDGE:
+ cap = pci_find_cap(d, PCI_CAP_ID_SSVID, PCI_CAP_NORMAL);
+ if (cap)
+ {
+ d->subsys_vendor_id = pci_read_word(d, cap->addr + PCI_SSVID_VENDOR);
+ d->subsys_id = pci_read_word(d, cap->addr + PCI_SSVID_DEVICE);
+ }
+ break;
+ case PCI_HEADER_TYPE_CARDBUS:
+ d->subsys_vendor_id = pci_read_word(d, PCI_CB_SUBSYSTEM_VENDOR_ID);
+ d->subsys_id = pci_read_word(d, PCI_CB_SUBSYSTEM_ID);
+ break;
+ default:
+ clear_fill(d, PCI_FILL_SUBSYS);
+ }
+ }
+
+ if (want_fill(d, flags, PCI_FILL_IRQ))
d->irq = pci_read_byte(d, PCI_INTERRUPT_LINE);
- if (flags & PCI_FILL_BASES)
+
+ if (want_fill(d, flags, PCI_FILL_BASES))
{
int cnt = 0, i;
- bzero(d->base_addr, sizeof(d->base_addr));
- switch (d->hdrtype)
+ memset(d->base_addr, 0, sizeof(d->base_addr));
+ switch (get_hdr_type(d))
{
case PCI_HEADER_TYPE_NORMAL:
cnt = 6;
}
if (cnt)
{
- for(i=0; i<cnt; i++)
+ for (i=0; i<cnt; i++)
{
u32 x = pci_read_long(d, PCI_BASE_ADDRESS_0 + i*4);
if (!x || x == (u32) ~0)
}
}
}
- if (flags & PCI_FILL_ROM_BASE)
+
+ if (want_fill(d, flags, PCI_FILL_ROM_BASE))
{
int reg = 0;
d->rom_base_addr = 0;
- switch (d->hdrtype)
+ switch (get_hdr_type(d))
{
case PCI_HEADER_TYPE_NORMAL:
reg = PCI_ROM_ADDRESS;
d->rom_base_addr = u;
}
}
- return flags & ~PCI_FILL_SIZES;
+
+ pci_scan_caps(d, flags);
}
static int