1*539ffff0Sskrll /* $NetBSD: power.c,v 1.3 2019/04/15 20:40:37 skrll Exp $ */
26d3ceb1dSskrll
36d3ceb1dSskrll /*
46d3ceb1dSskrll * Copyright (c) 2004 Jochen Kunz.
56d3ceb1dSskrll * All rights reserved.
66d3ceb1dSskrll *
76d3ceb1dSskrll * Redistribution and use in source and binary forms, with or without
86d3ceb1dSskrll * modification, are permitted provided that the following conditions
96d3ceb1dSskrll * are met:
106d3ceb1dSskrll * 1. Redistributions of source code must retain the above copyright
116d3ceb1dSskrll * notice, this list of conditions and the following disclaimer.
126d3ceb1dSskrll * 2. Redistributions in binary form must reproduce the above copyright
136d3ceb1dSskrll * notice, this list of conditions and the following disclaimer in the
146d3ceb1dSskrll * documentation and/or other materials provided with the distribution.
156d3ceb1dSskrll * 3. The name of Jochen Kunz may not be used to endorse or promote
166d3ceb1dSskrll * products derived from this software without specific prior
176d3ceb1dSskrll * written permission.
186d3ceb1dSskrll *
196d3ceb1dSskrll * THIS SOFTWARE IS PROVIDED BY JOCHEN KUNZ
206d3ceb1dSskrll * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
216d3ceb1dSskrll * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
226d3ceb1dSskrll * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JOCHEN KUNZ
236d3ceb1dSskrll * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
246d3ceb1dSskrll * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
256d3ceb1dSskrll * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
266d3ceb1dSskrll * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
276d3ceb1dSskrll * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
286d3ceb1dSskrll * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
296d3ceb1dSskrll * POSSIBILITY OF SUCH DAMAGE.
306d3ceb1dSskrll */
316d3ceb1dSskrll
326d3ceb1dSskrll /* $OpenBSD: power.c,v 1.5 2004/06/11 12:53:09 mickey Exp $ */
336d3ceb1dSskrll
346d3ceb1dSskrll /*
356d3ceb1dSskrll * Copyright (c) 2003 Michael Shalayeff
366d3ceb1dSskrll * All rights reserved.
376d3ceb1dSskrll *
386d3ceb1dSskrll * Redistribution and use in source and binary forms, with or without
396d3ceb1dSskrll * modification, are permitted provided that the following conditions
406d3ceb1dSskrll * are met:
416d3ceb1dSskrll * 1. Redistributions of source code must retain the above copyright
426d3ceb1dSskrll * notice, this list of conditions and the following disclaimer.
436d3ceb1dSskrll * 2. Redistributions in binary form must reproduce the above copyright
446d3ceb1dSskrll * notice, this list of conditions and the following disclaimer in the
456d3ceb1dSskrll * documentation and/or other materials provided with the distribution.
466d3ceb1dSskrll *
476d3ceb1dSskrll * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
486d3ceb1dSskrll * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
496d3ceb1dSskrll * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
506d3ceb1dSskrll * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT,
516d3ceb1dSskrll * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
526d3ceb1dSskrll * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
536d3ceb1dSskrll * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
546d3ceb1dSskrll * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
556d3ceb1dSskrll * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
566d3ceb1dSskrll * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
576d3ceb1dSskrll * THE POSSIBILITY OF SUCH DAMAGE.
586d3ceb1dSskrll */
596d3ceb1dSskrll
606d3ceb1dSskrll #include <sys/param.h>
616d3ceb1dSskrll #include <sys/kernel.h>
626d3ceb1dSskrll #include <sys/systm.h>
636d3ceb1dSskrll #include <sys/reboot.h>
646d3ceb1dSskrll #include <sys/device.h>
656d3ceb1dSskrll #include <sys/sysctl.h>
666d3ceb1dSskrll #include <sys/kmem.h>
676d3ceb1dSskrll
686d3ceb1dSskrll #include <machine/reg.h>
696d3ceb1dSskrll #include <machine/pdc.h>
706d3ceb1dSskrll #include <machine/autoconf.h>
716d3ceb1dSskrll
726d3ceb1dSskrll #include <hppa/dev/cpudevs.h>
736d3ceb1dSskrll
746d3ceb1dSskrll #include <dev/sysmon/sysmon_taskq.h>
756d3ceb1dSskrll #include <dev/sysmon/sysmonvar.h>
766d3ceb1dSskrll
776d3ceb1dSskrll /* Enable / disable control over the power switch. */
786d3ceb1dSskrll #define PWR_SW_CTRL_DISABLE 0
796d3ceb1dSskrll #define PWR_SW_CTRL_ENABLE 1
806d3ceb1dSskrll #define PWR_SW_CTRL_LOCK 2
816d3ceb1dSskrll #define PWR_SW_CTRL_MAX PWR_SW_CTRL_LOCK
826d3ceb1dSskrll
836d3ceb1dSskrll struct power_softc {
846d3ceb1dSskrll device_t sc_dev;
856d3ceb1dSskrll bus_space_tag_t sc_bst;
866d3ceb1dSskrll bus_space_handle_t sc_bsh;
876d3ceb1dSskrll
886d3ceb1dSskrll void (*sc_kicker)(void *);
896d3ceb1dSskrll
906d3ceb1dSskrll struct callout sc_callout;
916d3ceb1dSskrll int sc_timeout;
926d3ceb1dSskrll
936d3ceb1dSskrll int sc_dr_cnt;
946d3ceb1dSskrll };
956d3ceb1dSskrll
966d3ceb1dSskrll int powermatch(device_t, cfdata_t, void *);
976d3ceb1dSskrll void powerattach(device_t, device_t, void *);
986d3ceb1dSskrll
996d3ceb1dSskrll CFATTACH_DECL_NEW(power, sizeof(struct power_softc),
1006d3ceb1dSskrll powermatch, powerattach, NULL, NULL);
1016d3ceb1dSskrll
1026d3ceb1dSskrll static struct pdc_power_info pdc_power_info;
1036d3ceb1dSskrll static bool pswitch_on; /* power switch */
1046d3ceb1dSskrll static int pwr_sw_control;
1056d3ceb1dSskrll static const char *pwr_sw_control_str[] = {"disabled", "enabled", "locked"};
1066d3ceb1dSskrll static struct sysmon_pswitch *pwr_sw_sysmon;
1076d3ceb1dSskrll
1086d3ceb1dSskrll static int pwr_sw_sysctl_state(SYSCTLFN_PROTO);
1096d3ceb1dSskrll static int pwr_sw_sysctl_ctrl(SYSCTLFN_PROTO);
1106d3ceb1dSskrll static void pwr_sw_sysmon_cb(void *);
1116d3ceb1dSskrll static void pwr_sw_ctrl(int);
1126d3ceb1dSskrll static int pwr_sw_init(struct power_softc *);
1136d3ceb1dSskrll
1146d3ceb1dSskrll void power_thread_dr(void *v);
1156d3ceb1dSskrll void power_thread_reg(void *v);
1166d3ceb1dSskrll void power_cold_hook_reg(int);
1176d3ceb1dSskrll
1186d3ceb1dSskrll int
powermatch(device_t parent,cfdata_t cf,void * aux)1196d3ceb1dSskrll powermatch(device_t parent, cfdata_t cf, void *aux)
1206d3ceb1dSskrll {
1216d3ceb1dSskrll struct confargs *ca = aux;
1226d3ceb1dSskrll
1236d3ceb1dSskrll if (cf->cf_unit > 0 && !strcmp(ca->ca_name, "power"))
1246d3ceb1dSskrll return (0);
1256d3ceb1dSskrll
1266d3ceb1dSskrll return (1);
1276d3ceb1dSskrll }
1286d3ceb1dSskrll
1296d3ceb1dSskrll void
powerattach(device_t parent,device_t self,void * aux)1306d3ceb1dSskrll powerattach(device_t parent, device_t self, void *aux)
1316d3ceb1dSskrll {
1326d3ceb1dSskrll struct power_softc *sc = device_private(self);
1336d3ceb1dSskrll struct confargs *ca = aux;
1346d3ceb1dSskrll int err;
1356d3ceb1dSskrll
1366d3ceb1dSskrll sc->sc_dev = self;
1376d3ceb1dSskrll sc->sc_kicker = NULL;
1386d3ceb1dSskrll
1396d3ceb1dSskrll err = pdcproc_soft_power_info(&pdc_power_info);
1406d3ceb1dSskrll
1416d3ceb1dSskrll if (!err)
1426d3ceb1dSskrll ca->ca_hpa = pdc_power_info.addr;
1436d3ceb1dSskrll
1446d3ceb1dSskrll switch (cpu_modelno) {
1456d3ceb1dSskrll case HPPA_BOARD_HP712_60:
1466d3ceb1dSskrll case HPPA_BOARD_HP712_80:
1476d3ceb1dSskrll case HPPA_BOARD_HP712_100:
1486d3ceb1dSskrll case HPPA_BOARD_HP712_120:
1496d3ceb1dSskrll sc->sc_kicker = power_thread_dr;
1506d3ceb1dSskrll
1516d3ceb1dSskrll /* Diag Reg. needs software dampening, poll at 0.2 Hz.*/
1526d3ceb1dSskrll sc->sc_timeout = hz / 5;
1536d3ceb1dSskrll
1546d3ceb1dSskrll aprint_normal(": DR25\n");
1556d3ceb1dSskrll break;
1566d3ceb1dSskrll
1576d3ceb1dSskrll default:
1586d3ceb1dSskrll if (ca->ca_hpa) {
1596d3ceb1dSskrll sc->sc_bst = ca->ca_iot;
1606d3ceb1dSskrll if (bus_space_map(sc->sc_bst, ca->ca_hpa, 4, 0,
1616d3ceb1dSskrll &sc->sc_bsh) != 0)
1626d3ceb1dSskrll aprint_error_dev(self,
1636d3ceb1dSskrll "Can't map power switch status reg.\n");
1646d3ceb1dSskrll
1656d3ceb1dSskrll cold_hook = power_cold_hook_reg;
1666d3ceb1dSskrll sc->sc_kicker = power_thread_reg;
1676d3ceb1dSskrll
1686d3ceb1dSskrll /* Power Reg. is hardware dampened, poll at 1 Hz. */
1696d3ceb1dSskrll sc->sc_timeout = hz;
1706d3ceb1dSskrll
1716d3ceb1dSskrll aprint_normal("\n");
1726d3ceb1dSskrll } else
1736d3ceb1dSskrll aprint_normal(": not available\n");
1746d3ceb1dSskrll break;
1756d3ceb1dSskrll }
1766d3ceb1dSskrll
1776d3ceb1dSskrll if (sc->sc_kicker) {
1786d3ceb1dSskrll if (pwr_sw_init(sc))
1796d3ceb1dSskrll return;
1806d3ceb1dSskrll
1816d3ceb1dSskrll pswitch_on = true;
1826d3ceb1dSskrll pwr_sw_control = PWR_SW_CTRL_ENABLE;
1836d3ceb1dSskrll }
1846d3ceb1dSskrll }
1856d3ceb1dSskrll
1866d3ceb1dSskrll /*
1876d3ceb1dSskrll * If the power switch is turned off we schedule a sysmon task
1886d3ceb1dSskrll * to register that event for this power switch device.
1896d3ceb1dSskrll */
1906d3ceb1dSskrll static void
check_pwr_state(struct power_softc * sc)1916d3ceb1dSskrll check_pwr_state(struct power_softc *sc)
1926d3ceb1dSskrll {
1936d3ceb1dSskrll if (pswitch_on == false && pwr_sw_control != PWR_SW_CTRL_LOCK)
1946d3ceb1dSskrll sysmon_task_queue_sched(0, pwr_sw_sysmon_cb, NULL);
1956d3ceb1dSskrll else
1966d3ceb1dSskrll callout_reset(&sc->sc_callout, sc->sc_timeout,
1976d3ceb1dSskrll sc->sc_kicker, sc);
1986d3ceb1dSskrll }
1996d3ceb1dSskrll
2006d3ceb1dSskrll void
power_thread_dr(void * v)2016d3ceb1dSskrll power_thread_dr(void *v)
2026d3ceb1dSskrll {
2036d3ceb1dSskrll struct power_softc *sc = v;
2046d3ceb1dSskrll uint32_t r;
2056d3ceb1dSskrll
2066d3ceb1dSskrll /* Get Power Fail status from CPU Diagnose Register 25 */
2076d3ceb1dSskrll mfcpu(25, r);
2086d3ceb1dSskrll
2096d3ceb1dSskrll /*
2106d3ceb1dSskrll * On power failure, the hardware clears bit DR25_PCXL_POWFAIL
2116d3ceb1dSskrll * in CPU Diagnose Register 25.
2126d3ceb1dSskrll */
2136d3ceb1dSskrll if (r & (1 << DR25_PCXL_POWFAIL))
2146d3ceb1dSskrll sc->sc_dr_cnt = 0;
2156d3ceb1dSskrll else
2166d3ceb1dSskrll sc->sc_dr_cnt++;
2176d3ceb1dSskrll
2186d3ceb1dSskrll /*
2196d3ceb1dSskrll * the bit is undampened straight wire from the power
2206d3ceb1dSskrll * switch and thus we have do dampen it ourselves.
2216d3ceb1dSskrll */
2226d3ceb1dSskrll if (sc->sc_dr_cnt == sc->sc_timeout)
2236d3ceb1dSskrll pswitch_on = false;
2246d3ceb1dSskrll else
2256d3ceb1dSskrll pswitch_on = true;
2266d3ceb1dSskrll
2276d3ceb1dSskrll check_pwr_state(sc);
2286d3ceb1dSskrll }
2296d3ceb1dSskrll
2306d3ceb1dSskrll void
power_thread_reg(void * v)2316d3ceb1dSskrll power_thread_reg(void *v)
2326d3ceb1dSskrll {
2336d3ceb1dSskrll struct power_softc *sc = v;
2346d3ceb1dSskrll uint32_t r;
2356d3ceb1dSskrll
2366d3ceb1dSskrll r = bus_space_read_4(sc->sc_bst, sc->sc_bsh, 0);
2376d3ceb1dSskrll
2386d3ceb1dSskrll if (!(r & 1))
2396d3ceb1dSskrll pswitch_on = false;
2406d3ceb1dSskrll else
2416d3ceb1dSskrll pswitch_on = true;
2426d3ceb1dSskrll
2436d3ceb1dSskrll check_pwr_state(sc);
2446d3ceb1dSskrll }
2456d3ceb1dSskrll
2466d3ceb1dSskrll void
power_cold_hook_reg(int on)2476d3ceb1dSskrll power_cold_hook_reg(int on)
2486d3ceb1dSskrll {
2496d3ceb1dSskrll int error;
2506d3ceb1dSskrll
2516d3ceb1dSskrll error = pdcproc_soft_power_enable(on == HPPA_COLD_HOT);
2526d3ceb1dSskrll if (error)
2536d3ceb1dSskrll aprint_error("PDC_SOFT_POWER_ENABLE failed (%d)\n", error);
2546d3ceb1dSskrll }
2556d3ceb1dSskrll
2566d3ceb1dSskrll static int
pwr_sw_init(struct power_softc * sc)2576d3ceb1dSskrll pwr_sw_init(struct power_softc *sc)
2586d3ceb1dSskrll {
2596d3ceb1dSskrll struct sysctllog *sysctl_log = NULL;
2606d3ceb1dSskrll const struct sysctlnode *pwr_sw_node;
2616d3ceb1dSskrll const char *errmsg;
2626d3ceb1dSskrll int error = EINVAL;
2636d3ceb1dSskrll
2646d3ceb1dSskrll /*
2656d3ceb1dSskrll * Ensure that we are on a PCX-L / PA7100LC CPU if it is a
2666d3ceb1dSskrll * 712 style machine.
2676d3ceb1dSskrll */
2686d3ceb1dSskrll if (pdc_power_info.addr == 0 && hppa_cpu_info->hci_cputype != hpcxl) {
2696d3ceb1dSskrll aprint_error_dev(sc->sc_dev, "No soft power available.\n");
2706d3ceb1dSskrll return error;
2716d3ceb1dSskrll }
2726d3ceb1dSskrll
2736d3ceb1dSskrll errmsg = "Can't create sysctl machdep.power_switch (or children)\n";
2746d3ceb1dSskrll error = sysctl_createv(&sysctl_log, 0, NULL, NULL, 0,
2756d3ceb1dSskrll CTLTYPE_NODE, "machdep", NULL, NULL, 0, NULL, 0,
2766d3ceb1dSskrll CTL_MACHDEP, CTL_EOL);
2776d3ceb1dSskrll
2786d3ceb1dSskrll if (error)
2796d3ceb1dSskrll goto err_sysctl;
2806d3ceb1dSskrll
2816d3ceb1dSskrll error = sysctl_createv(&sysctl_log, 0, NULL, &pwr_sw_node, 0,
2826d3ceb1dSskrll CTLTYPE_NODE, "power_switch", NULL, NULL, 0, NULL, 0,
2836d3ceb1dSskrll CTL_MACHDEP, CTL_CREATE, CTL_EOL);
2846d3ceb1dSskrll
2856d3ceb1dSskrll if (error)
2866d3ceb1dSskrll goto err_sysctl;
2876d3ceb1dSskrll
2886d3ceb1dSskrll error = sysctl_createv(&sysctl_log, 0, NULL, NULL,
2896d3ceb1dSskrll CTLFLAG_READONLY, CTLTYPE_STRING, "state", NULL,
2906d3ceb1dSskrll pwr_sw_sysctl_state, 0, NULL, 16,
2916d3ceb1dSskrll CTL_MACHDEP, pwr_sw_node->sysctl_num, CTL_CREATE, CTL_EOL);
2926d3ceb1dSskrll
2936d3ceb1dSskrll if (error)
2946d3ceb1dSskrll goto err_sysctl;
2956d3ceb1dSskrll
2966d3ceb1dSskrll error = sysctl_createv(&sysctl_log, 0, NULL, NULL,
2976d3ceb1dSskrll CTLFLAG_READWRITE, CTLTYPE_STRING, "control", NULL,
2986d3ceb1dSskrll pwr_sw_sysctl_ctrl, 0, NULL, 16,
2996d3ceb1dSskrll CTL_MACHDEP, pwr_sw_node->sysctl_num, CTL_CREATE, CTL_EOL);
3006d3ceb1dSskrll
3016d3ceb1dSskrll if (error)
3026d3ceb1dSskrll goto err_sysctl;
3036d3ceb1dSskrll
3046d3ceb1dSskrll errmsg = "Can't alloc sysmon power switch.\n";
3056d3ceb1dSskrll pwr_sw_sysmon = kmem_zalloc(sizeof(*pwr_sw_sysmon), KM_SLEEP);
3066d3ceb1dSskrll errmsg = "Can't register power switch with sysmon.\n";
3076d3ceb1dSskrll sysmon_task_queue_init();
3086d3ceb1dSskrll pwr_sw_sysmon->smpsw_name = "power switch";
3096d3ceb1dSskrll pwr_sw_sysmon->smpsw_type = PSWITCH_TYPE_POWER;
3106d3ceb1dSskrll error = sysmon_pswitch_register(pwr_sw_sysmon);
3116d3ceb1dSskrll
3126d3ceb1dSskrll if (error)
3136d3ceb1dSskrll goto err_sysmon;
3146d3ceb1dSskrll
3156d3ceb1dSskrll callout_init(&sc->sc_callout, 0);
3166d3ceb1dSskrll callout_reset(&sc->sc_callout, sc->sc_timeout, sc->sc_kicker, sc);
3176d3ceb1dSskrll
3186d3ceb1dSskrll return error;
3196d3ceb1dSskrll
3206d3ceb1dSskrll err_sysmon:
3216d3ceb1dSskrll kmem_free(pwr_sw_sysmon, sizeof(*pwr_sw_sysmon));
3226d3ceb1dSskrll
3236d3ceb1dSskrll err_sysctl:
3246d3ceb1dSskrll sysctl_teardown(&sysctl_log);
3256d3ceb1dSskrll
3266d3ceb1dSskrll aprint_error_dev(sc->sc_dev, errmsg);
3276d3ceb1dSskrll
3286d3ceb1dSskrll return error;
3296d3ceb1dSskrll }
3306d3ceb1dSskrll
3316d3ceb1dSskrll static void
pwr_sw_sysmon_cb(void * not_used)3326d3ceb1dSskrll pwr_sw_sysmon_cb(void *not_used)
3336d3ceb1dSskrll {
3346d3ceb1dSskrll sysmon_pswitch_event(pwr_sw_sysmon, PSWITCH_EVENT_PRESSED);
3356d3ceb1dSskrll }
3366d3ceb1dSskrll
3376d3ceb1dSskrll static void
pwr_sw_ctrl(int enable)3386d3ceb1dSskrll pwr_sw_ctrl(int enable)
3396d3ceb1dSskrll {
3406d3ceb1dSskrll int on;
3416d3ceb1dSskrll
3426d3ceb1dSskrll #ifdef DEBUG
3436d3ceb1dSskrll printf("pwr_sw_control=%d enable=%d\n", pwr_sw_control, enable);
3446d3ceb1dSskrll #endif /* DEBUG */
3456d3ceb1dSskrll
3466d3ceb1dSskrll if (cold_hook == NULL)
3476d3ceb1dSskrll return;
3486d3ceb1dSskrll
3496d3ceb1dSskrll switch(enable) {
3506d3ceb1dSskrll case PWR_SW_CTRL_DISABLE:
3516d3ceb1dSskrll on = HPPA_COLD_OFF;
3526d3ceb1dSskrll break;
3536d3ceb1dSskrll case PWR_SW_CTRL_ENABLE:
3546d3ceb1dSskrll case PWR_SW_CTRL_LOCK:
3556d3ceb1dSskrll on = HPPA_COLD_HOT;
3566d3ceb1dSskrll break;
3576d3ceb1dSskrll default:
3586d3ceb1dSskrll panic("invalid power state in pwr_sw_control: %d", enable);
3596d3ceb1dSskrll }
3606d3ceb1dSskrll
3616d3ceb1dSskrll pwr_sw_control = enable;
3626d3ceb1dSskrll
3636d3ceb1dSskrll if (cold_hook)
3646d3ceb1dSskrll (*cold_hook)(on);
3656d3ceb1dSskrll }
3666d3ceb1dSskrll
3676d3ceb1dSskrll int
pwr_sw_sysctl_state(SYSCTLFN_ARGS)3686d3ceb1dSskrll pwr_sw_sysctl_state(SYSCTLFN_ARGS)
3696d3ceb1dSskrll {
3706d3ceb1dSskrll struct sysctlnode node;
3716d3ceb1dSskrll const char *status;
3726d3ceb1dSskrll
3736d3ceb1dSskrll if (pswitch_on == true)
3746d3ceb1dSskrll status = "on";
3756d3ceb1dSskrll else
3766d3ceb1dSskrll status = "off";
3776d3ceb1dSskrll
3786d3ceb1dSskrll node = *rnode;
3796d3ceb1dSskrll node.sysctl_data = __UNCONST(status);
3806d3ceb1dSskrll return sysctl_lookup(SYSCTLFN_CALL(&node));
3816d3ceb1dSskrll }
3826d3ceb1dSskrll
3836d3ceb1dSskrll int
pwr_sw_sysctl_ctrl(SYSCTLFN_ARGS)3846d3ceb1dSskrll pwr_sw_sysctl_ctrl(SYSCTLFN_ARGS)
3856d3ceb1dSskrll {
3866d3ceb1dSskrll struct sysctlnode node;
3876d3ceb1dSskrll int i, error;
3886d3ceb1dSskrll char val[16];
3896d3ceb1dSskrll
3906d3ceb1dSskrll node = *rnode;
3916d3ceb1dSskrll strcpy(val, pwr_sw_control_str[pwr_sw_control]);
3926d3ceb1dSskrll
3936d3ceb1dSskrll node.sysctl_data = val;
3946d3ceb1dSskrll
3956d3ceb1dSskrll error = sysctl_lookup(SYSCTLFN_CALL(&node));
3966d3ceb1dSskrll
3976d3ceb1dSskrll if (error || newp == NULL)
3986d3ceb1dSskrll return error;
3996d3ceb1dSskrll
4006d3ceb1dSskrll for (i = 0; i <= PWR_SW_CTRL_MAX; i++)
4016d3ceb1dSskrll if (strcmp(val, pwr_sw_control_str[i]) == 0) {
4026d3ceb1dSskrll pwr_sw_ctrl(i);
4036d3ceb1dSskrll return 0;
4046d3ceb1dSskrll }
4056d3ceb1dSskrll
4066d3ceb1dSskrll return EINVAL;
4076d3ceb1dSskrll }
408