make PCI devices attachable/detachable (as far as the particular drivers
allow), and allow to rescan a bus selectively (ie only the device/ function I'm looking at)
This commit is contained in:
parent
d95b59fae8
commit
c67a72f6ff
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: pci_machdep.c,v 1.48 2004/07/29 16:53:15 drochner Exp $ */
|
||||
/* $NetBSD: pci_machdep.c,v 1.49 2004/08/17 23:20:10 drochner Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1999, 2000 Matthew R. Green
|
||||
|
@ -33,7 +33,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: pci_machdep.c,v 1.48 2004/07/29 16:53:15 drochner Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: pci_machdep.c,v 1.49 2004/08/17 23:20:10 drochner Exp $");
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
|
@ -58,6 +58,8 @@ __KERNEL_RCSID(0, "$NetBSD: pci_machdep.c,v 1.48 2004/07/29 16:53:15 drochner Ex
|
|||
#include <sparc64/dev/psychovar.h>
|
||||
#include <sparc64/sparc64/cache.h>
|
||||
|
||||
#include "locators.h"
|
||||
|
||||
#ifdef DEBUG
|
||||
#define SPDB_CONF 0x01
|
||||
#define SPDB_INTR 0x04
|
||||
|
@ -265,7 +267,7 @@ pci_decompose_tag(pc, tag, bp, dp, fp)
|
|||
}
|
||||
|
||||
int
|
||||
sparc64_pci_enumerate_bus(struct pci_softc *sc,
|
||||
sparc64_pci_enumerate_bus(struct pci_softc *sc, const int *locators,
|
||||
int (*match)(struct pci_attach_args *), struct pci_attach_args *pap)
|
||||
{
|
||||
struct ofw_pci_register reg;
|
||||
|
@ -331,6 +333,12 @@ sparc64_pci_enumerate_bus(struct pci_softc *sc,
|
|||
"(%d/%d/%d)\n", sc->sc_dev.dv_xname, name, b, d, f);
|
||||
continue;
|
||||
}
|
||||
if ((locators[PCICF_DEV] != PCICF_DEV_DEFAULT) &&
|
||||
(locators[PCICF_DEV] != d))
|
||||
continue;
|
||||
if ((locators[PCICF_FUNCTION] != PCICF_FUNCTION_DEFAULT) &&
|
||||
(locators[PCICF_FUNCTION] != f))
|
||||
continue;
|
||||
|
||||
tag = ofpci_make_tag(pc, node, b, d, f);
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: pci_machdep.h,v 1.15 2004/07/29 16:53:16 drochner Exp $ */
|
||||
/* $NetBSD: pci_machdep.h,v 1.16 2004/08/17 23:20:10 drochner Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1999 Matthew R. Green
|
||||
|
@ -83,8 +83,8 @@ void *pci_intr_establish(pci_chipset_tag_t, pci_intr_handle_t,
|
|||
int, int (*)(void *), void *);
|
||||
void pci_intr_disestablish(pci_chipset_tag_t, void *);
|
||||
|
||||
int sparc64_pci_enumerate_bus(struct pci_softc *,
|
||||
int (*match)(struct pci_attach_args *),
|
||||
int sparc64_pci_enumerate_bus(struct pci_softc *, const int *,
|
||||
int (*)(struct pci_attach_args *),
|
||||
struct pci_attach_args *);
|
||||
#define PCI_MACHDEP_ENUMERATE_BUS sparc64_pci_enumerate_bus
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: pci.c,v 1.86 2004/07/29 16:51:01 drochner Exp $ */
|
||||
/* $NetBSD: pci.c,v 1.87 2004/08/17 23:20:10 drochner Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1995, 1996, 1997, 1998
|
||||
|
@ -36,7 +36,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: pci.c,v 1.86 2004/07/29 16:51:01 drochner Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: pci.c,v 1.87 2004/08/17 23:20:10 drochner Exp $");
|
||||
|
||||
#include "opt_pci.h"
|
||||
|
||||
|
@ -60,17 +60,20 @@ int pci_config_dump = 0;
|
|||
|
||||
int pcimatch __P((struct device *, struct cfdata *, void *));
|
||||
void pciattach __P((struct device *, struct device *, void *));
|
||||
int pcirescan(struct device *, const char *, const int *);
|
||||
void pcidevdetached(struct device *, struct device *);
|
||||
|
||||
CFATTACH_DECL(pci, sizeof(struct pci_softc),
|
||||
pcimatch, pciattach, NULL, NULL);
|
||||
CFATTACH_DECL2(pci, sizeof(struct pci_softc),
|
||||
pcimatch, pciattach, NULL, NULL, pcirescan, pcidevdetached);
|
||||
|
||||
int pciprint __P((void *, const char *));
|
||||
int pcisubmatch __P((struct device *, struct cfdata *, void *));
|
||||
int pcisubmatch __P((struct device *, struct cfdata *,
|
||||
const locdesc_t *, void *));
|
||||
|
||||
#ifdef PCI_MACHDEP_ENUMERATE_BUS
|
||||
#define pci_enumerate_bus PCI_MACHDEP_ENUMERATE_BUS
|
||||
#else
|
||||
int pci_enumerate_bus(struct pci_softc *,
|
||||
int pci_enumerate_bus(struct pci_softc *, const int *,
|
||||
int (*)(struct pci_attach_args *), struct pci_attach_args *);
|
||||
#endif
|
||||
|
||||
|
@ -136,6 +139,8 @@ pciattach(parent, self, aux)
|
|||
struct pci_softc *sc = (struct pci_softc *)self;
|
||||
int io_enabled, mem_enabled, mrl_enabled, mrm_enabled, mwi_enabled;
|
||||
const char *sep = "";
|
||||
static const int wildcard[2] = { PCICF_DEV_DEFAULT,
|
||||
PCICF_FUNCTION_DEFAULT };
|
||||
|
||||
pci_attach_hook(parent, self, pba);
|
||||
|
||||
|
@ -192,7 +197,18 @@ do { \
|
|||
sc->sc_intrswiz = pba->pba_intrswiz;
|
||||
sc->sc_intrtag = pba->pba_intrtag;
|
||||
sc->sc_flags = pba->pba_flags;
|
||||
pci_enumerate_bus(sc, NULL, NULL);
|
||||
pcirescan(&sc->sc_dev, "pci", wildcard);
|
||||
}
|
||||
|
||||
int
|
||||
pcirescan(struct device *sc, const char *ifattr, const int *locators)
|
||||
{
|
||||
|
||||
KASSERT(ifattr && !strcmp(ifattr, "pci"));
|
||||
KASSERT(locators);
|
||||
|
||||
pci_enumerate_bus((struct pci_softc *)sc, locators, NULL, NULL);
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -246,18 +262,15 @@ pciprint(aux, pnp)
|
|||
}
|
||||
|
||||
int
|
||||
pcisubmatch(parent, cf, aux)
|
||||
struct device *parent;
|
||||
struct cfdata *cf;
|
||||
void *aux;
|
||||
pcisubmatch(struct device *parent, struct cfdata *cf,
|
||||
const locdesc_t *ldesc, void *aux)
|
||||
{
|
||||
struct pci_attach_args *pa = aux;
|
||||
|
||||
if (cf->pcicf_dev != PCI_UNK_DEV &&
|
||||
cf->pcicf_dev != pa->pa_device)
|
||||
cf->pcicf_dev != ldesc->locs[PCICF_DEV])
|
||||
return (0);
|
||||
if (cf->pcicf_function != PCI_UNK_FUNCTION &&
|
||||
cf->pcicf_function != pa->pa_function)
|
||||
cf->pcicf_function != ldesc->locs[PCICF_FUNCTION])
|
||||
return (0);
|
||||
return (config_match(parent, cf, aux));
|
||||
}
|
||||
|
@ -270,9 +283,16 @@ pci_probe_device(struct pci_softc *sc, pcitag_t tag,
|
|||
struct pci_attach_args pa;
|
||||
pcireg_t id, csr, class, intr, bhlcr;
|
||||
int ret, pin, bus, device, function;
|
||||
int help[3];
|
||||
locdesc_t *ldp = (void *)&help; /* XXX XXX */
|
||||
struct device *subdev;
|
||||
|
||||
pci_decompose_tag(pc, tag, &bus, &device, &function);
|
||||
|
||||
/* a driver already attached? */
|
||||
if (sc->PCI_SC_DEVICESC(device, function) && !match)
|
||||
return (0);
|
||||
|
||||
bhlcr = pci_conf_read(pc, tag, PCI_BHLC_REG);
|
||||
if (PCI_HDRTYPE_TYPE(bhlcr) > 2)
|
||||
return (0);
|
||||
|
@ -348,13 +368,34 @@ pci_probe_device(struct pci_softc *sc, pcitag_t tag,
|
|||
if (ret != 0 && pap != NULL)
|
||||
*pap = pa;
|
||||
} else {
|
||||
ret = config_found_sm(&sc->sc_dev, &pa, pciprint,
|
||||
pcisubmatch) != NULL;
|
||||
ldp->len = 2;
|
||||
ldp->locs[PCICF_DEV] = device;
|
||||
ldp->locs[PCICF_FUNCTION] = function;
|
||||
|
||||
subdev = config_found_sm_loc(&sc->sc_dev, "pci", ldp, &pa,
|
||||
pciprint, pcisubmatch);
|
||||
sc->PCI_SC_DEVICESC(device, function) = subdev;
|
||||
ret = (subdev != NULL);
|
||||
}
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
void
|
||||
pcidevdetached(struct device *sc, struct device *dev)
|
||||
{
|
||||
struct pci_softc *psc = (struct pci_softc *)sc;
|
||||
int d, f;
|
||||
|
||||
KASSERT(dev->dv_locators);
|
||||
d = dev->dv_locators[PCICF_DEV];
|
||||
f = dev->dv_locators[PCICF_FUNCTION];
|
||||
|
||||
KASSERT(psc->PCI_SC_DEVICESC(d, f) == dev);
|
||||
|
||||
psc->PCI_SC_DEVICESC(d, f) = 0;
|
||||
}
|
||||
|
||||
int
|
||||
pci_get_capability(pc, tag, capid, offset, value)
|
||||
pci_chipset_tag_t pc;
|
||||
|
@ -410,11 +451,15 @@ pci_find_device(struct pci_attach_args *pa,
|
|||
extern struct cfdriver pci_cd;
|
||||
struct device *pcidev;
|
||||
int i;
|
||||
static const int wildcard[2] = {
|
||||
PCICF_DEV_DEFAULT,
|
||||
PCICF_FUNCTION_DEFAULT
|
||||
};
|
||||
|
||||
for (i = 0; i < pci_cd.cd_ndevs; i++) {
|
||||
pcidev = pci_cd.cd_devs[i];
|
||||
if (pcidev != NULL &&
|
||||
pci_enumerate_bus((struct pci_softc *) pcidev,
|
||||
pci_enumerate_bus((struct pci_softc *)pcidev, wildcard,
|
||||
match, pa) != 0)
|
||||
return (1);
|
||||
}
|
||||
|
@ -427,7 +472,7 @@ pci_find_device(struct pci_attach_args *pa,
|
|||
* code needs to provide something else.
|
||||
*/
|
||||
int
|
||||
pci_enumerate_bus(struct pci_softc *sc,
|
||||
pci_enumerate_bus(struct pci_softc *sc, const int *locators,
|
||||
int (*match)(struct pci_attach_args *), struct pci_attach_args *pap)
|
||||
{
|
||||
pci_chipset_tag_t pc = sc->sc_pc;
|
||||
|
@ -447,6 +492,10 @@ pci_enumerate_bus(struct pci_softc *sc,
|
|||
for (device = 0; device < sc->sc_maxndevs; device++)
|
||||
#endif
|
||||
{
|
||||
if ((locators[PCICF_DEV] != PCICF_DEV_DEFAULT) &&
|
||||
(locators[PCICF_DEV] != device))
|
||||
continue;
|
||||
|
||||
tag = pci_make_tag(pc, sc->sc_bus, device, 0);
|
||||
|
||||
bhlcr = pci_conf_read(pc, tag, PCI_BHLC_REG);
|
||||
|
@ -474,6 +523,10 @@ pci_enumerate_bus(struct pci_softc *sc,
|
|||
nfunctions = PCI_HDRTYPE_MULTIFN(bhlcr) ? 8 : 1;
|
||||
|
||||
for (function = 0; function < nfunctions; function++) {
|
||||
if ((locators[PCICF_FUNCTION] != PCICF_FUNCTION_DEFAULT)
|
||||
&& (locators[PCICF_FUNCTION] != function))
|
||||
continue;
|
||||
|
||||
if (qd != NULL &&
|
||||
(qd->quirks & PCI_QUIRK_SKIP_FUNC(function)) != 0)
|
||||
continue;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: pcivar.h,v 1.63 2004/08/02 18:43:38 mycroft Exp $ */
|
||||
/* $NetBSD: pcivar.h,v 1.64 2004/08/17 23:20:10 drochner Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1996, 1997 Christopher G. Demetriou. All rights reserved.
|
||||
|
@ -166,6 +166,9 @@ struct pci_softc {
|
|||
u_int sc_intrswiz;
|
||||
pcitag_t sc_intrtag;
|
||||
int sc_flags;
|
||||
/* accounting of child devices */
|
||||
struct device *sc_devices[32*8];
|
||||
#define PCI_SC_DEVICESC(d, f) sc_devices[(d) * 8 + (f)]
|
||||
};
|
||||
|
||||
extern struct cfdriver pci_cd;
|
||||
|
|
Loading…
Reference in New Issue