diff options
author | Brad Smith <brad@cvs.openbsd.org> | 2006-03-19 21:25:05 +0000 |
---|---|---|
committer | Brad Smith <brad@cvs.openbsd.org> | 2006-03-19 21:25:05 +0000 |
commit | c4f03a5ab739968e68c4e6b35e42c3f8f1c74eba (patch) | |
tree | 9fa82c0bcb626b42e9ecb92dba2663427bb7f091 /sys/dev/pci | |
parent | 698e7a5887c09b7d4dbee26ed3d963f94d45b792 (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.c | 27 | ||||
-rw-r--r-- | sys/dev/pci/pcivar.h | 5 |
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; |