summaryrefslogtreecommitdiff
path: root/sys/dev/pci
diff options
context:
space:
mode:
authorBrad Smith <brad@cvs.openbsd.org>2006-03-19 21:25:05 +0000
committerBrad Smith <brad@cvs.openbsd.org>2006-03-19 21:25:05 +0000
commitc4f03a5ab739968e68c4e6b35e42c3f8f1c74eba (patch)
tree9fa82c0bcb626b42e9ecb92dba2663427bb7f091 /sys/dev/pci
parent698e7a5887c09b7d4dbee26ed3d963f94d45b792 (diff)
- check HDRTYPE early, and ignore if it is not supported (n > 2).
- defer access to interrupt configuration register, as its existence depends on HDRTYPE. From itojun NetBSD
Diffstat (limited to 'sys/dev/pci')
-rw-r--r--sys/dev/pci/pci.c27
-rw-r--r--sys/dev/pci/pcivar.h5
2 files changed, 22 insertions, 10 deletions
diff --git a/sys/dev/pci/pci.c b/sys/dev/pci/pci.c
index e4e7a0b403e..7a49c141618 100644
--- a/sys/dev/pci/pci.c
+++ b/sys/dev/pci/pci.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pci.c,v 1.41 2006/03/19 02:43:38 brad Exp $ */
+/* $OpenBSD: pci.c,v 1.42 2006/03/19 21:25:04 brad Exp $ */
/* $NetBSD: pci.c,v 1.31 1997/06/06 23:48:04 thorpej Exp $ */
/*
@@ -272,11 +272,13 @@ pci_probe_device(struct pci_softc *sc, pcitag_t tag,
pci_decompose_tag(pc, tag, &bus, &device, &function);
+ bhlcr = pci_conf_read(pc, tag, PCI_BHLC_REG);
+ if (PCI_HDRTYPE_TYPE(bhlcr) > 2)
+ return (0);
+
id = pci_conf_read(pc, tag, PCI_ID_REG);
csr = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG);
class = pci_conf_read(pc, tag, PCI_CLASS_REG);
- intr = pci_conf_read(pc, tag, PCI_INTERRUPT_REG);
- bhlcr = pci_conf_read(pc, tag, PCI_BHLC_REG);
/* Invalid vendor ID value? */
if (PCI_VENDOR(id) == PCI_VENDOR_INVALID)
@@ -319,6 +321,9 @@ pci_probe_device(struct pci_softc *sc, pcitag_t tag,
pa.pa_intrtag = sc->sc_intrtag;
}
#endif
+
+ intr = pci_conf_read(pc, tag, PCI_INTERRUPT_REG);
+
pin = PCI_INTERRUPT_PIN(intr);
pa.pa_rawintrpin = pin;
if (pin == PCI_INTERRUPT_PIN_NONE) {
@@ -427,6 +432,11 @@ pci_enumerate_bus(struct pci_softc *sc,
for (device = 0; device < sc->sc_maxndevs; device++) {
tag = pci_make_tag(pc, sc->sc_bus, device, 0);
+
+ bhlcr = pci_conf_read(pc, tag, PCI_BHLC_REG);
+ if (PCI_HDRTYPE_TYPE(bhlcr) > 2)
+ continue;
+
id = pci_conf_read(pc, tag, PCI_ID_REG);
/* Invalid vendor ID value? */
@@ -438,13 +448,14 @@ pci_enumerate_bus(struct pci_softc *sc,
qd = pci_lookup_quirkdata(PCI_VENDOR(id), PCI_PRODUCT(id));
- bhlcr = pci_conf_read(pc, tag, PCI_BHLC_REG);
- if (PCI_HDRTYPE_MULTIFN(bhlcr) ||
- (qd != NULL &&
- (qd->quirks & PCI_QUIRK_MULTIFUNCTION) != 0))
+ if (qd != NULL &&
+ (qd->quirks & PCI_QUIRK_MULTIFUNCTION) != 0)
nfunctions = 8;
- else
+ else if (qd != NULL &&
+ (qd->quirks & PCI_QUIRK_MONOFUNCTION) != 0)
nfunctions = 1;
+ else
+ nfunctions = PCI_HDRTYPE_MULTIFN(bhlcr) ? 8 : 1;
for (function = 0; function < nfunctions; function++) {
tag = pci_make_tag(pc, sc->sc_bus, device, function);
diff --git a/sys/dev/pci/pcivar.h b/sys/dev/pci/pcivar.h
index 43b91f938ec..9329ef809a6 100644
--- a/sys/dev/pci/pcivar.h
+++ b/sys/dev/pci/pcivar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: pcivar.h,v 1.45 2006/03/19 02:43:38 brad Exp $ */
+/* $OpenBSD: pcivar.h,v 1.46 2006/03/19 21:25:04 brad Exp $ */
/* $NetBSD: pcivar.h,v 1.23 1997/06/06 23:48:05 thorpej Exp $ */
/*
@@ -147,7 +147,8 @@ struct pci_quirkdata {
pci_product_id_t product; /* Product ID */
int quirks; /* quirks; see below */
};
-#define PCI_QUIRK_MULTIFUNCTION 0x00000001
+#define PCI_QUIRK_MULTIFUNCTION 1
+#define PCI_QUIRK_MONOFUNCTION 2
struct pci_softc {
struct device sc_dev;