diff options
-rw-r--r-- | sys/conf/options.sparc64 | 1 | ||||
-rw-r--r-- | sys/sparc64/pci/psycho.c | 71 |
2 files changed, 44 insertions, 28 deletions
diff --git a/sys/conf/options.sparc64 b/sys/conf/options.sparc64 index bc6af5a..883db16 100644 --- a/sys/conf/options.sparc64 +++ b/sys/conf/options.sparc64 @@ -23,7 +23,6 @@ PSM_DEBUG opt_psm.h PSM_HOOKRESUME opt_psm.h PSM_RESETAFTERSUSPEND opt_psm.h -DEBUGGER_ON_POWERFAIL opt_psycho.h PSYCHO_DEBUG opt_psycho.h SCHIZO_DEBUG opt_schizo.h diff --git a/sys/sparc64/pci/psycho.c b/sys/sparc64/pci/psycho.c index a44af7c..8f4f23e 100644 --- a/sys/sparc64/pci/psycho.c +++ b/sys/sparc64/pci/psycho.c @@ -54,6 +54,7 @@ __FBSDID("$FreeBSD$"); #include <sys/pcpu.h> #include <sys/reboot.h> #include <sys/rman.h> +#include <sys/sysctl.h> #include <dev/ofw/ofw_bus.h> #include <dev/ofw/ofw_pci.h> @@ -80,7 +81,7 @@ static const struct psycho_desc *psycho_find_desc(const struct psycho_desc *, const char *); static const struct psycho_desc *psycho_get_desc(device_t); static void psycho_set_intr(struct psycho_softc *, u_int, bus_addr_t, - driver_filter_t, driver_intr_t); + driver_filter_t); static int psycho_find_intrmap(struct psycho_softc *, u_int, bus_addr_t *, bus_addr_t *, u_long *); static void sabre_dmamap_sync(bus_dma_tag_t dt, bus_dmamap_t map, @@ -94,8 +95,9 @@ static void psycho_intr_clear(void *); static driver_filter_t psycho_ue; static driver_filter_t psycho_ce; static driver_filter_t psycho_pci_bus; -static driver_filter_t psycho_powerfail; -static driver_intr_t psycho_overtemp; +static driver_filter_t psycho_powerdebug; +static driver_filter_t psycho_powerdown; +static driver_filter_t psycho_overtemp; #ifdef PSYCHO_MAP_WAKEUP static driver_filter_t psycho_wakeup; #endif @@ -159,9 +161,16 @@ static devclass_t psycho_devclass; DEFINE_CLASS_0(pcib, psycho_driver, psycho_methods, sizeof(struct psycho_softc)); -EARLY_DRIVER_MODULE(psycho, nexus, psycho_driver, psycho_devclass, 0, 0, +EARLY_DRIVER_MODULE(psycho, nexus, psycho_driver, psycho_devclass, NULL, NULL, BUS_PASS_BUS); +static SYSCTL_NODE(_hw, OID_AUTO, psycho, CTLFLAG_RD, 0, "psycho parameters"); + +static u_int psycho_powerfail = 1; +TUNABLE_INT("hw.psycho.powerfail", &psycho_powerfail); +SYSCTL_UINT(_hw_psycho, OID_AUTO, powerfail, CTLFLAG_RDTUN, &psycho_powerfail, + 0, "powerfail action (0: none, 1: shutdown (default), 2: debugger)"); + static SLIST_HEAD(, psycho_softc) psycho_softcs = SLIST_HEAD_INITIALIZER(psycho_softcs); @@ -610,15 +619,20 @@ psycho_attach(device_t dev) * XXX Not all controllers have these, but installing them * is better than trying to sort through this mess. */ - psycho_set_intr(sc, 1, PSR_UE_INT_MAP, psycho_ue, NULL); - psycho_set_intr(sc, 2, PSR_CE_INT_MAP, psycho_ce, NULL); -#ifdef DEBUGGER_ON_POWERFAIL - psycho_set_intr(sc, 3, PSR_POWER_INT_MAP, psycho_powerfail, - NULL); -#else - psycho_set_intr(sc, 3, PSR_POWER_INT_MAP, NULL, - (driver_intr_t *)psycho_powerfail); -#endif + psycho_set_intr(sc, 1, PSR_UE_INT_MAP, psycho_ue); + psycho_set_intr(sc, 2, PSR_CE_INT_MAP, psycho_ce); + switch (psycho_powerfail) { + case 0: + break; + case 2: + psycho_set_intr(sc, 3, PSR_POWER_INT_MAP, + psycho_powerdebug); + break; + default: + psycho_set_intr(sc, 3, PSR_POWER_INT_MAP, + psycho_powerdown); + break; + } if (sc->sc_mode == PSYCHO_MODE_PSYCHO) { /* * Hummingbirds/Sabres do not have the following two @@ -630,14 +644,14 @@ psycho_attach(device_t dev) * over-temperature interrupt. */ psycho_set_intr(sc, 4, PSR_SPARE_INT_MAP, - NULL, psycho_overtemp); + psycho_overtemp); #ifdef PSYCHO_MAP_WAKEUP /* * psycho_wakeup() doesn't do anything useful right * now. */ psycho_set_intr(sc, 5, PSR_PWRMGT_INT_MAP, - psycho_wakeup, NULL); + psycho_wakeup); #endif /* PSYCHO_MAP_WAKEUP */ } } @@ -647,7 +661,7 @@ psycho_attach(device_t dev) * interrupt but they are also only used for PCI bus A. */ psycho_set_intr(sc, 0, sc->sc_half == 0 ? PSR_PCIAERR_INT_MAP : - PSR_PCIBERR_INT_MAP, psycho_pci_bus, NULL); + PSR_PCIBERR_INT_MAP, psycho_pci_bus); /* * Set the latency timer register as this isn't always done by the @@ -687,7 +701,7 @@ psycho_attach(device_t dev) static void psycho_set_intr(struct psycho_softc *sc, u_int index, bus_addr_t intrmap, - driver_filter_t filt, driver_intr_t intr) + driver_filter_t handler) { u_long vec; int rid; @@ -708,7 +722,7 @@ psycho_set_intr(struct psycho_softc *sc, u_int index, bus_addr_t intrmap, INTVEC(PSYCHO_READ8(sc, intrmap)) != vec || intr_vectors[vec].iv_ic != &psycho_ic || bus_setup_intr(sc->sc_dev, sc->sc_irq_res[index], - INTR_TYPE_MISC | INTR_BRIDGE, filt, intr, sc, + INTR_TYPE_MISC | INTR_BRIDGE, handler, NULL, sc, &sc->sc_ihand[index]) != 0) panic("%s: failed to set up interrupt %d", __func__, index); } @@ -837,13 +851,16 @@ psycho_pci_bus(void *arg) } static int -psycho_powerfail(void *arg) +psycho_powerdebug(void *arg __unused) { -#ifdef DEBUGGER_ON_POWERFAIL - struct psycho_softc *sc = arg; kdb_enter(KDB_WHY_POWERFAIL, "powerfail"); -#else + return (FILTER_HANDLED); +} + +static int +psycho_powerdown(void *arg __unused) +{ static int shutdown; /* As the interrupt is cleared we may be called multiple times. */ @@ -851,22 +868,22 @@ psycho_powerfail(void *arg) return (FILTER_HANDLED); shutdown++; printf("Power Failure Detected: Shutting down NOW.\n"); - shutdown_nice(0); -#endif + shutdown_nice(RB_POWEROFF); return (FILTER_HANDLED); } -static void -psycho_overtemp(void *arg) +static int +psycho_overtemp(void *arg __unused) { static int shutdown; /* As the interrupt is cleared we may be called multiple times. */ if (shutdown != 0) - return; + return (FILTER_HANDLED); shutdown++; printf("DANGER: OVER TEMPERATURE detected.\nShutting down NOW.\n"); shutdown_nice(RB_POWEROFF); + return (FILTER_HANDLED); } #ifdef PSYCHO_MAP_WAKEUP |