tctrl.c revision 1.24.2.6 1 1.24.2.6 christos /* $NetBSD: tctrl.c,v 1.24.2.6 2005/12/11 10:28:26 christos Exp $ */
2 1.1 matt
3 1.1 matt /*-
4 1.1 matt * Copyright (c) 1998 The NetBSD Foundation, Inc.
5 1.1 matt * All rights reserved.
6 1.1 matt *
7 1.1 matt * This code is derived from software contributed to The NetBSD Foundation
8 1.1 matt * by Matt Thomas.
9 1.1 matt *
10 1.1 matt * Redistribution and use in source and binary forms, with or without
11 1.1 matt * modification, are permitted provided that the following conditions
12 1.1 matt * are met:
13 1.1 matt * 1. Redistributions of source code must retain the above copyright
14 1.1 matt * notice, this list of conditions and the following disclaimer.
15 1.1 matt * 2. Redistributions in binary form must reproduce the above copyright
16 1.1 matt * notice, this list of conditions and the following disclaimer in the
17 1.1 matt * documentation and/or other materials provided with the distribution.
18 1.1 matt * 3. All advertising materials mentioning features or use of this software
19 1.1 matt * must display the following acknowledgement:
20 1.1 matt * This product includes software developed by the NetBSD
21 1.1 matt * Foundation, Inc. and its contributors.
22 1.1 matt * 4. Neither the name of The NetBSD Foundation nor the names of its
23 1.1 matt * contributors may be used to endorse or promote products derived
24 1.1 matt * from this software without specific prior written permission.
25 1.1 matt *
26 1.1 matt * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27 1.1 matt * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 1.1 matt * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 1.1 matt * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30 1.1 matt * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 1.1 matt * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 1.1 matt * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 1.1 matt * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 1.1 matt * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 1.1 matt * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 1.1 matt * POSSIBILITY OF SUCH DAMAGE.
37 1.1 matt */
38 1.1 matt
39 1.24.2.1 skrll #include <sys/cdefs.h>
40 1.24.2.6 christos __KERNEL_RCSID(0, "$NetBSD: tctrl.c,v 1.24.2.6 2005/12/11 10:28:26 christos Exp $");
41 1.24.2.1 skrll
42 1.1 matt #include <sys/param.h>
43 1.1 matt #include <sys/systm.h>
44 1.8 thorpej #include <sys/callout.h>
45 1.1 matt #include <sys/ioctl.h>
46 1.1 matt #include <sys/select.h>
47 1.1 matt #include <sys/tty.h>
48 1.1 matt #include <sys/proc.h>
49 1.1 matt #include <sys/user.h>
50 1.1 matt #include <sys/conf.h>
51 1.1 matt #include <sys/file.h>
52 1.1 matt #include <sys/uio.h>
53 1.1 matt #include <sys/kernel.h>
54 1.1 matt #include <sys/syslog.h>
55 1.1 matt #include <sys/types.h>
56 1.1 matt #include <sys/device.h>
57 1.4 garbled #include <sys/envsys.h>
58 1.4 garbled #include <sys/poll.h>
59 1.1 matt
60 1.4 garbled #include <machine/apmvar.h>
61 1.1 matt #include <machine/autoconf.h>
62 1.1 matt #include <machine/bus.h>
63 1.11 pk #include <machine/intr.h>
64 1.4 garbled #include <machine/tctrl.h>
65 1.1 matt
66 1.1 matt #include <sparc/dev/ts102reg.h>
67 1.1 matt #include <sparc/dev/tctrlvar.h>
68 1.7 jdc #include <sparc/sparc/auxiotwo.h>
69 1.24.2.5 skrll #include <sparc/sparc/auxreg.h>
70 1.24.2.5 skrll
71 1.24.2.5 skrll #include <dev/sysmon/sysmonvar.h>
72 1.24.2.5 skrll #include <dev/sysmon/sysmon_taskq.h>
73 1.24.2.5 skrll #include "sysmon_envsys.h"
74 1.1 matt
75 1.15 gehenna extern struct cfdriver tctrl_cd;
76 1.4 garbled
77 1.15 gehenna dev_type_open(tctrlopen);
78 1.15 gehenna dev_type_close(tctrlclose);
79 1.15 gehenna dev_type_ioctl(tctrlioctl);
80 1.15 gehenna dev_type_poll(tctrlpoll);
81 1.20 jdolecek dev_type_kqfilter(tctrlkqfilter);
82 1.15 gehenna
83 1.15 gehenna const struct cdevsw tctrl_cdevsw = {
84 1.15 gehenna tctrlopen, tctrlclose, noread, nowrite, tctrlioctl,
85 1.20 jdolecek nostop, notty, tctrlpoll, nommap, tctrlkqfilter,
86 1.15 gehenna };
87 1.4 garbled
88 1.1 matt static const char *tctrl_ext_statuses[16] = {
89 1.1 matt "main power available",
90 1.1 matt "internal battery attached",
91 1.1 matt "external battery attached",
92 1.1 matt "external VGA attached",
93 1.1 matt "external keyboard attached",
94 1.1 matt "external mouse attached",
95 1.1 matt "lid down",
96 1.1 matt "internal battery charging",
97 1.1 matt "external battery charging",
98 1.1 matt "internal battery discharging",
99 1.1 matt "external battery discharging",
100 1.1 matt };
101 1.1 matt
102 1.1 matt struct tctrl_softc {
103 1.4 garbled struct device sc_dev;
104 1.4 garbled bus_space_tag_t sc_memt;
105 1.4 garbled bus_space_handle_t sc_memh;
106 1.4 garbled unsigned int sc_junk;
107 1.4 garbled unsigned int sc_ext_status;
108 1.4 garbled unsigned int sc_flags;
109 1.4 garbled #define TCTRL_SEND_REQUEST 0x0001
110 1.4 garbled #define TCTRL_APM_CTLOPEN 0x0002
111 1.4 garbled unsigned int sc_wantdata;
112 1.6 garbled volatile unsigned short sc_lcdstate;
113 1.1 matt enum { TCTRL_IDLE, TCTRL_ARGS,
114 1.1 matt TCTRL_ACK, TCTRL_DATA } sc_state;
115 1.24.2.6 christos uint8_t sc_cmdbuf[16];
116 1.24.2.6 christos uint8_t sc_rspbuf[16];
117 1.24.2.6 christos uint8_t sc_bitport;
118 1.24.2.6 christos uint8_t sc_tft_on;
119 1.24.2.6 christos uint8_t sc_op;
120 1.24.2.6 christos uint8_t sc_cmdoff;
121 1.24.2.6 christos uint8_t sc_cmdlen;
122 1.24.2.6 christos uint8_t sc_rspoff;
123 1.24.2.6 christos uint8_t sc_rsplen;
124 1.4 garbled /* APM stuff */
125 1.4 garbled #define APM_NEVENTS 16
126 1.4 garbled struct apm_event_info sc_event_list[APM_NEVENTS];
127 1.4 garbled int sc_event_count;
128 1.4 garbled int sc_event_ptr;
129 1.4 garbled struct selinfo sc_rsel;
130 1.24.2.5 skrll
131 1.4 garbled /* ENVSYS stuff */
132 1.4 garbled #define ENVSYS_NUMSENSORS 3
133 1.4 garbled struct evcnt sc_intrcnt; /* interrupt counting */
134 1.24.2.5 skrll struct sysmon_envsys sc_sme;
135 1.24.2.5 skrll struct envsys_tre_data sc_tre[ENVSYS_NUMSENSORS];
136 1.24.2.5 skrll struct envsys_basic_info sc_binfo[ENVSYS_NUMSENSORS];
137 1.24.2.5 skrll struct envsys_range sc_range[ENVSYS_NUMSENSORS];
138 1.24.2.6 christos
139 1.24.2.5 skrll struct sysmon_pswitch sc_smcontext;
140 1.24.2.5 skrll int sc_powerpressed;
141 1.1 matt };
142 1.1 matt
143 1.4 garbled #define TCTRL_STD_DEV 0
144 1.4 garbled #define TCTRL_APMCTL_DEV 8
145 1.1 matt
146 1.9 thorpej static struct callout tctrl_event_ch = CALLOUT_INITIALIZER;
147 1.8 thorpej
148 1.24.2.6 christos static int tctrl_match(struct device *, struct cfdata *, void *);
149 1.24.2.6 christos static void tctrl_attach(struct device *, struct device *, void *);
150 1.24.2.6 christos static void tctrl_write(struct tctrl_softc *, bus_size_t, uint8_t);
151 1.24.2.6 christos static uint8_t tctrl_read(struct tctrl_softc *, bus_size_t);
152 1.24.2.6 christos static void tctrl_write_data(struct tctrl_softc *, uint8_t);
153 1.24.2.6 christos static uint8_t tctrl_read_data(struct tctrl_softc *);
154 1.24.2.6 christos static int tctrl_intr(void *);
155 1.24.2.6 christos static void tctrl_setup_bitport(void);
156 1.24.2.6 christos static void tctrl_setup_bitport_nop(void);
157 1.24.2.6 christos static void tctrl_read_ext_status(void);
158 1.24.2.6 christos static void tctrl_read_event_status(void *);
159 1.24.2.6 christos static int tctrl_apm_record_event(struct tctrl_softc *, u_int);
160 1.24.2.6 christos static void tctrl_init_lcd(void);
161 1.1 matt
162 1.24.2.5 skrll static void tctrl_sensor_setup(struct tctrl_softc *);
163 1.24.2.5 skrll static int tctrl_gtredata(struct sysmon_envsys *, struct envsys_tre_data *);
164 1.24.2.5 skrll static int tctrl_streinfo(struct sysmon_envsys *, struct envsys_basic_info *);
165 1.24.2.5 skrll
166 1.24.2.5 skrll static void tctrl_power_button_pressed(void *);
167 1.24.2.5 skrll static int tctrl_powerfail(void *);
168 1.24.2.5 skrll
169 1.17 thorpej CFATTACH_DECL(tctrl, sizeof(struct tctrl_softc),
170 1.18 thorpej tctrl_match, tctrl_attach, NULL, NULL);
171 1.1 matt
172 1.24.2.6 christos
173 1.4 garbled /* XXX wtf is this? see i386/apm.c */
174 1.4 garbled int tctrl_apm_evindex;
175 1.1 matt
176 1.1 matt static int
177 1.24.2.6 christos tctrl_match(struct device *parent, struct cfdata *cf, void *aux)
178 1.1 matt {
179 1.1 matt union obio_attach_args *uoba = aux;
180 1.1 matt struct sbus_attach_args *sa = &uoba->uoba_sbus;
181 1.1 matt
182 1.1 matt if (uoba->uoba_isobio4 != 0) {
183 1.1 matt return (0);
184 1.1 matt }
185 1.1 matt
186 1.1 matt /* Tadpole 3GX/3GS uses "uctrl" for the Tadpole Microcontroller
187 1.1 matt * (who's interface is off the TS102 PCMCIA controller but there
188 1.1 matt * exists a OpenProm for microcontroller interface).
189 1.1 matt */
190 1.1 matt return strcmp("uctrl", sa->sa_name) == 0;
191 1.1 matt }
192 1.1 matt
193 1.1 matt static void
194 1.24.2.6 christos tctrl_attach(struct device *parent, struct device *self, void *aux)
195 1.1 matt {
196 1.1 matt struct tctrl_softc *sc = (void *)self;
197 1.1 matt union obio_attach_args *uoba = aux;
198 1.1 matt struct sbus_attach_args *sa = &uoba->uoba_sbus;
199 1.2 matt unsigned int i, v;
200 1.1 matt
201 1.1 matt /* We're living on a sbus slot that looks like an obio that
202 1.1 matt * looks like an sbus slot.
203 1.1 matt */
204 1.1 matt sc->sc_memt = sa->sa_bustag;
205 1.14 pk if (sbus_bus_map(sc->sc_memt,
206 1.14 pk sa->sa_slot,
207 1.14 pk sa->sa_offset - TS102_REG_UCTRL_INT,
208 1.14 pk sa->sa_size,
209 1.14 pk BUS_SPACE_MAP_LINEAR, &sc->sc_memh) != 0) {
210 1.1 matt printf(": can't map registers\n");
211 1.1 matt return;
212 1.1 matt }
213 1.1 matt
214 1.2 matt printf("\n");
215 1.2 matt
216 1.1 matt sc->sc_tft_on = 1;
217 1.2 matt
218 1.1 matt /* clear any pending data.
219 1.1 matt */
220 1.1 matt for (i = 0; i < 10000; i++) {
221 1.4 garbled if ((TS102_UCTRL_STS_RXNE_STA &
222 1.4 garbled tctrl_read(sc, TS102_REG_UCTRL_STS)) == 0) {
223 1.1 matt break;
224 1.1 matt }
225 1.1 matt v = tctrl_read(sc, TS102_REG_UCTRL_DATA);
226 1.2 matt tctrl_write(sc, TS102_REG_UCTRL_STS, TS102_UCTRL_STS_RXNE_STA);
227 1.1 matt }
228 1.1 matt
229 1.3 pk if (sa->sa_nintr != 0) {
230 1.11 pk (void)bus_intr_establish(sc->sc_memt, sa->sa_pri, IPL_NONE,
231 1.22 pk tctrl_intr, sc);
232 1.10 cgd evcnt_attach_dynamic(&sc->sc_intrcnt, EVCNT_TYPE_INTR, NULL,
233 1.22 pk sc->sc_dev.dv_xname, "intr");
234 1.3 pk }
235 1.2 matt
236 1.24.2.5 skrll /* See what the external status is */
237 1.1 matt
238 1.4 garbled tctrl_read_ext_status();
239 1.2 matt if (sc->sc_ext_status != 0) {
240 1.2 matt const char *sep;
241 1.1 matt
242 1.1 matt printf("%s: ", sc->sc_dev.dv_xname);
243 1.2 matt v = sc->sc_ext_status;
244 1.1 matt for (i = 0, sep = ""; v != 0; i++, v >>= 1) {
245 1.1 matt if (v & 1) {
246 1.1 matt printf("%s%s", sep, tctrl_ext_statuses[i]);
247 1.1 matt sep = ", ";
248 1.1 matt }
249 1.1 matt }
250 1.1 matt printf("\n");
251 1.1 matt }
252 1.1 matt
253 1.24.2.5 skrll /* Get a current of the control bitport */
254 1.4 garbled tctrl_setup_bitport_nop();
255 1.2 matt tctrl_write(sc, TS102_REG_UCTRL_INT,
256 1.2 matt TS102_UCTRL_INT_RXNE_REQ|TS102_UCTRL_INT_RXNE_MSK);
257 1.1 matt
258 1.4 garbled sc->sc_wantdata = 0;
259 1.4 garbled sc->sc_event_count = 0;
260 1.4 garbled
261 1.24.2.5 skrll /* setup sensors and register the power button */
262 1.24.2.5 skrll tctrl_sensor_setup(sc);
263 1.24.2.6 christos
264 1.6 garbled /* initialize the LCD */
265 1.6 garbled tctrl_init_lcd();
266 1.6 garbled
267 1.6 garbled /* initialize sc_lcdstate */
268 1.6 garbled sc->sc_lcdstate = 0;
269 1.6 garbled tctrl_set_lcd(2, 0);
270 1.1 matt }
271 1.1 matt
272 1.1 matt static int
273 1.24.2.6 christos tctrl_intr(void *arg)
274 1.1 matt {
275 1.1 matt struct tctrl_softc *sc = arg;
276 1.1 matt unsigned int v, d;
277 1.1 matt int progress = 0;
278 1.1 matt
279 1.1 matt again:
280 1.1 matt /* find out the cause(s) of the interrupt */
281 1.12 toddpw v = tctrl_read(sc, TS102_REG_UCTRL_STS) & TS102_UCTRL_STS_MASK;
282 1.1 matt
283 1.1 matt /* clear the cause(s) of the interrupt */
284 1.1 matt tctrl_write(sc, TS102_REG_UCTRL_STS, v);
285 1.1 matt
286 1.2 matt v &= ~(TS102_UCTRL_STS_RXO_STA|TS102_UCTRL_STS_TXE_STA);
287 1.1 matt if (sc->sc_cmdoff >= sc->sc_cmdlen) {
288 1.2 matt v &= ~TS102_UCTRL_STS_TXNF_STA;
289 1.24.2.6 christos if (tctrl_read(sc, TS102_REG_UCTRL_INT) &
290 1.24.2.5 skrll TS102_UCTRL_INT_TXNF_REQ) {
291 1.4 garbled tctrl_write(sc, TS102_REG_UCTRL_INT, 0);
292 1.4 garbled progress = 1;
293 1.4 garbled }
294 1.1 matt }
295 1.4 garbled if ((v == 0) && ((sc->sc_flags & TCTRL_SEND_REQUEST) == 0 ||
296 1.4 garbled sc->sc_state != TCTRL_IDLE)) {
297 1.4 garbled wakeup(sc);
298 1.1 matt return progress;
299 1.1 matt }
300 1.1 matt
301 1.1 matt progress = 1;
302 1.2 matt if (v & TS102_UCTRL_STS_RXNE_STA) {
303 1.1 matt d = tctrl_read_data(sc);
304 1.1 matt switch (sc->sc_state) {
305 1.1 matt case TCTRL_IDLE:
306 1.2 matt if (d == 0xfa) {
307 1.4 garbled /* external event */
308 1.8 thorpej callout_reset(&tctrl_event_ch, 1,
309 1.8 thorpej tctrl_read_event_status, NULL);
310 1.2 matt } else {
311 1.2 matt printf("%s: (op=0x%02x): unexpected data (0x%02x)\n",
312 1.2 matt sc->sc_dev.dv_xname, sc->sc_op, d);
313 1.1 matt }
314 1.2 matt goto again;
315 1.1 matt case TCTRL_ACK:
316 1.1 matt if (d != 0xfe) {
317 1.2 matt printf("%s: (op=0x%02x): unexpected ack value (0x%02x)\n",
318 1.1 matt sc->sc_dev.dv_xname, sc->sc_op, d);
319 1.1 matt }
320 1.4 garbled #ifdef TCTRLDEBUG
321 1.2 matt printf(" ack=0x%02x", d);
322 1.2 matt #endif
323 1.2 matt sc->sc_rsplen--;
324 1.2 matt sc->sc_rspoff = 0;
325 1.1 matt sc->sc_state = sc->sc_rsplen ? TCTRL_DATA : TCTRL_IDLE;
326 1.4 garbled sc->sc_wantdata = sc->sc_rsplen ? 1 : 0;
327 1.4 garbled #ifdef TCTRLDEBUG
328 1.2 matt if (sc->sc_rsplen > 0) {
329 1.2 matt printf(" [data(%u)]", sc->sc_rsplen);
330 1.2 matt } else {
331 1.2 matt printf(" [idle]\n");
332 1.2 matt }
333 1.2 matt #endif
334 1.2 matt goto again;
335 1.1 matt case TCTRL_DATA:
336 1.1 matt sc->sc_rspbuf[sc->sc_rspoff++] = d;
337 1.4 garbled #ifdef TCTRLDEBUG
338 1.2 matt printf(" [%d]=0x%02x", sc->sc_rspoff-1, d);
339 1.2 matt #endif
340 1.1 matt if (sc->sc_rspoff == sc->sc_rsplen) {
341 1.4 garbled #ifdef TCTRLDEBUG
342 1.2 matt printf(" [idle]\n");
343 1.2 matt #endif
344 1.1 matt sc->sc_state = TCTRL_IDLE;
345 1.4 garbled sc->sc_wantdata = 0;
346 1.1 matt }
347 1.2 matt goto again;
348 1.1 matt default:
349 1.1 matt printf("%s: (op=0x%02x): unexpected data (0x%02x) in state %d\n",
350 1.1 matt sc->sc_dev.dv_xname, sc->sc_op, d, sc->sc_state);
351 1.2 matt goto again;
352 1.1 matt }
353 1.1 matt }
354 1.4 garbled if ((sc->sc_state == TCTRL_IDLE && sc->sc_wantdata == 0) ||
355 1.4 garbled sc->sc_flags & TCTRL_SEND_REQUEST) {
356 1.4 garbled if (sc->sc_flags & TCTRL_SEND_REQUEST) {
357 1.4 garbled sc->sc_flags &= ~TCTRL_SEND_REQUEST;
358 1.4 garbled sc->sc_wantdata = 1;
359 1.4 garbled }
360 1.1 matt if (sc->sc_cmdlen > 0) {
361 1.1 matt tctrl_write(sc, TS102_REG_UCTRL_INT,
362 1.1 matt tctrl_read(sc, TS102_REG_UCTRL_INT)
363 1.1 matt |TS102_UCTRL_INT_TXNF_MSK
364 1.1 matt |TS102_UCTRL_INT_TXNF_REQ);
365 1.1 matt v = tctrl_read(sc, TS102_REG_UCTRL_STS);
366 1.1 matt }
367 1.1 matt }
368 1.2 matt if ((sc->sc_cmdoff < sc->sc_cmdlen) && (v & TS102_UCTRL_STS_TXNF_STA)) {
369 1.1 matt tctrl_write_data(sc, sc->sc_cmdbuf[sc->sc_cmdoff++]);
370 1.4 garbled #ifdef TCTRLDEBUG
371 1.2 matt if (sc->sc_cmdoff == 1) {
372 1.2 matt printf("%s: op=0x%02x(l=%u)", sc->sc_dev.dv_xname,
373 1.2 matt sc->sc_cmdbuf[0], sc->sc_rsplen);
374 1.2 matt } else {
375 1.2 matt printf(" [%d]=0x%02x", sc->sc_cmdoff-1,
376 1.2 matt sc->sc_cmdbuf[sc->sc_cmdoff-1]);
377 1.2 matt }
378 1.2 matt #endif
379 1.1 matt if (sc->sc_cmdoff == sc->sc_cmdlen) {
380 1.1 matt sc->sc_state = sc->sc_rsplen ? TCTRL_ACK : TCTRL_IDLE;
381 1.4 garbled #ifdef TCTRLDEBUG
382 1.2 matt printf(" %s", sc->sc_rsplen ? "[ack]" : "[idle]\n");
383 1.2 matt #endif
384 1.2 matt if (sc->sc_cmdoff == 1) {
385 1.2 matt sc->sc_op = sc->sc_cmdbuf[0];
386 1.2 matt }
387 1.1 matt tctrl_write(sc, TS102_REG_UCTRL_INT,
388 1.1 matt tctrl_read(sc, TS102_REG_UCTRL_INT)
389 1.1 matt & (~TS102_UCTRL_INT_TXNF_MSK
390 1.1 matt |TS102_UCTRL_INT_TXNF_REQ));
391 1.1 matt } else if (sc->sc_state == TCTRL_IDLE) {
392 1.1 matt sc->sc_op = sc->sc_cmdbuf[0];
393 1.1 matt sc->sc_state = TCTRL_ARGS;
394 1.4 garbled #ifdef TCTRLDEBUG
395 1.2 matt printf(" [args]");
396 1.2 matt #endif
397 1.1 matt }
398 1.1 matt }
399 1.1 matt goto again;
400 1.1 matt }
401 1.1 matt
402 1.1 matt static void
403 1.4 garbled tctrl_setup_bitport_nop(void)
404 1.4 garbled {
405 1.4 garbled struct tctrl_softc *sc;
406 1.4 garbled struct tctrl_req req;
407 1.4 garbled int s;
408 1.24.2.6 christos
409 1.4 garbled sc = (struct tctrl_softc *) tctrl_cd.cd_devs[TCTRL_STD_DEV];
410 1.4 garbled req.cmdbuf[0] = TS102_OP_CTL_BITPORT;
411 1.4 garbled req.cmdbuf[1] = 0xff;
412 1.4 garbled req.cmdbuf[2] = 0;
413 1.4 garbled req.cmdlen = 3;
414 1.4 garbled req.rsplen = 2;
415 1.4 garbled req.p = NULL;
416 1.4 garbled tadpole_request(&req, 1);
417 1.4 garbled s = splts102();
418 1.4 garbled sc->sc_bitport = (req.rspbuf[0] & req.cmdbuf[1]) ^ req.cmdbuf[2];
419 1.4 garbled splx(s);
420 1.4 garbled }
421 1.4 garbled
422 1.4 garbled static void
423 1.4 garbled tctrl_setup_bitport(void)
424 1.1 matt {
425 1.4 garbled struct tctrl_softc *sc;
426 1.4 garbled struct tctrl_req req;
427 1.4 garbled int s;
428 1.24.2.6 christos
429 1.4 garbled sc = (struct tctrl_softc *) tctrl_cd.cd_devs[TCTRL_STD_DEV];
430 1.4 garbled s = splts102();
431 1.4 garbled if ((sc->sc_ext_status & TS102_EXT_STATUS_LID_DOWN)
432 1.4 garbled || (!sc->sc_tft_on)) {
433 1.4 garbled req.cmdbuf[2] = TS102_BITPORT_TFTPWR;
434 1.1 matt } else {
435 1.4 garbled req.cmdbuf[2] = 0;
436 1.4 garbled }
437 1.4 garbled req.cmdbuf[0] = TS102_OP_CTL_BITPORT;
438 1.4 garbled req.cmdbuf[1] = ~TS102_BITPORT_TFTPWR;
439 1.4 garbled req.cmdlen = 3;
440 1.4 garbled req.rsplen = 2;
441 1.4 garbled req.p = NULL;
442 1.4 garbled tadpole_request(&req, 1);
443 1.4 garbled s = splts102();
444 1.4 garbled sc->sc_bitport = (req.rspbuf[0] & req.cmdbuf[1]) ^ req.cmdbuf[2];
445 1.4 garbled splx(s);
446 1.4 garbled }
447 1.4 garbled
448 1.6 garbled /*
449 1.6 garbled * The tadpole microcontroller is not preprogrammed with icon
450 1.6 garbled * representations. The machine boots with the DC-IN light as
451 1.6 garbled * a blank (all 0x00) and the other lights, as 4 rows of horizontal
452 1.6 garbled * bars. The below code initializes the icons in the system to
453 1.6 garbled * sane values. Some of these icons could be used for any purpose
454 1.6 garbled * desired, namely the pcmcia, LAN and WAN lights. For the disk spinner,
455 1.6 garbled * only the backslash is unprogrammed. (sigh)
456 1.6 garbled *
457 1.6 garbled * programming the icons is simple. It is a 5x8 matrix, which each row a
458 1.6 garbled * bitfield in the order 0x10 0x08 0x04 0x02 0x01.
459 1.6 garbled */
460 1.6 garbled
461 1.6 garbled static void
462 1.6 garbled tctrl_init_lcd(void)
463 1.6 garbled {
464 1.6 garbled struct tctrl_req req;
465 1.6 garbled
466 1.6 garbled req.cmdbuf[0] = TS102_OP_BLK_DEF_SPCL_CHAR;
467 1.6 garbled req.cmdlen = 11;
468 1.6 garbled req.rsplen = 1;
469 1.6 garbled req.cmdbuf[1] = 0x08; /*len*/
470 1.6 garbled req.cmdbuf[2] = TS102_BLK_OFF_DEF_DC_GOOD;
471 1.6 garbled req.cmdbuf[3] = 0x00; /* ..... */
472 1.6 garbled req.cmdbuf[4] = 0x00; /* ..... */
473 1.6 garbled req.cmdbuf[5] = 0x1f; /* XXXXX */
474 1.6 garbled req.cmdbuf[6] = 0x00; /* ..... */
475 1.6 garbled req.cmdbuf[7] = 0x15; /* X.X.X */
476 1.6 garbled req.cmdbuf[8] = 0x00; /* ..... */
477 1.6 garbled req.cmdbuf[9] = 0x00; /* ..... */
478 1.6 garbled req.cmdbuf[10] = 0x00; /* ..... */
479 1.6 garbled req.p = NULL;
480 1.6 garbled tadpole_request(&req, 1);
481 1.6 garbled
482 1.6 garbled req.cmdbuf[0] = TS102_OP_BLK_DEF_SPCL_CHAR;
483 1.6 garbled req.cmdlen = 11;
484 1.6 garbled req.rsplen = 1;
485 1.6 garbled req.cmdbuf[1] = 0x08; /*len*/
486 1.6 garbled req.cmdbuf[2] = TS102_BLK_OFF_DEF_BACKSLASH;
487 1.6 garbled req.cmdbuf[3] = 0x00; /* ..... */
488 1.6 garbled req.cmdbuf[4] = 0x10; /* X.... */
489 1.6 garbled req.cmdbuf[5] = 0x08; /* .X... */
490 1.6 garbled req.cmdbuf[6] = 0x04; /* ..X.. */
491 1.6 garbled req.cmdbuf[7] = 0x02; /* ...X. */
492 1.6 garbled req.cmdbuf[8] = 0x01; /* ....X */
493 1.6 garbled req.cmdbuf[9] = 0x00; /* ..... */
494 1.6 garbled req.cmdbuf[10] = 0x00; /* ..... */
495 1.6 garbled req.p = NULL;
496 1.6 garbled tadpole_request(&req, 1);
497 1.6 garbled
498 1.6 garbled req.cmdbuf[0] = TS102_OP_BLK_DEF_SPCL_CHAR;
499 1.6 garbled req.cmdlen = 11;
500 1.6 garbled req.rsplen = 1;
501 1.6 garbled req.cmdbuf[1] = 0x08; /*len*/
502 1.6 garbled req.cmdbuf[2] = TS102_BLK_OFF_DEF_WAN1;
503 1.6 garbled req.cmdbuf[3] = 0x0c; /* .XXX. */
504 1.6 garbled req.cmdbuf[4] = 0x16; /* X.XX. */
505 1.6 garbled req.cmdbuf[5] = 0x10; /* X.... */
506 1.6 garbled req.cmdbuf[6] = 0x15; /* X.X.X */
507 1.6 garbled req.cmdbuf[7] = 0x10; /* X.... */
508 1.6 garbled req.cmdbuf[8] = 0x16; /* X.XX. */
509 1.6 garbled req.cmdbuf[9] = 0x0c; /* .XXX. */
510 1.6 garbled req.cmdbuf[10] = 0x00; /* ..... */
511 1.6 garbled req.p = NULL;
512 1.6 garbled tadpole_request(&req, 1);
513 1.6 garbled
514 1.6 garbled req.cmdbuf[0] = TS102_OP_BLK_DEF_SPCL_CHAR;
515 1.6 garbled req.cmdlen = 11;
516 1.6 garbled req.rsplen = 1;
517 1.6 garbled req.cmdbuf[1] = 0x08; /*len*/
518 1.6 garbled req.cmdbuf[2] = TS102_BLK_OFF_DEF_WAN2;
519 1.6 garbled req.cmdbuf[3] = 0x0c; /* .XXX. */
520 1.6 garbled req.cmdbuf[4] = 0x0d; /* .XX.X */
521 1.6 garbled req.cmdbuf[5] = 0x01; /* ....X */
522 1.6 garbled req.cmdbuf[6] = 0x15; /* X.X.X */
523 1.6 garbled req.cmdbuf[7] = 0x01; /* ....X */
524 1.6 garbled req.cmdbuf[8] = 0x0d; /* .XX.X */
525 1.6 garbled req.cmdbuf[9] = 0x0c; /* .XXX. */
526 1.6 garbled req.cmdbuf[10] = 0x00; /* ..... */
527 1.6 garbled req.p = NULL;
528 1.6 garbled tadpole_request(&req, 1);
529 1.6 garbled
530 1.6 garbled req.cmdbuf[0] = TS102_OP_BLK_DEF_SPCL_CHAR;
531 1.6 garbled req.cmdlen = 11;
532 1.6 garbled req.rsplen = 1;
533 1.6 garbled req.cmdbuf[1] = 0x08; /*len*/
534 1.6 garbled req.cmdbuf[2] = TS102_BLK_OFF_DEF_LAN1;
535 1.6 garbled req.cmdbuf[3] = 0x00; /* ..... */
536 1.6 garbled req.cmdbuf[4] = 0x04; /* ..X.. */
537 1.6 garbled req.cmdbuf[5] = 0x08; /* .X... */
538 1.6 garbled req.cmdbuf[6] = 0x13; /* X..XX */
539 1.6 garbled req.cmdbuf[7] = 0x08; /* .X... */
540 1.6 garbled req.cmdbuf[8] = 0x04; /* ..X.. */
541 1.6 garbled req.cmdbuf[9] = 0x00; /* ..... */
542 1.6 garbled req.cmdbuf[10] = 0x00; /* ..... */
543 1.6 garbled req.p = NULL;
544 1.6 garbled tadpole_request(&req, 1);
545 1.6 garbled
546 1.6 garbled req.cmdbuf[0] = TS102_OP_BLK_DEF_SPCL_CHAR;
547 1.6 garbled req.cmdlen = 11;
548 1.6 garbled req.rsplen = 1;
549 1.6 garbled req.cmdbuf[1] = 0x08; /*len*/
550 1.6 garbled req.cmdbuf[2] = TS102_BLK_OFF_DEF_LAN2;
551 1.6 garbled req.cmdbuf[3] = 0x00; /* ..... */
552 1.6 garbled req.cmdbuf[4] = 0x04; /* ..X.. */
553 1.6 garbled req.cmdbuf[5] = 0x02; /* ...X. */
554 1.6 garbled req.cmdbuf[6] = 0x19; /* XX..X */
555 1.6 garbled req.cmdbuf[7] = 0x02; /* ...X. */
556 1.6 garbled req.cmdbuf[8] = 0x04; /* ..X.. */
557 1.6 garbled req.cmdbuf[9] = 0x00; /* ..... */
558 1.6 garbled req.cmdbuf[10] = 0x00; /* ..... */
559 1.6 garbled req.p = NULL;
560 1.6 garbled tadpole_request(&req, 1);
561 1.6 garbled
562 1.6 garbled req.cmdbuf[0] = TS102_OP_BLK_DEF_SPCL_CHAR;
563 1.6 garbled req.cmdlen = 11;
564 1.6 garbled req.rsplen = 1;
565 1.6 garbled req.cmdbuf[1] = 0x08; /*len*/
566 1.6 garbled req.cmdbuf[2] = TS102_BLK_OFF_DEF_PCMCIA;
567 1.6 garbled req.cmdbuf[3] = 0x00; /* ..... */
568 1.6 garbled req.cmdbuf[4] = 0x0c; /* .XXX. */
569 1.6 garbled req.cmdbuf[5] = 0x1f; /* XXXXX */
570 1.6 garbled req.cmdbuf[6] = 0x1f; /* XXXXX */
571 1.6 garbled req.cmdbuf[7] = 0x1f; /* XXXXX */
572 1.6 garbled req.cmdbuf[8] = 0x1f; /* XXXXX */
573 1.6 garbled req.cmdbuf[9] = 0x00; /* ..... */
574 1.6 garbled req.cmdbuf[10] = 0x00; /* ..... */
575 1.6 garbled req.p = NULL;
576 1.6 garbled tadpole_request(&req, 1);
577 1.6 garbled }
578 1.6 garbled
579 1.6 garbled
580 1.6 garbled
581 1.6 garbled /*
582 1.6 garbled * set the blinken-lights on the lcd. what:
583 1.6 garbled * what = 0 off, what = 1 on, what = 2 toggle
584 1.6 garbled */
585 1.6 garbled
586 1.6 garbled void
587 1.24.2.6 christos tctrl_set_lcd(int what, unsigned short which)
588 1.6 garbled {
589 1.6 garbled struct tctrl_softc *sc;
590 1.6 garbled struct tctrl_req req;
591 1.6 garbled int s;
592 1.24.2.5 skrll
593 1.6 garbled sc = (struct tctrl_softc *) tctrl_cd.cd_devs[TCTRL_STD_DEV];
594 1.6 garbled s = splts102();
595 1.6 garbled
596 1.24.2.1 skrll /* provide a quick exit to save CPU time */
597 1.6 garbled if ((what == 1 && sc->sc_lcdstate & which) ||
598 1.6 garbled (what == 0 && !(sc->sc_lcdstate & which))) {
599 1.6 garbled splx(s);
600 1.6 garbled return;
601 1.6 garbled }
602 1.6 garbled /*
603 1.6 garbled * the mask setup on this particular command is *very* bizzare
604 1.6 garbled * and totally undocumented.
605 1.6 garbled */
606 1.6 garbled if ((what == 1) || (what == 2 && !(sc->sc_lcdstate & which))) {
607 1.24.2.6 christos req.cmdbuf[2] = (uint8_t)(which&0xff);
608 1.24.2.6 christos req.cmdbuf[3] = (uint8_t)((which&0x100)>>8);
609 1.24.2.5 skrll sc->sc_lcdstate|=which;
610 1.6 garbled } else {
611 1.6 garbled req.cmdbuf[2] = 0;
612 1.6 garbled req.cmdbuf[3] = 0;
613 1.24.2.5 skrll sc->sc_lcdstate&=(~which);
614 1.6 garbled }
615 1.6 garbled req.cmdbuf[0] = TS102_OP_CTL_LCD;
616 1.24.2.6 christos req.cmdbuf[1] = (uint8_t)((~which)&0xff);
617 1.24.2.6 christos req.cmdbuf[4] = (uint8_t)((~which>>8)&1);
618 1.24.2.6 christos
619 1.6 garbled
620 1.13 wiz /* XXX this thing is weird.... */
621 1.6 garbled req.cmdlen = 3;
622 1.6 garbled req.rsplen = 2;
623 1.24.2.6 christos
624 1.24.2.5 skrll /* below are the values one would expect but which won't work */
625 1.6 garbled #if 0
626 1.6 garbled req.cmdlen = 5;
627 1.6 garbled req.rsplen = 4;
628 1.6 garbled #endif
629 1.6 garbled req.p = NULL;
630 1.6 garbled tadpole_request(&req, 1);
631 1.24.2.5 skrll
632 1.6 garbled splx(s);
633 1.6 garbled }
634 1.6 garbled
635 1.4 garbled static void
636 1.4 garbled tctrl_read_ext_status(void)
637 1.4 garbled {
638 1.4 garbled struct tctrl_softc *sc;
639 1.4 garbled struct tctrl_req req;
640 1.4 garbled int s;
641 1.24.2.6 christos
642 1.4 garbled sc = (struct tctrl_softc *) tctrl_cd.cd_devs[TCTRL_STD_DEV];
643 1.4 garbled req.cmdbuf[0] = TS102_OP_RD_EXT_STATUS;
644 1.4 garbled req.cmdlen = 1;
645 1.4 garbled req.rsplen = 3;
646 1.4 garbled req.p = NULL;
647 1.4 garbled #ifdef TCTRLDEBUG
648 1.4 garbled printf("pre read: sc->sc_ext_status = 0x%x\n", sc->sc_ext_status);
649 1.4 garbled #endif
650 1.4 garbled tadpole_request(&req, 1);
651 1.4 garbled s = splts102();
652 1.4 garbled sc->sc_ext_status = req.rspbuf[0] * 256 + req.rspbuf[1];
653 1.4 garbled splx(s);
654 1.4 garbled #ifdef TCTRLDEBUG
655 1.4 garbled printf("post read: sc->sc_ext_status = 0x%x\n", sc->sc_ext_status);
656 1.4 garbled #endif
657 1.4 garbled }
658 1.4 garbled
659 1.4 garbled /*
660 1.4 garbled * return 0 if the user will notice and handle the event,
661 1.4 garbled * return 1 if the kernel driver should do so.
662 1.4 garbled */
663 1.4 garbled static int
664 1.24.2.6 christos tctrl_apm_record_event(struct tctrl_softc *sc, u_int event_type)
665 1.4 garbled {
666 1.4 garbled struct apm_event_info *evp;
667 1.4 garbled
668 1.4 garbled if ((sc->sc_flags & TCTRL_APM_CTLOPEN) &&
669 1.4 garbled (sc->sc_event_count < APM_NEVENTS)) {
670 1.4 garbled evp = &sc->sc_event_list[sc->sc_event_ptr];
671 1.4 garbled sc->sc_event_count++;
672 1.4 garbled sc->sc_event_ptr++;
673 1.4 garbled sc->sc_event_ptr %= APM_NEVENTS;
674 1.4 garbled evp->type = event_type;
675 1.4 garbled evp->index = ++tctrl_apm_evindex;
676 1.20 jdolecek selnotify(&sc->sc_rsel, 0);
677 1.4 garbled return(sc->sc_flags & TCTRL_APM_CTLOPEN) ? 0 : 1;
678 1.1 matt }
679 1.4 garbled return(1);
680 1.1 matt }
681 1.1 matt
682 1.1 matt static void
683 1.24.2.6 christos tctrl_read_event_status(void *arg)
684 1.1 matt {
685 1.4 garbled struct tctrl_softc *sc;
686 1.4 garbled struct tctrl_req req;
687 1.4 garbled int s;
688 1.4 garbled unsigned int v;
689 1.24.2.6 christos
690 1.4 garbled sc = (struct tctrl_softc *) tctrl_cd.cd_devs[TCTRL_STD_DEV];
691 1.4 garbled req.cmdbuf[0] = TS102_OP_RD_EVENT_STATUS;
692 1.4 garbled req.cmdlen = 1;
693 1.4 garbled req.rsplen = 3;
694 1.4 garbled req.p = NULL;
695 1.4 garbled tadpole_request(&req, 1);
696 1.4 garbled s = splts102();
697 1.4 garbled v = req.rspbuf[0] * 256 + req.rspbuf[1];
698 1.24.2.5 skrll #ifdef TCTRLDEBUG
699 1.24.2.5 skrll printf("event: %x\n",v);
700 1.24.2.5 skrll #endif
701 1.24.2.6 christos if (v & TS102_EVENT_STATUS_POWERON_BTN_PRESSED) {
702 1.24.2.5 skrll printf("%s: Power button pressed\n",sc->sc_dev.dv_xname);
703 1.24.2.5 skrll tctrl_powerfail(sc);
704 1.24.2.5 skrll }
705 1.4 garbled if (v & TS102_EVENT_STATUS_SHUTDOWN_REQUEST) {
706 1.4 garbled printf("%s: SHUTDOWN REQUEST!\n", sc->sc_dev.dv_xname);
707 1.4 garbled }
708 1.4 garbled if (v & TS102_EVENT_STATUS_VERY_LOW_POWER_WARNING) {
709 1.4 garbled /*printf("%s: VERY LOW POWER WARNING!\n", sc->sc_dev.dv_xname);*/
710 1.4 garbled /* according to a tadpole header, and observation */
711 1.4 garbled #ifdef TCTRLDEBUG
712 1.24.2.6 christos printf("%s: Battery charge level change\n",
713 1.24.2.5 skrll sc->sc_dev.dv_xname);
714 1.4 garbled #endif
715 1.1 matt }
716 1.4 garbled if (v & TS102_EVENT_STATUS_LOW_POWER_WARNING) {
717 1.4 garbled if (tctrl_apm_record_event(sc, APM_BATTERY_LOW))
718 1.1 matt printf("%s: LOW POWER WARNING!\n", sc->sc_dev.dv_xname);
719 1.4 garbled }
720 1.4 garbled if (v & TS102_EVENT_STATUS_DC_STATUS_CHANGE) {
721 1.4 garbled splx(s);
722 1.4 garbled tctrl_read_ext_status();
723 1.4 garbled s = splts102();
724 1.4 garbled if (tctrl_apm_record_event(sc, APM_POWER_CHANGE))
725 1.1 matt printf("%s: main power %s\n", sc->sc_dev.dv_xname,
726 1.4 garbled (sc->sc_ext_status &
727 1.4 garbled TS102_EXT_STATUS_MAIN_POWER_AVAILABLE) ?
728 1.4 garbled "restored" : "removed");
729 1.4 garbled }
730 1.4 garbled if (v & TS102_EVENT_STATUS_LID_STATUS_CHANGE) {
731 1.4 garbled splx(s);
732 1.4 garbled tctrl_read_ext_status();
733 1.4 garbled tctrl_setup_bitport();
734 1.4 garbled #ifdef TCTRLDEBUG
735 1.4 garbled printf("%s: lid %s\n", sc->sc_dev.dv_xname,
736 1.4 garbled (sc->sc_ext_status & TS102_EXT_STATUS_LID_DOWN)
737 1.4 garbled ? "closed" : "opened");
738 1.2 matt #endif
739 1.1 matt }
740 1.4 garbled splx(s);
741 1.1 matt }
742 1.1 matt
743 1.1 matt void
744 1.24.2.6 christos tadpole_request(struct tctrl_req *req, int spin)
745 1.1 matt {
746 1.1 matt struct tctrl_softc *sc;
747 1.1 matt int i, s;
748 1.1 matt
749 1.1 matt if (tctrl_cd.cd_devs == NULL
750 1.1 matt || tctrl_cd.cd_ndevs == 0
751 1.4 garbled || tctrl_cd.cd_devs[TCTRL_STD_DEV] == NULL) {
752 1.1 matt return;
753 1.1 matt }
754 1.1 matt
755 1.4 garbled sc = (struct tctrl_softc *) tctrl_cd.cd_devs[TCTRL_STD_DEV];
756 1.4 garbled while (sc->sc_wantdata != 0) {
757 1.4 garbled if (req->p != NULL)
758 1.4 garbled tsleep(&sc->sc_wantdata, PLOCK, "tctrl_lock", 10);
759 1.4 garbled else
760 1.4 garbled DELAY(1);
761 1.4 garbled }
762 1.4 garbled if (spin)
763 1.4 garbled s = splhigh();
764 1.4 garbled else
765 1.4 garbled s = splts102();
766 1.4 garbled sc->sc_flags |= TCTRL_SEND_REQUEST;
767 1.4 garbled memcpy(sc->sc_cmdbuf, req->cmdbuf, req->cmdlen);
768 1.4 garbled sc->sc_wantdata = 1;
769 1.4 garbled sc->sc_rsplen = req->rsplen;
770 1.4 garbled sc->sc_cmdlen = req->cmdlen;
771 1.4 garbled sc->sc_cmdoff = sc->sc_rspoff = 0;
772 1.4 garbled
773 1.4 garbled /* we spin for certain commands, like poweroffs */
774 1.4 garbled if (spin) {
775 1.6 garbled /* for (i = 0; i < 30000; i++) {*/
776 1.6 garbled while (sc->sc_wantdata == 1) {
777 1.4 garbled tctrl_intr(sc);
778 1.4 garbled DELAY(1);
779 1.4 garbled }
780 1.4 garbled } else {
781 1.1 matt tctrl_intr(sc);
782 1.5 garbled i = 0;
783 1.5 garbled while (((sc->sc_rspoff != sc->sc_rsplen) ||
784 1.5 garbled (sc->sc_cmdoff != sc->sc_cmdlen)) &&
785 1.5 garbled (i < (5 * sc->sc_rsplen + sc->sc_cmdlen)))
786 1.5 garbled if (req->p != NULL) {
787 1.5 garbled tsleep(sc, PWAIT, "tctrl_data", 15);
788 1.5 garbled i++;
789 1.5 garbled }
790 1.4 garbled else
791 1.4 garbled DELAY(1);
792 1.1 matt }
793 1.5 garbled /*
794 1.5 garbled * we give the user a reasonable amount of time for a command
795 1.5 garbled * to complete. If it doesn't complete in time, we hand them
796 1.5 garbled * garbage. This is here to stop things like setting the
797 1.5 garbled * rsplen too long, and sleeping forever in a CMD_REQ ioctl.
798 1.5 garbled */
799 1.5 garbled sc->sc_wantdata = 0;
800 1.4 garbled memcpy(req->rspbuf, sc->sc_rspbuf, req->rsplen);
801 1.1 matt splx(s);
802 1.1 matt }
803 1.1 matt
804 1.1 matt void
805 1.4 garbled tadpole_powerdown(void)
806 1.4 garbled {
807 1.4 garbled struct tctrl_req req;
808 1.24.2.6 christos
809 1.4 garbled req.cmdbuf[0] = TS102_OP_ADMIN_POWER_OFF;
810 1.4 garbled req.cmdlen = 1;
811 1.4 garbled req.rsplen = 1;
812 1.4 garbled req.p = NULL;
813 1.4 garbled tadpole_request(&req, 1);
814 1.4 garbled }
815 1.4 garbled
816 1.4 garbled void
817 1.24.2.6 christos tadpole_set_video(int enabled)
818 1.1 matt {
819 1.1 matt struct tctrl_softc *sc;
820 1.4 garbled struct tctrl_req req;
821 1.1 matt int s;
822 1.1 matt
823 1.4 garbled sc = (struct tctrl_softc *) tctrl_cd.cd_devs[TCTRL_STD_DEV];
824 1.4 garbled while (sc->sc_wantdata != 0)
825 1.4 garbled DELAY(1);
826 1.4 garbled s = splts102();
827 1.4 garbled req.p = NULL;
828 1.4 garbled if ((sc->sc_ext_status & TS102_EXT_STATUS_LID_DOWN && !enabled)
829 1.4 garbled || (sc->sc_tft_on)) {
830 1.4 garbled req.cmdbuf[2] = TS102_BITPORT_TFTPWR;
831 1.4 garbled } else {
832 1.4 garbled req.cmdbuf[2] = 0;
833 1.1 matt }
834 1.4 garbled req.cmdbuf[0] = TS102_OP_CTL_BITPORT;
835 1.4 garbled req.cmdbuf[1] = ~TS102_BITPORT_TFTPWR;
836 1.4 garbled req.cmdlen = 3;
837 1.4 garbled req.rsplen = 2;
838 1.1 matt
839 1.1 matt if ((sc->sc_tft_on && !enabled) || (!sc->sc_tft_on && enabled)) {
840 1.1 matt sc->sc_tft_on = enabled;
841 1.1 matt if (sc->sc_ext_status & TS102_EXT_STATUS_LID_DOWN) {
842 1.1 matt splx(s);
843 1.1 matt return;
844 1.1 matt }
845 1.4 garbled tadpole_request(&req, 1);
846 1.4 garbled sc->sc_bitport =
847 1.4 garbled (req.rspbuf[0] & req.cmdbuf[1]) ^ req.cmdbuf[2];
848 1.1 matt }
849 1.1 matt splx(s);
850 1.1 matt }
851 1.1 matt
852 1.1 matt static void
853 1.24.2.6 christos tctrl_write_data(struct tctrl_softc *sc, uint8_t v)
854 1.1 matt {
855 1.1 matt unsigned int i;
856 1.4 garbled
857 1.1 matt for (i = 0; i < 100; i++) {
858 1.24.2.6 christos if (TS102_UCTRL_STS_TXNF_STA &
859 1.24.2.5 skrll tctrl_read(sc, TS102_REG_UCTRL_STS))
860 1.1 matt break;
861 1.1 matt }
862 1.1 matt tctrl_write(sc, TS102_REG_UCTRL_DATA, v);
863 1.1 matt }
864 1.1 matt
865 1.24.2.6 christos static uint8_t
866 1.24.2.6 christos tctrl_read_data(struct tctrl_softc *sc)
867 1.4 garbled {
868 1.1 matt unsigned int i, v;
869 1.1 matt
870 1.1 matt for (i = 0; i < 100000; i++) {
871 1.24.2.6 christos if (TS102_UCTRL_STS_RXNE_STA &
872 1.24.2.5 skrll tctrl_read(sc, TS102_REG_UCTRL_STS))
873 1.1 matt break;
874 1.1 matt DELAY(1);
875 1.1 matt }
876 1.1 matt
877 1.1 matt v = tctrl_read(sc, TS102_REG_UCTRL_DATA);
878 1.2 matt tctrl_write(sc, TS102_REG_UCTRL_STS, TS102_UCTRL_STS_RXNE_STA);
879 1.1 matt return v;
880 1.1 matt }
881 1.1 matt
882 1.24.2.6 christos static uint8_t
883 1.24.2.6 christos tctrl_read(struct tctrl_softc *sc, bus_size_t off)
884 1.1 matt {
885 1.4 garbled
886 1.2 matt sc->sc_junk = bus_space_read_1(sc->sc_memt, sc->sc_memh, off);
887 1.1 matt return sc->sc_junk;
888 1.1 matt }
889 1.1 matt
890 1.1 matt static void
891 1.24.2.6 christos tctrl_write(struct tctrl_softc *sc, bus_size_t off, uint8_t v)
892 1.1 matt {
893 1.4 garbled
894 1.1 matt sc->sc_junk = v;
895 1.2 matt bus_space_write_1(sc->sc_memt, sc->sc_memh, off, v);
896 1.4 garbled }
897 1.4 garbled
898 1.4 garbled int
899 1.24.2.6 christos tctrlopen(dev_t dev, int flags, int mode, struct lwp *l)
900 1.4 garbled {
901 1.4 garbled int unit = (minor(dev)&0xf0);
902 1.4 garbled int ctl = (minor(dev)&0x0f);
903 1.4 garbled struct tctrl_softc *sc;
904 1.4 garbled
905 1.4 garbled if (unit >= tctrl_cd.cd_ndevs)
906 1.4 garbled return(ENXIO);
907 1.4 garbled sc = tctrl_cd.cd_devs[TCTRL_STD_DEV];
908 1.4 garbled if (!sc)
909 1.4 garbled return(ENXIO);
910 1.24.2.6 christos
911 1.4 garbled switch (ctl) {
912 1.4 garbled case TCTRL_STD_DEV:
913 1.4 garbled break;
914 1.4 garbled case TCTRL_APMCTL_DEV:
915 1.4 garbled if (!(flags & FWRITE))
916 1.4 garbled return(EINVAL);
917 1.4 garbled if (sc->sc_flags & TCTRL_APM_CTLOPEN)
918 1.4 garbled return(EBUSY);
919 1.4 garbled sc->sc_flags |= TCTRL_APM_CTLOPEN;
920 1.4 garbled break;
921 1.4 garbled default:
922 1.4 garbled return(ENXIO);
923 1.4 garbled break;
924 1.4 garbled }
925 1.4 garbled
926 1.4 garbled return(0);
927 1.4 garbled }
928 1.4 garbled
929 1.4 garbled int
930 1.24.2.6 christos tctrlclose(dev_t dev, int flags, int mode, struct lwp *l)
931 1.4 garbled {
932 1.4 garbled int ctl = (minor(dev)&0x0f);
933 1.4 garbled struct tctrl_softc *sc;
934 1.4 garbled
935 1.4 garbled sc = tctrl_cd.cd_devs[TCTRL_STD_DEV];
936 1.4 garbled if (!sc)
937 1.4 garbled return(ENXIO);
938 1.4 garbled
939 1.4 garbled switch (ctl) {
940 1.4 garbled case TCTRL_STD_DEV:
941 1.4 garbled break;
942 1.4 garbled case TCTRL_APMCTL_DEV:
943 1.4 garbled sc->sc_flags &= ~TCTRL_APM_CTLOPEN;
944 1.4 garbled break;
945 1.4 garbled }
946 1.4 garbled return(0);
947 1.4 garbled }
948 1.4 garbled
949 1.4 garbled int
950 1.24.2.6 christos tctrlioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct lwp *l)
951 1.4 garbled {
952 1.4 garbled struct tctrl_req req, *reqn;
953 1.24.2.6 christos struct tctrl_pwr *pwrreq;
954 1.4 garbled struct apm_power_info *powerp;
955 1.4 garbled struct apm_event_info *evp;
956 1.4 garbled struct tctrl_softc *sc;
957 1.4 garbled int i;
958 1.24.2.5 skrll /*u_int j;*/
959 1.24.2.6 christos uint16_t a;
960 1.24.2.6 christos uint8_t c;
961 1.4 garbled
962 1.4 garbled if (tctrl_cd.cd_devs == NULL
963 1.4 garbled || tctrl_cd.cd_ndevs == 0
964 1.4 garbled || tctrl_cd.cd_devs[TCTRL_STD_DEV] == NULL) {
965 1.4 garbled return ENXIO;
966 1.4 garbled }
967 1.4 garbled sc = (struct tctrl_softc *) tctrl_cd.cd_devs[TCTRL_STD_DEV];
968 1.4 garbled switch (cmd) {
969 1.4 garbled
970 1.4 garbled case APM_IOC_STANDBY:
971 1.4 garbled return(EOPNOTSUPP); /* for now */
972 1.4 garbled
973 1.4 garbled case APM_IOC_SUSPEND:
974 1.4 garbled return(EOPNOTSUPP); /* for now */
975 1.4 garbled
976 1.19 takemura case OAPM_IOC_GETPOWER:
977 1.4 garbled case APM_IOC_GETPOWER:
978 1.4 garbled powerp = (struct apm_power_info *)data;
979 1.4 garbled req.cmdbuf[0] = TS102_OP_RD_INT_CHARGE_RATE;
980 1.4 garbled req.cmdlen = 1;
981 1.4 garbled req.rsplen = 2;
982 1.24.2.4 skrll req.p = l->l_proc;
983 1.4 garbled tadpole_request(&req, 0);
984 1.4 garbled if (req.rspbuf[0] > 0x00)
985 1.4 garbled powerp->battery_state = APM_BATT_CHARGING;
986 1.4 garbled req.cmdbuf[0] = TS102_OP_RD_INT_CHARGE_LEVEL;
987 1.4 garbled req.cmdlen = 1;
988 1.4 garbled req.rsplen = 3;
989 1.24.2.4 skrll req.p = l->l_proc;
990 1.4 garbled tadpole_request(&req, 0);
991 1.4 garbled c = req.rspbuf[0];
992 1.4 garbled powerp->battery_life = c;
993 1.6 garbled if (c > 0x70) /* the tadpole sometimes dips below zero, and */
994 1.6 garbled c = 0; /* into the 255 range. */
995 1.4 garbled powerp->minutes_left = (45 * c) / 100; /* XXX based on 45 min */
996 1.4 garbled if (powerp->battery_state != APM_BATT_CHARGING) {
997 1.4 garbled if (c < 0x20)
998 1.4 garbled powerp->battery_state = APM_BATT_CRITICAL;
999 1.4 garbled else if (c < 0x40)
1000 1.4 garbled powerp->battery_state = APM_BATT_LOW;
1001 1.4 garbled else if (c < 0x66)
1002 1.4 garbled powerp->battery_state = APM_BATT_HIGH;
1003 1.4 garbled else
1004 1.4 garbled powerp->battery_state = APM_BATT_UNKNOWN;
1005 1.4 garbled }
1006 1.4 garbled req.cmdbuf[0] = TS102_OP_RD_EXT_STATUS;
1007 1.4 garbled req.cmdlen = 1;
1008 1.4 garbled req.rsplen = 3;
1009 1.24.2.4 skrll req.p = l->l_proc;
1010 1.4 garbled tadpole_request(&req, 0);
1011 1.4 garbled a = req.rspbuf[0] * 256 + req.rspbuf[1];
1012 1.4 garbled if (a & TS102_EXT_STATUS_MAIN_POWER_AVAILABLE)
1013 1.4 garbled powerp->ac_state = APM_AC_ON;
1014 1.4 garbled else
1015 1.4 garbled powerp->ac_state = APM_AC_OFF;
1016 1.4 garbled break;
1017 1.4 garbled
1018 1.4 garbled case APM_IOC_NEXTEVENT:
1019 1.4 garbled if (!sc->sc_event_count)
1020 1.4 garbled return EAGAIN;
1021 1.4 garbled
1022 1.4 garbled evp = (struct apm_event_info *)data;
1023 1.4 garbled i = sc->sc_event_ptr + APM_NEVENTS - sc->sc_event_count;
1024 1.4 garbled i %= APM_NEVENTS;
1025 1.4 garbled *evp = sc->sc_event_list[i];
1026 1.4 garbled sc->sc_event_count--;
1027 1.4 garbled return(0);
1028 1.4 garbled
1029 1.4 garbled /* this ioctl assumes the caller knows exactly what he is doing */
1030 1.4 garbled case TCTRL_CMD_REQ:
1031 1.4 garbled reqn = (struct tctrl_req *)data;
1032 1.24.2.4 skrll if ((i = suser(l->l_proc->p_ucred, &l->l_proc->p_acflag)) != 0 &&
1033 1.4 garbled (reqn->cmdbuf[0] == TS102_OP_CTL_BITPORT ||
1034 1.4 garbled (reqn->cmdbuf[0] >= TS102_OP_CTL_WATCHDOG &&
1035 1.4 garbled reqn->cmdbuf[0] <= TS102_OP_CTL_SECURITY_KEY) ||
1036 1.4 garbled reqn->cmdbuf[0] == TS102_OP_CTL_TIMEZONE ||
1037 1.4 garbled reqn->cmdbuf[0] == TS102_OP_CTL_DIAGNOSTIC_MODE ||
1038 1.4 garbled reqn->cmdbuf[0] == TS102_OP_CMD_SOFTWARE_RESET ||
1039 1.4 garbled (reqn->cmdbuf[0] >= TS102_OP_CMD_SET_RTC &&
1040 1.4 garbled reqn->cmdbuf[0] < TS102_OP_RD_INT_CHARGE_LEVEL) ||
1041 1.4 garbled reqn->cmdbuf[0] > TS102_OP_RD_EXT_CHARGE_LEVEL))
1042 1.4 garbled return(i);
1043 1.24.2.4 skrll reqn->p = l->l_proc;
1044 1.4 garbled tadpole_request(reqn, 0);
1045 1.4 garbled break;
1046 1.7 jdc /* serial power mode (via auxiotwo) */
1047 1.7 jdc case TCTRL_SERIAL_PWR:
1048 1.24.2.6 christos pwrreq = (struct tctrl_pwr *)data;
1049 1.7 jdc if (pwrreq->rw)
1050 1.7 jdc pwrreq->state = auxiotwoserialgetapm();
1051 1.7 jdc else
1052 1.7 jdc auxiotwoserialsetapm(pwrreq->state);
1053 1.7 jdc break;
1054 1.7 jdc
1055 1.7 jdc /* modem power mode (via auxio) */
1056 1.7 jdc case TCTRL_MODEM_PWR:
1057 1.7 jdc return(EOPNOTSUPP); /* for now */
1058 1.7 jdc break;
1059 1.4 garbled
1060 1.4 garbled
1061 1.4 garbled default:
1062 1.4 garbled return (ENOTTY);
1063 1.4 garbled }
1064 1.4 garbled return (0);
1065 1.4 garbled }
1066 1.4 garbled
1067 1.4 garbled int
1068 1.24.2.6 christos tctrlpoll(dev_t dev, int events, struct lwp *l)
1069 1.4 garbled {
1070 1.4 garbled struct tctrl_softc *sc = tctrl_cd.cd_devs[TCTRL_STD_DEV];
1071 1.4 garbled int revents = 0;
1072 1.4 garbled
1073 1.4 garbled if (events & (POLLIN | POLLRDNORM)) {
1074 1.4 garbled if (sc->sc_event_count)
1075 1.4 garbled revents |= events & (POLLIN | POLLRDNORM);
1076 1.4 garbled else
1077 1.24.2.4 skrll selrecord(l, &sc->sc_rsel);
1078 1.4 garbled }
1079 1.4 garbled
1080 1.4 garbled return (revents);
1081 1.1 matt }
1082 1.20 jdolecek
1083 1.20 jdolecek static void
1084 1.20 jdolecek filt_tctrlrdetach(struct knote *kn)
1085 1.20 jdolecek {
1086 1.20 jdolecek struct tctrl_softc *sc = kn->kn_hook;
1087 1.20 jdolecek int s;
1088 1.20 jdolecek
1089 1.20 jdolecek s = splts102();
1090 1.21 christos SLIST_REMOVE(&sc->sc_rsel.sel_klist, kn, knote, kn_selnext);
1091 1.20 jdolecek splx(s);
1092 1.20 jdolecek }
1093 1.20 jdolecek
1094 1.20 jdolecek static int
1095 1.20 jdolecek filt_tctrlread(struct knote *kn, long hint)
1096 1.20 jdolecek {
1097 1.20 jdolecek struct tctrl_softc *sc = kn->kn_hook;
1098 1.20 jdolecek
1099 1.20 jdolecek kn->kn_data = sc->sc_event_count;
1100 1.20 jdolecek return (kn->kn_data > 0);
1101 1.20 jdolecek }
1102 1.20 jdolecek
1103 1.20 jdolecek static const struct filterops tctrlread_filtops =
1104 1.20 jdolecek { 1, NULL, filt_tctrlrdetach, filt_tctrlread };
1105 1.20 jdolecek
1106 1.20 jdolecek int
1107 1.20 jdolecek tctrlkqfilter(dev_t dev, struct knote *kn)
1108 1.20 jdolecek {
1109 1.20 jdolecek struct tctrl_softc *sc = tctrl_cd.cd_devs[TCTRL_STD_DEV];
1110 1.20 jdolecek struct klist *klist;
1111 1.20 jdolecek int s;
1112 1.20 jdolecek
1113 1.20 jdolecek switch (kn->kn_filter) {
1114 1.20 jdolecek case EVFILT_READ:
1115 1.21 christos klist = &sc->sc_rsel.sel_klist;
1116 1.20 jdolecek kn->kn_fop = &tctrlread_filtops;
1117 1.20 jdolecek break;
1118 1.20 jdolecek
1119 1.20 jdolecek default:
1120 1.20 jdolecek return (1);
1121 1.20 jdolecek }
1122 1.20 jdolecek
1123 1.20 jdolecek kn->kn_hook = sc;
1124 1.20 jdolecek
1125 1.20 jdolecek s = splts102();
1126 1.20 jdolecek SLIST_INSERT_HEAD(klist, kn, kn_selnext);
1127 1.20 jdolecek splx(s);
1128 1.20 jdolecek
1129 1.20 jdolecek return (0);
1130 1.20 jdolecek }
1131 1.20 jdolecek
1132 1.6 garbled /* DO NOT SET THIS OPTION */
1133 1.6 garbled #ifdef TADPOLE_BLINK
1134 1.6 garbled void
1135 1.24.2.6 christos cpu_disk_unbusy(int busy)
1136 1.6 garbled {
1137 1.6 garbled static struct timeval tctrl_ds_timestamp;
1138 1.6 garbled struct timeval dv_time, diff_time;
1139 1.6 garbled struct tctrl_softc *sc;
1140 1.6 garbled
1141 1.6 garbled sc = (struct tctrl_softc *) tctrl_cd.cd_devs[TCTRL_STD_DEV];
1142 1.6 garbled
1143 1.6 garbled /* quickly bail */
1144 1.6 garbled if (!(sc->sc_lcdstate & TS102_LCD_DISK_ACTIVE) || busy > 0)
1145 1.6 garbled return;
1146 1.6 garbled
1147 1.6 garbled /* we aren't terribly concerned with precision here */
1148 1.6 garbled dv_time = mono_time;
1149 1.6 garbled timersub(&dv_time, &tctrl_ds_timestamp, &diff_time);
1150 1.6 garbled
1151 1.6 garbled if (diff_time.tv_sec > 0) {
1152 1.6 garbled tctrl_set_lcd(0, TS102_LCD_DISK_ACTIVE);
1153 1.6 garbled tctrl_ds_timestamp = mono_time;
1154 1.6 garbled }
1155 1.6 garbled }
1156 1.6 garbled #endif
1157 1.24.2.5 skrll
1158 1.24.2.5 skrll static void
1159 1.24.2.5 skrll tctrl_sensor_setup(struct tctrl_softc *sc)
1160 1.24.2.5 skrll {
1161 1.24.2.5 skrll int error;
1162 1.24.2.6 christos
1163 1.24.2.5 skrll /* case temperature */
1164 1.24.2.5 skrll strcpy(sc->sc_binfo[0].desc, "Case temperature");
1165 1.24.2.5 skrll sc->sc_binfo[0].sensor = 0;
1166 1.24.2.5 skrll sc->sc_binfo[0].units = ENVSYS_STEMP;
1167 1.24.2.5 skrll sc->sc_binfo[0].validflags = ENVSYS_FVALID | ENVSYS_FCURVALID;
1168 1.24.2.5 skrll sc->sc_range[0].low = 0;
1169 1.24.2.5 skrll sc->sc_range[0].high = 0;
1170 1.24.2.5 skrll sc->sc_range[0].units = ENVSYS_STEMP;
1171 1.24.2.5 skrll sc->sc_tre[0].sensor = 0;
1172 1.24.2.5 skrll sc->sc_tre[0].warnflags = ENVSYS_WARN_OK;
1173 1.24.2.5 skrll sc->sc_tre[0].validflags = ENVSYS_FVALID | ENVSYS_FCURVALID;
1174 1.24.2.5 skrll sc->sc_tre[0].units = ENVSYS_STEMP;
1175 1.24.2.6 christos
1176 1.24.2.5 skrll /* battery voltage */
1177 1.24.2.5 skrll strcpy(sc->sc_binfo[1].desc, "Internal battery voltage");
1178 1.24.2.5 skrll sc->sc_binfo[1].sensor = 1;
1179 1.24.2.5 skrll sc->sc_binfo[1].units = ENVSYS_SVOLTS_DC;
1180 1.24.2.5 skrll sc->sc_binfo[1].validflags = ENVSYS_FVALID | ENVSYS_FCURVALID;
1181 1.24.2.5 skrll sc->sc_range[1].low = 0;
1182 1.24.2.5 skrll sc->sc_range[1].high = 0;
1183 1.24.2.5 skrll sc->sc_range[1].units = ENVSYS_SVOLTS_DC;
1184 1.24.2.5 skrll sc->sc_tre[1].sensor = 0;
1185 1.24.2.5 skrll sc->sc_tre[1].warnflags = ENVSYS_WARN_OK;
1186 1.24.2.5 skrll sc->sc_tre[1].validflags = ENVSYS_FVALID | ENVSYS_FCURVALID;
1187 1.24.2.5 skrll sc->sc_tre[1].units = ENVSYS_SVOLTS_DC;
1188 1.24.2.6 christos
1189 1.24.2.5 skrll /* DC voltage */
1190 1.24.2.5 skrll strcpy(sc->sc_binfo[2].desc, "DC-In voltage");
1191 1.24.2.5 skrll sc->sc_binfo[2].sensor = 2;
1192 1.24.2.5 skrll sc->sc_binfo[2].units = ENVSYS_SVOLTS_DC;
1193 1.24.2.5 skrll sc->sc_binfo[2].validflags = ENVSYS_FVALID | ENVSYS_FCURVALID;
1194 1.24.2.5 skrll sc->sc_range[2].low = 0;
1195 1.24.2.5 skrll sc->sc_range[2].high = 0;
1196 1.24.2.5 skrll sc->sc_range[2].units = ENVSYS_SVOLTS_DC;
1197 1.24.2.5 skrll sc->sc_tre[2].sensor = 0;
1198 1.24.2.5 skrll sc->sc_tre[2].warnflags = ENVSYS_WARN_OK;
1199 1.24.2.5 skrll sc->sc_tre[2].validflags = ENVSYS_FVALID | ENVSYS_FCURVALID;
1200 1.24.2.5 skrll sc->sc_tre[2].units = ENVSYS_SVOLTS_DC;
1201 1.24.2.6 christos
1202 1.24.2.5 skrll sc->sc_sme.sme_nsensors = ENVSYS_NUMSENSORS;
1203 1.24.2.5 skrll sc->sc_sme.sme_envsys_version = 1000;
1204 1.24.2.5 skrll sc->sc_sme.sme_ranges = sc->sc_range;
1205 1.24.2.5 skrll sc->sc_sme.sme_sensor_info = sc->sc_binfo;
1206 1.24.2.5 skrll sc->sc_sme.sme_sensor_data = sc->sc_tre;
1207 1.24.2.5 skrll sc->sc_sme.sme_cookie = sc;
1208 1.24.2.5 skrll sc->sc_sme.sme_gtredata = tctrl_gtredata;
1209 1.24.2.5 skrll sc->sc_sme.sme_streinfo = tctrl_streinfo;
1210 1.24.2.5 skrll sc->sc_sme.sme_flags = 0;
1211 1.24.2.6 christos
1212 1.24.2.5 skrll if ((error = sysmon_envsys_register(&sc->sc_sme)) != 0) {
1213 1.24.2.6 christos printf("%s: couldn't register sensors (%d)\n",
1214 1.24.2.5 skrll sc->sc_dev.dv_xname, error);
1215 1.24.2.5 skrll }
1216 1.24.2.6 christos
1217 1.24.2.5 skrll /* now register the power button */
1218 1.24.2.6 christos
1219 1.24.2.5 skrll sysmon_task_queue_init();
1220 1.24.2.5 skrll
1221 1.24.2.5 skrll sc->sc_powerpressed = 0;
1222 1.24.2.5 skrll memset(&sc->sc_smcontext, 0, sizeof(struct sysmon_pswitch));
1223 1.24.2.5 skrll sc->sc_smcontext.smpsw_name = sc->sc_dev.dv_xname;
1224 1.24.2.5 skrll sc->sc_smcontext.smpsw_type = PSWITCH_TYPE_POWER;
1225 1.24.2.5 skrll if (sysmon_pswitch_register(&sc->sc_smcontext) != 0)
1226 1.24.2.6 christos printf("%s: unable to register power button with sysmon\n",
1227 1.24.2.5 skrll sc->sc_dev.dv_xname);
1228 1.24.2.5 skrll }
1229 1.24.2.5 skrll
1230 1.24.2.5 skrll static void
1231 1.24.2.5 skrll tctrl_power_button_pressed(void *arg)
1232 1.24.2.5 skrll {
1233 1.24.2.5 skrll struct tctrl_softc *sc = arg;
1234 1.24.2.5 skrll
1235 1.24.2.5 skrll sysmon_pswitch_event(&sc->sc_smcontext, PSWITCH_EVENT_PRESSED);
1236 1.24.2.5 skrll sc->sc_powerpressed = 0;
1237 1.24.2.5 skrll }
1238 1.24.2.5 skrll
1239 1.24.2.6 christos static int
1240 1.24.2.5 skrll tctrl_powerfail(void *arg)
1241 1.24.2.5 skrll {
1242 1.24.2.5 skrll struct tctrl_softc *sc = (struct tctrl_softc *)arg;
1243 1.24.2.5 skrll
1244 1.24.2.5 skrll /*
1245 1.24.2.5 skrll * We lost power. Queue a callback with thread context to
1246 1.24.2.5 skrll * handle all the real work.
1247 1.24.2.5 skrll */
1248 1.24.2.5 skrll if (sc->sc_powerpressed == 0) {
1249 1.24.2.5 skrll sc->sc_powerpressed = 1;
1250 1.24.2.5 skrll sysmon_task_queue_sched(0, tctrl_power_button_pressed, sc);
1251 1.24.2.5 skrll }
1252 1.24.2.5 skrll return (1);
1253 1.24.2.5 skrll }
1254 1.24.2.5 skrll
1255 1.24.2.5 skrll static int
1256 1.24.2.5 skrll tctrl_gtredata(struct sysmon_envsys *sme, struct envsys_tre_data *tred)
1257 1.24.2.5 skrll {
1258 1.24.2.5 skrll /*struct tctrl_softc *sc = sme->sme_cookie;*/
1259 1.24.2.5 skrll struct envsys_tre_data *cur_tre;
1260 1.24.2.5 skrll struct envsys_basic_info *cur_i;
1261 1.24.2.5 skrll struct tctrl_req req;
1262 1.24.2.5 skrll struct proc *p;
1263 1.24.2.5 skrll int i;
1264 1.24.2.6 christos
1265 1.24.2.5 skrll i = tred->sensor;
1266 1.24.2.5 skrll cur_tre = &sme->sme_sensor_data[i];
1267 1.24.2.5 skrll cur_i = &sme->sme_sensor_info[i];
1268 1.24.2.5 skrll p = __curproc();
1269 1.24.2.6 christos
1270 1.24.2.5 skrll switch (i)
1271 1.24.2.5 skrll {
1272 1.24.2.5 skrll case 0: /* case temperature */
1273 1.24.2.5 skrll req.cmdbuf[0] = TS102_OP_RD_CURRENT_TEMP;
1274 1.24.2.5 skrll req.cmdlen = 1;
1275 1.24.2.5 skrll req.rsplen = 2;
1276 1.24.2.5 skrll req.p = p;
1277 1.24.2.5 skrll tadpole_request(&req, 0);
1278 1.24.2.5 skrll cur_tre->cur.data_us = /* 273160? */
1279 1.24.2.6 christos (uint32_t)((int)((int)req.rspbuf[0] - 32) * 5000000
1280 1.24.2.5 skrll / 9 + 273150000);
1281 1.24.2.5 skrll cur_tre->validflags |= ENVSYS_FCURVALID;
1282 1.24.2.5 skrll req.cmdbuf[0] = TS102_OP_RD_MAX_TEMP;
1283 1.24.2.5 skrll req.cmdlen = 1;
1284 1.24.2.5 skrll req.rsplen = 2;
1285 1.24.2.5 skrll req.p = p;
1286 1.24.2.5 skrll tadpole_request(&req, 0);
1287 1.24.2.5 skrll cur_tre->max.data_us =
1288 1.24.2.6 christos (uint32_t)((int)((int)req.rspbuf[0] - 32) * 5000000
1289 1.24.2.5 skrll / 9 + 273150000);
1290 1.24.2.5 skrll cur_tre->validflags |= ENVSYS_FMAXVALID;
1291 1.24.2.5 skrll req.cmdbuf[0] = TS102_OP_RD_MIN_TEMP;
1292 1.24.2.5 skrll req.cmdlen = 1;
1293 1.24.2.5 skrll req.rsplen = 2;
1294 1.24.2.5 skrll req.p = p;
1295 1.24.2.5 skrll tadpole_request(&req, 0);
1296 1.24.2.5 skrll cur_tre->min.data_us =
1297 1.24.2.6 christos (uint32_t)((int)((int)req.rspbuf[0] - 32) * 5000000
1298 1.24.2.5 skrll / 9 + 273150000);
1299 1.24.2.5 skrll cur_tre->validflags |= ENVSYS_FMINVALID;
1300 1.24.2.5 skrll cur_tre->units = ENVSYS_STEMP;
1301 1.24.2.5 skrll break;
1302 1.24.2.6 christos
1303 1.24.2.5 skrll case 1: /* battery voltage */
1304 1.24.2.5 skrll {
1305 1.24.2.6 christos cur_tre->validflags =
1306 1.24.2.5 skrll ENVSYS_FVALID|ENVSYS_FCURVALID;
1307 1.24.2.5 skrll cur_tre->units = ENVSYS_SVOLTS_DC;
1308 1.24.2.5 skrll req.cmdbuf[0] = TS102_OP_RD_INT_BATT_VLT;
1309 1.24.2.5 skrll req.cmdlen = 1;
1310 1.24.2.5 skrll req.rsplen = 2;
1311 1.24.2.5 skrll req.p = p;
1312 1.24.2.5 skrll tadpole_request(&req, 0);
1313 1.24.2.6 christos cur_tre->cur.data_s = (int32_t)req.rspbuf[0] *
1314 1.24.2.5 skrll 1000000 / 11;
1315 1.24.2.5 skrll }
1316 1.24.2.5 skrll break;
1317 1.24.2.5 skrll case 2: /* DC voltage */
1318 1.24.2.5 skrll {
1319 1.24.2.6 christos cur_tre->validflags =
1320 1.24.2.5 skrll ENVSYS_FVALID|ENVSYS_FCURVALID;
1321 1.24.2.5 skrll cur_tre->units = ENVSYS_SVOLTS_DC;
1322 1.24.2.5 skrll req.cmdbuf[0] = TS102_OP_RD_DC_IN_VLT;
1323 1.24.2.5 skrll req.cmdlen = 1;
1324 1.24.2.5 skrll req.rsplen = 2;
1325 1.24.2.5 skrll req.p = p;
1326 1.24.2.5 skrll tadpole_request(&req, 0);
1327 1.24.2.6 christos cur_tre->cur.data_s = (int32_t)req.rspbuf[0] *
1328 1.24.2.5 skrll 1000000 / 11;
1329 1.24.2.5 skrll }
1330 1.24.2.5 skrll break;
1331 1.24.2.5 skrll }
1332 1.24.2.5 skrll cur_tre->validflags |= ENVSYS_FVALID;
1333 1.24.2.5 skrll *tred = sme->sme_sensor_data[i];
1334 1.24.2.5 skrll return 0;
1335 1.24.2.5 skrll }
1336 1.24.2.5 skrll
1337 1.24.2.5 skrll
1338 1.24.2.5 skrll static int
1339 1.24.2.5 skrll tctrl_streinfo(struct sysmon_envsys *sme, struct envsys_basic_info *binfo)
1340 1.24.2.5 skrll {
1341 1.24.2.6 christos
1342 1.24.2.5 skrll /* There is nothing to set here. */
1343 1.24.2.5 skrll return (EINVAL);
1344 1.24.2.5 skrll }
1345