1 /* $NetBSD: pwctl.c,v 1.18 2009/05/12 12:13:49 cegger Exp $ */
4 * Copyright (c) 1999-2001
5 * TAKEMURA Shin and PocketBSD Project. All rights reserved.
6 * Copyright (c) 2000,2001
7 * SATO Kazumi. All rights reserved.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement:
19 * This product includes software developed by the PocketBSD project
20 * and its contributors.
21 * 4. Neither the name of the project nor the names of its contributors
22 * may be used to endorse or promote products derived from this software
23 * without specific prior written permission.
25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
39 #include <sys/cdefs.h>
40 __KERNEL_RCSID(0, "$NetBSD: pwctl.c,v 1.18 2009/05/12 12:13:49 cegger Exp $");
43 #include "opt_pwctl.h"
46 #include <sys/param.h>
47 #include <sys/systm.h>
48 #include <sys/device.h>
49 #include <sys/reboot.h>
52 #include <machine/config_hook.h>
53 #include <machine/platid.h>
54 #include <machine/platid_mask.h>
56 #include <dev/hpc/hpciovar.h>
61 #ifndef PWCTLDEBUG_CONF
62 #define PWCTLDEBUG_CONF 0
64 int pwctl_debug
= PWCTLDEBUG_CONF
;
65 #define DPRINTF(arg) if (pwctl_debug) printf arg;
66 #define VPRINTF(arg) if (bootverbose) printf arg;
69 #define VPRINTF(arg) if (bootverbose) printf arg;
78 config_hook_tag sc_hook_tag
;
79 config_hook_tag sc_hook_hardpower
;
80 config_hook_tag sc_ghook_tag
;
85 static int pwctl_match(device_t
, cfdata_t
, void *);
86 static void pwctl_attach(device_t
, device_t
, void *);
87 static int pwctl_hook(void *, int, long, void *);
88 static int pwctl_ghook(void *, int, long, void *);
89 int pwctl_hardpower(void *, int, long, void *);
91 CFATTACH_DECL(pwctl
, sizeof(struct pwctl_softc
),
92 pwctl_match
, pwctl_attach
, NULL
, NULL
);
95 pwctl_match(device_t parent
, cfdata_t match
, void *aux
)
97 struct hpcio_attach_args
*haa
= aux
;
100 if (strcmp(haa
->haa_busname
, HPCIO_BUSNAME
))
102 if (match
->cf_loc
[HPCIOIFCF_PLATFORM
] == 0)
104 mask
= PLATID_DEREF(match
->cf_loc
[HPCIOIFCF_PLATFORM
]);
105 if (!platid_match(&platid
, &mask
))
111 pwctl_attach(device_t parent
, device_t self
, void *aux
)
113 struct hpcio_attach_args
*haa
= aux
;
115 struct pwctl_softc
*sc
= device_private(self
);
117 loc
= device_cfdata(&sc
->sc_dev
)->cf_loc
;
118 sc
->sc_hc
= (*haa
->haa_getchip
)(haa
->haa_sc
, loc
[HPCIOIFCF_IOCHIP
]);
119 sc
->sc_port
= loc
[HPCIOIFCF_PORT
];
120 sc
->sc_id
= loc
[HPCIOIFCF_ID
];
121 sc
->sc_on
= loc
[HPCIOIFCF_ACTIVE
] ? 1 : 0;
122 sc
->sc_off
= loc
[HPCIOIFCF_ACTIVE
] ? 0 : 1;
123 sc
->sc_initvalue
= loc
[HPCIOIFCF_INITVALUE
];
125 printf(" port=%d id=%ld on=%d%s",
126 sc
->sc_port
, sc
->sc_id
, sc
->sc_on
,
127 sc
->sc_initvalue
== -1 ? "" :
128 sc
->sc_initvalue
? " init=on" : " init=off");
130 if (sc
->sc_port
== HPCIOIFCF_PORT_DEFAULT
||
131 sc
->sc_id
== HPCIOIFCF_ID_DEFAULT
) {
132 printf(" (ignored)");
134 sc
->sc_hook_tag
= config_hook(CONFIG_HOOK_POWERCONTROL
,
135 sc
->sc_id
, CONFIG_HOOK_SHARE
, pwctl_hook
, sc
);
136 sc
->sc_ghook_tag
= config_hook(CONFIG_HOOK_GET
,
137 sc
->sc_id
, CONFIG_HOOK_SHARE
, pwctl_ghook
, sc
);
138 sc
->sc_hook_hardpower
= config_hook(CONFIG_HOOK_PMEVENT
,
139 CONFIG_HOOK_PMEVENT_HARDPOWER
, CONFIG_HOOK_SHARE
,
140 pwctl_hardpower
, sc
);
143 if (sc
->sc_initvalue
!= -1)
144 hpcio_portwrite(sc
->sc_hc
, sc
->sc_port
,
145 sc
->sc_initvalue
? sc
->sc_on
: sc
->sc_off
);
150 pwctl_hook(void *ctx
, int type
, long id
, void *msg
)
152 struct pwctl_softc
*sc
= ctx
;
154 DPRINTF(("pwctl hook: port %d %s(%d)", sc
->sc_port
,
155 msg
? "ON" : "OFF", msg
? sc
->sc_on
: sc
->sc_off
));
156 hpcio_portwrite(sc
->sc_hc
, sc
->sc_port
,
157 msg
? sc
->sc_on
: sc
->sc_off
);
163 pwctl_ghook(void *ctx
, int type
, long id
, void *msg
)
165 struct pwctl_softc
*sc
= ctx
;
167 if (CONFIG_HOOK_VALUEP(msg
))
170 *(int*)msg
= hpcio_portread(sc
->sc_hc
, sc
->sc_port
) == sc
->sc_on
;
171 DPRINTF(("pwctl ghook: port %d %s(%d)", sc
->sc_port
,
172 *(int*)msg
? "ON" : "OFF", *(int*)msg
? sc
->sc_on
: sc
->sc_off
));
178 pwctl_hardpower(void *ctx
, int type
, long id
, void *msg
)
180 struct pwctl_softc
*sc
= ctx
;
183 VPRINTF(("pwctl hardpower: port %d %s: %s(%d)\n", sc
->sc_port
,
184 why
== PWR_RESUME
? "resume"
185 : why
== PWR_SUSPEND
? "suspend" : "standby",
186 sc
->sc_save
== sc
->sc_on
? "on": "off", sc
->sc_save
));
192 sc
->sc_save
= hpcio_portread(sc
->sc_hc
, sc
->sc_port
);
193 hpcio_portwrite(sc
->sc_hc
, sc
->sc_port
, sc
->sc_off
);
196 hpcio_portwrite(sc
->sc_hc
, sc
->sc_port
, sc
->sc_save
);