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