tctrl.c revision 1.2.8.1 1 1.2.8.1 wrstuden /* $NetBSD: tctrl.c,v 1.2.8.1 1999/12/27 18:33:47 wrstuden 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.1 matt #include <sys/param.h>
40 1.1 matt #include <sys/systm.h>
41 1.1 matt #include <sys/ioctl.h>
42 1.1 matt #include <sys/select.h>
43 1.1 matt #include <sys/tty.h>
44 1.1 matt #include <sys/proc.h>
45 1.1 matt #include <sys/user.h>
46 1.1 matt #include <sys/conf.h>
47 1.1 matt #include <sys/file.h>
48 1.1 matt #include <sys/uio.h>
49 1.1 matt #include <sys/kernel.h>
50 1.1 matt #include <sys/syslog.h>
51 1.1 matt #include <sys/types.h>
52 1.1 matt #include <sys/device.h>
53 1.2.8.1 wrstuden #include <sys/envsys.h>
54 1.2.8.1 wrstuden #include <sys/poll.h>
55 1.1 matt
56 1.2.8.1 wrstuden #include <machine/apmvar.h>
57 1.1 matt #include <machine/autoconf.h>
58 1.1 matt #include <machine/cpu.h>
59 1.1 matt #include <machine/bus.h>
60 1.2.8.1 wrstuden #include <machine/tctrl.h>
61 1.1 matt
62 1.1 matt #include <sparc/dev/ts102reg.h>
63 1.1 matt #include <sparc/dev/tctrlvar.h>
64 1.1 matt
65 1.2.8.1 wrstuden cdev_decl(tctrl);
66 1.2.8.1 wrstuden
67 1.2.8.1 wrstuden extern struct cfdriver tctrl_cd;
68 1.2.8.1 wrstuden
69 1.1 matt static const char *tctrl_ext_statuses[16] = {
70 1.1 matt "main power available",
71 1.1 matt "internal battery attached",
72 1.1 matt "external battery attached",
73 1.1 matt "external VGA attached",
74 1.1 matt "external keyboard attached",
75 1.1 matt "external mouse attached",
76 1.1 matt "lid down",
77 1.1 matt "internal battery charging",
78 1.1 matt "external battery charging",
79 1.1 matt "internal battery discharging",
80 1.1 matt "external battery discharging",
81 1.1 matt };
82 1.1 matt
83 1.1 matt struct tctrl_softc {
84 1.2.8.1 wrstuden struct device sc_dev;
85 1.2.8.1 wrstuden bus_space_tag_t sc_memt;
86 1.2.8.1 wrstuden bus_space_handle_t sc_memh;
87 1.2.8.1 wrstuden unsigned int sc_junk;
88 1.2.8.1 wrstuden unsigned int sc_ext_status;
89 1.2.8.1 wrstuden unsigned int sc_flags;
90 1.2.8.1 wrstuden #define TCTRL_SEND_REQUEST 0x0001
91 1.2.8.1 wrstuden #define TCTRL_APM_CTLOPEN 0x0002
92 1.2.8.1 wrstuden unsigned int sc_wantdata;
93 1.1 matt enum { TCTRL_IDLE, TCTRL_ARGS,
94 1.1 matt TCTRL_ACK, TCTRL_DATA } sc_state;
95 1.2.8.1 wrstuden u_int8_t sc_cmdbuf[16];
96 1.2.8.1 wrstuden u_int8_t sc_rspbuf[16];
97 1.2.8.1 wrstuden u_int8_t sc_bitport;
98 1.2.8.1 wrstuden u_int8_t sc_tft_on;
99 1.2.8.1 wrstuden u_int8_t sc_op;
100 1.2.8.1 wrstuden u_int8_t sc_cmdoff;
101 1.2.8.1 wrstuden u_int8_t sc_cmdlen;
102 1.2.8.1 wrstuden u_int8_t sc_rspoff;
103 1.2.8.1 wrstuden u_int8_t sc_rsplen;
104 1.2.8.1 wrstuden /* APM stuff */
105 1.2.8.1 wrstuden #define APM_NEVENTS 16
106 1.2.8.1 wrstuden struct apm_event_info sc_event_list[APM_NEVENTS];
107 1.2.8.1 wrstuden int sc_event_count;
108 1.2.8.1 wrstuden int sc_event_ptr;
109 1.2.8.1 wrstuden struct selinfo sc_rsel;
110 1.2.8.1 wrstuden /* ENVSYS stuff */
111 1.2.8.1 wrstuden #define ENVSYS_NUMSENSORS 3
112 1.2.8.1 wrstuden struct envsys_sensor sc_esensors[ENVSYS_NUMSENSORS];
113 1.1 matt
114 1.2.8.1 wrstuden struct evcnt sc_intrcnt; /* interrupt counting */
115 1.1 matt };
116 1.1 matt
117 1.2.8.1 wrstuden #define TCTRL_STD_DEV 0
118 1.2.8.1 wrstuden #define TCTRL_APMCTL_DEV 8
119 1.1 matt
120 1.2.8.1 wrstuden static int tctrl_match __P((struct device *parent, struct cfdata *cf,
121 1.2.8.1 wrstuden void *aux));
122 1.2.8.1 wrstuden static void tctrl_attach __P((struct device *parent, struct device *self,
123 1.2.8.1 wrstuden void *aux));
124 1.2.8.1 wrstuden static void tctrl_write __P((struct tctrl_softc *sc, bus_size_t off,
125 1.2.8.1 wrstuden u_int8_t v));
126 1.2.8.1 wrstuden static u_int8_t tctrl_read __P((struct tctrl_softc *sc, bus_size_t off));
127 1.2.8.1 wrstuden static void tctrl_write_data __P((struct tctrl_softc *sc, u_int8_t v));
128 1.2.8.1 wrstuden static u_int8_t tctrl_read_data __P((struct tctrl_softc *sc));
129 1.2.8.1 wrstuden static int tctrl_intr __P((void *arg));
130 1.2.8.1 wrstuden static void tctrl_setup_bitport __P((void));
131 1.2.8.1 wrstuden static void tctrl_setup_bitport_nop __P((void));
132 1.2.8.1 wrstuden static void tctrl_read_ext_status __P((void));
133 1.2.8.1 wrstuden static void tctrl_read_event_status __P((void *arg));
134 1.2.8.1 wrstuden static int tctrl_apm_record_event __P((struct tctrl_softc *sc,
135 1.2.8.1 wrstuden u_int event_type));
136 1.1 matt
137 1.1 matt struct cfattach tctrl_ca = {
138 1.1 matt sizeof(struct tctrl_softc), tctrl_match, tctrl_attach
139 1.1 matt };
140 1.1 matt
141 1.1 matt extern struct cfdriver tctrl_cd;
142 1.2.8.1 wrstuden /* XXX wtf is this? see i386/apm.c */
143 1.2.8.1 wrstuden int tctrl_apm_evindex;
144 1.1 matt
145 1.1 matt static int
146 1.2.8.1 wrstuden tctrl_match(parent, cf, aux)
147 1.2.8.1 wrstuden struct device *parent;
148 1.2.8.1 wrstuden struct cfdata *cf;
149 1.2.8.1 wrstuden void *aux;
150 1.1 matt {
151 1.1 matt union obio_attach_args *uoba = aux;
152 1.1 matt struct sbus_attach_args *sa = &uoba->uoba_sbus;
153 1.1 matt
154 1.1 matt if (uoba->uoba_isobio4 != 0) {
155 1.1 matt return (0);
156 1.1 matt }
157 1.1 matt
158 1.1 matt /* Tadpole 3GX/3GS uses "uctrl" for the Tadpole Microcontroller
159 1.1 matt * (who's interface is off the TS102 PCMCIA controller but there
160 1.1 matt * exists a OpenProm for microcontroller interface).
161 1.1 matt */
162 1.1 matt return strcmp("uctrl", sa->sa_name) == 0;
163 1.1 matt }
164 1.1 matt
165 1.1 matt static void
166 1.2.8.1 wrstuden tctrl_attach(parent, self, aux)
167 1.2.8.1 wrstuden struct device *parent;
168 1.2.8.1 wrstuden struct device *self;
169 1.2.8.1 wrstuden void *aux;
170 1.1 matt {
171 1.1 matt struct tctrl_softc *sc = (void *)self;
172 1.1 matt union obio_attach_args *uoba = aux;
173 1.1 matt struct sbus_attach_args *sa = &uoba->uoba_sbus;
174 1.2 matt unsigned int i, v;
175 1.2 matt #if 0
176 1.1 matt unsigned int ack, msb, lsb;
177 1.2 matt #endif
178 1.1 matt
179 1.1 matt /* We're living on a sbus slot that looks like an obio that
180 1.1 matt * looks like an sbus slot.
181 1.1 matt */
182 1.1 matt sc->sc_memt = sa->sa_bustag;
183 1.1 matt if (sbus_bus_map(sc->sc_memt, sa->sa_slot,
184 1.1 matt sa->sa_offset - TS102_REG_UCTRL_INT, sa->sa_size,
185 1.1 matt BUS_SPACE_MAP_LINEAR, 0,
186 1.1 matt &sc->sc_memh) != 0) {
187 1.1 matt printf(": can't map registers\n");
188 1.1 matt return;
189 1.1 matt }
190 1.1 matt
191 1.2 matt printf("\n");
192 1.2 matt
193 1.1 matt sc->sc_tft_on = 1;
194 1.2 matt
195 1.1 matt /* clear any pending data.
196 1.1 matt */
197 1.1 matt for (i = 0; i < 10000; i++) {
198 1.2.8.1 wrstuden if ((TS102_UCTRL_STS_RXNE_STA &
199 1.2.8.1 wrstuden tctrl_read(sc, TS102_REG_UCTRL_STS)) == 0) {
200 1.1 matt break;
201 1.1 matt }
202 1.1 matt v = tctrl_read(sc, TS102_REG_UCTRL_DATA);
203 1.2 matt tctrl_write(sc, TS102_REG_UCTRL_STS, TS102_UCTRL_STS_RXNE_STA);
204 1.1 matt }
205 1.1 matt
206 1.2.8.1 wrstuden if (sa->sa_nintr != 0) {
207 1.2.8.1 wrstuden (void)bus_intr_establish(sc->sc_memt, sa->sa_pri,
208 1.2.8.1 wrstuden 0, tctrl_intr, sc);
209 1.2.8.1 wrstuden evcnt_attach(&sc->sc_dev, "intr", &sc->sc_intrcnt);
210 1.2.8.1 wrstuden }
211 1.2 matt
212 1.2 matt /* See what the external status is
213 1.2 matt */
214 1.1 matt
215 1.2.8.1 wrstuden tctrl_read_ext_status();
216 1.2 matt if (sc->sc_ext_status != 0) {
217 1.2 matt const char *sep;
218 1.1 matt
219 1.1 matt printf("%s: ", sc->sc_dev.dv_xname);
220 1.2 matt v = sc->sc_ext_status;
221 1.1 matt for (i = 0, sep = ""; v != 0; i++, v >>= 1) {
222 1.1 matt if (v & 1) {
223 1.1 matt printf("%s%s", sep, tctrl_ext_statuses[i]);
224 1.1 matt sep = ", ";
225 1.1 matt }
226 1.1 matt }
227 1.1 matt printf("\n");
228 1.1 matt }
229 1.1 matt
230 1.2 matt /* Get a current of the control bitport;
231 1.2 matt */
232 1.2.8.1 wrstuden tctrl_setup_bitport_nop();
233 1.2 matt tctrl_write(sc, TS102_REG_UCTRL_INT,
234 1.2 matt TS102_UCTRL_INT_RXNE_REQ|TS102_UCTRL_INT_RXNE_MSK);
235 1.1 matt
236 1.2.8.1 wrstuden sc->sc_wantdata = 0;
237 1.2.8.1 wrstuden sc->sc_event_count = 0;
238 1.2.8.1 wrstuden
239 1.2.8.1 wrstuden /* prime the sensor data */
240 1.2.8.1 wrstuden sprintf(sc->sc_esensors[0].desc, "%s", "Internal Unit Temperature");
241 1.2.8.1 wrstuden sc->sc_esensors[0].units = ENVSYS_STEMP;
242 1.2.8.1 wrstuden sprintf(sc->sc_esensors[1].desc, "%s", "Internal Battery Voltage");
243 1.2.8.1 wrstuden sc->sc_esensors[1].units = ENVSYS_SVOLTS_DC;
244 1.2.8.1 wrstuden sprintf(sc->sc_esensors[2].desc, "%s", "DC-In Voltage");
245 1.2.8.1 wrstuden sc->sc_esensors[2].units = ENVSYS_SVOLTS_DC;
246 1.1 matt }
247 1.1 matt
248 1.1 matt static int
249 1.2.8.1 wrstuden tctrl_intr(arg)
250 1.2.8.1 wrstuden void *arg;
251 1.1 matt {
252 1.1 matt struct tctrl_softc *sc = arg;
253 1.1 matt unsigned int v, d;
254 1.1 matt int progress = 0;
255 1.1 matt
256 1.1 matt again:
257 1.1 matt /* find out the cause(s) of the interrupt */
258 1.1 matt v = tctrl_read(sc, TS102_REG_UCTRL_STS);
259 1.1 matt
260 1.1 matt /* clear the cause(s) of the interrupt */
261 1.1 matt tctrl_write(sc, TS102_REG_UCTRL_STS, v);
262 1.1 matt
263 1.2 matt v &= ~(TS102_UCTRL_STS_RXO_STA|TS102_UCTRL_STS_TXE_STA);
264 1.1 matt if (sc->sc_cmdoff >= sc->sc_cmdlen) {
265 1.2 matt v &= ~TS102_UCTRL_STS_TXNF_STA;
266 1.2.8.1 wrstuden if (tctrl_read(sc, TS102_REG_UCTRL_INT) & TS102_UCTRL_INT_TXNF_REQ) {
267 1.2.8.1 wrstuden tctrl_write(sc, TS102_REG_UCTRL_INT, 0);
268 1.2.8.1 wrstuden progress = 1;
269 1.2.8.1 wrstuden }
270 1.1 matt }
271 1.2.8.1 wrstuden if ((v == 0) && ((sc->sc_flags & TCTRL_SEND_REQUEST) == 0 ||
272 1.2.8.1 wrstuden sc->sc_state != TCTRL_IDLE)) {
273 1.2.8.1 wrstuden wakeup(sc);
274 1.1 matt return progress;
275 1.1 matt }
276 1.1 matt
277 1.1 matt progress = 1;
278 1.2 matt if (v & TS102_UCTRL_STS_RXNE_STA) {
279 1.1 matt d = tctrl_read_data(sc);
280 1.1 matt switch (sc->sc_state) {
281 1.1 matt case TCTRL_IDLE:
282 1.2 matt if (d == 0xfa) {
283 1.2.8.1 wrstuden /* external event */
284 1.2.8.1 wrstuden timeout(tctrl_read_event_status, (void *)0, 1);
285 1.2 matt } else {
286 1.2 matt printf("%s: (op=0x%02x): unexpected data (0x%02x)\n",
287 1.2 matt sc->sc_dev.dv_xname, sc->sc_op, d);
288 1.1 matt }
289 1.2 matt goto again;
290 1.1 matt case TCTRL_ACK:
291 1.1 matt if (d != 0xfe) {
292 1.2 matt printf("%s: (op=0x%02x): unexpected ack value (0x%02x)\n",
293 1.1 matt sc->sc_dev.dv_xname, sc->sc_op, d);
294 1.1 matt }
295 1.2.8.1 wrstuden #ifdef TCTRLDEBUG
296 1.2 matt printf(" ack=0x%02x", d);
297 1.2 matt #endif
298 1.2 matt sc->sc_rsplen--;
299 1.2 matt sc->sc_rspoff = 0;
300 1.1 matt sc->sc_state = sc->sc_rsplen ? TCTRL_DATA : TCTRL_IDLE;
301 1.2.8.1 wrstuden sc->sc_wantdata = sc->sc_rsplen ? 1 : 0;
302 1.2.8.1 wrstuden #ifdef TCTRLDEBUG
303 1.2 matt if (sc->sc_rsplen > 0) {
304 1.2 matt printf(" [data(%u)]", sc->sc_rsplen);
305 1.2 matt } else {
306 1.2 matt printf(" [idle]\n");
307 1.2 matt }
308 1.2 matt #endif
309 1.2 matt goto again;
310 1.1 matt case TCTRL_DATA:
311 1.1 matt sc->sc_rspbuf[sc->sc_rspoff++] = d;
312 1.2.8.1 wrstuden #ifdef TCTRLDEBUG
313 1.2 matt printf(" [%d]=0x%02x", sc->sc_rspoff-1, d);
314 1.2 matt #endif
315 1.1 matt if (sc->sc_rspoff == sc->sc_rsplen) {
316 1.2.8.1 wrstuden #ifdef TCTRLDEBUG
317 1.2 matt printf(" [idle]\n");
318 1.2 matt #endif
319 1.1 matt sc->sc_state = TCTRL_IDLE;
320 1.2.8.1 wrstuden sc->sc_wantdata = 0;
321 1.1 matt }
322 1.2 matt goto again;
323 1.1 matt default:
324 1.1 matt printf("%s: (op=0x%02x): unexpected data (0x%02x) in state %d\n",
325 1.1 matt sc->sc_dev.dv_xname, sc->sc_op, d, sc->sc_state);
326 1.2 matt goto again;
327 1.1 matt }
328 1.1 matt }
329 1.2.8.1 wrstuden if ((sc->sc_state == TCTRL_IDLE && sc->sc_wantdata == 0) ||
330 1.2.8.1 wrstuden sc->sc_flags & TCTRL_SEND_REQUEST) {
331 1.2.8.1 wrstuden if (sc->sc_flags & TCTRL_SEND_REQUEST) {
332 1.2.8.1 wrstuden sc->sc_flags &= ~TCTRL_SEND_REQUEST;
333 1.2.8.1 wrstuden sc->sc_wantdata = 1;
334 1.2.8.1 wrstuden }
335 1.1 matt if (sc->sc_cmdlen > 0) {
336 1.1 matt tctrl_write(sc, TS102_REG_UCTRL_INT,
337 1.1 matt tctrl_read(sc, TS102_REG_UCTRL_INT)
338 1.1 matt |TS102_UCTRL_INT_TXNF_MSK
339 1.1 matt |TS102_UCTRL_INT_TXNF_REQ);
340 1.1 matt v = tctrl_read(sc, TS102_REG_UCTRL_STS);
341 1.1 matt }
342 1.1 matt }
343 1.2 matt if ((sc->sc_cmdoff < sc->sc_cmdlen) && (v & TS102_UCTRL_STS_TXNF_STA)) {
344 1.1 matt tctrl_write_data(sc, sc->sc_cmdbuf[sc->sc_cmdoff++]);
345 1.2.8.1 wrstuden #ifdef TCTRLDEBUG
346 1.2 matt if (sc->sc_cmdoff == 1) {
347 1.2 matt printf("%s: op=0x%02x(l=%u)", sc->sc_dev.dv_xname,
348 1.2 matt sc->sc_cmdbuf[0], sc->sc_rsplen);
349 1.2 matt } else {
350 1.2 matt printf(" [%d]=0x%02x", sc->sc_cmdoff-1,
351 1.2 matt sc->sc_cmdbuf[sc->sc_cmdoff-1]);
352 1.2 matt }
353 1.2 matt #endif
354 1.1 matt if (sc->sc_cmdoff == sc->sc_cmdlen) {
355 1.1 matt sc->sc_state = sc->sc_rsplen ? TCTRL_ACK : TCTRL_IDLE;
356 1.2.8.1 wrstuden #ifdef TCTRLDEBUG
357 1.2 matt printf(" %s", sc->sc_rsplen ? "[ack]" : "[idle]\n");
358 1.2 matt #endif
359 1.2 matt if (sc->sc_cmdoff == 1) {
360 1.2 matt sc->sc_op = sc->sc_cmdbuf[0];
361 1.2 matt }
362 1.1 matt tctrl_write(sc, TS102_REG_UCTRL_INT,
363 1.1 matt tctrl_read(sc, TS102_REG_UCTRL_INT)
364 1.1 matt & (~TS102_UCTRL_INT_TXNF_MSK
365 1.1 matt |TS102_UCTRL_INT_TXNF_REQ));
366 1.1 matt } else if (sc->sc_state == TCTRL_IDLE) {
367 1.1 matt sc->sc_op = sc->sc_cmdbuf[0];
368 1.1 matt sc->sc_state = TCTRL_ARGS;
369 1.2.8.1 wrstuden #ifdef TCTRLDEBUG
370 1.2 matt printf(" [args]");
371 1.2 matt #endif
372 1.1 matt }
373 1.1 matt }
374 1.1 matt goto again;
375 1.1 matt }
376 1.1 matt
377 1.1 matt static void
378 1.2.8.1 wrstuden tctrl_setup_bitport_nop(void)
379 1.1 matt {
380 1.2.8.1 wrstuden struct tctrl_softc *sc;
381 1.2.8.1 wrstuden struct tctrl_req req;
382 1.2.8.1 wrstuden int s;
383 1.2.8.1 wrstuden
384 1.2.8.1 wrstuden sc = (struct tctrl_softc *) tctrl_cd.cd_devs[TCTRL_STD_DEV];
385 1.2.8.1 wrstuden req.cmdbuf[0] = TS102_OP_CTL_BITPORT;
386 1.2.8.1 wrstuden req.cmdbuf[1] = 0xff;
387 1.2.8.1 wrstuden req.cmdbuf[2] = 0;
388 1.2.8.1 wrstuden req.cmdlen = 3;
389 1.2.8.1 wrstuden req.rsplen = 2;
390 1.2.8.1 wrstuden req.p = NULL;
391 1.2.8.1 wrstuden tadpole_request(&req, 1);
392 1.2.8.1 wrstuden s = splts102();
393 1.2.8.1 wrstuden sc->sc_bitport = (req.rspbuf[0] & req.cmdbuf[1]) ^ req.cmdbuf[2];
394 1.2.8.1 wrstuden splx(s);
395 1.2.8.1 wrstuden }
396 1.2.8.1 wrstuden
397 1.2.8.1 wrstuden static void
398 1.2.8.1 wrstuden tctrl_setup_bitport(void)
399 1.2.8.1 wrstuden {
400 1.2.8.1 wrstuden struct tctrl_softc *sc;
401 1.2.8.1 wrstuden struct tctrl_req req;
402 1.2.8.1 wrstuden int s;
403 1.2.8.1 wrstuden
404 1.2.8.1 wrstuden sc = (struct tctrl_softc *) tctrl_cd.cd_devs[TCTRL_STD_DEV];
405 1.2.8.1 wrstuden s = splts102();
406 1.2.8.1 wrstuden if ((sc->sc_ext_status & TS102_EXT_STATUS_LID_DOWN)
407 1.2.8.1 wrstuden || (!sc->sc_tft_on)) {
408 1.2.8.1 wrstuden req.cmdbuf[2] = TS102_BITPORT_TFTPWR;
409 1.1 matt } else {
410 1.2.8.1 wrstuden req.cmdbuf[2] = 0;
411 1.1 matt }
412 1.2.8.1 wrstuden req.cmdbuf[0] = TS102_OP_CTL_BITPORT;
413 1.2.8.1 wrstuden req.cmdbuf[1] = ~TS102_BITPORT_TFTPWR;
414 1.2.8.1 wrstuden req.cmdlen = 3;
415 1.2.8.1 wrstuden req.rsplen = 2;
416 1.2.8.1 wrstuden req.p = NULL;
417 1.2.8.1 wrstuden tadpole_request(&req, 1);
418 1.2.8.1 wrstuden s = splts102();
419 1.2.8.1 wrstuden sc->sc_bitport = (req.rspbuf[0] & req.cmdbuf[1]) ^ req.cmdbuf[2];
420 1.2.8.1 wrstuden splx(s);
421 1.1 matt }
422 1.1 matt
423 1.1 matt static void
424 1.2.8.1 wrstuden tctrl_read_ext_status(void)
425 1.1 matt {
426 1.2.8.1 wrstuden struct tctrl_softc *sc;
427 1.2.8.1 wrstuden struct tctrl_req req;
428 1.2.8.1 wrstuden int s;
429 1.2.8.1 wrstuden
430 1.2.8.1 wrstuden sc = (struct tctrl_softc *) tctrl_cd.cd_devs[TCTRL_STD_DEV];
431 1.2.8.1 wrstuden req.cmdbuf[0] = TS102_OP_RD_EXT_STATUS;
432 1.2.8.1 wrstuden req.cmdlen = 1;
433 1.2.8.1 wrstuden req.rsplen = 3;
434 1.2.8.1 wrstuden req.p = NULL;
435 1.2.8.1 wrstuden #ifdef TCTRLDEBUG
436 1.2.8.1 wrstuden printf("pre read: sc->sc_ext_status = 0x%x\n", sc->sc_ext_status);
437 1.2.8.1 wrstuden #endif
438 1.2.8.1 wrstuden tadpole_request(&req, 1);
439 1.2.8.1 wrstuden s = splts102();
440 1.2.8.1 wrstuden sc->sc_ext_status = req.rspbuf[0] * 256 + req.rspbuf[1];
441 1.2.8.1 wrstuden splx(s);
442 1.2.8.1 wrstuden #ifdef TCTRLDEBUG
443 1.2.8.1 wrstuden printf("post read: sc->sc_ext_status = 0x%x\n", sc->sc_ext_status);
444 1.2.8.1 wrstuden #endif
445 1.2.8.1 wrstuden }
446 1.2.8.1 wrstuden
447 1.2.8.1 wrstuden /*
448 1.2.8.1 wrstuden * return 0 if the user will notice and handle the event,
449 1.2.8.1 wrstuden * return 1 if the kernel driver should do so.
450 1.2.8.1 wrstuden */
451 1.2.8.1 wrstuden static int
452 1.2.8.1 wrstuden tctrl_apm_record_event(sc, event_type)
453 1.2.8.1 wrstuden struct tctrl_softc *sc;
454 1.2.8.1 wrstuden u_int event_type;
455 1.2.8.1 wrstuden {
456 1.2.8.1 wrstuden struct apm_event_info *evp;
457 1.2.8.1 wrstuden
458 1.2.8.1 wrstuden if ((sc->sc_flags & TCTRL_APM_CTLOPEN) &&
459 1.2.8.1 wrstuden (sc->sc_event_count < APM_NEVENTS)) {
460 1.2.8.1 wrstuden evp = &sc->sc_event_list[sc->sc_event_ptr];
461 1.2.8.1 wrstuden sc->sc_event_count++;
462 1.2.8.1 wrstuden sc->sc_event_ptr++;
463 1.2.8.1 wrstuden sc->sc_event_ptr %= APM_NEVENTS;
464 1.2.8.1 wrstuden evp->type = event_type;
465 1.2.8.1 wrstuden evp->index = ++tctrl_apm_evindex;
466 1.2.8.1 wrstuden selwakeup(&sc->sc_rsel);
467 1.2.8.1 wrstuden return(sc->sc_flags & TCTRL_APM_CTLOPEN) ? 0 : 1;
468 1.1 matt }
469 1.2.8.1 wrstuden return(1);
470 1.2.8.1 wrstuden }
471 1.2.8.1 wrstuden
472 1.2.8.1 wrstuden static void
473 1.2.8.1 wrstuden tctrl_read_event_status(arg)
474 1.2.8.1 wrstuden void *arg;
475 1.2.8.1 wrstuden {
476 1.2.8.1 wrstuden struct tctrl_softc *sc;
477 1.2.8.1 wrstuden struct tctrl_req req;
478 1.2.8.1 wrstuden int s;
479 1.2.8.1 wrstuden unsigned int v;
480 1.2.8.1 wrstuden
481 1.2.8.1 wrstuden sc = (struct tctrl_softc *) tctrl_cd.cd_devs[TCTRL_STD_DEV];
482 1.2.8.1 wrstuden req.cmdbuf[0] = TS102_OP_RD_EVENT_STATUS;
483 1.2.8.1 wrstuden req.cmdlen = 1;
484 1.2.8.1 wrstuden req.rsplen = 3;
485 1.2.8.1 wrstuden req.p = NULL;
486 1.2.8.1 wrstuden tadpole_request(&req, 1);
487 1.2.8.1 wrstuden s = splts102();
488 1.2.8.1 wrstuden v = req.rspbuf[0] * 256 + req.rspbuf[1];
489 1.2.8.1 wrstuden if (v & TS102_EVENT_STATUS_SHUTDOWN_REQUEST) {
490 1.2.8.1 wrstuden printf("%s: SHUTDOWN REQUEST!\n", sc->sc_dev.dv_xname);
491 1.2.8.1 wrstuden }
492 1.2.8.1 wrstuden if (v & TS102_EVENT_STATUS_VERY_LOW_POWER_WARNING) {
493 1.2.8.1 wrstuden /*printf("%s: VERY LOW POWER WARNING!\n", sc->sc_dev.dv_xname);*/
494 1.2.8.1 wrstuden /* according to a tadpole header, and observation */
495 1.2.8.1 wrstuden #ifdef TCTRLDEBUG
496 1.2.8.1 wrstuden printf("%s: Battery charge level change\n", sc->sc_dev.dv_xname);
497 1.2.8.1 wrstuden #endif
498 1.2.8.1 wrstuden }
499 1.2.8.1 wrstuden if (v & TS102_EVENT_STATUS_LOW_POWER_WARNING) {
500 1.2.8.1 wrstuden if (tctrl_apm_record_event(sc, APM_BATTERY_LOW))
501 1.1 matt printf("%s: LOW POWER WARNING!\n", sc->sc_dev.dv_xname);
502 1.2.8.1 wrstuden }
503 1.2.8.1 wrstuden if (v & TS102_EVENT_STATUS_DC_STATUS_CHANGE) {
504 1.2.8.1 wrstuden splx(s);
505 1.2.8.1 wrstuden tctrl_read_ext_status();
506 1.2.8.1 wrstuden s = splts102();
507 1.2.8.1 wrstuden if (tctrl_apm_record_event(sc, APM_POWER_CHANGE))
508 1.1 matt printf("%s: main power %s\n", sc->sc_dev.dv_xname,
509 1.2.8.1 wrstuden (sc->sc_ext_status &
510 1.2.8.1 wrstuden TS102_EXT_STATUS_MAIN_POWER_AVAILABLE) ?
511 1.2.8.1 wrstuden "restored" : "removed");
512 1.2.8.1 wrstuden }
513 1.2.8.1 wrstuden if (v & TS102_EVENT_STATUS_LID_STATUS_CHANGE) {
514 1.2.8.1 wrstuden splx(s);
515 1.2.8.1 wrstuden tctrl_read_ext_status();
516 1.2.8.1 wrstuden tctrl_setup_bitport();
517 1.2.8.1 wrstuden #ifdef TCTRLDEBUG
518 1.2.8.1 wrstuden printf("%s: lid %s\n", sc->sc_dev.dv_xname,
519 1.2.8.1 wrstuden (sc->sc_ext_status & TS102_EXT_STATUS_LID_DOWN)
520 1.2.8.1 wrstuden ? "closed" : "opened");
521 1.2 matt #endif
522 1.1 matt }
523 1.2.8.1 wrstuden splx(s);
524 1.1 matt }
525 1.1 matt
526 1.1 matt void
527 1.2.8.1 wrstuden tadpole_request(req, spin)
528 1.2.8.1 wrstuden struct tctrl_req *req;
529 1.2.8.1 wrstuden int spin;
530 1.1 matt {
531 1.1 matt struct tctrl_softc *sc;
532 1.1 matt int i, s;
533 1.1 matt
534 1.1 matt if (tctrl_cd.cd_devs == NULL
535 1.1 matt || tctrl_cd.cd_ndevs == 0
536 1.2.8.1 wrstuden || tctrl_cd.cd_devs[TCTRL_STD_DEV] == NULL) {
537 1.1 matt return;
538 1.1 matt }
539 1.1 matt
540 1.2.8.1 wrstuden sc = (struct tctrl_softc *) tctrl_cd.cd_devs[TCTRL_STD_DEV];
541 1.2.8.1 wrstuden while (sc->sc_wantdata != 0) {
542 1.2.8.1 wrstuden if (req->p != NULL)
543 1.2.8.1 wrstuden tsleep(&sc->sc_wantdata, PLOCK, "tctrl_lock", 10);
544 1.2.8.1 wrstuden else
545 1.2.8.1 wrstuden DELAY(1);
546 1.2.8.1 wrstuden }
547 1.2.8.1 wrstuden if (spin)
548 1.2.8.1 wrstuden s = splhigh();
549 1.2.8.1 wrstuden else
550 1.2.8.1 wrstuden s = splts102();
551 1.2.8.1 wrstuden sc->sc_flags |= TCTRL_SEND_REQUEST;
552 1.2.8.1 wrstuden memcpy(sc->sc_cmdbuf, req->cmdbuf, req->cmdlen);
553 1.2.8.1 wrstuden sc->sc_wantdata = 1;
554 1.2.8.1 wrstuden sc->sc_rsplen = req->rsplen;
555 1.2.8.1 wrstuden sc->sc_cmdlen = req->cmdlen;
556 1.2.8.1 wrstuden sc->sc_cmdoff = sc->sc_rspoff = 0;
557 1.2.8.1 wrstuden
558 1.2.8.1 wrstuden /* we spin for certain commands, like poweroffs */
559 1.2.8.1 wrstuden if (spin) {
560 1.2.8.1 wrstuden for (i = 0; i < 30000; i++) {
561 1.2.8.1 wrstuden tctrl_intr(sc);
562 1.2.8.1 wrstuden DELAY(1);
563 1.2.8.1 wrstuden }
564 1.2.8.1 wrstuden } else {
565 1.1 matt tctrl_intr(sc);
566 1.2.8.1 wrstuden i = 0;
567 1.2.8.1 wrstuden while (((sc->sc_rspoff != sc->sc_rsplen) ||
568 1.2.8.1 wrstuden (sc->sc_cmdoff != sc->sc_cmdlen)) &&
569 1.2.8.1 wrstuden (i < (5 * sc->sc_rsplen + sc->sc_cmdlen)))
570 1.2.8.1 wrstuden if (req->p != NULL) {
571 1.2.8.1 wrstuden tsleep(sc, PWAIT, "tctrl_data", 15);
572 1.2.8.1 wrstuden i++;
573 1.2.8.1 wrstuden }
574 1.2.8.1 wrstuden else
575 1.2.8.1 wrstuden DELAY(1);
576 1.1 matt }
577 1.2.8.1 wrstuden /*
578 1.2.8.1 wrstuden * we give the user a reasonable amount of time for a command
579 1.2.8.1 wrstuden * to complete. If it doesn't complete in time, we hand them
580 1.2.8.1 wrstuden * garbage. This is here to stop things like setting the
581 1.2.8.1 wrstuden * rsplen too long, and sleeping forever in a CMD_REQ ioctl.
582 1.2.8.1 wrstuden */
583 1.2.8.1 wrstuden sc->sc_wantdata = 0;
584 1.2.8.1 wrstuden memcpy(req->rspbuf, sc->sc_rspbuf, req->rsplen);
585 1.1 matt splx(s);
586 1.1 matt }
587 1.1 matt
588 1.1 matt void
589 1.2.8.1 wrstuden tadpole_powerdown(void)
590 1.2.8.1 wrstuden {
591 1.2.8.1 wrstuden struct tctrl_req req;
592 1.2.8.1 wrstuden
593 1.2.8.1 wrstuden req.cmdbuf[0] = TS102_OP_ADMIN_POWER_OFF;
594 1.2.8.1 wrstuden req.cmdlen = 1;
595 1.2.8.1 wrstuden req.rsplen = 1;
596 1.2.8.1 wrstuden req.p = NULL;
597 1.2.8.1 wrstuden tadpole_request(&req, 1);
598 1.2.8.1 wrstuden }
599 1.2.8.1 wrstuden
600 1.2.8.1 wrstuden void
601 1.2.8.1 wrstuden tadpole_set_video(enabled)
602 1.2.8.1 wrstuden int enabled;
603 1.1 matt {
604 1.1 matt struct tctrl_softc *sc;
605 1.2.8.1 wrstuden struct tctrl_req req;
606 1.1 matt int s;
607 1.1 matt
608 1.2.8.1 wrstuden sc = (struct tctrl_softc *) tctrl_cd.cd_devs[TCTRL_STD_DEV];
609 1.2.8.1 wrstuden while (sc->sc_wantdata != 0)
610 1.2.8.1 wrstuden DELAY(1);
611 1.2.8.1 wrstuden s = splts102();
612 1.2.8.1 wrstuden req.p = NULL;
613 1.2.8.1 wrstuden if ((sc->sc_ext_status & TS102_EXT_STATUS_LID_DOWN && !enabled)
614 1.2.8.1 wrstuden || (sc->sc_tft_on)) {
615 1.2.8.1 wrstuden req.cmdbuf[2] = TS102_BITPORT_TFTPWR;
616 1.2.8.1 wrstuden } else {
617 1.2.8.1 wrstuden req.cmdbuf[2] = 0;
618 1.1 matt }
619 1.2.8.1 wrstuden req.cmdbuf[0] = TS102_OP_CTL_BITPORT;
620 1.2.8.1 wrstuden req.cmdbuf[1] = ~TS102_BITPORT_TFTPWR;
621 1.2.8.1 wrstuden req.cmdlen = 3;
622 1.2.8.1 wrstuden req.rsplen = 2;
623 1.1 matt
624 1.1 matt if ((sc->sc_tft_on && !enabled) || (!sc->sc_tft_on && enabled)) {
625 1.1 matt sc->sc_tft_on = enabled;
626 1.1 matt if (sc->sc_ext_status & TS102_EXT_STATUS_LID_DOWN) {
627 1.1 matt splx(s);
628 1.1 matt return;
629 1.1 matt }
630 1.2.8.1 wrstuden tadpole_request(&req, 1);
631 1.2.8.1 wrstuden sc->sc_bitport =
632 1.2.8.1 wrstuden (req.rspbuf[0] & req.cmdbuf[1]) ^ req.cmdbuf[2];
633 1.1 matt }
634 1.1 matt splx(s);
635 1.1 matt }
636 1.1 matt
637 1.1 matt static void
638 1.2.8.1 wrstuden tctrl_write_data(sc, v)
639 1.2.8.1 wrstuden struct tctrl_softc *sc;
640 1.2.8.1 wrstuden u_int8_t v;
641 1.1 matt {
642 1.1 matt unsigned int i;
643 1.2.8.1 wrstuden
644 1.1 matt for (i = 0; i < 100; i++) {
645 1.2 matt if (TS102_UCTRL_STS_TXNF_STA & tctrl_read(sc, TS102_REG_UCTRL_STS))
646 1.1 matt break;
647 1.1 matt }
648 1.1 matt tctrl_write(sc, TS102_REG_UCTRL_DATA, v);
649 1.1 matt }
650 1.1 matt
651 1.1 matt static u_int8_t
652 1.2.8.1 wrstuden tctrl_read_data(sc)
653 1.2.8.1 wrstuden struct tctrl_softc *sc;
654 1.2.8.1 wrstuden {
655 1.1 matt unsigned int i, v;
656 1.1 matt
657 1.1 matt for (i = 0; i < 100000; i++) {
658 1.2 matt if (TS102_UCTRL_STS_RXNE_STA & tctrl_read(sc, TS102_REG_UCTRL_STS))
659 1.1 matt break;
660 1.1 matt DELAY(1);
661 1.1 matt }
662 1.1 matt
663 1.1 matt v = tctrl_read(sc, TS102_REG_UCTRL_DATA);
664 1.2 matt tctrl_write(sc, TS102_REG_UCTRL_STS, TS102_UCTRL_STS_RXNE_STA);
665 1.1 matt return v;
666 1.1 matt }
667 1.1 matt
668 1.1 matt static u_int8_t
669 1.2.8.1 wrstuden tctrl_read(sc, off)
670 1.2.8.1 wrstuden struct tctrl_softc *sc;
671 1.2.8.1 wrstuden bus_size_t off;
672 1.1 matt {
673 1.2.8.1 wrstuden
674 1.2 matt sc->sc_junk = bus_space_read_1(sc->sc_memt, sc->sc_memh, off);
675 1.1 matt return sc->sc_junk;
676 1.1 matt }
677 1.1 matt
678 1.1 matt static void
679 1.2.8.1 wrstuden tctrl_write(sc, off, v)
680 1.2.8.1 wrstuden struct tctrl_softc *sc;
681 1.2.8.1 wrstuden bus_size_t off;
682 1.2.8.1 wrstuden u_int8_t v;
683 1.1 matt {
684 1.2.8.1 wrstuden
685 1.1 matt sc->sc_junk = v;
686 1.2 matt bus_space_write_1(sc->sc_memt, sc->sc_memh, off, v);
687 1.2.8.1 wrstuden }
688 1.2.8.1 wrstuden
689 1.2.8.1 wrstuden int
690 1.2.8.1 wrstuden tctrlopen(dev, flags, mode, p)
691 1.2.8.1 wrstuden dev_t dev;
692 1.2.8.1 wrstuden int flags, mode;
693 1.2.8.1 wrstuden struct proc *p;
694 1.2.8.1 wrstuden {
695 1.2.8.1 wrstuden int unit = (minor(dev)&0xf0);
696 1.2.8.1 wrstuden int ctl = (minor(dev)&0x0f);
697 1.2.8.1 wrstuden struct tctrl_softc *sc;
698 1.2.8.1 wrstuden
699 1.2.8.1 wrstuden if (unit >= tctrl_cd.cd_ndevs)
700 1.2.8.1 wrstuden return(ENXIO);
701 1.2.8.1 wrstuden sc = tctrl_cd.cd_devs[TCTRL_STD_DEV];
702 1.2.8.1 wrstuden if (!sc)
703 1.2.8.1 wrstuden return(ENXIO);
704 1.2.8.1 wrstuden
705 1.2.8.1 wrstuden switch (ctl) {
706 1.2.8.1 wrstuden case TCTRL_STD_DEV:
707 1.2.8.1 wrstuden break;
708 1.2.8.1 wrstuden case TCTRL_APMCTL_DEV:
709 1.2.8.1 wrstuden if (!(flags & FWRITE))
710 1.2.8.1 wrstuden return(EINVAL);
711 1.2.8.1 wrstuden if (sc->sc_flags & TCTRL_APM_CTLOPEN)
712 1.2.8.1 wrstuden return(EBUSY);
713 1.2.8.1 wrstuden sc->sc_flags |= TCTRL_APM_CTLOPEN;
714 1.2.8.1 wrstuden break;
715 1.2.8.1 wrstuden default:
716 1.2.8.1 wrstuden return(ENXIO);
717 1.2.8.1 wrstuden break;
718 1.2.8.1 wrstuden }
719 1.2.8.1 wrstuden
720 1.2.8.1 wrstuden return(0);
721 1.2.8.1 wrstuden }
722 1.2.8.1 wrstuden
723 1.2.8.1 wrstuden int
724 1.2.8.1 wrstuden tctrlclose(dev, flags, mode, p)
725 1.2.8.1 wrstuden dev_t dev;
726 1.2.8.1 wrstuden int flags, mode;
727 1.2.8.1 wrstuden struct proc *p;
728 1.2.8.1 wrstuden {
729 1.2.8.1 wrstuden int ctl = (minor(dev)&0x0f);
730 1.2.8.1 wrstuden struct tctrl_softc *sc;
731 1.2.8.1 wrstuden
732 1.2.8.1 wrstuden sc = tctrl_cd.cd_devs[TCTRL_STD_DEV];
733 1.2.8.1 wrstuden if (!sc)
734 1.2.8.1 wrstuden return(ENXIO);
735 1.2.8.1 wrstuden
736 1.2.8.1 wrstuden switch (ctl) {
737 1.2.8.1 wrstuden case TCTRL_STD_DEV:
738 1.2.8.1 wrstuden break;
739 1.2.8.1 wrstuden case TCTRL_APMCTL_DEV:
740 1.2.8.1 wrstuden sc->sc_flags &= ~TCTRL_APM_CTLOPEN;
741 1.2.8.1 wrstuden break;
742 1.2.8.1 wrstuden }
743 1.2.8.1 wrstuden return(0);
744 1.2.8.1 wrstuden }
745 1.2.8.1 wrstuden
746 1.2.8.1 wrstuden int
747 1.2.8.1 wrstuden tctrlioctl(dev, cmd, data, flags, p)
748 1.2.8.1 wrstuden dev_t dev;
749 1.2.8.1 wrstuden u_long cmd;
750 1.2.8.1 wrstuden caddr_t data;
751 1.2.8.1 wrstuden int flags;
752 1.2.8.1 wrstuden struct proc *p;
753 1.2.8.1 wrstuden {
754 1.2.8.1 wrstuden struct tctrl_req req, *reqn;
755 1.2.8.1 wrstuden envsys_range_t *envrange;
756 1.2.8.1 wrstuden envsys_temp_data_t *envdata;
757 1.2.8.1 wrstuden envsys_temp_info_t *envinfo;
758 1.2.8.1 wrstuden struct apm_power_info *powerp;
759 1.2.8.1 wrstuden struct apm_event_info *evp;
760 1.2.8.1 wrstuden struct tctrl_softc *sc;
761 1.2.8.1 wrstuden int i;
762 1.2.8.1 wrstuden u_int j;
763 1.2.8.1 wrstuden u_int16_t a;
764 1.2.8.1 wrstuden u_int8_t c;
765 1.2.8.1 wrstuden
766 1.2.8.1 wrstuden if (tctrl_cd.cd_devs == NULL
767 1.2.8.1 wrstuden || tctrl_cd.cd_ndevs == 0
768 1.2.8.1 wrstuden || tctrl_cd.cd_devs[TCTRL_STD_DEV] == NULL) {
769 1.2.8.1 wrstuden return ENXIO;
770 1.2.8.1 wrstuden }
771 1.2.8.1 wrstuden sc = (struct tctrl_softc *) tctrl_cd.cd_devs[TCTRL_STD_DEV];
772 1.2.8.1 wrstuden switch (cmd) {
773 1.2.8.1 wrstuden
774 1.2.8.1 wrstuden case APM_IOC_STANDBY:
775 1.2.8.1 wrstuden return(EOPNOTSUPP); /* for now */
776 1.2.8.1 wrstuden
777 1.2.8.1 wrstuden case APM_IOC_SUSPEND:
778 1.2.8.1 wrstuden return(EOPNOTSUPP); /* for now */
779 1.2.8.1 wrstuden
780 1.2.8.1 wrstuden case APM_IOC_GETPOWER:
781 1.2.8.1 wrstuden powerp = (struct apm_power_info *)data;
782 1.2.8.1 wrstuden req.cmdbuf[0] = TS102_OP_RD_INT_CHARGE_RATE;
783 1.2.8.1 wrstuden req.cmdlen = 1;
784 1.2.8.1 wrstuden req.rsplen = 2;
785 1.2.8.1 wrstuden req.p = p;
786 1.2.8.1 wrstuden tadpole_request(&req, 0);
787 1.2.8.1 wrstuden if (req.rspbuf[0] > 0x00)
788 1.2.8.1 wrstuden powerp->battery_state = APM_BATT_CHARGING;
789 1.2.8.1 wrstuden req.cmdbuf[0] = TS102_OP_RD_INT_CHARGE_LEVEL;
790 1.2.8.1 wrstuden req.cmdlen = 1;
791 1.2.8.1 wrstuden req.rsplen = 3;
792 1.2.8.1 wrstuden req.p = p;
793 1.2.8.1 wrstuden tadpole_request(&req, 0);
794 1.2.8.1 wrstuden c = req.rspbuf[0];
795 1.2.8.1 wrstuden powerp->battery_life = c;
796 1.2.8.1 wrstuden powerp->minutes_left = (45 * c) / 100; /* XXX based on 45 min */
797 1.2.8.1 wrstuden if (powerp->battery_state != APM_BATT_CHARGING) {
798 1.2.8.1 wrstuden if (c < 0x20)
799 1.2.8.1 wrstuden powerp->battery_state = APM_BATT_CRITICAL;
800 1.2.8.1 wrstuden else if (c < 0x40)
801 1.2.8.1 wrstuden powerp->battery_state = APM_BATT_LOW;
802 1.2.8.1 wrstuden else if (c < 0x66)
803 1.2.8.1 wrstuden powerp->battery_state = APM_BATT_HIGH;
804 1.2.8.1 wrstuden else
805 1.2.8.1 wrstuden powerp->battery_state = APM_BATT_UNKNOWN;
806 1.2.8.1 wrstuden }
807 1.2.8.1 wrstuden req.cmdbuf[0] = TS102_OP_RD_EXT_STATUS;
808 1.2.8.1 wrstuden req.cmdlen = 1;
809 1.2.8.1 wrstuden req.rsplen = 3;
810 1.2.8.1 wrstuden req.p = p;
811 1.2.8.1 wrstuden tadpole_request(&req, 0);
812 1.2.8.1 wrstuden a = req.rspbuf[0] * 256 + req.rspbuf[1];
813 1.2.8.1 wrstuden if (a & TS102_EXT_STATUS_MAIN_POWER_AVAILABLE)
814 1.2.8.1 wrstuden powerp->ac_state = APM_AC_ON;
815 1.2.8.1 wrstuden else
816 1.2.8.1 wrstuden powerp->ac_state = APM_AC_OFF;
817 1.2.8.1 wrstuden break;
818 1.2.8.1 wrstuden
819 1.2.8.1 wrstuden case APM_IOC_NEXTEVENT:
820 1.2.8.1 wrstuden if (!sc->sc_event_count)
821 1.2.8.1 wrstuden return EAGAIN;
822 1.2.8.1 wrstuden
823 1.2.8.1 wrstuden evp = (struct apm_event_info *)data;
824 1.2.8.1 wrstuden i = sc->sc_event_ptr + APM_NEVENTS - sc->sc_event_count;
825 1.2.8.1 wrstuden i %= APM_NEVENTS;
826 1.2.8.1 wrstuden *evp = sc->sc_event_list[i];
827 1.2.8.1 wrstuden sc->sc_event_count--;
828 1.2.8.1 wrstuden return(0);
829 1.2.8.1 wrstuden
830 1.2.8.1 wrstuden /* this ioctl assumes the caller knows exactly what he is doing */
831 1.2.8.1 wrstuden case TCTRL_CMD_REQ:
832 1.2.8.1 wrstuden reqn = (struct tctrl_req *)data;
833 1.2.8.1 wrstuden if ((i = suser(p->p_ucred, &p->p_acflag)) != 0 &&
834 1.2.8.1 wrstuden (reqn->cmdbuf[0] == TS102_OP_CTL_BITPORT ||
835 1.2.8.1 wrstuden (reqn->cmdbuf[0] >= TS102_OP_CTL_WATCHDOG &&
836 1.2.8.1 wrstuden reqn->cmdbuf[0] <= TS102_OP_CTL_SECURITY_KEY) ||
837 1.2.8.1 wrstuden reqn->cmdbuf[0] == TS102_OP_CTL_TIMEZONE ||
838 1.2.8.1 wrstuden reqn->cmdbuf[0] == TS102_OP_CTL_DIAGNOSTIC_MODE ||
839 1.2.8.1 wrstuden reqn->cmdbuf[0] == TS102_OP_CMD_SOFTWARE_RESET ||
840 1.2.8.1 wrstuden (reqn->cmdbuf[0] >= TS102_OP_CMD_SET_RTC &&
841 1.2.8.1 wrstuden reqn->cmdbuf[0] < TS102_OP_RD_INT_CHARGE_LEVEL) ||
842 1.2.8.1 wrstuden reqn->cmdbuf[0] > TS102_OP_RD_EXT_CHARGE_LEVEL))
843 1.2.8.1 wrstuden return(i);
844 1.2.8.1 wrstuden reqn->p = p;
845 1.2.8.1 wrstuden tadpole_request(reqn, 0);
846 1.2.8.1 wrstuden break;
847 1.2.8.1 wrstuden
848 1.2.8.1 wrstuden case ENVSYS_VERSION:
849 1.2.8.1 wrstuden *(int32_t *)data = 1000;
850 1.2.8.1 wrstuden break;
851 1.2.8.1 wrstuden
852 1.2.8.1 wrstuden case ENVSYS_GRANGE:
853 1.2.8.1 wrstuden envrange = (envsys_range_t *)data;
854 1.2.8.1 wrstuden i = 0;
855 1.2.8.1 wrstuden envrange->high = envrange->low = 0;
856 1.2.8.1 wrstuden for (j=0; j < ENVSYS_NUMSENSORS; j++) {
857 1.2.8.1 wrstuden if (!i && envrange->units == sc->sc_esensors[j].units) {
858 1.2.8.1 wrstuden envrange->low = j;
859 1.2.8.1 wrstuden i++;
860 1.2.8.1 wrstuden }
861 1.2.8.1 wrstuden if (i && envrange->units == sc->sc_esensors[j].units)
862 1.2.8.1 wrstuden envrange->high = j;
863 1.2.8.1 wrstuden }
864 1.2.8.1 wrstuden if (!i) {
865 1.2.8.1 wrstuden envrange->high = 0;
866 1.2.8.1 wrstuden envrange->low = 1;
867 1.2.8.1 wrstuden }
868 1.2.8.1 wrstuden break;
869 1.2.8.1 wrstuden
870 1.2.8.1 wrstuden case ENVSYS_GTREDATA:
871 1.2.8.1 wrstuden envdata = (envsys_temp_data_t *)data;
872 1.2.8.1 wrstuden if (envdata->sensor >= ENVSYS_NUMSENSORS) {
873 1.2.8.1 wrstuden envdata->validflags = 0;
874 1.2.8.1 wrstuden break;
875 1.2.8.1 wrstuden }
876 1.2.8.1 wrstuden envdata->warnflags = ENVSYS_WARN_OK;
877 1.2.8.1 wrstuden if (envdata->sensor == 0) {
878 1.2.8.1 wrstuden envdata->validflags |= ENVSYS_FVALID;
879 1.2.8.1 wrstuden req.cmdbuf[0] = TS102_OP_RD_CURRENT_TEMP;
880 1.2.8.1 wrstuden req.cmdlen = 1;
881 1.2.8.1 wrstuden req.rsplen = 2;
882 1.2.8.1 wrstuden req.p = p;
883 1.2.8.1 wrstuden tadpole_request(&req, 0);
884 1.2.8.1 wrstuden envdata->cur.data_us = /* 273160? */
885 1.2.8.1 wrstuden (u_int32_t)((int)((int)req.rspbuf[0]-32)*5000/9+273000);
886 1.2.8.1 wrstuden envdata->validflags |= ENVSYS_FCURVALID;
887 1.2.8.1 wrstuden req.cmdbuf[0] = TS102_OP_RD_MAX_TEMP;
888 1.2.8.1 wrstuden req.cmdlen = 1;
889 1.2.8.1 wrstuden req.rsplen = 2;
890 1.2.8.1 wrstuden req.p = p;
891 1.2.8.1 wrstuden tadpole_request(&req, 0);
892 1.2.8.1 wrstuden envdata->max.data_us =
893 1.2.8.1 wrstuden (u_int32_t)((int)((int)req.rspbuf[0]-32)*5000/9+273000);
894 1.2.8.1 wrstuden envdata->validflags |= ENVSYS_FMAXVALID;
895 1.2.8.1 wrstuden req.cmdbuf[0] = TS102_OP_RD_MIN_TEMP;
896 1.2.8.1 wrstuden req.cmdlen = 1;
897 1.2.8.1 wrstuden req.rsplen = 2;
898 1.2.8.1 wrstuden req.p = p;
899 1.2.8.1 wrstuden tadpole_request(&req, 0);
900 1.2.8.1 wrstuden envdata->min.data_us =
901 1.2.8.1 wrstuden (u_int32_t)((int)((int)req.rspbuf[0]-32)*5000/9+273000);
902 1.2.8.1 wrstuden envdata->validflags |= ENVSYS_FMINVALID;
903 1.2.8.1 wrstuden envdata->units = sc->sc_esensors[envdata->sensor].units;
904 1.2.8.1 wrstuden break;
905 1.2.8.1 wrstuden } else if (envdata->sensor == 1 || envdata->sensor == 2) {
906 1.2.8.1 wrstuden envdata->validflags = ENVSYS_FVALID|ENVSYS_FCURVALID;
907 1.2.8.1 wrstuden envdata->units = sc->sc_esensors[envdata->sensor].units;
908 1.2.8.1 wrstuden if (envdata->sensor == 1)
909 1.2.8.1 wrstuden req.cmdbuf[0] = TS102_OP_RD_INT_BATT_VLT;
910 1.2.8.1 wrstuden else
911 1.2.8.1 wrstuden req.cmdbuf[0] = TS102_OP_RD_DC_IN_VLT;
912 1.2.8.1 wrstuden req.cmdlen = 1;
913 1.2.8.1 wrstuden req.rsplen = 2;
914 1.2.8.1 wrstuden req.p = p;
915 1.2.8.1 wrstuden tadpole_request(&req, 0);
916 1.2.8.1 wrstuden envdata->cur.data_s = (int32_t)req.rspbuf[0]*1000/11;
917 1.2.8.1 wrstuden break;
918 1.2.8.1 wrstuden }
919 1.2.8.1 wrstuden break;
920 1.2.8.1 wrstuden
921 1.2.8.1 wrstuden case ENVSYS_GTREINFO:
922 1.2.8.1 wrstuden envinfo = (envsys_temp_info_t *)data;
923 1.2.8.1 wrstuden if (envinfo->sensor >= ENVSYS_NUMSENSORS) {
924 1.2.8.1 wrstuden envinfo->validflags = 0;
925 1.2.8.1 wrstuden break;
926 1.2.8.1 wrstuden }
927 1.2.8.1 wrstuden envinfo->units = sc->sc_esensors[envinfo->sensor].units;
928 1.2.8.1 wrstuden memcpy(envinfo->desc, sc->sc_esensors[envinfo->sensor].desc,
929 1.2.8.1 wrstuden sizeof(sc->sc_esensors[envinfo->sensor].desc) >
930 1.2.8.1 wrstuden sizeof(envinfo->desc) ? sizeof(envinfo->desc) :
931 1.2.8.1 wrstuden sizeof(sc->sc_esensors[envinfo->sensor].desc));
932 1.2.8.1 wrstuden if (envinfo->units == ENVSYS_STEMP) {
933 1.2.8.1 wrstuden envinfo->validflags = ENVSYS_FVALID|ENVSYS_FCURVALID|
934 1.2.8.1 wrstuden ENVSYS_FMINVALID|ENVSYS_FMAXVALID;
935 1.2.8.1 wrstuden } else if (envinfo->units == ENVSYS_SVOLTS_DC) {
936 1.2.8.1 wrstuden envinfo->validflags = ENVSYS_FVALID|ENVSYS_FCURVALID;
937 1.2.8.1 wrstuden } else
938 1.2.8.1 wrstuden envinfo->validflags = 0;
939 1.2.8.1 wrstuden break;
940 1.2.8.1 wrstuden
941 1.2.8.1 wrstuden case ENVSYS_STREINFO:
942 1.2.8.1 wrstuden envinfo = (envsys_temp_info_t *)data;
943 1.2.8.1 wrstuden if (envinfo->sensor >= ENVSYS_NUMSENSORS) {
944 1.2.8.1 wrstuden envinfo->validflags = 0;
945 1.2.8.1 wrstuden break;
946 1.2.8.1 wrstuden }
947 1.2.8.1 wrstuden if (envinfo->units == sc->sc_esensors[envinfo->sensor].units)
948 1.2.8.1 wrstuden memcpy(sc->sc_esensors[envinfo->sensor].desc,
949 1.2.8.1 wrstuden envinfo->desc,
950 1.2.8.1 wrstuden sizeof(envinfo->desc) > sizeof(char)*32 ?
951 1.2.8.1 wrstuden sizeof(char)*32 : sizeof(envinfo->desc) );
952 1.2.8.1 wrstuden if (envinfo->units == ENVSYS_STEMP) {
953 1.2.8.1 wrstuden envinfo->validflags = ENVSYS_FVALID|ENVSYS_FCURVALID|
954 1.2.8.1 wrstuden ENVSYS_FMINVALID|ENVSYS_FMAXVALID;
955 1.2.8.1 wrstuden } else if (envinfo->units == ENVSYS_SVOLTS_DC) {
956 1.2.8.1 wrstuden envinfo->validflags = ENVSYS_FVALID|ENVSYS_FCURVALID;
957 1.2.8.1 wrstuden } else
958 1.2.8.1 wrstuden envinfo->validflags = 0;
959 1.2.8.1 wrstuden break;
960 1.2.8.1 wrstuden
961 1.2.8.1 wrstuden
962 1.2.8.1 wrstuden default:
963 1.2.8.1 wrstuden return (ENOTTY);
964 1.2.8.1 wrstuden }
965 1.2.8.1 wrstuden return (0);
966 1.2.8.1 wrstuden }
967 1.2.8.1 wrstuden
968 1.2.8.1 wrstuden int
969 1.2.8.1 wrstuden tctrlpoll(dev, events, p)
970 1.2.8.1 wrstuden dev_t dev;
971 1.2.8.1 wrstuden int events;
972 1.2.8.1 wrstuden struct proc *p;
973 1.2.8.1 wrstuden {
974 1.2.8.1 wrstuden struct tctrl_softc *sc = tctrl_cd.cd_devs[TCTRL_STD_DEV];
975 1.2.8.1 wrstuden int revents = 0;
976 1.2.8.1 wrstuden
977 1.2.8.1 wrstuden if (events & (POLLIN | POLLRDNORM)) {
978 1.2.8.1 wrstuden if (sc->sc_event_count)
979 1.2.8.1 wrstuden revents |= events & (POLLIN | POLLRDNORM);
980 1.2.8.1 wrstuden else
981 1.2.8.1 wrstuden selrecord(p, &sc->sc_rsel);
982 1.2.8.1 wrstuden }
983 1.2.8.1 wrstuden
984 1.2.8.1 wrstuden return (revents);
985 1.1 matt }
986