summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
Diffstat (limited to 'sys')
-rw-r--r--sys/arch/sparc64/dev/pci_machdep.c197
-rw-r--r--sys/arch/sparc64/dev/psycho.c3
-rw-r--r--sys/arch/sparc64/dev/schizo.c3
-rw-r--r--sys/arch/sparc64/include/pci_machdep.h21
-rw-r--r--sys/dev/pci/pci.c334
-rw-r--r--sys/dev/pci/pcivar.h10
6 files changed, 253 insertions, 315 deletions
diff --git a/sys/arch/sparc64/dev/pci_machdep.c b/sys/arch/sparc64/dev/pci_machdep.c
index 7b7c6469a75..2582d98aefc 100644
--- a/sys/arch/sparc64/dev/pci_machdep.c
+++ b/sys/arch/sparc64/dev/pci_machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pci_machdep.c,v 1.21 2006/01/06 20:30:09 kettenis Exp $ */
+/* $OpenBSD: pci_machdep.c,v 1.22 2006/03/19 02:43:38 brad Exp $ */
/* $NetBSD: pci_machdep.c,v 1.22 2001/07/20 00:07:13 eeh Exp $ */
/*
@@ -37,7 +37,6 @@
#define SPDB_CONF 0x01
#define SPDB_INTR 0x04
#define SPDB_INTMAP 0x08
-#define SPDB_INTFIX 0x10
#define SPDB_PROBE 0x20
int sparc_pci_debug = 0x0;
#define DPRINTF(l, s) do { if (sparc_pci_debug & l) printf s; } while (0)
@@ -73,6 +72,21 @@ struct sparc_pci_chipset _sparc_pci_chipset = {
NULL,
};
+static pcitag_t
+ofpci_make_tag(pci_chipset_tag_t pc, int node, int b, int d, int f)
+{
+ pcitag_t tag;
+
+ tag = PCITAG_CREATE(node, b, d, f);
+
+ /* Enable all the different spaces for this device */
+ pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG,
+ PCI_COMMAND_MEM_ENABLE|PCI_COMMAND_MASTER_ENABLE|
+ PCI_COMMAND_IO_ENABLE);
+
+ return (tag);
+}
+
/*
* functions provided to the MI code.
*/
@@ -95,124 +109,6 @@ pci_bus_maxdevs(pc, busno)
return 32;
}
-#ifdef __PCI_BUS_DEVORDER
-int
-pci_bus_devorder(pc, busno, devs)
- pci_chipset_tag_t pc;
- int busno;
- char *devs;
-{
- struct ofw_pci_register reg;
- int node, len, device, i = 0;
- u_int32_t done = 0;
-#ifdef DEBUG
- char name[80];
-#endif
-
- node = pc->curnode;
-#ifdef DEBUG
- if (sparc_pci_debug & SPDB_PROBE) {
- OF_getprop(node, "name", &name, sizeof(name));
- printf("pci_bus_devorder: curnode %x %s\n", node, name);
- }
-#endif
- /*
- * Initially, curnode is the root of the pci tree. As we
- * attach bridges, curnode should be set to that of the bridge.
- */
- for (node = OF_child(node); node; node = OF_peer(node)) {
- len = OF_getproplen(node, "reg");
- if (len < sizeof(reg))
- continue;
- if (OF_getprop(node, "reg", (void *)&reg, sizeof(reg)) != len)
- panic("pci_probe_bus: OF_getprop len botch");
-
- device = OFW_PCI_PHYS_HI_DEVICE(reg.phys_hi);
-
- if (done & (1 << device))
- continue;
-
- devs[i++] = device;
- done |= 1 << device;
-#ifdef DEBUG
- if (sparc_pci_debug & SPDB_PROBE) {
- OF_getprop(node, "name", &name, sizeof(name));
- printf("pci_bus_devorder: adding %x %s\n", node, name);
- }
-#endif
- if (i == 32)
- break;
- }
- if (i < 32)
- devs[i] = -1;
-
- return i;
-}
-#endif
-
-#ifdef __PCI_DEV_FUNCORDER
-int
-pci_dev_funcorder(pc, busno, device, funcs)
- pci_chipset_tag_t pc;
- int busno;
- int device;
- char *funcs;
-{
- struct ofw_pci_register reg;
- int node, len, function, i = 0;
- u_int8_t done = 0;
-#ifdef DEBUG
- char name[80];
-#endif
-
- node = pc->curnode;
-#ifdef DEBUG
- if (sparc_pci_debug & SPDB_PROBE) {
- OF_getprop(node, "name", &name, sizeof(name));
- printf("pci_bus_funcorder: curnode %x %s\n", node, name);
- }
-#endif
- /*
- * Functions are siblings. Presumably we're only called when the
- * first instance of this device is detected, so we should be able to
- * get to all the other functions with OF_peer(). But there seems
- * some issues with this scheme, so we always go to the first node on
- * this bus segment for a scan.
- */
- for (node = OF_child(OF_parent(node)); node; node = OF_peer(node)) {
- len = OF_getproplen(node, "reg");
- if (len < sizeof(reg))
- continue;
- if (OF_getprop(node, "reg", (void *)&reg, sizeof(reg)) != len)
- panic("pci_probe_bus: OF_getprop len botch");
-
- if (device != OFW_PCI_PHYS_HI_DEVICE(reg.phys_hi))
- continue;
-
-
- function = OFW_PCI_PHYS_HI_FUNCTION(reg.phys_hi);
-
- if (done & (1 << function))
- continue;
-
- funcs[i++] = function;
- done |= 1 << function;
-#ifdef DEBUG
- if (sparc_pci_debug & SPDB_PROBE) {
- OF_getprop(node, "name", &name, sizeof(name));
- printf("pci_bus_funcorder: adding %x %s\n", node, name);
- }
-#endif
- if (i == 8)
- break;
- }
- if (i < 8)
- funcs[i] = -1;
-
- return i;
-}
-#endif
-
pcitag_t
pci_make_tag(pc, b, d, f)
pci_chipset_tag_t pc;
@@ -323,21 +219,8 @@ pci_make_tag(pc, b, d, f)
continue;
/* Got a match */
- tag = PCITAG_CREATE(node, b, d, f);
-
- /*
- * Record the node. This has two effects:
- *
- * 1) We don't have to search as far.
- * 2) pci_bus_devorder will scan the right bus.
- */
- pc->curnode = node;
+ tag = ofpci_make_tag(pc, node, b, d, f);
- /* Enable all the different spaces for this device */
- pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG,
- PCI_COMMAND_MEM_ENABLE|PCI_COMMAND_MASTER_ENABLE|
- PCI_COMMAND_IO_ENABLE);
- DPRINTF(SPDB_PROBE, ("found node %x %s\n", node, name));
return (tag);
}
/* No device found -- return a dead tag */
@@ -359,6 +242,52 @@ pci_decompose_tag(pc, tag, bp, dp, fp)
*fp = PCITAG_FUN(tag);
}
+int
+sparc64_pci_enumerate_bus(struct pci_softc *sc,
+ int (*match)(struct pci_attach_args *), struct pci_attach_args *pap)
+{
+ struct ofw_pci_register reg;
+ pci_chipset_tag_t pc = sc->sc_pc;
+ pcitag_t tag;
+ pcireg_t class;
+ int node, b, d, f, ret;
+ char name[30];
+
+ if (sc->sc_bridgetag)
+ node = PCITAG_NODE(*sc->sc_bridgetag);
+ else
+ node = pc->rootnode;
+
+ for (node = OF_child(node); node != 0 && node != -1;
+ node = OF_peer(node)) {
+ name[0] = name[29] = 0;
+ OF_getprop(node, "name", name, sizeof(name));
+
+ if (OF_getprop(node, "class-code", &class, sizeof(class)) !=
+ sizeof(class))
+ continue;
+ if (OF_getprop(node, "reg", &reg, sizeof(reg)) < sizeof(reg))
+ panic("pci_enumerate_bus: \"%s\" regs too small", name);
+
+ b = OFW_PCI_PHYS_HI_BUS(reg.phys_hi);
+ d = OFW_PCI_PHYS_HI_DEVICE(reg.phys_hi);
+ f = OFW_PCI_PHYS_HI_FUNCTION(reg.phys_hi);
+
+ if (sc->sc_bus != b) {
+ printf("%s: WARNING: incorrect bus # for \"%s\" "
+ "(%d/%d/%d)\n", sc->sc_dev.dv_xname, name, b, d, f);
+ continue;
+ }
+
+ tag = ofpci_make_tag(pc, node, b, d, f);
+ ret = pci_probe_device(sc, tag, match, pap);
+ if (match != NULL && ret != 0)
+ return (ret);
+ }
+
+ return (0);
+}
+
/* assume we are mapped little-endian/side-effect */
pcireg_t
pci_conf_read(pci_chipset_tag_t pc, pcitag_t tag, int reg)
diff --git a/sys/arch/sparc64/dev/psycho.c b/sys/arch/sparc64/dev/psycho.c
index b187a7e81c7..0f3defc211d 100644
--- a/sys/arch/sparc64/dev/psycho.c
+++ b/sys/arch/sparc64/dev/psycho.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: psycho.c,v 1.42 2006/03/13 20:10:49 brad Exp $ */
+/* $OpenBSD: psycho.c,v 1.43 2006/03/19 02:43:38 brad Exp $ */
/* $NetBSD: psycho.c,v 1.39 2001/10/07 20:30:41 eeh Exp $ */
/*
@@ -650,7 +650,6 @@ psycho_alloc_chipset(struct psycho_pbm *pp, int node, pci_chipset_tag_t pc)
memcpy(npc, pc, sizeof *pc);
npc->cookie = pp;
npc->rootnode = node;
- npc->curnode = node;
return (npc);
}
diff --git a/sys/arch/sparc64/dev/schizo.c b/sys/arch/sparc64/dev/schizo.c
index 252275b7eba..2a3b0800300 100644
--- a/sys/arch/sparc64/dev/schizo.c
+++ b/sys/arch/sparc64/dev/schizo.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: schizo.c,v 1.17 2006/03/13 20:10:49 brad Exp $ */
+/* $OpenBSD: schizo.c,v 1.18 2006/03/19 02:43:38 brad Exp $ */
/*
* Copyright (c) 2002 Jason L. Wright (jason@thought.net)
@@ -347,7 +347,6 @@ schizo_alloc_chipset(struct schizo_pbm *pbm, int node, pci_chipset_tag_t pc)
memcpy(npc, pc, sizeof *pc);
npc->cookie = pbm;
npc->rootnode = node;
- npc->curnode = node;
return (npc);
}
diff --git a/sys/arch/sparc64/include/pci_machdep.h b/sys/arch/sparc64/include/pci_machdep.h
index e9148812ebf..ddbc74de461 100644
--- a/sys/arch/sparc64/include/pci_machdep.h
+++ b/sys/arch/sparc64/include/pci_machdep.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: pci_machdep.h,v 1.14 2005/09/04 20:40:53 brad Exp $ */
+/* $OpenBSD: pci_machdep.h,v 1.15 2006/03/19 02:43:38 brad Exp $ */
/* $NetBSD: pci_machdep.h,v 1.7 2001/07/20 00:07:14 eeh Exp $ */
/*
@@ -33,12 +33,6 @@
#define _MACHINE_PCI_MACHDEP_H_
/*
- * We want to control both device & function probe order.
- */
-#define __PCI_BUS_DEVORDER
-#define __PCI_DEV_FUNCORDER
-
-/*
* Forward declarations.
*/
struct pci_attach_args;
@@ -73,18 +67,11 @@ struct sparc_pci_chipset {
bus_space_tag_t bustag;
bus_space_handle_t bushandle;
int rootnode; /* PCI controller */
- int curnode; /* Current OFW node */
int (*intr_map)(struct pci_attach_args *, pci_intr_handle_t *);
};
void pci_attach_hook(struct device *, struct device *,
struct pcibus_attach_args *);
-#ifdef __PCI_BUS_DEVORDER
-int pci_bus_devorder(pci_chipset_tag_t, int, char *);
-#endif
-#ifdef __PCI_DEV_FUNCORDER
-int pci_dev_funcorder(pci_chipset_tag_t, int, int, char *);
-#endif
int pci_bus_maxdevs(pci_chipset_tag_t, int);
pcitag_t pci_make_tag(pci_chipset_tag_t, int, int, int);
void pci_decompose_tag(pci_chipset_tag_t, pcitag_t, int *, int *,
@@ -98,6 +85,12 @@ void *pci_intr_establish(pci_chipset_tag_t, pci_intr_handle_t,
int, int (*)(void *), void *, char *);
void pci_intr_disestablish(pci_chipset_tag_t, void *);
+int sparc64_pci_enumerate_bus(struct pci_softc *,
+ int (*match)(struct pci_attach_args *),
+ struct pci_attach_args *);
+
+#define PCI_MACHDEP_ENUMERATE_BUS sparc64_pci_enumerate_bus
+
#define pciide_machdep_compat_intr_establish(a, b, c, d, e) (NULL)
#define pciide_machdep_compat_intr_disestablish(a, b) do { } while (0)
diff --git a/sys/dev/pci/pci.c b/sys/dev/pci/pci.c
index 24477ece9cb..e4e7a0b403e 100644
--- a/sys/dev/pci/pci.c
+++ b/sys/dev/pci/pci.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pci.c,v 1.40 2006/03/11 22:08:07 brad Exp $ */
+/* $OpenBSD: pci.c,v 1.41 2006/03/19 02:43:38 brad Exp $ */
/* $NetBSD: pci.c,v 1.31 1997/06/06 23:48:04 thorpej Exp $ */
/*
@@ -75,6 +75,13 @@ struct cfdriver pci_cd = {
int pciprint(void *, const char *);
int pcisubmatch(struct device *, void *, void *);
+#ifdef PCI_MACHDEP_ENUMERATE_BUS
+#define pci_enumerate_bus PCI_MACHDEP_ENUMERATE_BUS
+#else
+int pci_enumerate_bus(struct pci_softc *,
+ int (*)(struct pci_attach_args *), struct pci_attach_args *);
+#endif
+
/*
* Important note about PCI-ISA bridges:
*
@@ -125,7 +132,7 @@ pcimatch(parent, match, aux)
* XXX check other (hardware?) indicators
*/
- return 1;
+ return (1);
}
void
@@ -134,171 +141,25 @@ pciattach(parent, self, aux)
void *aux;
{
struct pcibus_attach_args *pba = aux;
- bus_space_tag_t iot, memt;
- pci_chipset_tag_t pc;
- int bus, device, maxndevs, function, nfunctions;
struct pci_softc *sc = (struct pci_softc *)self;
- struct pci_dev *pd;
- struct device *dev;
-#ifdef __PCI_BUS_DEVORDER
- char devs[32];
- int i;
-#endif
-#ifdef __PCI_DEV_FUNCORDER
- char funcs[8];
- int j;
-#endif
pci_attach_hook(parent, self, pba);
- printf("\n");
- iot = pba->pba_iot;
- memt = pba->pba_memt;
- pc = pba->pba_pc;
- bus = pba->pba_bus;
- maxndevs = pci_bus_maxdevs(pc, bus);
+ printf("\n");
- sc->sc_pc = pba->pba_pc;
LIST_INIT(&sc->sc_devs);
sc->sc_powerhook = powerhook_establish(pcipower, sc);
-#ifdef USER_PCICONF
- sc->sc_bus = bus;
-#endif
-
-#ifdef __PCI_BUS_DEVORDER
- pci_bus_devorder(pc, bus, devs);
- for (i = 0; (device = devs[i]) < 32 && device >= 0; i++) {
-#else
- for (device = 0; device < maxndevs; device++) {
-#endif
- pcitag_t tag;
- pcireg_t id, class, intr;
-#ifndef __sparc64__
- pcireg_t bhlcr;
-#endif
- struct pci_attach_args pa;
- int pin;
-
- tag = pci_make_tag(pc, bus, device, 0);
- id = pci_conf_read(pc, tag, PCI_ID_REG);
-
-#ifdef __sparc64__
- pci_dev_funcorder(pc, bus, device, funcs);
- nfunctions = 8;
-
- /* Invalid vendor ID value or 0 (see below for zero)
- * ... of course, if the pci_dev_funcorder found
- * functions other than zero, we probably want
- * to attach them.
- */
- if (PCI_VENDOR(id) == PCI_VENDOR_INVALID || PCI_VENDOR(id) == 0)
- if (funcs[0] < 0)
- continue;
-
- for (j = 0; (function = funcs[j]) < nfunctions &&
- function >= 0; j++) {
-#else
- /* Invalid vendor ID value? */
- if (PCI_VENDOR(id) == PCI_VENDOR_INVALID)
- continue;
- /* XXX Not invalid, but we've done this ~forever. */
- if (PCI_VENDOR(id) == 0)
- continue;
-
- bhlcr = pci_conf_read(pc, tag, PCI_BHLC_REG);
- nfunctions = PCI_HDRTYPE_MULTIFN(bhlcr) ? 8 : 1;
-
-#ifdef __PCI_DEV_FUNCORDER
- pci_dev_funcorder(pc, bus, device, funcs);
- for (j = 0; (function = funcs[j]) < nfunctions &&
- function >= 0; j++) {
-#else
- for (function = 0; function < nfunctions; function++) {
-#endif
-#endif
- tag = pci_make_tag(pc, bus, device, function);
- id = pci_conf_read(pc, tag, PCI_ID_REG);
-
- /* Invalid vendor ID value? */
- if (PCI_VENDOR(id) == PCI_VENDOR_INVALID)
- continue;
- /* XXX Not invalid, but we've done this ~forever. */
- if (PCI_VENDOR(id) == 0)
- continue;
-
- class = pci_conf_read(pc, tag, PCI_CLASS_REG);
- intr = pci_conf_read(pc, tag, PCI_INTERRUPT_REG);
-
- pa.pa_iot = iot;
- pa.pa_memt = memt;
- pa.pa_dmat = pba->pba_dmat;
- pa.pa_pc = pc;
- pa.pa_device = device;
- pa.pa_function = function;
- pa.pa_bus = bus;
- pa.pa_tag = tag;
- pa.pa_id = id;
- pa.pa_class = class;
-
- /* This is a simplification of the NetBSD code.
- We don't support turning off I/O or memory
- on broken hardware. <csapuntz@stanford.edu> */
- pa.pa_flags = PCI_FLAGS_IO_ENABLED | PCI_FLAGS_MEM_ENABLED;
-#ifdef __i386__
- /*
- * on i386 we really need to know the device tag
- * and not the pci bridge tag, in intr_map
- * to be able to program the device and the
- * pci interrupt router.
- */
- pa.pa_intrtag = tag;
- pa.pa_intrswiz = 0;
-#else
- if (bus == 0) {
- pa.pa_intrswiz = 0;
- pa.pa_intrtag = tag;
- } else {
- pa.pa_intrswiz = pba->pba_intrswiz + device;
- pa.pa_intrtag = pba->pba_intrtag;
- }
-#endif
- pin = PCI_INTERRUPT_PIN(intr);
- pa.pa_rawintrpin = pin;
- if (pin == PCI_INTERRUPT_PIN_NONE) {
- /* no interrupt */
- pa.pa_intrpin = 0;
- } else {
- /*
- * swizzle it based on the number of
- * busses we're behind and our device
- * number.
- */
- pa.pa_intrpin = /* XXX */
- ((pin + pa.pa_intrswiz - 1) % 4) + 1;
- }
- pa.pa_intrline = PCI_INTERRUPT_LINE(intr);
-
- if ((dev = config_found_sm(self, &pa, pciprint,
- pcisubmatch))) {
- pcireg_t reg;
-
- /* skip header type != 0 */
- reg = pci_conf_read(pc, tag, PCI_BHLC_REG);
- if (PCI_HDRTYPE_TYPE(reg) != 0)
- continue;
- if (pci_get_capability(pc, tag,
- PCI_CAP_PWRMGMT, NULL, NULL) == 0)
- continue;
- if (!(pd = malloc(sizeof *pd, M_DEVBUF,
- M_NOWAIT)))
- continue;
- pd->pd_tag = tag;
- pd->pd_dev = dev;
- LIST_INSERT_HEAD(&sc->sc_devs, pd, pd_next);
- }
- }
- }
+ sc->sc_iot = pba->pba_iot;
+ sc->sc_memt = pba->pba_memt;
+ sc->sc_dmat = pba->pba_dmat;
+ sc->sc_pc = pba->pba_pc;
+ sc->sc_bus = pba->pba_bus;
+ sc->sc_bridgetag = pba->pba_bridgetag;
+ sc->sc_maxndevs = pci_bus_maxdevs(pba->pba_pc, pba->pba_bus);
+ sc->sc_intrswiz = pba->pba_intrswiz;
+ sc->sc_intrtag = pba->pba_intrtag;
+ pci_enumerate_bus(sc, NULL, NULL);
}
/* save and restore the pci config space */
@@ -373,10 +234,10 @@ pcisubmatch(parent, match, aux)
if (cf->pcicf_dev != PCI_UNK_DEV &&
cf->pcicf_dev != pa->pa_device)
- return 0;
+ return (0);
if (cf->pcicf_function != PCI_UNK_FUNCTION &&
cf->pcicf_function != pa->pa_function)
- return 0;
+ return (0);
success = (*cf->cf_attach->ca_match)(parent, match, aux);
@@ -399,6 +260,109 @@ pcisubmatch(parent, match, aux)
}
int
+pci_probe_device(struct pci_softc *sc, pcitag_t tag,
+ int (*match)(struct pci_attach_args *), struct pci_attach_args *pap)
+{
+ pci_chipset_tag_t pc = sc->sc_pc;
+ struct pci_attach_args pa;
+ struct pci_dev *pd;
+ struct device *dev;
+ pcireg_t id, csr, class, intr, bhlcr;
+ int ret, pin, bus, device, function;
+
+ pci_decompose_tag(pc, tag, &bus, &device, &function);
+
+ 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)
+ return (0);
+ /* XXX Not invalid, but we've done this ~forever. */
+ if (PCI_VENDOR(id) == 0)
+ return (0);
+
+ pa.pa_iot = sc->sc_iot;
+ pa.pa_memt = sc->sc_memt;
+ pa.pa_dmat = sc->sc_dmat;
+ pa.pa_pc = pc;
+ pa.pa_bus = bus;
+ pa.pa_device = device;
+ pa.pa_function = function;
+ pa.pa_tag = tag;
+ pa.pa_id = id;
+ pa.pa_class = class;
+
+ /* This is a simplification of the NetBSD code.
+ We don't support turning off I/O or memory
+ on broken hardware. <csapuntz@stanford.edu> */
+ pa.pa_flags = PCI_FLAGS_IO_ENABLED | PCI_FLAGS_MEM_ENABLED;
+
+#ifdef __i386__
+ /*
+ * on i386 we really need to know the device tag
+ * and not the pci bridge tag, in intr_map
+ * to be able to program the device and the
+ * pci interrupt router.
+ */
+ pa.pa_intrtag = tag;
+ pa.pa_intrswiz = 0;
+#else
+ if (sc->sc_bridgetag == NULL) {
+ pa.pa_intrswiz = 0;
+ pa.pa_intrtag = tag;
+ } else {
+ pa.pa_intrswiz = sc->sc_intrswiz + device;
+ pa.pa_intrtag = sc->sc_intrtag;
+ }
+#endif
+ pin = PCI_INTERRUPT_PIN(intr);
+ pa.pa_rawintrpin = pin;
+ if (pin == PCI_INTERRUPT_PIN_NONE) {
+ /* no interrupt */
+ pa.pa_intrpin = 0;
+ } else {
+ /*
+ * swizzle it based on the number of busses we're
+ * behind and our device number.
+ */
+ pa.pa_intrpin = /* XXX */
+ ((pin + pa.pa_intrswiz - 1) % 4) + 1;
+ }
+ pa.pa_intrline = PCI_INTERRUPT_LINE(intr);
+
+ if (match != NULL) {
+ ret = (*match)(&pa);
+ if (ret != 0 && pap != NULL)
+ *pap = pa;
+ } else {
+ if ((dev = config_found_sm(&sc->sc_dev, &pa, pciprint,
+ pcisubmatch))) {
+ pcireg_t reg;
+
+ /* skip header type != 0 */
+ reg = pci_conf_read(pc, tag, PCI_BHLC_REG);
+ if (PCI_HDRTYPE_TYPE(reg) != 0)
+ return(0);
+ if (pci_get_capability(pc, tag,
+ PCI_CAP_PWRMGMT, NULL, NULL) == 0)
+ return(0);
+ if (!(pd = malloc(sizeof *pd, M_DEVBUF,
+ M_NOWAIT)))
+ return(0);
+ pd->pd_tag = tag;
+ pd->pd_dev = dev;
+ LIST_INSERT_HEAD(&sc->sc_devs, pd, pd_next);
+ }
+ }
+
+ return (ret);
+}
+
+int
pci_get_capability(pc, tag, capid, offset, value)
pci_chipset_tag_t pc;
pcitag_t tag;
@@ -446,6 +410,54 @@ pci_get_capability(pc, tag, capid, offset, value)
return (0);
}
+#ifndef PCI_MACHDEP_ENUMERATE_BUS
+/*
+ * Generic PCI bus enumeration routine. Used unless machine-dependent
+ * code needs to provide something else.
+ */
+int
+pci_enumerate_bus(struct pci_softc *sc,
+ int (*match)(struct pci_attach_args *), struct pci_attach_args *pap)
+{
+ pci_chipset_tag_t pc = sc->sc_pc;
+ int device, function, nfunctions, ret;
+ const struct pci_quirkdata *qd;
+ pcireg_t id, bhlcr;
+ pcitag_t tag;
+
+ for (device = 0; device < sc->sc_maxndevs; device++) {
+ tag = pci_make_tag(pc, sc->sc_bus, device, 0);
+ id = pci_conf_read(pc, tag, PCI_ID_REG);
+
+ /* Invalid vendor ID value? */
+ if (PCI_VENDOR(id) == PCI_VENDOR_INVALID)
+ continue;
+ /* XXX Not invalid, but we've done this ~forever. */
+ if (PCI_VENDOR(id) == 0)
+ continue;
+
+ 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))
+ nfunctions = 8;
+ else
+ nfunctions = 1;
+
+ for (function = 0; function < nfunctions; function++) {
+ tag = pci_make_tag(pc, sc->sc_bus, device, function);
+ ret = pci_probe_device(sc, tag, match, pap);
+ if (match != NULL && ret != 0)
+ return (ret);
+ }
+ }
+
+ return (0);
+}
+#endif /* PCI_MACHDEP_ENUMERATE_BUS */
+
int
pci_matchbyid(struct pci_attach_args *pa, const struct pci_matchid *ids,
int nent)
diff --git a/sys/dev/pci/pcivar.h b/sys/dev/pci/pcivar.h
index a3546de0868..43b91f938ec 100644
--- a/sys/dev/pci/pcivar.h
+++ b/sys/dev/pci/pcivar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: pcivar.h,v 1.44 2006/03/13 20:10:49 brad Exp $ */
+/* $OpenBSD: pcivar.h,v 1.45 2006/03/19 02:43:38 brad Exp $ */
/* $NetBSD: pcivar.h,v 1.23 1997/06/06 23:48:05 thorpej Exp $ */
/*
@@ -151,11 +151,15 @@ struct pci_quirkdata {
struct pci_softc {
struct device sc_dev;
+ bus_space_tag_t sc_iot, sc_memt;
+ bus_dma_tag_t sc_dmat;
pci_chipset_tag_t sc_pc;
void *sc_powerhook;
LIST_HEAD(, pci_dev) sc_devs;
- int sc_bus;
+ int sc_bus, sc_maxndevs;
pcitag_t *sc_bridgetag;
+ u_int sc_intrswiz;
+ pcitag_t sc_intrtag;
};
/*
@@ -204,6 +208,8 @@ int pci_matchbyid(struct pci_attach_args *, const struct pci_matchid *, int);
* Helper functions for autoconfiguration.
*/
const char *pci_findvendor(pcireg_t);
+int pci_probe_device(struct pci_softc *, pcitag_t tag,
+ int (*)(struct pci_attach_args *), struct pci_attach_args *);
void pci_devinfo(pcireg_t, pcireg_t, int, char *, size_t);
const struct pci_quirkdata *
pci_lookup_quirkdata(pci_vendor_id_t, pci_product_id_t);