summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/conf/options.sparc641
-rw-r--r--sys/sparc64/pci/psycho.c71
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
OpenPOWER on IntegriCloud