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