From 25713af802cddeafae65918278e5be5d223498fd Mon Sep 17 00:00:00 2001 From: Mark Kettenis Date: Thu, 3 Apr 2008 19:41:21 +0000 Subject: Make ebus(4) work on sun4v. --- sys/arch/sparc64/dev/ebus_mainbus.c | 94 +++++++++++++++++++++++++++++++------ 1 file 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 #include +#include #include #include @@ -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 -- cgit v1.2.3