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