diff options
Diffstat (limited to 'sys')
-rw-r--r-- | sys/arch/sparc64/dev/pci_machdep.c | 197 | ||||
-rw-r--r-- | sys/arch/sparc64/dev/psycho.c | 3 | ||||
-rw-r--r-- | sys/arch/sparc64/dev/schizo.c | 3 | ||||
-rw-r--r-- | sys/arch/sparc64/include/pci_machdep.h | 21 | ||||
-rw-r--r-- | sys/dev/pci/pci.c | 334 | ||||
-rw-r--r-- | sys/dev/pci/pcivar.h | 10 |
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 *)®, 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 *)®, 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", ®, 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); |