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