tctrl.c revision 1.2.2.1 1 1.2.2.1 bouyer /* $NetBSD: tctrl.c,v 1.2.2.1 2000/11/20 20:25:34 bouyer 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.2.2.1 bouyer #include <sys/callout.h>
42 1.1 matt #include <sys/ioctl.h>
43 1.1 matt #include <sys/select.h>
44 1.1 matt #include <sys/tty.h>
45 1.1 matt #include <sys/proc.h>
46 1.1 matt #include <sys/user.h>
47 1.1 matt #include <sys/conf.h>
48 1.1 matt #include <sys/file.h>
49 1.1 matt #include <sys/uio.h>
50 1.1 matt #include <sys/kernel.h>
51 1.1 matt #include <sys/syslog.h>
52 1.1 matt #include <sys/types.h>
53 1.1 matt #include <sys/device.h>
54 1.2.2.1 bouyer #include <sys/envsys.h>
55 1.2.2.1 bouyer #include <sys/poll.h>
56 1.1 matt
57 1.2.2.1 bouyer #include <machine/apmvar.h>
58 1.1 matt #include <machine/autoconf.h>
59 1.1 matt #include <machine/bus.h>
60 1.2.2.1 bouyer #include <machine/intr.h>
61 1.2.2.1 bouyer #include <machine/tctrl.h>
62 1.1 matt
63 1.1 matt #include <sparc/dev/ts102reg.h>
64 1.1 matt #include <sparc/dev/tctrlvar.h>
65 1.2.2.1 bouyer #include <sparc/sparc/auxiotwo.h>
66 1.2.2.1 bouyer
67 1.2.2.1 bouyer cdev_decl(tctrl);
68 1.2.2.1 bouyer
69 1.2.2.1 bouyer extern struct cfdriver tctrl_cd;
70 1.1 matt
71 1.1 matt static const char *tctrl_ext_statuses[16] = {
72 1.1 matt "main power available",
73 1.1 matt "internal battery attached",
74 1.1 matt "external battery attached",
75 1.1 matt "external VGA attached",
76 1.1 matt "external keyboard attached",
77 1.1 matt "external mouse attached",
78 1.1 matt "lid down",
79 1.1 matt "internal battery charging",
80 1.1 matt "external battery charging",
81 1.1 matt "internal battery discharging",
82 1.1 matt "external battery discharging",
83 1.1 matt };
84 1.1 matt
85 1.1 matt struct tctrl_softc {
86 1.2.2.1 bouyer struct device sc_dev;
87 1.2.2.1 bouyer bus_space_tag_t sc_memt;
88 1.2.2.1 bouyer bus_space_handle_t sc_memh;
89 1.2.2.1 bouyer unsigned int sc_junk;
90 1.2.2.1 bouyer unsigned int sc_ext_status;
91 1.2.2.1 bouyer unsigned int sc_flags;
92 1.2.2.1 bouyer #define TCTRL_SEND_REQUEST 0x0001
93 1.2.2.1 bouyer #define TCTRL_APM_CTLOPEN 0x0002
94 1.2.2.1 bouyer unsigned int sc_wantdata;
95 1.2.2.1 bouyer volatile unsigned short sc_lcdstate;
96 1.1 matt enum { TCTRL_IDLE, TCTRL_ARGS,
97 1.1 matt TCTRL_ACK, TCTRL_DATA } sc_state;
98 1.2.2.1 bouyer u_int8_t sc_cmdbuf[16];
99 1.2.2.1 bouyer u_int8_t sc_rspbuf[16];
100 1.2.2.1 bouyer u_int8_t sc_bitport;
101 1.2.2.1 bouyer u_int8_t sc_tft_on;
102 1.2.2.1 bouyer u_int8_t sc_op;
103 1.2.2.1 bouyer u_int8_t sc_cmdoff;
104 1.2.2.1 bouyer u_int8_t sc_cmdlen;
105 1.2.2.1 bouyer u_int8_t sc_rspoff;
106 1.2.2.1 bouyer u_int8_t sc_rsplen;
107 1.2.2.1 bouyer /* APM stuff */
108 1.2.2.1 bouyer #define APM_NEVENTS 16
109 1.2.2.1 bouyer struct apm_event_info sc_event_list[APM_NEVENTS];
110 1.2.2.1 bouyer int sc_event_count;
111 1.2.2.1 bouyer int sc_event_ptr;
112 1.2.2.1 bouyer struct selinfo sc_rsel;
113 1.2.2.1 bouyer /* ENVSYS stuff */
114 1.2.2.1 bouyer #define ENVSYS_NUMSENSORS 3
115 1.2.2.1 bouyer struct envsys_sensor sc_esensors[ENVSYS_NUMSENSORS];
116 1.1 matt
117 1.2.2.1 bouyer struct evcnt sc_intrcnt; /* interrupt counting */
118 1.1 matt };
119 1.1 matt
120 1.2.2.1 bouyer #define TCTRL_STD_DEV 0
121 1.2.2.1 bouyer #define TCTRL_APMCTL_DEV 8
122 1.2.2.1 bouyer
123 1.2.2.1 bouyer static struct callout tctrl_event_ch = CALLOUT_INITIALIZER;
124 1.1 matt
125 1.2.2.1 bouyer static int tctrl_match __P((struct device *parent, struct cfdata *cf,
126 1.2.2.1 bouyer void *aux));
127 1.2.2.1 bouyer static void tctrl_attach __P((struct device *parent, struct device *self,
128 1.2.2.1 bouyer void *aux));
129 1.2.2.1 bouyer static void tctrl_write __P((struct tctrl_softc *sc, bus_size_t off,
130 1.2.2.1 bouyer u_int8_t v));
131 1.2.2.1 bouyer static u_int8_t tctrl_read __P((struct tctrl_softc *sc, bus_size_t off));
132 1.2.2.1 bouyer static void tctrl_write_data __P((struct tctrl_softc *sc, u_int8_t v));
133 1.2.2.1 bouyer static u_int8_t tctrl_read_data __P((struct tctrl_softc *sc));
134 1.2.2.1 bouyer static int tctrl_intr __P((void *arg));
135 1.2.2.1 bouyer static void tctrl_setup_bitport __P((void));
136 1.2.2.1 bouyer static void tctrl_setup_bitport_nop __P((void));
137 1.2.2.1 bouyer static void tctrl_read_ext_status __P((void));
138 1.2.2.1 bouyer static void tctrl_read_event_status __P((void *arg));
139 1.2.2.1 bouyer static int tctrl_apm_record_event __P((struct tctrl_softc *sc,
140 1.2.2.1 bouyer u_int event_type));
141 1.2.2.1 bouyer static void tctrl_init_lcd __P((void));
142 1.1 matt
143 1.1 matt struct cfattach tctrl_ca = {
144 1.1 matt sizeof(struct tctrl_softc), tctrl_match, tctrl_attach
145 1.1 matt };
146 1.1 matt
147 1.1 matt extern struct cfdriver tctrl_cd;
148 1.2.2.1 bouyer /* XXX wtf is this? see i386/apm.c */
149 1.2.2.1 bouyer int tctrl_apm_evindex;
150 1.1 matt
151 1.1 matt static int
152 1.2.2.1 bouyer tctrl_match(parent, cf, aux)
153 1.2.2.1 bouyer struct device *parent;
154 1.2.2.1 bouyer struct cfdata *cf;
155 1.2.2.1 bouyer void *aux;
156 1.1 matt {
157 1.1 matt union obio_attach_args *uoba = aux;
158 1.1 matt struct sbus_attach_args *sa = &uoba->uoba_sbus;
159 1.1 matt
160 1.1 matt if (uoba->uoba_isobio4 != 0) {
161 1.1 matt return (0);
162 1.1 matt }
163 1.1 matt
164 1.1 matt /* Tadpole 3GX/3GS uses "uctrl" for the Tadpole Microcontroller
165 1.1 matt * (who's interface is off the TS102 PCMCIA controller but there
166 1.1 matt * exists a OpenProm for microcontroller interface).
167 1.1 matt */
168 1.1 matt return strcmp("uctrl", sa->sa_name) == 0;
169 1.1 matt }
170 1.1 matt
171 1.1 matt static void
172 1.2.2.1 bouyer tctrl_attach(parent, self, aux)
173 1.2.2.1 bouyer struct device *parent;
174 1.2.2.1 bouyer struct device *self;
175 1.2.2.1 bouyer void *aux;
176 1.1 matt {
177 1.1 matt struct tctrl_softc *sc = (void *)self;
178 1.1 matt union obio_attach_args *uoba = aux;
179 1.1 matt struct sbus_attach_args *sa = &uoba->uoba_sbus;
180 1.2 matt unsigned int i, v;
181 1.2 matt #if 0
182 1.1 matt unsigned int ack, msb, lsb;
183 1.2 matt #endif
184 1.1 matt
185 1.1 matt /* We're living on a sbus slot that looks like an obio that
186 1.1 matt * looks like an sbus slot.
187 1.1 matt */
188 1.1 matt sc->sc_memt = sa->sa_bustag;
189 1.1 matt if (sbus_bus_map(sc->sc_memt, sa->sa_slot,
190 1.1 matt sa->sa_offset - TS102_REG_UCTRL_INT, sa->sa_size,
191 1.1 matt BUS_SPACE_MAP_LINEAR, 0,
192 1.1 matt &sc->sc_memh) != 0) {
193 1.1 matt printf(": can't map registers\n");
194 1.1 matt return;
195 1.1 matt }
196 1.1 matt
197 1.2 matt printf("\n");
198 1.2 matt
199 1.1 matt sc->sc_tft_on = 1;
200 1.2 matt
201 1.1 matt /* clear any pending data.
202 1.1 matt */
203 1.1 matt for (i = 0; i < 10000; i++) {
204 1.2.2.1 bouyer if ((TS102_UCTRL_STS_RXNE_STA &
205 1.2.2.1 bouyer tctrl_read(sc, TS102_REG_UCTRL_STS)) == 0) {
206 1.1 matt break;
207 1.1 matt }
208 1.1 matt v = tctrl_read(sc, TS102_REG_UCTRL_DATA);
209 1.2 matt tctrl_write(sc, TS102_REG_UCTRL_STS, TS102_UCTRL_STS_RXNE_STA);
210 1.1 matt }
211 1.1 matt
212 1.2.2.1 bouyer if (sa->sa_nintr != 0) {
213 1.2.2.1 bouyer (void)bus_intr_establish(sc->sc_memt, sa->sa_pri, IPL_NONE,
214 1.2.2.1 bouyer 0, tctrl_intr, sc);
215 1.2.2.1 bouyer evcnt_attach_dynamic(&sc->sc_intrcnt, EVCNT_TYPE_INTR, NULL,
216 1.2.2.1 bouyer sc->sc_dev.dv_xname, "intr");
217 1.2.2.1 bouyer }
218 1.2 matt
219 1.2 matt /* See what the external status is
220 1.2 matt */
221 1.1 matt
222 1.2.2.1 bouyer tctrl_read_ext_status();
223 1.2 matt if (sc->sc_ext_status != 0) {
224 1.2 matt const char *sep;
225 1.1 matt
226 1.1 matt printf("%s: ", sc->sc_dev.dv_xname);
227 1.2 matt v = sc->sc_ext_status;
228 1.1 matt for (i = 0, sep = ""; v != 0; i++, v >>= 1) {
229 1.1 matt if (v & 1) {
230 1.1 matt printf("%s%s", sep, tctrl_ext_statuses[i]);
231 1.1 matt sep = ", ";
232 1.1 matt }
233 1.1 matt }
234 1.1 matt printf("\n");
235 1.1 matt }
236 1.1 matt
237 1.2 matt /* Get a current of the control bitport;
238 1.2 matt */
239 1.2.2.1 bouyer tctrl_setup_bitport_nop();
240 1.2 matt tctrl_write(sc, TS102_REG_UCTRL_INT,
241 1.2 matt TS102_UCTRL_INT_RXNE_REQ|TS102_UCTRL_INT_RXNE_MSK);
242 1.1 matt
243 1.2.2.1 bouyer sc->sc_wantdata = 0;
244 1.2.2.1 bouyer sc->sc_event_count = 0;
245 1.2.2.1 bouyer
246 1.2.2.1 bouyer /* prime the sensor data */
247 1.2.2.1 bouyer sprintf(sc->sc_esensors[0].desc, "%s", "Internal Unit Temperature");
248 1.2.2.1 bouyer sc->sc_esensors[0].units = ENVSYS_STEMP;
249 1.2.2.1 bouyer sprintf(sc->sc_esensors[1].desc, "%s", "Internal Battery Voltage");
250 1.2.2.1 bouyer sc->sc_esensors[1].units = ENVSYS_SVOLTS_DC;
251 1.2.2.1 bouyer sprintf(sc->sc_esensors[2].desc, "%s", "DC-In Voltage");
252 1.2.2.1 bouyer sc->sc_esensors[2].units = ENVSYS_SVOLTS_DC;
253 1.2.2.1 bouyer
254 1.2.2.1 bouyer /* initialize the LCD */
255 1.2.2.1 bouyer tctrl_init_lcd();
256 1.2.2.1 bouyer
257 1.2.2.1 bouyer /* initialize sc_lcdstate */
258 1.2.2.1 bouyer sc->sc_lcdstate = 0;
259 1.2.2.1 bouyer tctrl_set_lcd(2, 0);
260 1.1 matt }
261 1.1 matt
262 1.1 matt static int
263 1.2.2.1 bouyer tctrl_intr(arg)
264 1.2.2.1 bouyer void *arg;
265 1.1 matt {
266 1.1 matt struct tctrl_softc *sc = arg;
267 1.1 matt unsigned int v, d;
268 1.1 matt int progress = 0;
269 1.1 matt
270 1.1 matt again:
271 1.1 matt /* find out the cause(s) of the interrupt */
272 1.2.2.1 bouyer v = tctrl_read(sc, TS102_REG_UCTRL_STS) & TS102_UCTRL_STS_MASK;
273 1.1 matt
274 1.1 matt /* clear the cause(s) of the interrupt */
275 1.1 matt tctrl_write(sc, TS102_REG_UCTRL_STS, v);
276 1.1 matt
277 1.2 matt v &= ~(TS102_UCTRL_STS_RXO_STA|TS102_UCTRL_STS_TXE_STA);
278 1.1 matt if (sc->sc_cmdoff >= sc->sc_cmdlen) {
279 1.2 matt v &= ~TS102_UCTRL_STS_TXNF_STA;
280 1.2.2.1 bouyer if (tctrl_read(sc, TS102_REG_UCTRL_INT) & TS102_UCTRL_INT_TXNF_REQ) {
281 1.2.2.1 bouyer tctrl_write(sc, TS102_REG_UCTRL_INT, 0);
282 1.2.2.1 bouyer progress = 1;
283 1.2.2.1 bouyer }
284 1.1 matt }
285 1.2.2.1 bouyer if ((v == 0) && ((sc->sc_flags & TCTRL_SEND_REQUEST) == 0 ||
286 1.2.2.1 bouyer sc->sc_state != TCTRL_IDLE)) {
287 1.2.2.1 bouyer wakeup(sc);
288 1.1 matt return progress;
289 1.1 matt }
290 1.1 matt
291 1.1 matt progress = 1;
292 1.2 matt if (v & TS102_UCTRL_STS_RXNE_STA) {
293 1.1 matt d = tctrl_read_data(sc);
294 1.1 matt switch (sc->sc_state) {
295 1.1 matt case TCTRL_IDLE:
296 1.2 matt if (d == 0xfa) {
297 1.2.2.1 bouyer /* external event */
298 1.2.2.1 bouyer callout_reset(&tctrl_event_ch, 1,
299 1.2.2.1 bouyer tctrl_read_event_status, NULL);
300 1.2 matt } else {
301 1.2 matt printf("%s: (op=0x%02x): unexpected data (0x%02x)\n",
302 1.2 matt sc->sc_dev.dv_xname, sc->sc_op, d);
303 1.1 matt }
304 1.2 matt goto again;
305 1.1 matt case TCTRL_ACK:
306 1.1 matt if (d != 0xfe) {
307 1.2 matt printf("%s: (op=0x%02x): unexpected ack value (0x%02x)\n",
308 1.1 matt sc->sc_dev.dv_xname, sc->sc_op, d);
309 1.1 matt }
310 1.2.2.1 bouyer #ifdef TCTRLDEBUG
311 1.2 matt printf(" ack=0x%02x", d);
312 1.2 matt #endif
313 1.2 matt sc->sc_rsplen--;
314 1.2 matt sc->sc_rspoff = 0;
315 1.1 matt sc->sc_state = sc->sc_rsplen ? TCTRL_DATA : TCTRL_IDLE;
316 1.2.2.1 bouyer sc->sc_wantdata = sc->sc_rsplen ? 1 : 0;
317 1.2.2.1 bouyer #ifdef TCTRLDEBUG
318 1.2 matt if (sc->sc_rsplen > 0) {
319 1.2 matt printf(" [data(%u)]", sc->sc_rsplen);
320 1.2 matt } else {
321 1.2 matt printf(" [idle]\n");
322 1.2 matt }
323 1.2 matt #endif
324 1.2 matt goto again;
325 1.1 matt case TCTRL_DATA:
326 1.1 matt sc->sc_rspbuf[sc->sc_rspoff++] = d;
327 1.2.2.1 bouyer #ifdef TCTRLDEBUG
328 1.2 matt printf(" [%d]=0x%02x", sc->sc_rspoff-1, d);
329 1.2 matt #endif
330 1.1 matt if (sc->sc_rspoff == sc->sc_rsplen) {
331 1.2.2.1 bouyer #ifdef TCTRLDEBUG
332 1.2 matt printf(" [idle]\n");
333 1.2 matt #endif
334 1.1 matt sc->sc_state = TCTRL_IDLE;
335 1.2.2.1 bouyer sc->sc_wantdata = 0;
336 1.1 matt }
337 1.2 matt goto again;
338 1.1 matt default:
339 1.1 matt printf("%s: (op=0x%02x): unexpected data (0x%02x) in state %d\n",
340 1.1 matt sc->sc_dev.dv_xname, sc->sc_op, d, sc->sc_state);
341 1.2 matt goto again;
342 1.1 matt }
343 1.1 matt }
344 1.2.2.1 bouyer if ((sc->sc_state == TCTRL_IDLE && sc->sc_wantdata == 0) ||
345 1.2.2.1 bouyer sc->sc_flags & TCTRL_SEND_REQUEST) {
346 1.2.2.1 bouyer if (sc->sc_flags & TCTRL_SEND_REQUEST) {
347 1.2.2.1 bouyer sc->sc_flags &= ~TCTRL_SEND_REQUEST;
348 1.2.2.1 bouyer sc->sc_wantdata = 1;
349 1.2.2.1 bouyer }
350 1.1 matt if (sc->sc_cmdlen > 0) {
351 1.1 matt tctrl_write(sc, TS102_REG_UCTRL_INT,
352 1.1 matt tctrl_read(sc, TS102_REG_UCTRL_INT)
353 1.1 matt |TS102_UCTRL_INT_TXNF_MSK
354 1.1 matt |TS102_UCTRL_INT_TXNF_REQ);
355 1.1 matt v = tctrl_read(sc, TS102_REG_UCTRL_STS);
356 1.1 matt }
357 1.1 matt }
358 1.2 matt if ((sc->sc_cmdoff < sc->sc_cmdlen) && (v & TS102_UCTRL_STS_TXNF_STA)) {
359 1.1 matt tctrl_write_data(sc, sc->sc_cmdbuf[sc->sc_cmdoff++]);
360 1.2.2.1 bouyer #ifdef TCTRLDEBUG
361 1.2 matt if (sc->sc_cmdoff == 1) {
362 1.2 matt printf("%s: op=0x%02x(l=%u)", sc->sc_dev.dv_xname,
363 1.2 matt sc->sc_cmdbuf[0], sc->sc_rsplen);
364 1.2 matt } else {
365 1.2 matt printf(" [%d]=0x%02x", sc->sc_cmdoff-1,
366 1.2 matt sc->sc_cmdbuf[sc->sc_cmdoff-1]);
367 1.2 matt }
368 1.2 matt #endif
369 1.1 matt if (sc->sc_cmdoff == sc->sc_cmdlen) {
370 1.1 matt sc->sc_state = sc->sc_rsplen ? TCTRL_ACK : TCTRL_IDLE;
371 1.2.2.1 bouyer #ifdef TCTRLDEBUG
372 1.2 matt printf(" %s", sc->sc_rsplen ? "[ack]" : "[idle]\n");
373 1.2 matt #endif
374 1.2 matt if (sc->sc_cmdoff == 1) {
375 1.2 matt sc->sc_op = sc->sc_cmdbuf[0];
376 1.2 matt }
377 1.1 matt tctrl_write(sc, TS102_REG_UCTRL_INT,
378 1.1 matt tctrl_read(sc, TS102_REG_UCTRL_INT)
379 1.1 matt & (~TS102_UCTRL_INT_TXNF_MSK
380 1.1 matt |TS102_UCTRL_INT_TXNF_REQ));
381 1.1 matt } else if (sc->sc_state == TCTRL_IDLE) {
382 1.1 matt sc->sc_op = sc->sc_cmdbuf[0];
383 1.1 matt sc->sc_state = TCTRL_ARGS;
384 1.2.2.1 bouyer #ifdef TCTRLDEBUG
385 1.2 matt printf(" [args]");
386 1.2 matt #endif
387 1.1 matt }
388 1.1 matt }
389 1.1 matt goto again;
390 1.1 matt }
391 1.1 matt
392 1.1 matt static void
393 1.2.2.1 bouyer tctrl_setup_bitport_nop(void)
394 1.2.2.1 bouyer {
395 1.2.2.1 bouyer struct tctrl_softc *sc;
396 1.2.2.1 bouyer struct tctrl_req req;
397 1.2.2.1 bouyer int s;
398 1.2.2.1 bouyer
399 1.2.2.1 bouyer sc = (struct tctrl_softc *) tctrl_cd.cd_devs[TCTRL_STD_DEV];
400 1.2.2.1 bouyer req.cmdbuf[0] = TS102_OP_CTL_BITPORT;
401 1.2.2.1 bouyer req.cmdbuf[1] = 0xff;
402 1.2.2.1 bouyer req.cmdbuf[2] = 0;
403 1.2.2.1 bouyer req.cmdlen = 3;
404 1.2.2.1 bouyer req.rsplen = 2;
405 1.2.2.1 bouyer req.p = NULL;
406 1.2.2.1 bouyer tadpole_request(&req, 1);
407 1.2.2.1 bouyer s = splts102();
408 1.2.2.1 bouyer sc->sc_bitport = (req.rspbuf[0] & req.cmdbuf[1]) ^ req.cmdbuf[2];
409 1.2.2.1 bouyer splx(s);
410 1.2.2.1 bouyer }
411 1.2.2.1 bouyer
412 1.2.2.1 bouyer static void
413 1.2.2.1 bouyer tctrl_setup_bitport(void)
414 1.1 matt {
415 1.2.2.1 bouyer struct tctrl_softc *sc;
416 1.2.2.1 bouyer struct tctrl_req req;
417 1.2.2.1 bouyer int s;
418 1.2.2.1 bouyer
419 1.2.2.1 bouyer sc = (struct tctrl_softc *) tctrl_cd.cd_devs[TCTRL_STD_DEV];
420 1.2.2.1 bouyer s = splts102();
421 1.2.2.1 bouyer if ((sc->sc_ext_status & TS102_EXT_STATUS_LID_DOWN)
422 1.2.2.1 bouyer || (!sc->sc_tft_on)) {
423 1.2.2.1 bouyer req.cmdbuf[2] = TS102_BITPORT_TFTPWR;
424 1.1 matt } else {
425 1.2.2.1 bouyer req.cmdbuf[2] = 0;
426 1.1 matt }
427 1.2.2.1 bouyer req.cmdbuf[0] = TS102_OP_CTL_BITPORT;
428 1.2.2.1 bouyer req.cmdbuf[1] = ~TS102_BITPORT_TFTPWR;
429 1.2.2.1 bouyer req.cmdlen = 3;
430 1.2.2.1 bouyer req.rsplen = 2;
431 1.2.2.1 bouyer req.p = NULL;
432 1.2.2.1 bouyer tadpole_request(&req, 1);
433 1.2.2.1 bouyer s = splts102();
434 1.2.2.1 bouyer sc->sc_bitport = (req.rspbuf[0] & req.cmdbuf[1]) ^ req.cmdbuf[2];
435 1.2.2.1 bouyer splx(s);
436 1.1 matt }
437 1.1 matt
438 1.2.2.1 bouyer /*
439 1.2.2.1 bouyer * The tadpole microcontroller is not preprogrammed with icon
440 1.2.2.1 bouyer * representations. The machine boots with the DC-IN light as
441 1.2.2.1 bouyer * a blank (all 0x00) and the other lights, as 4 rows of horizontal
442 1.2.2.1 bouyer * bars. The below code initializes the icons in the system to
443 1.2.2.1 bouyer * sane values. Some of these icons could be used for any purpose
444 1.2.2.1 bouyer * desired, namely the pcmcia, LAN and WAN lights. For the disk spinner,
445 1.2.2.1 bouyer * only the backslash is unprogrammed. (sigh)
446 1.2.2.1 bouyer *
447 1.2.2.1 bouyer * programming the icons is simple. It is a 5x8 matrix, which each row a
448 1.2.2.1 bouyer * bitfield in the order 0x10 0x08 0x04 0x02 0x01.
449 1.2.2.1 bouyer */
450 1.2.2.1 bouyer
451 1.1 matt static void
452 1.2.2.1 bouyer tctrl_init_lcd(void)
453 1.1 matt {
454 1.2.2.1 bouyer struct tctrl_req req;
455 1.2.2.1 bouyer
456 1.2.2.1 bouyer req.cmdbuf[0] = TS102_OP_BLK_DEF_SPCL_CHAR;
457 1.2.2.1 bouyer req.cmdlen = 11;
458 1.2.2.1 bouyer req.rsplen = 1;
459 1.2.2.1 bouyer req.cmdbuf[1] = 0x08; /*len*/
460 1.2.2.1 bouyer req.cmdbuf[2] = TS102_BLK_OFF_DEF_DC_GOOD;
461 1.2.2.1 bouyer req.cmdbuf[3] = 0x00; /* ..... */
462 1.2.2.1 bouyer req.cmdbuf[4] = 0x00; /* ..... */
463 1.2.2.1 bouyer req.cmdbuf[5] = 0x1f; /* XXXXX */
464 1.2.2.1 bouyer req.cmdbuf[6] = 0x00; /* ..... */
465 1.2.2.1 bouyer req.cmdbuf[7] = 0x15; /* X.X.X */
466 1.2.2.1 bouyer req.cmdbuf[8] = 0x00; /* ..... */
467 1.2.2.1 bouyer req.cmdbuf[9] = 0x00; /* ..... */
468 1.2.2.1 bouyer req.cmdbuf[10] = 0x00; /* ..... */
469 1.2.2.1 bouyer req.p = NULL;
470 1.2.2.1 bouyer tadpole_request(&req, 1);
471 1.2.2.1 bouyer
472 1.2.2.1 bouyer req.cmdbuf[0] = TS102_OP_BLK_DEF_SPCL_CHAR;
473 1.2.2.1 bouyer req.cmdlen = 11;
474 1.2.2.1 bouyer req.rsplen = 1;
475 1.2.2.1 bouyer req.cmdbuf[1] = 0x08; /*len*/
476 1.2.2.1 bouyer req.cmdbuf[2] = TS102_BLK_OFF_DEF_BACKSLASH;
477 1.2.2.1 bouyer req.cmdbuf[3] = 0x00; /* ..... */
478 1.2.2.1 bouyer req.cmdbuf[4] = 0x10; /* X.... */
479 1.2.2.1 bouyer req.cmdbuf[5] = 0x08; /* .X... */
480 1.2.2.1 bouyer req.cmdbuf[6] = 0x04; /* ..X.. */
481 1.2.2.1 bouyer req.cmdbuf[7] = 0x02; /* ...X. */
482 1.2.2.1 bouyer req.cmdbuf[8] = 0x01; /* ....X */
483 1.2.2.1 bouyer req.cmdbuf[9] = 0x00; /* ..... */
484 1.2.2.1 bouyer req.cmdbuf[10] = 0x00; /* ..... */
485 1.2.2.1 bouyer req.p = NULL;
486 1.2.2.1 bouyer tadpole_request(&req, 1);
487 1.2.2.1 bouyer
488 1.2.2.1 bouyer req.cmdbuf[0] = TS102_OP_BLK_DEF_SPCL_CHAR;
489 1.2.2.1 bouyer req.cmdlen = 11;
490 1.2.2.1 bouyer req.rsplen = 1;
491 1.2.2.1 bouyer req.cmdbuf[1] = 0x08; /*len*/
492 1.2.2.1 bouyer req.cmdbuf[2] = TS102_BLK_OFF_DEF_WAN1;
493 1.2.2.1 bouyer req.cmdbuf[3] = 0x0c; /* .XXX. */
494 1.2.2.1 bouyer req.cmdbuf[4] = 0x16; /* X.XX. */
495 1.2.2.1 bouyer req.cmdbuf[5] = 0x10; /* X.... */
496 1.2.2.1 bouyer req.cmdbuf[6] = 0x15; /* X.X.X */
497 1.2.2.1 bouyer req.cmdbuf[7] = 0x10; /* X.... */
498 1.2.2.1 bouyer req.cmdbuf[8] = 0x16; /* X.XX. */
499 1.2.2.1 bouyer req.cmdbuf[9] = 0x0c; /* .XXX. */
500 1.2.2.1 bouyer req.cmdbuf[10] = 0x00; /* ..... */
501 1.2.2.1 bouyer req.p = NULL;
502 1.2.2.1 bouyer tadpole_request(&req, 1);
503 1.2.2.1 bouyer
504 1.2.2.1 bouyer req.cmdbuf[0] = TS102_OP_BLK_DEF_SPCL_CHAR;
505 1.2.2.1 bouyer req.cmdlen = 11;
506 1.2.2.1 bouyer req.rsplen = 1;
507 1.2.2.1 bouyer req.cmdbuf[1] = 0x08; /*len*/
508 1.2.2.1 bouyer req.cmdbuf[2] = TS102_BLK_OFF_DEF_WAN2;
509 1.2.2.1 bouyer req.cmdbuf[3] = 0x0c; /* .XXX. */
510 1.2.2.1 bouyer req.cmdbuf[4] = 0x0d; /* .XX.X */
511 1.2.2.1 bouyer req.cmdbuf[5] = 0x01; /* ....X */
512 1.2.2.1 bouyer req.cmdbuf[6] = 0x15; /* X.X.X */
513 1.2.2.1 bouyer req.cmdbuf[7] = 0x01; /* ....X */
514 1.2.2.1 bouyer req.cmdbuf[8] = 0x0d; /* .XX.X */
515 1.2.2.1 bouyer req.cmdbuf[9] = 0x0c; /* .XXX. */
516 1.2.2.1 bouyer req.cmdbuf[10] = 0x00; /* ..... */
517 1.2.2.1 bouyer req.p = NULL;
518 1.2.2.1 bouyer tadpole_request(&req, 1);
519 1.2.2.1 bouyer
520 1.2.2.1 bouyer req.cmdbuf[0] = TS102_OP_BLK_DEF_SPCL_CHAR;
521 1.2.2.1 bouyer req.cmdlen = 11;
522 1.2.2.1 bouyer req.rsplen = 1;
523 1.2.2.1 bouyer req.cmdbuf[1] = 0x08; /*len*/
524 1.2.2.1 bouyer req.cmdbuf[2] = TS102_BLK_OFF_DEF_LAN1;
525 1.2.2.1 bouyer req.cmdbuf[3] = 0x00; /* ..... */
526 1.2.2.1 bouyer req.cmdbuf[4] = 0x04; /* ..X.. */
527 1.2.2.1 bouyer req.cmdbuf[5] = 0x08; /* .X... */
528 1.2.2.1 bouyer req.cmdbuf[6] = 0x13; /* X..XX */
529 1.2.2.1 bouyer req.cmdbuf[7] = 0x08; /* .X... */
530 1.2.2.1 bouyer req.cmdbuf[8] = 0x04; /* ..X.. */
531 1.2.2.1 bouyer req.cmdbuf[9] = 0x00; /* ..... */
532 1.2.2.1 bouyer req.cmdbuf[10] = 0x00; /* ..... */
533 1.2.2.1 bouyer req.p = NULL;
534 1.2.2.1 bouyer tadpole_request(&req, 1);
535 1.2.2.1 bouyer
536 1.2.2.1 bouyer req.cmdbuf[0] = TS102_OP_BLK_DEF_SPCL_CHAR;
537 1.2.2.1 bouyer req.cmdlen = 11;
538 1.2.2.1 bouyer req.rsplen = 1;
539 1.2.2.1 bouyer req.cmdbuf[1] = 0x08; /*len*/
540 1.2.2.1 bouyer req.cmdbuf[2] = TS102_BLK_OFF_DEF_LAN2;
541 1.2.2.1 bouyer req.cmdbuf[3] = 0x00; /* ..... */
542 1.2.2.1 bouyer req.cmdbuf[4] = 0x04; /* ..X.. */
543 1.2.2.1 bouyer req.cmdbuf[5] = 0x02; /* ...X. */
544 1.2.2.1 bouyer req.cmdbuf[6] = 0x19; /* XX..X */
545 1.2.2.1 bouyer req.cmdbuf[7] = 0x02; /* ...X. */
546 1.2.2.1 bouyer req.cmdbuf[8] = 0x04; /* ..X.. */
547 1.2.2.1 bouyer req.cmdbuf[9] = 0x00; /* ..... */
548 1.2.2.1 bouyer req.cmdbuf[10] = 0x00; /* ..... */
549 1.2.2.1 bouyer req.p = NULL;
550 1.2.2.1 bouyer tadpole_request(&req, 1);
551 1.2.2.1 bouyer
552 1.2.2.1 bouyer req.cmdbuf[0] = TS102_OP_BLK_DEF_SPCL_CHAR;
553 1.2.2.1 bouyer req.cmdlen = 11;
554 1.2.2.1 bouyer req.rsplen = 1;
555 1.2.2.1 bouyer req.cmdbuf[1] = 0x08; /*len*/
556 1.2.2.1 bouyer req.cmdbuf[2] = TS102_BLK_OFF_DEF_PCMCIA;
557 1.2.2.1 bouyer req.cmdbuf[3] = 0x00; /* ..... */
558 1.2.2.1 bouyer req.cmdbuf[4] = 0x0c; /* .XXX. */
559 1.2.2.1 bouyer req.cmdbuf[5] = 0x1f; /* XXXXX */
560 1.2.2.1 bouyer req.cmdbuf[6] = 0x1f; /* XXXXX */
561 1.2.2.1 bouyer req.cmdbuf[7] = 0x1f; /* XXXXX */
562 1.2.2.1 bouyer req.cmdbuf[8] = 0x1f; /* XXXXX */
563 1.2.2.1 bouyer req.cmdbuf[9] = 0x00; /* ..... */
564 1.2.2.1 bouyer req.cmdbuf[10] = 0x00; /* ..... */
565 1.2.2.1 bouyer req.p = NULL;
566 1.2.2.1 bouyer tadpole_request(&req, 1);
567 1.2.2.1 bouyer }
568 1.2.2.1 bouyer
569 1.2.2.1 bouyer
570 1.2.2.1 bouyer
571 1.2.2.1 bouyer /*
572 1.2.2.1 bouyer * set the blinken-lights on the lcd. what:
573 1.2.2.1 bouyer * what = 0 off, what = 1 on, what = 2 toggle
574 1.2.2.1 bouyer */
575 1.2.2.1 bouyer
576 1.2.2.1 bouyer void
577 1.2.2.1 bouyer tctrl_set_lcd(what, which)
578 1.2.2.1 bouyer int what;
579 1.2.2.1 bouyer unsigned short which;
580 1.2.2.1 bouyer {
581 1.2.2.1 bouyer struct tctrl_softc *sc;
582 1.2.2.1 bouyer struct tctrl_req req;
583 1.2.2.1 bouyer int s;
584 1.2.2.1 bouyer
585 1.2.2.1 bouyer sc = (struct tctrl_softc *) tctrl_cd.cd_devs[TCTRL_STD_DEV];
586 1.2.2.1 bouyer s = splts102();
587 1.2.2.1 bouyer
588 1.2.2.1 bouyer /* provide a quick exit to save cpu time */
589 1.2.2.1 bouyer if ((what == 1 && sc->sc_lcdstate & which) ||
590 1.2.2.1 bouyer (what == 0 && !(sc->sc_lcdstate & which))) {
591 1.2.2.1 bouyer splx(s);
592 1.2.2.1 bouyer return;
593 1.1 matt }
594 1.2.2.1 bouyer /*
595 1.2.2.1 bouyer * the mask setup on this particular command is *very* bizzare
596 1.2.2.1 bouyer * and totally undocumented.
597 1.2.2.1 bouyer */
598 1.2.2.1 bouyer if ((what == 1) || (what == 2 && !(sc->sc_lcdstate & which))) {
599 1.2.2.1 bouyer req.cmdbuf[2] = (u_int8_t)(which&0xff);
600 1.2.2.1 bouyer req.cmdbuf[3] = (u_int8_t)(which>>8);
601 1.2.2.1 bouyer } else {
602 1.2.2.1 bouyer req.cmdbuf[2] = 0;
603 1.2.2.1 bouyer req.cmdbuf[3] = 0;
604 1.2.2.1 bouyer }
605 1.2.2.1 bouyer req.cmdbuf[0] = TS102_OP_CTL_LCD;
606 1.2.2.1 bouyer req.cmdbuf[4] = (u_int8_t)(~which>>8);
607 1.2.2.1 bouyer req.cmdbuf[1] = (u_int8_t)(~which&0xff);
608 1.2.2.1 bouyer
609 1.2.2.1 bouyer /* XXX this thing is wierd.... */
610 1.2.2.1 bouyer req.cmdlen = 3;
611 1.2.2.1 bouyer req.rsplen = 2;
612 1.2 matt #if 0
613 1.2.2.1 bouyer req.cmdlen = 5;
614 1.2.2.1 bouyer req.rsplen = 4;
615 1.2 matt #endif
616 1.2.2.1 bouyer req.p = NULL;
617 1.2.2.1 bouyer tadpole_request(&req, 1);
618 1.2.2.1 bouyer s = splts102();
619 1.2.2.1 bouyer sc->sc_lcdstate = (unsigned short)req.rspbuf[0];
620 1.2.2.1 bouyer splx(s);
621 1.2.2.1 bouyer }
622 1.2.2.1 bouyer
623 1.2.2.1 bouyer static void
624 1.2.2.1 bouyer tctrl_read_ext_status(void)
625 1.2.2.1 bouyer {
626 1.2.2.1 bouyer struct tctrl_softc *sc;
627 1.2.2.1 bouyer struct tctrl_req req;
628 1.2.2.1 bouyer int s;
629 1.2.2.1 bouyer
630 1.2.2.1 bouyer sc = (struct tctrl_softc *) tctrl_cd.cd_devs[TCTRL_STD_DEV];
631 1.2.2.1 bouyer req.cmdbuf[0] = TS102_OP_RD_EXT_STATUS;
632 1.2.2.1 bouyer req.cmdlen = 1;
633 1.2.2.1 bouyer req.rsplen = 3;
634 1.2.2.1 bouyer req.p = NULL;
635 1.2.2.1 bouyer #ifdef TCTRLDEBUG
636 1.2.2.1 bouyer printf("pre read: sc->sc_ext_status = 0x%x\n", sc->sc_ext_status);
637 1.2.2.1 bouyer #endif
638 1.2.2.1 bouyer tadpole_request(&req, 1);
639 1.2.2.1 bouyer s = splts102();
640 1.2.2.1 bouyer sc->sc_ext_status = req.rspbuf[0] * 256 + req.rspbuf[1];
641 1.2.2.1 bouyer splx(s);
642 1.2.2.1 bouyer #ifdef TCTRLDEBUG
643 1.2.2.1 bouyer printf("post read: sc->sc_ext_status = 0x%x\n", sc->sc_ext_status);
644 1.2.2.1 bouyer #endif
645 1.2.2.1 bouyer }
646 1.2.2.1 bouyer
647 1.2.2.1 bouyer /*
648 1.2.2.1 bouyer * return 0 if the user will notice and handle the event,
649 1.2.2.1 bouyer * return 1 if the kernel driver should do so.
650 1.2.2.1 bouyer */
651 1.2.2.1 bouyer static int
652 1.2.2.1 bouyer tctrl_apm_record_event(sc, event_type)
653 1.2.2.1 bouyer struct tctrl_softc *sc;
654 1.2.2.1 bouyer u_int event_type;
655 1.2.2.1 bouyer {
656 1.2.2.1 bouyer struct apm_event_info *evp;
657 1.2.2.1 bouyer
658 1.2.2.1 bouyer if ((sc->sc_flags & TCTRL_APM_CTLOPEN) &&
659 1.2.2.1 bouyer (sc->sc_event_count < APM_NEVENTS)) {
660 1.2.2.1 bouyer evp = &sc->sc_event_list[sc->sc_event_ptr];
661 1.2.2.1 bouyer sc->sc_event_count++;
662 1.2.2.1 bouyer sc->sc_event_ptr++;
663 1.2.2.1 bouyer sc->sc_event_ptr %= APM_NEVENTS;
664 1.2.2.1 bouyer evp->type = event_type;
665 1.2.2.1 bouyer evp->index = ++tctrl_apm_evindex;
666 1.2.2.1 bouyer selwakeup(&sc->sc_rsel);
667 1.2.2.1 bouyer return(sc->sc_flags & TCTRL_APM_CTLOPEN) ? 0 : 1;
668 1.1 matt }
669 1.2.2.1 bouyer return(1);
670 1.2.2.1 bouyer }
671 1.2.2.1 bouyer
672 1.2.2.1 bouyer static void
673 1.2.2.1 bouyer tctrl_read_event_status(arg)
674 1.2.2.1 bouyer void *arg;
675 1.2.2.1 bouyer {
676 1.2.2.1 bouyer struct tctrl_softc *sc;
677 1.2.2.1 bouyer struct tctrl_req req;
678 1.2.2.1 bouyer int s;
679 1.2.2.1 bouyer unsigned int v;
680 1.2.2.1 bouyer
681 1.2.2.1 bouyer sc = (struct tctrl_softc *) tctrl_cd.cd_devs[TCTRL_STD_DEV];
682 1.2.2.1 bouyer req.cmdbuf[0] = TS102_OP_RD_EVENT_STATUS;
683 1.2.2.1 bouyer req.cmdlen = 1;
684 1.2.2.1 bouyer req.rsplen = 3;
685 1.2.2.1 bouyer req.p = NULL;
686 1.2.2.1 bouyer tadpole_request(&req, 1);
687 1.2.2.1 bouyer s = splts102();
688 1.2.2.1 bouyer v = req.rspbuf[0] * 256 + req.rspbuf[1];
689 1.2.2.1 bouyer if (v & TS102_EVENT_STATUS_SHUTDOWN_REQUEST) {
690 1.2.2.1 bouyer printf("%s: SHUTDOWN REQUEST!\n", sc->sc_dev.dv_xname);
691 1.2.2.1 bouyer }
692 1.2.2.1 bouyer if (v & TS102_EVENT_STATUS_VERY_LOW_POWER_WARNING) {
693 1.2.2.1 bouyer /*printf("%s: VERY LOW POWER WARNING!\n", sc->sc_dev.dv_xname);*/
694 1.2.2.1 bouyer /* according to a tadpole header, and observation */
695 1.2.2.1 bouyer #ifdef TCTRLDEBUG
696 1.2.2.1 bouyer printf("%s: Battery charge level change\n", sc->sc_dev.dv_xname);
697 1.2.2.1 bouyer #endif
698 1.1 matt }
699 1.2.2.1 bouyer if (v & TS102_EVENT_STATUS_LOW_POWER_WARNING) {
700 1.2.2.1 bouyer if (tctrl_apm_record_event(sc, APM_BATTERY_LOW))
701 1.2.2.1 bouyer printf("%s: LOW POWER WARNING!\n", sc->sc_dev.dv_xname);
702 1.2.2.1 bouyer }
703 1.2.2.1 bouyer if (v & TS102_EVENT_STATUS_DC_STATUS_CHANGE) {
704 1.2.2.1 bouyer splx(s);
705 1.2.2.1 bouyer tctrl_read_ext_status();
706 1.2.2.1 bouyer s = splts102();
707 1.2.2.1 bouyer if (tctrl_apm_record_event(sc, APM_POWER_CHANGE))
708 1.2.2.1 bouyer printf("%s: main power %s\n", sc->sc_dev.dv_xname,
709 1.2.2.1 bouyer (sc->sc_ext_status &
710 1.2.2.1 bouyer TS102_EXT_STATUS_MAIN_POWER_AVAILABLE) ?
711 1.2.2.1 bouyer "restored" : "removed");
712 1.2.2.1 bouyer }
713 1.2.2.1 bouyer if (v & TS102_EVENT_STATUS_LID_STATUS_CHANGE) {
714 1.2.2.1 bouyer splx(s);
715 1.2.2.1 bouyer tctrl_read_ext_status();
716 1.2.2.1 bouyer tctrl_setup_bitport();
717 1.2.2.1 bouyer #ifdef TCTRLDEBUG
718 1.2.2.1 bouyer printf("%s: lid %s\n", sc->sc_dev.dv_xname,
719 1.2.2.1 bouyer (sc->sc_ext_status & TS102_EXT_STATUS_LID_DOWN)
720 1.2.2.1 bouyer ? "closed" : "opened");
721 1.2.2.1 bouyer #endif
722 1.2.2.1 bouyer }
723 1.2.2.1 bouyer splx(s);
724 1.1 matt }
725 1.1 matt
726 1.1 matt void
727 1.2.2.1 bouyer tadpole_request(req, spin)
728 1.2.2.1 bouyer struct tctrl_req *req;
729 1.2.2.1 bouyer int spin;
730 1.1 matt {
731 1.1 matt struct tctrl_softc *sc;
732 1.1 matt int i, s;
733 1.1 matt
734 1.1 matt if (tctrl_cd.cd_devs == NULL
735 1.1 matt || tctrl_cd.cd_ndevs == 0
736 1.2.2.1 bouyer || tctrl_cd.cd_devs[TCTRL_STD_DEV] == NULL) {
737 1.1 matt return;
738 1.1 matt }
739 1.1 matt
740 1.2.2.1 bouyer sc = (struct tctrl_softc *) tctrl_cd.cd_devs[TCTRL_STD_DEV];
741 1.2.2.1 bouyer while (sc->sc_wantdata != 0) {
742 1.2.2.1 bouyer if (req->p != NULL)
743 1.2.2.1 bouyer tsleep(&sc->sc_wantdata, PLOCK, "tctrl_lock", 10);
744 1.2.2.1 bouyer else
745 1.2.2.1 bouyer DELAY(1);
746 1.2.2.1 bouyer }
747 1.2.2.1 bouyer if (spin)
748 1.2.2.1 bouyer s = splhigh();
749 1.2.2.1 bouyer else
750 1.2.2.1 bouyer s = splts102();
751 1.2.2.1 bouyer sc->sc_flags |= TCTRL_SEND_REQUEST;
752 1.2.2.1 bouyer memcpy(sc->sc_cmdbuf, req->cmdbuf, req->cmdlen);
753 1.2.2.1 bouyer sc->sc_wantdata = 1;
754 1.2.2.1 bouyer sc->sc_rsplen = req->rsplen;
755 1.2.2.1 bouyer sc->sc_cmdlen = req->cmdlen;
756 1.2.2.1 bouyer sc->sc_cmdoff = sc->sc_rspoff = 0;
757 1.2.2.1 bouyer
758 1.2.2.1 bouyer /* we spin for certain commands, like poweroffs */
759 1.2.2.1 bouyer if (spin) {
760 1.2.2.1 bouyer /* for (i = 0; i < 30000; i++) {*/
761 1.2.2.1 bouyer while (sc->sc_wantdata == 1) {
762 1.2.2.1 bouyer tctrl_intr(sc);
763 1.2.2.1 bouyer DELAY(1);
764 1.2.2.1 bouyer }
765 1.2.2.1 bouyer } else {
766 1.1 matt tctrl_intr(sc);
767 1.2.2.1 bouyer i = 0;
768 1.2.2.1 bouyer while (((sc->sc_rspoff != sc->sc_rsplen) ||
769 1.2.2.1 bouyer (sc->sc_cmdoff != sc->sc_cmdlen)) &&
770 1.2.2.1 bouyer (i < (5 * sc->sc_rsplen + sc->sc_cmdlen)))
771 1.2.2.1 bouyer if (req->p != NULL) {
772 1.2.2.1 bouyer tsleep(sc, PWAIT, "tctrl_data", 15);
773 1.2.2.1 bouyer i++;
774 1.2.2.1 bouyer }
775 1.2.2.1 bouyer else
776 1.2.2.1 bouyer DELAY(1);
777 1.1 matt }
778 1.2.2.1 bouyer /*
779 1.2.2.1 bouyer * we give the user a reasonable amount of time for a command
780 1.2.2.1 bouyer * to complete. If it doesn't complete in time, we hand them
781 1.2.2.1 bouyer * garbage. This is here to stop things like setting the
782 1.2.2.1 bouyer * rsplen too long, and sleeping forever in a CMD_REQ ioctl.
783 1.2.2.1 bouyer */
784 1.2.2.1 bouyer sc->sc_wantdata = 0;
785 1.2.2.1 bouyer memcpy(req->rspbuf, sc->sc_rspbuf, req->rsplen);
786 1.1 matt splx(s);
787 1.1 matt }
788 1.1 matt
789 1.1 matt void
790 1.2.2.1 bouyer tadpole_powerdown(void)
791 1.2.2.1 bouyer {
792 1.2.2.1 bouyer struct tctrl_req req;
793 1.2.2.1 bouyer
794 1.2.2.1 bouyer req.cmdbuf[0] = TS102_OP_ADMIN_POWER_OFF;
795 1.2.2.1 bouyer req.cmdlen = 1;
796 1.2.2.1 bouyer req.rsplen = 1;
797 1.2.2.1 bouyer req.p = NULL;
798 1.2.2.1 bouyer tadpole_request(&req, 1);
799 1.2.2.1 bouyer }
800 1.2.2.1 bouyer
801 1.2.2.1 bouyer void
802 1.2.2.1 bouyer tadpole_set_video(enabled)
803 1.2.2.1 bouyer int enabled;
804 1.1 matt {
805 1.1 matt struct tctrl_softc *sc;
806 1.2.2.1 bouyer struct tctrl_req req;
807 1.1 matt int s;
808 1.1 matt
809 1.2.2.1 bouyer sc = (struct tctrl_softc *) tctrl_cd.cd_devs[TCTRL_STD_DEV];
810 1.2.2.1 bouyer while (sc->sc_wantdata != 0)
811 1.2.2.1 bouyer DELAY(1);
812 1.2.2.1 bouyer s = splts102();
813 1.2.2.1 bouyer req.p = NULL;
814 1.2.2.1 bouyer if ((sc->sc_ext_status & TS102_EXT_STATUS_LID_DOWN && !enabled)
815 1.2.2.1 bouyer || (sc->sc_tft_on)) {
816 1.2.2.1 bouyer req.cmdbuf[2] = TS102_BITPORT_TFTPWR;
817 1.2.2.1 bouyer } else {
818 1.2.2.1 bouyer req.cmdbuf[2] = 0;
819 1.1 matt }
820 1.2.2.1 bouyer req.cmdbuf[0] = TS102_OP_CTL_BITPORT;
821 1.2.2.1 bouyer req.cmdbuf[1] = ~TS102_BITPORT_TFTPWR;
822 1.2.2.1 bouyer req.cmdlen = 3;
823 1.2.2.1 bouyer req.rsplen = 2;
824 1.1 matt
825 1.1 matt if ((sc->sc_tft_on && !enabled) || (!sc->sc_tft_on && enabled)) {
826 1.1 matt sc->sc_tft_on = enabled;
827 1.1 matt if (sc->sc_ext_status & TS102_EXT_STATUS_LID_DOWN) {
828 1.1 matt splx(s);
829 1.1 matt return;
830 1.1 matt }
831 1.2.2.1 bouyer tadpole_request(&req, 1);
832 1.2.2.1 bouyer sc->sc_bitport =
833 1.2.2.1 bouyer (req.rspbuf[0] & req.cmdbuf[1]) ^ req.cmdbuf[2];
834 1.1 matt }
835 1.1 matt splx(s);
836 1.1 matt }
837 1.1 matt
838 1.1 matt static void
839 1.2.2.1 bouyer tctrl_write_data(sc, v)
840 1.2.2.1 bouyer struct tctrl_softc *sc;
841 1.2.2.1 bouyer u_int8_t v;
842 1.1 matt {
843 1.1 matt unsigned int i;
844 1.2.2.1 bouyer
845 1.1 matt for (i = 0; i < 100; i++) {
846 1.2 matt if (TS102_UCTRL_STS_TXNF_STA & tctrl_read(sc, TS102_REG_UCTRL_STS))
847 1.1 matt break;
848 1.1 matt }
849 1.1 matt tctrl_write(sc, TS102_REG_UCTRL_DATA, v);
850 1.1 matt }
851 1.1 matt
852 1.1 matt static u_int8_t
853 1.2.2.1 bouyer tctrl_read_data(sc)
854 1.2.2.1 bouyer struct tctrl_softc *sc;
855 1.2.2.1 bouyer {
856 1.1 matt unsigned int i, v;
857 1.1 matt
858 1.1 matt for (i = 0; i < 100000; i++) {
859 1.2 matt if (TS102_UCTRL_STS_RXNE_STA & tctrl_read(sc, TS102_REG_UCTRL_STS))
860 1.1 matt break;
861 1.1 matt DELAY(1);
862 1.1 matt }
863 1.1 matt
864 1.1 matt v = tctrl_read(sc, TS102_REG_UCTRL_DATA);
865 1.2 matt tctrl_write(sc, TS102_REG_UCTRL_STS, TS102_UCTRL_STS_RXNE_STA);
866 1.1 matt return v;
867 1.1 matt }
868 1.1 matt
869 1.1 matt static u_int8_t
870 1.2.2.1 bouyer tctrl_read(sc, off)
871 1.2.2.1 bouyer struct tctrl_softc *sc;
872 1.2.2.1 bouyer bus_size_t off;
873 1.1 matt {
874 1.2.2.1 bouyer
875 1.2 matt sc->sc_junk = bus_space_read_1(sc->sc_memt, sc->sc_memh, off);
876 1.1 matt return sc->sc_junk;
877 1.1 matt }
878 1.1 matt
879 1.1 matt static void
880 1.2.2.1 bouyer tctrl_write(sc, off, v)
881 1.2.2.1 bouyer struct tctrl_softc *sc;
882 1.2.2.1 bouyer bus_size_t off;
883 1.2.2.1 bouyer u_int8_t v;
884 1.1 matt {
885 1.2.2.1 bouyer
886 1.1 matt sc->sc_junk = v;
887 1.2 matt bus_space_write_1(sc->sc_memt, sc->sc_memh, off, v);
888 1.1 matt }
889 1.2.2.1 bouyer
890 1.2.2.1 bouyer int
891 1.2.2.1 bouyer tctrlopen(dev, flags, mode, p)
892 1.2.2.1 bouyer dev_t dev;
893 1.2.2.1 bouyer int flags, mode;
894 1.2.2.1 bouyer struct proc *p;
895 1.2.2.1 bouyer {
896 1.2.2.1 bouyer int unit = (minor(dev)&0xf0);
897 1.2.2.1 bouyer int ctl = (minor(dev)&0x0f);
898 1.2.2.1 bouyer struct tctrl_softc *sc;
899 1.2.2.1 bouyer
900 1.2.2.1 bouyer if (unit >= tctrl_cd.cd_ndevs)
901 1.2.2.1 bouyer return(ENXIO);
902 1.2.2.1 bouyer sc = tctrl_cd.cd_devs[TCTRL_STD_DEV];
903 1.2.2.1 bouyer if (!sc)
904 1.2.2.1 bouyer return(ENXIO);
905 1.2.2.1 bouyer
906 1.2.2.1 bouyer switch (ctl) {
907 1.2.2.1 bouyer case TCTRL_STD_DEV:
908 1.2.2.1 bouyer break;
909 1.2.2.1 bouyer case TCTRL_APMCTL_DEV:
910 1.2.2.1 bouyer if (!(flags & FWRITE))
911 1.2.2.1 bouyer return(EINVAL);
912 1.2.2.1 bouyer if (sc->sc_flags & TCTRL_APM_CTLOPEN)
913 1.2.2.1 bouyer return(EBUSY);
914 1.2.2.1 bouyer sc->sc_flags |= TCTRL_APM_CTLOPEN;
915 1.2.2.1 bouyer break;
916 1.2.2.1 bouyer default:
917 1.2.2.1 bouyer return(ENXIO);
918 1.2.2.1 bouyer break;
919 1.2.2.1 bouyer }
920 1.2.2.1 bouyer
921 1.2.2.1 bouyer return(0);
922 1.2.2.1 bouyer }
923 1.2.2.1 bouyer
924 1.2.2.1 bouyer int
925 1.2.2.1 bouyer tctrlclose(dev, flags, mode, p)
926 1.2.2.1 bouyer dev_t dev;
927 1.2.2.1 bouyer int flags, mode;
928 1.2.2.1 bouyer struct proc *p;
929 1.2.2.1 bouyer {
930 1.2.2.1 bouyer int ctl = (minor(dev)&0x0f);
931 1.2.2.1 bouyer struct tctrl_softc *sc;
932 1.2.2.1 bouyer
933 1.2.2.1 bouyer sc = tctrl_cd.cd_devs[TCTRL_STD_DEV];
934 1.2.2.1 bouyer if (!sc)
935 1.2.2.1 bouyer return(ENXIO);
936 1.2.2.1 bouyer
937 1.2.2.1 bouyer switch (ctl) {
938 1.2.2.1 bouyer case TCTRL_STD_DEV:
939 1.2.2.1 bouyer break;
940 1.2.2.1 bouyer case TCTRL_APMCTL_DEV:
941 1.2.2.1 bouyer sc->sc_flags &= ~TCTRL_APM_CTLOPEN;
942 1.2.2.1 bouyer break;
943 1.2.2.1 bouyer }
944 1.2.2.1 bouyer return(0);
945 1.2.2.1 bouyer }
946 1.2.2.1 bouyer
947 1.2.2.1 bouyer int
948 1.2.2.1 bouyer tctrlioctl(dev, cmd, data, flags, p)
949 1.2.2.1 bouyer dev_t dev;
950 1.2.2.1 bouyer u_long cmd;
951 1.2.2.1 bouyer caddr_t data;
952 1.2.2.1 bouyer int flags;
953 1.2.2.1 bouyer struct proc *p;
954 1.2.2.1 bouyer {
955 1.2.2.1 bouyer struct tctrl_req req, *reqn;
956 1.2.2.1 bouyer struct tctrl_pwr *pwrreq;
957 1.2.2.1 bouyer envsys_range_t *envrange;
958 1.2.2.1 bouyer envsys_temp_data_t *envdata;
959 1.2.2.1 bouyer envsys_temp_info_t *envinfo;
960 1.2.2.1 bouyer struct apm_power_info *powerp;
961 1.2.2.1 bouyer struct apm_event_info *evp;
962 1.2.2.1 bouyer struct tctrl_softc *sc;
963 1.2.2.1 bouyer int i;
964 1.2.2.1 bouyer u_int j;
965 1.2.2.1 bouyer u_int16_t a;
966 1.2.2.1 bouyer u_int8_t c;
967 1.2.2.1 bouyer
968 1.2.2.1 bouyer if (tctrl_cd.cd_devs == NULL
969 1.2.2.1 bouyer || tctrl_cd.cd_ndevs == 0
970 1.2.2.1 bouyer || tctrl_cd.cd_devs[TCTRL_STD_DEV] == NULL) {
971 1.2.2.1 bouyer return ENXIO;
972 1.2.2.1 bouyer }
973 1.2.2.1 bouyer sc = (struct tctrl_softc *) tctrl_cd.cd_devs[TCTRL_STD_DEV];
974 1.2.2.1 bouyer switch (cmd) {
975 1.2.2.1 bouyer
976 1.2.2.1 bouyer case APM_IOC_STANDBY:
977 1.2.2.1 bouyer return(EOPNOTSUPP); /* for now */
978 1.2.2.1 bouyer
979 1.2.2.1 bouyer case APM_IOC_SUSPEND:
980 1.2.2.1 bouyer return(EOPNOTSUPP); /* for now */
981 1.2.2.1 bouyer
982 1.2.2.1 bouyer case APM_IOC_GETPOWER:
983 1.2.2.1 bouyer powerp = (struct apm_power_info *)data;
984 1.2.2.1 bouyer req.cmdbuf[0] = TS102_OP_RD_INT_CHARGE_RATE;
985 1.2.2.1 bouyer req.cmdlen = 1;
986 1.2.2.1 bouyer req.rsplen = 2;
987 1.2.2.1 bouyer req.p = p;
988 1.2.2.1 bouyer tadpole_request(&req, 0);
989 1.2.2.1 bouyer if (req.rspbuf[0] > 0x00)
990 1.2.2.1 bouyer powerp->battery_state = APM_BATT_CHARGING;
991 1.2.2.1 bouyer req.cmdbuf[0] = TS102_OP_RD_INT_CHARGE_LEVEL;
992 1.2.2.1 bouyer req.cmdlen = 1;
993 1.2.2.1 bouyer req.rsplen = 3;
994 1.2.2.1 bouyer req.p = p;
995 1.2.2.1 bouyer tadpole_request(&req, 0);
996 1.2.2.1 bouyer c = req.rspbuf[0];
997 1.2.2.1 bouyer powerp->battery_life = c;
998 1.2.2.1 bouyer if (c > 0x70) /* the tadpole sometimes dips below zero, and */
999 1.2.2.1 bouyer c = 0; /* into the 255 range. */
1000 1.2.2.1 bouyer powerp->minutes_left = (45 * c) / 100; /* XXX based on 45 min */
1001 1.2.2.1 bouyer if (powerp->battery_state != APM_BATT_CHARGING) {
1002 1.2.2.1 bouyer if (c < 0x20)
1003 1.2.2.1 bouyer powerp->battery_state = APM_BATT_CRITICAL;
1004 1.2.2.1 bouyer else if (c < 0x40)
1005 1.2.2.1 bouyer powerp->battery_state = APM_BATT_LOW;
1006 1.2.2.1 bouyer else if (c < 0x66)
1007 1.2.2.1 bouyer powerp->battery_state = APM_BATT_HIGH;
1008 1.2.2.1 bouyer else
1009 1.2.2.1 bouyer powerp->battery_state = APM_BATT_UNKNOWN;
1010 1.2.2.1 bouyer }
1011 1.2.2.1 bouyer req.cmdbuf[0] = TS102_OP_RD_EXT_STATUS;
1012 1.2.2.1 bouyer req.cmdlen = 1;
1013 1.2.2.1 bouyer req.rsplen = 3;
1014 1.2.2.1 bouyer req.p = p;
1015 1.2.2.1 bouyer tadpole_request(&req, 0);
1016 1.2.2.1 bouyer a = req.rspbuf[0] * 256 + req.rspbuf[1];
1017 1.2.2.1 bouyer if (a & TS102_EXT_STATUS_MAIN_POWER_AVAILABLE)
1018 1.2.2.1 bouyer powerp->ac_state = APM_AC_ON;
1019 1.2.2.1 bouyer else
1020 1.2.2.1 bouyer powerp->ac_state = APM_AC_OFF;
1021 1.2.2.1 bouyer break;
1022 1.2.2.1 bouyer
1023 1.2.2.1 bouyer case APM_IOC_NEXTEVENT:
1024 1.2.2.1 bouyer if (!sc->sc_event_count)
1025 1.2.2.1 bouyer return EAGAIN;
1026 1.2.2.1 bouyer
1027 1.2.2.1 bouyer evp = (struct apm_event_info *)data;
1028 1.2.2.1 bouyer i = sc->sc_event_ptr + APM_NEVENTS - sc->sc_event_count;
1029 1.2.2.1 bouyer i %= APM_NEVENTS;
1030 1.2.2.1 bouyer *evp = sc->sc_event_list[i];
1031 1.2.2.1 bouyer sc->sc_event_count--;
1032 1.2.2.1 bouyer return(0);
1033 1.2.2.1 bouyer
1034 1.2.2.1 bouyer /* this ioctl assumes the caller knows exactly what he is doing */
1035 1.2.2.1 bouyer case TCTRL_CMD_REQ:
1036 1.2.2.1 bouyer reqn = (struct tctrl_req *)data;
1037 1.2.2.1 bouyer if ((i = suser(p->p_ucred, &p->p_acflag)) != 0 &&
1038 1.2.2.1 bouyer (reqn->cmdbuf[0] == TS102_OP_CTL_BITPORT ||
1039 1.2.2.1 bouyer (reqn->cmdbuf[0] >= TS102_OP_CTL_WATCHDOG &&
1040 1.2.2.1 bouyer reqn->cmdbuf[0] <= TS102_OP_CTL_SECURITY_KEY) ||
1041 1.2.2.1 bouyer reqn->cmdbuf[0] == TS102_OP_CTL_TIMEZONE ||
1042 1.2.2.1 bouyer reqn->cmdbuf[0] == TS102_OP_CTL_DIAGNOSTIC_MODE ||
1043 1.2.2.1 bouyer reqn->cmdbuf[0] == TS102_OP_CMD_SOFTWARE_RESET ||
1044 1.2.2.1 bouyer (reqn->cmdbuf[0] >= TS102_OP_CMD_SET_RTC &&
1045 1.2.2.1 bouyer reqn->cmdbuf[0] < TS102_OP_RD_INT_CHARGE_LEVEL) ||
1046 1.2.2.1 bouyer reqn->cmdbuf[0] > TS102_OP_RD_EXT_CHARGE_LEVEL))
1047 1.2.2.1 bouyer return(i);
1048 1.2.2.1 bouyer reqn->p = p;
1049 1.2.2.1 bouyer tadpole_request(reqn, 0);
1050 1.2.2.1 bouyer break;
1051 1.2.2.1 bouyer
1052 1.2.2.1 bouyer case ENVSYS_VERSION:
1053 1.2.2.1 bouyer *(int32_t *)data = 1000;
1054 1.2.2.1 bouyer break;
1055 1.2.2.1 bouyer
1056 1.2.2.1 bouyer case ENVSYS_GRANGE:
1057 1.2.2.1 bouyer envrange = (envsys_range_t *)data;
1058 1.2.2.1 bouyer i = 0;
1059 1.2.2.1 bouyer envrange->high = envrange->low = 0;
1060 1.2.2.1 bouyer for (j=0; j < ENVSYS_NUMSENSORS; j++) {
1061 1.2.2.1 bouyer if (!i && envrange->units == sc->sc_esensors[j].units) {
1062 1.2.2.1 bouyer envrange->low = j;
1063 1.2.2.1 bouyer i++;
1064 1.2.2.1 bouyer }
1065 1.2.2.1 bouyer if (i && envrange->units == sc->sc_esensors[j].units)
1066 1.2.2.1 bouyer envrange->high = j;
1067 1.2.2.1 bouyer }
1068 1.2.2.1 bouyer if (!i) {
1069 1.2.2.1 bouyer envrange->high = 0;
1070 1.2.2.1 bouyer envrange->low = 1;
1071 1.2.2.1 bouyer }
1072 1.2.2.1 bouyer break;
1073 1.2.2.1 bouyer
1074 1.2.2.1 bouyer case ENVSYS_GTREDATA:
1075 1.2.2.1 bouyer envdata = (envsys_temp_data_t *)data;
1076 1.2.2.1 bouyer if (envdata->sensor >= ENVSYS_NUMSENSORS) {
1077 1.2.2.1 bouyer envdata->validflags = 0;
1078 1.2.2.1 bouyer break;
1079 1.2.2.1 bouyer }
1080 1.2.2.1 bouyer envdata->warnflags = ENVSYS_WARN_OK;
1081 1.2.2.1 bouyer if (envdata->sensor == 0) {
1082 1.2.2.1 bouyer envdata->validflags |= ENVSYS_FVALID;
1083 1.2.2.1 bouyer req.cmdbuf[0] = TS102_OP_RD_CURRENT_TEMP;
1084 1.2.2.1 bouyer req.cmdlen = 1;
1085 1.2.2.1 bouyer req.rsplen = 2;
1086 1.2.2.1 bouyer req.p = p;
1087 1.2.2.1 bouyer tadpole_request(&req, 0);
1088 1.2.2.1 bouyer envdata->cur.data_us = /* 273160? */
1089 1.2.2.1 bouyer (u_int32_t)((int)((int)req.rspbuf[0]-32)*5000000/9+273150000);
1090 1.2.2.1 bouyer envdata->validflags |= ENVSYS_FCURVALID;
1091 1.2.2.1 bouyer req.cmdbuf[0] = TS102_OP_RD_MAX_TEMP;
1092 1.2.2.1 bouyer req.cmdlen = 1;
1093 1.2.2.1 bouyer req.rsplen = 2;
1094 1.2.2.1 bouyer req.p = p;
1095 1.2.2.1 bouyer tadpole_request(&req, 0);
1096 1.2.2.1 bouyer envdata->max.data_us =
1097 1.2.2.1 bouyer (u_int32_t)((int)((int)req.rspbuf[0]-32)*5000000/9+273150000);
1098 1.2.2.1 bouyer envdata->validflags |= ENVSYS_FMAXVALID;
1099 1.2.2.1 bouyer req.cmdbuf[0] = TS102_OP_RD_MIN_TEMP;
1100 1.2.2.1 bouyer req.cmdlen = 1;
1101 1.2.2.1 bouyer req.rsplen = 2;
1102 1.2.2.1 bouyer req.p = p;
1103 1.2.2.1 bouyer tadpole_request(&req, 0);
1104 1.2.2.1 bouyer envdata->min.data_us =
1105 1.2.2.1 bouyer (u_int32_t)((int)((int)req.rspbuf[0]-32)*5000000/9+273150000);
1106 1.2.2.1 bouyer envdata->validflags |= ENVSYS_FMINVALID;
1107 1.2.2.1 bouyer envdata->units = sc->sc_esensors[envdata->sensor].units;
1108 1.2.2.1 bouyer break;
1109 1.2.2.1 bouyer } else if (envdata->sensor == 1 || envdata->sensor == 2) {
1110 1.2.2.1 bouyer envdata->validflags = ENVSYS_FVALID|ENVSYS_FCURVALID;
1111 1.2.2.1 bouyer envdata->units = sc->sc_esensors[envdata->sensor].units;
1112 1.2.2.1 bouyer if (envdata->sensor == 1)
1113 1.2.2.1 bouyer req.cmdbuf[0] = TS102_OP_RD_INT_BATT_VLT;
1114 1.2.2.1 bouyer else
1115 1.2.2.1 bouyer req.cmdbuf[0] = TS102_OP_RD_DC_IN_VLT;
1116 1.2.2.1 bouyer req.cmdlen = 1;
1117 1.2.2.1 bouyer req.rsplen = 2;
1118 1.2.2.1 bouyer req.p = p;
1119 1.2.2.1 bouyer tadpole_request(&req, 0);
1120 1.2.2.1 bouyer envdata->cur.data_s = (int32_t)req.rspbuf[0]*1000000/11;
1121 1.2.2.1 bouyer break;
1122 1.2.2.1 bouyer }
1123 1.2.2.1 bouyer break;
1124 1.2.2.1 bouyer
1125 1.2.2.1 bouyer case ENVSYS_GTREINFO:
1126 1.2.2.1 bouyer envinfo = (envsys_temp_info_t *)data;
1127 1.2.2.1 bouyer if (envinfo->sensor >= ENVSYS_NUMSENSORS) {
1128 1.2.2.1 bouyer envinfo->validflags = 0;
1129 1.2.2.1 bouyer break;
1130 1.2.2.1 bouyer }
1131 1.2.2.1 bouyer envinfo->units = sc->sc_esensors[envinfo->sensor].units;
1132 1.2.2.1 bouyer memcpy(envinfo->desc, sc->sc_esensors[envinfo->sensor].desc,
1133 1.2.2.1 bouyer sizeof(sc->sc_esensors[envinfo->sensor].desc) >
1134 1.2.2.1 bouyer sizeof(envinfo->desc) ? sizeof(envinfo->desc) :
1135 1.2.2.1 bouyer sizeof(sc->sc_esensors[envinfo->sensor].desc));
1136 1.2.2.1 bouyer if (envinfo->units == ENVSYS_STEMP) {
1137 1.2.2.1 bouyer envinfo->validflags = ENVSYS_FVALID|ENVSYS_FCURVALID|
1138 1.2.2.1 bouyer ENVSYS_FMINVALID|ENVSYS_FMAXVALID;
1139 1.2.2.1 bouyer } else if (envinfo->units == ENVSYS_SVOLTS_DC) {
1140 1.2.2.1 bouyer envinfo->validflags = ENVSYS_FVALID|ENVSYS_FCURVALID;
1141 1.2.2.1 bouyer } else
1142 1.2.2.1 bouyer envinfo->validflags = 0;
1143 1.2.2.1 bouyer break;
1144 1.2.2.1 bouyer
1145 1.2.2.1 bouyer case ENVSYS_STREINFO:
1146 1.2.2.1 bouyer envinfo = (envsys_temp_info_t *)data;
1147 1.2.2.1 bouyer if (envinfo->sensor >= ENVSYS_NUMSENSORS) {
1148 1.2.2.1 bouyer envinfo->validflags = 0;
1149 1.2.2.1 bouyer break;
1150 1.2.2.1 bouyer }
1151 1.2.2.1 bouyer if (envinfo->units == sc->sc_esensors[envinfo->sensor].units)
1152 1.2.2.1 bouyer memcpy(sc->sc_esensors[envinfo->sensor].desc,
1153 1.2.2.1 bouyer envinfo->desc,
1154 1.2.2.1 bouyer sizeof(envinfo->desc) > sizeof(char)*32 ?
1155 1.2.2.1 bouyer sizeof(char)*32 : sizeof(envinfo->desc) );
1156 1.2.2.1 bouyer if (envinfo->units == ENVSYS_STEMP) {
1157 1.2.2.1 bouyer envinfo->validflags = ENVSYS_FVALID|ENVSYS_FCURVALID|
1158 1.2.2.1 bouyer ENVSYS_FMINVALID|ENVSYS_FMAXVALID;
1159 1.2.2.1 bouyer } else if (envinfo->units == ENVSYS_SVOLTS_DC) {
1160 1.2.2.1 bouyer envinfo->validflags = ENVSYS_FVALID|ENVSYS_FCURVALID;
1161 1.2.2.1 bouyer } else
1162 1.2.2.1 bouyer envinfo->validflags = 0;
1163 1.2.2.1 bouyer break;
1164 1.2.2.1 bouyer
1165 1.2.2.1 bouyer /* serial power mode (via auxiotwo) */
1166 1.2.2.1 bouyer case TCTRL_SERIAL_PWR:
1167 1.2.2.1 bouyer pwrreq = (struct tctrl_pwr *)data;
1168 1.2.2.1 bouyer if (pwrreq->rw)
1169 1.2.2.1 bouyer pwrreq->state = auxiotwoserialgetapm();
1170 1.2.2.1 bouyer else
1171 1.2.2.1 bouyer auxiotwoserialsetapm(pwrreq->state);
1172 1.2.2.1 bouyer break;
1173 1.2.2.1 bouyer
1174 1.2.2.1 bouyer /* modem power mode (via auxio) */
1175 1.2.2.1 bouyer case TCTRL_MODEM_PWR:
1176 1.2.2.1 bouyer return(EOPNOTSUPP); /* for now */
1177 1.2.2.1 bouyer break;
1178 1.2.2.1 bouyer
1179 1.2.2.1 bouyer
1180 1.2.2.1 bouyer default:
1181 1.2.2.1 bouyer return (ENOTTY);
1182 1.2.2.1 bouyer }
1183 1.2.2.1 bouyer return (0);
1184 1.2.2.1 bouyer }
1185 1.2.2.1 bouyer
1186 1.2.2.1 bouyer int
1187 1.2.2.1 bouyer tctrlpoll(dev, events, p)
1188 1.2.2.1 bouyer dev_t dev;
1189 1.2.2.1 bouyer int events;
1190 1.2.2.1 bouyer struct proc *p;
1191 1.2.2.1 bouyer {
1192 1.2.2.1 bouyer struct tctrl_softc *sc = tctrl_cd.cd_devs[TCTRL_STD_DEV];
1193 1.2.2.1 bouyer int revents = 0;
1194 1.2.2.1 bouyer
1195 1.2.2.1 bouyer if (events & (POLLIN | POLLRDNORM)) {
1196 1.2.2.1 bouyer if (sc->sc_event_count)
1197 1.2.2.1 bouyer revents |= events & (POLLIN | POLLRDNORM);
1198 1.2.2.1 bouyer else
1199 1.2.2.1 bouyer selrecord(p, &sc->sc_rsel);
1200 1.2.2.1 bouyer }
1201 1.2.2.1 bouyer
1202 1.2.2.1 bouyer return (revents);
1203 1.2.2.1 bouyer }
1204 1.2.2.1 bouyer /* DO NOT SET THIS OPTION */
1205 1.2.2.1 bouyer #ifdef TADPOLE_BLINK
1206 1.2.2.1 bouyer void
1207 1.2.2.1 bouyer cpu_disk_unbusy(busy)
1208 1.2.2.1 bouyer int busy;
1209 1.2.2.1 bouyer {
1210 1.2.2.1 bouyer static struct timeval tctrl_ds_timestamp;
1211 1.2.2.1 bouyer struct timeval dv_time, diff_time;
1212 1.2.2.1 bouyer struct tctrl_softc *sc;
1213 1.2.2.1 bouyer
1214 1.2.2.1 bouyer sc = (struct tctrl_softc *) tctrl_cd.cd_devs[TCTRL_STD_DEV];
1215 1.2.2.1 bouyer
1216 1.2.2.1 bouyer /* quickly bail */
1217 1.2.2.1 bouyer if (!(sc->sc_lcdstate & TS102_LCD_DISK_ACTIVE) || busy > 0)
1218 1.2.2.1 bouyer return;
1219 1.2.2.1 bouyer
1220 1.2.2.1 bouyer /* we aren't terribly concerned with precision here */
1221 1.2.2.1 bouyer dv_time = mono_time;
1222 1.2.2.1 bouyer timersub(&dv_time, &tctrl_ds_timestamp, &diff_time);
1223 1.2.2.1 bouyer
1224 1.2.2.1 bouyer if (diff_time.tv_sec > 0) {
1225 1.2.2.1 bouyer tctrl_set_lcd(0, TS102_LCD_DISK_ACTIVE);
1226 1.2.2.1 bouyer tctrl_ds_timestamp = mono_time;
1227 1.2.2.1 bouyer }
1228 1.2.2.1 bouyer }
1229 1.2.2.1 bouyer #endif
1230