summaryrefslogtreecommitdiffstats
path: root/sys/powerpc/powermac/pmu.c
diff options
context:
space:
mode:
authornwhitehorn <nwhitehorn@FreeBSD.org>2008-12-07 00:42:15 +0000
committernwhitehorn <nwhitehorn@FreeBSD.org>2008-12-07 00:42:15 +0000
commiteff63b34b11c4791d1aaa3cc5d59c42367c7ffaa (patch)
tree2783a301cc06439cbe1430817027abf73074d83b /sys/powerpc/powermac/pmu.c
parente6bc656165feaa55eb1bb3b7ba07f1e02c7e307b (diff)
downloadFreeBSD-src-eff63b34b11c4791d1aaa3cc5d59c42367c7ffaa.zip
FreeBSD-src-eff63b34b11c4791d1aaa3cc5d59c42367c7ffaa.tar.gz
Add support for automated reboot after power failure on Apple Core99 machines
(G3 laptops, all G4 machines, early G5s, G5 Xserves). The relevant sysctl is named dev.pmu.0.server_mode for mental compatibility with Linux.
Diffstat (limited to 'sys/powerpc/powermac/pmu.c')
-rw-r--r--sys/powerpc/powermac/pmu.c64
1 files changed, 61 insertions, 3 deletions
diff --git a/sys/powerpc/powermac/pmu.c b/sys/powerpc/powermac/pmu.c
index b5dcdf8..d767358 100644
--- a/sys/powerpc/powermac/pmu.c
+++ b/sys/powerpc/powermac/pmu.c
@@ -37,6 +37,7 @@ __FBSDID("$FreeBSD$");
#include <sys/bus.h>
#include <sys/conf.h>
#include <sys/kernel.h>
+#include <sys/sysctl.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/openfirm.h>
@@ -65,10 +66,11 @@ static int pmu_probe(device_t);
static int pmu_attach(device_t);
static int pmu_detach(device_t);
-static u_int pmu_adb_send(device_t dev, u_char command_byte, int len,
+static u_int pmu_adb_send(device_t dev, u_char command_byte, int len,
u_char *data, u_char poll);
-static u_int pmu_adb_autopoll(device_t dev, uint16_t mask);
-static void pmu_poll(device_t dev);
+static u_int pmu_adb_autopoll(device_t dev, uint16_t mask);
+static void pmu_poll(device_t dev);
+static int pmu_server_mode(SYSCTL_HANDLER_ARGS);
static device_method_t pmu_methods[] = {
/* Device interface */
@@ -282,6 +284,8 @@ pmu_attach(device_t dev)
uint8_t cmd[2] = {2, 0};
uint8_t resp[16];
phandle_t node,child;
+ struct sysctl_ctx_list *ctx;
+ struct sysctl_oid *tree;
sc = device_get_softc(dev);
sc->sc_dev = dev;
@@ -341,6 +345,17 @@ pmu_attach(device_t dev)
}
}
+ /*
+ * Set up sysctls
+ */
+
+ ctx = device_get_sysctl_ctx(dev);
+ tree = device_get_sysctl_tree(dev);
+
+ SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
+ "server_mode", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
+ pmu_server_mode, "I", "Enable reboot after power failure");
+
return (bus_generic_attach(dev));
}
@@ -613,3 +628,46 @@ pmu_adb_autopoll(device_t dev, uint16_t mask)
return 0;
}
+
+static int
+pmu_server_mode(SYSCTL_HANDLER_ARGS)
+{
+ struct pmu_softc *sc = arg1;
+
+ u_int server_mode = 0;
+ uint8_t getcmd[] = {PMU_PWR_GET_POWERUP_EVENTS};
+ uint8_t setcmd[] = {0, 0, PMU_PWR_WAKEUP_AC_INSERT};
+ uint8_t resp[3];
+ int error, len;
+
+ mtx_lock(&sc->sc_mutex);
+ len = pmu_send(sc, PMU_POWER_EVENTS, 1, getcmd, 3, resp);
+ mtx_unlock(&sc->sc_mutex);
+
+ if (len == 3)
+ server_mode = (resp[2] & PMU_PWR_WAKEUP_AC_INSERT) ? 1 : 0;
+
+ error = sysctl_handle_int(oidp, &server_mode, 0, req);
+
+ if (len != 3)
+ return (EINVAL);
+
+ if (error || !req->newptr)
+ return (error);
+
+ if (server_mode == 1)
+ setcmd[0] = PMU_PWR_SET_POWERUP_EVENTS;
+ else if (server_mode == 0)
+ setcmd[0] = PMU_PWR_CLR_POWERUP_EVENTS;
+ else
+ return (EINVAL);
+
+ setcmd[1] = resp[1];
+
+ mtx_lock(&sc->sc_mutex);
+ pmu_send(sc, PMU_POWER_EVENTS, 3, setcmd, 2, resp);
+ mtx_unlock(&sc->sc_mutex);
+
+ return (0);
+}
+
OpenPOWER on IntegriCloud