diff options
author | Mark Kettenis <kettenis@cvs.openbsd.org> | 2008-04-03 19:41:21 +0000 |
---|---|---|
committer | Mark Kettenis <kettenis@cvs.openbsd.org> | 2008-04-03 19:41:21 +0000 |
commit | 25713af802cddeafae65918278e5be5d223498fd (patch) | |
tree | 560f3cff6dcced54e674376ffdea857a2273e7b3 /sys/arch/sparc64/dev | |
parent | c7c3afede8ed8d78a1e13d88210863785aad1e22 (diff) |
Make ebus(4) work on sun4v.
Diffstat (limited to 'sys/arch/sparc64/dev')
-rw-r--r-- | sys/arch/sparc64/dev/ebus_mainbus.c | 94 |
1 files changed, 79 insertions, 15 deletions
diff --git a/sys/arch/sparc64/dev/ebus_mainbus.c b/sys/arch/sparc64/dev/ebus_mainbus.c index 5d62eeb7b1e..82e5d91b562 100644 --- a/sys/arch/sparc64/dev/ebus_mainbus.c +++ b/sys/arch/sparc64/dev/ebus_mainbus.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ebus_mainbus.c,v 1.5 2008/04/03 18:08:04 kettenis Exp $ */ +/* $OpenBSD: ebus_mainbus.c,v 1.6 2008/04/03 19:41:20 kettenis Exp $ */ /* * Copyright (c) 2007 Mark Kettenis @@ -41,6 +41,7 @@ extern int ebus_debug; #define _SPARC_BUS_DMA_PRIVATE #include <machine/bus.h> #include <machine/autoconf.h> +#include <machine/hypervisor.h> #include <machine/openfirm.h> #include <dev/pci/pcivar.h> @@ -65,7 +66,7 @@ int ebus_mainbus_bus_map(bus_space_tag_t, bus_space_tag_t, void *ebus_mainbus_intr_establish(bus_space_tag_t, bus_space_tag_t, int, int, int, int (*)(void *), void *, const char *); bus_space_tag_t ebus_alloc_bus_tag(struct ebus_softc *, bus_space_tag_t); - +void ebus_mainbus_intr_ack(struct intrhand *); int ebus_mainbus_match(struct device *parent, void *match, void *aux) @@ -91,21 +92,23 @@ ebus_mainbus_attach(struct device *parent, struct device *self, void *aux) sc->sc_node = node = ma->ma_node; sc->sc_ign = INTIGN((ma->ma_upaid) << INTMAP_IGN_SHIFT); - printf(": ign %x", sc->sc_ign); - - for (i = 0; i < pyro_cd.cd_ndevs; i++) { - psc = pyro_cd.cd_devs[i]; - if (psc && psc->sc_ign == sc->sc_ign) { - sc->sc_bust = psc->sc_bust; - sc->sc_csr = psc->sc_csr; - sc->sc_csrh = psc->sc_csrh; - break; + if (CPU_ISSUN4U) { + printf(": ign %x", sc->sc_ign); + + for (i = 0; i < pyro_cd.cd_ndevs; i++) { + psc = pyro_cd.cd_devs[i]; + if (psc && psc->sc_ign == sc->sc_ign) { + sc->sc_bust = psc->sc_bust; + sc->sc_csr = psc->sc_csr; + sc->sc_csrh = psc->sc_csrh; + break; + } } - } - if (sc->sc_csr == 0) { - printf(": can't find matching host bridge leaf\n"); - return; + if (sc->sc_csr == 0) { + printf(": can't find matching host bridge leaf\n"); + return; + } } printf("\n"); @@ -244,6 +247,57 @@ ebus_mainbus_intr_establish(bus_space_tag_t t, bus_space_tag_t t0, int ihandle, volatile u_int64_t *intrmapptr = NULL, *intrclrptr = NULL; int ino; +#ifdef SUN4V + if (CPU_ISSUN4V) { + struct upa_reg reg; + u_int64_t devhandle, devino = INTINO(ihandle); + u_int64_t sysino; + int node = -1; + int i, err; + + for (i = 0; i < sc->sc_nintmap; i++) { + if (sc->sc_intmap[i].cintr == ihandle) { + node = sc->sc_intmap[i].cnode; + break; + } + } + if (node == -1) + return (NULL); + + if (OF_getprop(node, "reg", ®, sizeof(reg)) != sizeof(reg)) + return (NULL); + devhandle = (reg.ur_paddr >> 32) & 0x0fffffff; + + err = hv_intr_devino_to_sysino(devhandle, devino, &sysino); + if (err != H_EOK) + return (NULL); + + KASSERT(sysino == INTVEC(sysino)); + ih = bus_intr_allocate(t0, handler, arg, sysino, level, + NULL, NULL, what); + if (ih == NULL) + return (NULL); + + intr_establish(ih->ih_pil, ih); + ih->ih_ack = ebus_mainbus_intr_ack; + + err = hv_intr_settarget(sysino, cpus->ci_upaid); + if (err != H_EOK) + return (NULL); + + /* Clear pending interrupts. */ + err = hv_intr_setstate(sysino, INTR_IDLE); + if (err != H_EOK) + return (NULL); + + err = hv_intr_setenabled(sysino, INTR_ENABLED); + if (err != H_EOK) + return (NULL); + + return (ih); + } +#endif + ihandle |= sc->sc_ign; ino = INTINO(ihandle); @@ -278,3 +332,13 @@ ebus_mainbus_intr_establish(bus_space_tag_t t, bus_space_tag_t t0, int ihandle, return (ih); } + +#ifdef SUN4V + +void +ebus_mainbus_intr_ack(struct intrhand *ih) +{ + hv_intr_setstate(ih->ih_number, INTR_IDLE); +} + +#endif |