1 /*- 2 * Copyright (c) 1992 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Ralph Campbell and Rick Macklem. 7 * 8 * %sccs.include.redist.c% 9 * 10 * @(#)dtop.c 7.1 (Berkeley) 11/15/92 11 */ 12 13 /* 14 * Mach Operating System 15 * Copyright (c) 1991,1990,1989 Carnegie Mellon University 16 * All Rights Reserved. 17 * 18 * Permission to use, copy, modify and distribute this software and its 19 * documentation is hereby granted, provided that both the copyright 20 * notice and this permission notice appear in all copies of the 21 * software, derivative works or modified versions, and any portions 22 * thereof, and that both notices appear in supporting documentation. 23 * 24 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS 25 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR 26 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 27 * 28 * Carnegie Mellon requests users of this software to return to 29 * 30 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 31 * School of Computer Science 32 * Carnegie Mellon University 33 * Pittsburgh PA 15213-3890 34 * 35 * any improvements or extensions that they make and grant Carnegie the 36 * rights to redistribute these changes. 37 */ 38 /* 39 * Author: Alessandro Forin, Carnegie Mellon University 40 * 41 * Hardware-level operations for the Desktop serial line 42 * bus (i2c aka ACCESS). 43 */ 44 45 #include <dtop.h> 46 #if NDTOP > 0 47 #include <sys/param.h> 48 #include <sys/systm.h> 49 #include <sys/ioctl.h> 50 #include <sys/tty.h> 51 #include <sys/proc.h> 52 #include <sys/map.h> 53 #include <sys/buf.h> 54 #include <sys/conf.h> 55 #include <sys/file.h> 56 #include <sys/uio.h> 57 #include <sys/kernel.h> 58 #include <sys/syslog.h> 59 60 #include <machine/pmioctl.h> 61 #include <machine/machConst.h> 62 #include <machine/dc7085cons.h> 63 64 #include <pmax/pmax/pmaxtype.h> 65 #include <pmax/pmax/maxine.h> 66 #include <pmax/pmax/asic.h> 67 68 #include <pmax/dev/device.h> 69 #include <pmax/dev/dtopreg.h> 70 #include <pmax/dev/fbreg.h> 71 72 extern int pmax_boardtype; 73 74 extern int ttrstrt __P((void *)); 75 void dtop_keyboard_autorepeat __P((void *)); 76 int dtop_null_device_handler __P((dtop_device_t, dtop_message_t, int, int)); 77 int dtop_locator_handler __P((dtop_device_t, dtop_message_t, int, int)); 78 int dtop_keyboard_handler __P((dtop_device_t, dtop_message_t, int, int)); 79 int dtopparam __P((struct tty *, struct termios *)); 80 int dtopstop __P((struct tty *, int)); 81 void dtopstart __P((struct tty *)); 82 void dtopKBDPutc __P((dev_t, int)); 83 84 struct tty dtop_tty[NDTOP]; 85 void (*dtopDivertXInput)(); /* X windows keyboard input routine */ 86 void (*dtopMouseEvent)(); /* X windows mouse motion event routine */ 87 void (*dtopMouseButtons)(); /* X windows mouse buttons event routine */ 88 89 #define DTOP_MAX_POLL 0x7fff /* about half a sec */ 90 91 typedef volatile unsigned int *data_reg_t; /* uC */ 92 #define DTOP_GET_BYTE(data) (((*(data)) >> 8) & 0xff) 93 #define DTOP_PUT_BYTE(data,c) { *(data) = (c) << 8; } 94 95 typedef volatile unsigned int *poll_reg_t; /* SIR */ 96 #define DTOP_RX_AVAIL(poll) (*(poll) & 1) 97 #define DTOP_TX_AVAIL(poll) (*(poll) & 2) 98 99 #define GET_SHORT(b0,b1) (((b0)<<8)|(b1)) 100 101 /* 102 * Driver status 103 */ 104 struct dtop_softc { 105 data_reg_t data; 106 poll_reg_t poll; 107 char polling_mode; 108 char probed_once; 109 short bad_pkts; 110 111 struct dtop_ds { 112 int (*handler)(); 113 dtop_device status; 114 } device[(DTOP_ADDR_DEFAULT - DTOP_ADDR_FIRST) >> 1]; 115 116 # define DTOP_DEVICE_NO(address) (((address)-DTOP_ADDR_FIRST)>>1) 117 118 } dtop_softc[NDTOP]; 119 120 typedef struct dtop_softc *dtop_softc_t; 121 struct tty dtop_tty[NDTOP]; 122 static int dtopenabled = 0; 123 124 /* 125 * Definition of the driver for the auto-configuration program. 126 */ 127 int dtopprobe(); 128 void dtopintr(); 129 struct driver dtopdriver = { 130 "dtop", dtopprobe, 0, 0, dtopintr, 131 }; 132 133 dtopprobe(cp) 134 struct pmax_ctlr *cp; 135 { 136 register struct tty *tp; 137 register int cntr; 138 int dtopunit = cp->pmax_unit, i, s; 139 dtop_softc_t dtop; 140 141 if (dtopunit >= NDTOP) 142 return (0); 143 if (badaddr(cp->pmax_addr, 2)) 144 return (0); 145 dtop = &dtop_softc[dtopunit]; 146 147 dtop->poll = (poll_reg_t)MACH_PHYS_TO_UNCACHED(XINE_REG_INTR); 148 dtop->data = (data_reg_t)cp->pmax_addr; 149 150 for (i = 0; i < DTOP_MAX_DEVICES; i++) 151 dtop->device[i].handler = dtop_null_device_handler; 152 153 /* a lot more needed here, fornow: */ 154 dtop->device[DTOP_DEVICE_NO(0x6a)].handler = dtop_locator_handler; 155 dtop->device[DTOP_DEVICE_NO(0x6c)].handler = dtop_keyboard_handler; 156 dtop->device[DTOP_DEVICE_NO(0x6c)].status.keyboard.poll_frequency = 157 (hz * 5) / 100; /* x0.01 secs */ 158 dtop->device[DTOP_DEVICE_NO(0x6c)].status.keyboard.k_ar_state = 159 K_AR_IDLE; 160 161 /* 162 * Sometimes a first interrupt gets lost, so just in case 163 * poke it now. 164 */ 165 dtopintr(dtopunit); 166 dtopenabled = 1; 167 return (1); 168 } 169 170 dtopopen(dev, flag, mode, p) 171 dev_t dev; 172 int flag, mode; 173 struct proc *p; 174 { 175 register struct tty *tp; 176 register int unit; 177 int s, error = 0; 178 179 unit = minor(dev); 180 if (unit >= NDTOP) 181 return (ENXIO); 182 tp = &dtop_tty[unit]; 183 tp->t_oproc = dtopstart; 184 tp->t_param = dtopparam; 185 tp->t_dev = dev; 186 if ((tp->t_state & TS_ISOPEN) == 0) { 187 tp->t_state |= TS_WOPEN; 188 ttychars(tp); 189 if (tp->t_ispeed == 0) { 190 tp->t_iflag = TTYDEF_IFLAG; 191 tp->t_oflag = TTYDEF_OFLAG; 192 tp->t_cflag = TTYDEF_CFLAG; 193 tp->t_lflag = TTYDEF_LFLAG; 194 tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED; 195 } 196 (void) dtopparam(tp, &tp->t_termios); 197 ttsetwater(tp); 198 } else if ((tp->t_state & TS_XCLUDE) && curproc->p_ucred->cr_uid != 0) 199 return (EBUSY); 200 s = spltty(); 201 while (!(flag & O_NONBLOCK) && !(tp->t_cflag & CLOCAL) && 202 !(tp->t_state & TS_CARR_ON)) { 203 tp->t_state |= TS_WOPEN; 204 if (error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH, 205 ttopen, 0)) 206 break; 207 } 208 splx(s); 209 if (error) 210 return (error); 211 error = (*linesw[tp->t_line].l_open)(dev, tp); 212 return (error); 213 } 214 215 /*ARGSUSED*/ 216 dtopclose(dev, flag, mode, p) 217 dev_t dev; 218 int flag, mode; 219 struct proc *p; 220 { 221 register struct tty *tp; 222 register int unit; 223 224 unit = minor(dev); 225 tp = &dtop_tty[unit]; 226 (*linesw[tp->t_line].l_close)(tp, flag); 227 return (ttyclose(tp)); 228 } 229 230 dtopread(dev, uio, flag) 231 dev_t dev; 232 struct uio *uio; 233 { 234 register struct tty *tp; 235 236 tp = &dtop_tty[minor(dev)]; 237 return ((*linesw[tp->t_line].l_read)(tp, uio, flag)); 238 } 239 240 dtopwrite(dev, uio, flag) 241 dev_t dev; 242 struct uio *uio; 243 { 244 register struct tty *tp; 245 246 tp = &dtop_tty[minor(dev)]; 247 return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); 248 } 249 250 /*ARGSUSED*/ 251 dtopioctl(dev, cmd, data, flag, p) 252 dev_t dev; 253 int cmd; 254 caddr_t data; 255 int flag; 256 struct proc *p; 257 { 258 register struct tty *tp; 259 register int unit = minor(dev); 260 int error; 261 262 tp = &dtop_tty[unit]; 263 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); 264 if (error >= 0) 265 return (error); 266 error = ttioctl(tp, cmd, data, flag); 267 if (error >= 0) 268 return (error); 269 270 switch (cmd) { 271 272 case TIOCSBRK: 273 ttyoutput(0, tp); 274 break; 275 276 case TIOCCBRK: 277 ttyoutput(0, tp); 278 break; 279 280 case TIOCMGET: 281 *(int *)data = DML_DTR | DML_DSR | DML_CAR; 282 break; 283 284 default: 285 return (ENOTTY); 286 } 287 return (0); 288 } 289 290 /* 291 * Interrupt routine 292 */ 293 void 294 dtopintr(unit) 295 int unit; 296 { 297 dtop_message msg; 298 int devno; 299 dtop_softc_t dtop; 300 301 dtop = &dtop_softc[unit]; 302 if (dtop_get_packet(dtop, &msg) < 0) { 303 if (dtopenabled) 304 printf("%s", "dtop: overrun (or stray)\n"); 305 return; 306 } 307 308 devno = DTOP_DEVICE_NO(msg.src_address); 309 if (devno < 0 || devno > 15) 310 return; 311 312 (void) (*dtop->device[devno].handler) 313 (&dtop->device[devno].status, &msg, 314 DTOP_EVENT_RECEIVE_PACKET, 0); 315 } 316 317 void 318 dtopstart(tp) 319 register struct tty *tp; 320 { 321 register int cc; 322 int s; 323 324 s = spltty(); 325 if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) 326 goto out; 327 if (tp->t_outq.c_cc <= tp->t_lowat) { 328 if (tp->t_state & TS_ASLEEP) { 329 tp->t_state &= ~TS_ASLEEP; 330 wakeup((caddr_t)&tp->t_outq); 331 } 332 selwakeup(&tp->t_wsel); 333 } 334 if (tp->t_outq.c_cc == 0) 335 goto out; 336 /* handle console specially */ 337 if (tp == dtop_tty) { 338 while (tp->t_outq.c_cc > 0) { 339 cc = getc(&tp->t_outq) & 0x7f; 340 cnputc(cc); 341 } 342 /* 343 * After we flush the output queue we may need to wake 344 * up the process that made the output. 345 */ 346 if (tp->t_outq.c_cc <= tp->t_lowat) { 347 if (tp->t_state & TS_ASLEEP) { 348 tp->t_state &= ~TS_ASLEEP; 349 wakeup((caddr_t)&tp->t_outq); 350 } 351 selwakeup(&tp->t_wsel); 352 } 353 } 354 out: 355 splx(s); 356 } 357 358 void 359 dtopKBDPutc(dev, c) 360 dev_t dev; 361 int c; 362 { 363 364 /* 365 * Not yet, someday we will know how to send commands to the 366 * LK501 over the Access bus. 367 */ 368 } 369 370 /* 371 * Take a packet off dtop interface 372 * A packet MUST be there, this is not checked for. 373 */ 374 #define DTOP_ESC_CHAR 0xf8 375 dtop_escape(c) 376 { 377 /* I donno much about this stuff.. */ 378 switch (c) { 379 case 0xe8: return (0xf8); 380 case 0xe9: return (0xf9); 381 case 0xea: return (0xfa); 382 case 0xeb: return (0xfb); 383 default: /* printf("{esc %x}", c); */ 384 return (c); 385 } 386 } 387 388 dtop_get_packet(dtop, pkt) 389 dtop_softc_t dtop; 390 dtop_message_t pkt; 391 { 392 register poll_reg_t poll; 393 register data_reg_t data; 394 register int max, i, len; 395 register unsigned char c; 396 397 poll = dtop->poll; 398 data = dtop->data; 399 400 /* 401 * The interface does not handle us the first byte, 402 * which is our address and cannot ever be anything 403 * else but 0x50. This is a good thing, it makes 404 * the average packet exactly one word long, too. 405 */ 406 for (max = 0; (max < DTOP_MAX_POLL) && !DTOP_RX_AVAIL(poll); max++) 407 DELAY(16); 408 if (max == DTOP_MAX_POLL) 409 goto bad; 410 pkt->src_address = DTOP_GET_BYTE(data); 411 412 for (max = 0; (max < DTOP_MAX_POLL) && !DTOP_RX_AVAIL(poll); max++) 413 DELAY(16); 414 if (max == DTOP_MAX_POLL) 415 goto bad; 416 pkt->code.bits = DTOP_GET_BYTE(data); 417 418 /* 419 * Now get data and checksum 420 */ 421 len = pkt->code.val.len + 1; 422 c = 0; 423 for (i = 0; i < len; i++) { 424 again: 425 for (max = 0; (max < DTOP_MAX_POLL) && !DTOP_RX_AVAIL(poll); max++) 426 DELAY(16); 427 if (max == DTOP_MAX_POLL) 428 goto bad; 429 if (c == DTOP_ESC_CHAR) { 430 c = dtop_escape(DTOP_GET_BYTE(data) & 0xff); 431 } else { 432 c = DTOP_GET_BYTE(data); 433 if (c == DTOP_ESC_CHAR) 434 goto again; 435 } 436 pkt->body[i] = c; 437 } 438 return (len); 439 bad: 440 dtop->bad_pkts++; 441 return (-1); 442 } 443 444 /* 445 * Get a keyboard char for the console 446 */ 447 dtopKBDGetc() 448 { 449 register int c; 450 dtop_softc_t dtop; 451 452 dtop = &dtop_softc[0]; 453 again: 454 c = -1; 455 456 /* 457 * Now check keyboard 458 */ 459 if (DTOP_RX_AVAIL(dtop->poll)) { 460 461 dtop_message msg; 462 struct dtop_ds *ds; 463 464 if (dtop_get_packet(dtop, &msg) >= 0) { 465 466 ds = &dtop->device[DTOP_DEVICE_NO(msg.src_address)]; 467 if (ds->handler == dtop_keyboard_handler) { 468 469 c = dtop_keyboard_handler( 470 &ds->status, &msg, 471 DTOP_EVENT_RECEIVE_PACKET, -1); 472 473 if (c > 0) return c; 474 475 c = -1; 476 } 477 } 478 } 479 480 if (c == -1) { 481 DELAY(100); 482 goto again; 483 } 484 485 return c; 486 } 487 488 int 489 dtopparam(tp, t) 490 struct tty *tp; 491 struct termios *t; 492 { 493 if (tp->t_ispeed == 0) 494 ttymodem(tp, 0); 495 else 496 /* called too early to invoke ttymodem, sigh */ 497 tp->t_state |= TS_CARR_ON; 498 return (0); 499 } 500 501 /* 502 * Stop output on a line. 503 */ 504 /*ARGSUSED*/ 505 dtopstop(tp, flag) 506 register struct tty *tp; 507 int flag; 508 { 509 int s; 510 511 s = spltty(); 512 if (tp->t_state & TS_BUSY) { 513 if (!(tp->t_state & TS_TTSTOP)) 514 tp->t_state |= TS_FLUSH; 515 } 516 splx(s); 517 } 518 519 /* 520 * Default handler function 521 */ 522 int 523 dtop_null_device_handler(dev, msg, event, outc) 524 dtop_device_t dev; 525 dtop_message_t msg; 526 int event; 527 int outc; 528 { 529 /* See if the message was to the default address (powerup) */ 530 531 /* Uhmm, donno how to handle this. Drop it */ 532 if (event == DTOP_EVENT_RECEIVE_PACKET) 533 dev->unknown_report = *msg; 534 return 0; 535 } 536 537 /* 538 * Handler for locator devices (mice) 539 */ 540 int 541 dtop_locator_handler(dev, msg, event, outc) 542 dtop_device_t dev; 543 dtop_message_t msg; 544 int event; 545 int outc; 546 { 547 register unsigned short buttons; 548 register short coord; 549 register int moved = 0; 550 static MouseReport currentRep; 551 register MouseReport *mrp = ¤tRep; 552 553 if (dtopMouseButtons) { 554 /* 555 * Do the position first 556 */ 557 coord = GET_SHORT(msg->body[2], msg->body[3]); 558 mrp->dx = coord; 559 if (coord != 0) 560 moved = 1; 561 coord = GET_SHORT(msg->body[4], msg->body[5]); 562 coord = - coord; 563 mrp->dy = coord; 564 if (coord != 0) 565 moved = 1; 566 567 /* 568 * Time for the buttons now 569 */ 570 buttons = GET_SHORT(msg->body[0], msg->body[1]); 571 mrp->state = MOUSE_Y_SIGN | MOUSE_X_SIGN | (buttons & 0x7); 572 if (moved) 573 (*dtopMouseEvent)(mrp); 574 (*dtopMouseButtons)(mrp); 575 } 576 return (0); 577 } 578 579 /* 580 * Handler for keyboard devices 581 * Special case: outc set for recv packet means 582 * we are inside the kernel debugger 583 */ 584 int 585 dtop_keyboard_handler(dev, msg, event, outc) 586 dtop_device_t dev; 587 dtop_message_t msg; 588 int event; 589 int outc; 590 { 591 register u_char *ls, *le, *ns, *ne; 592 u_char save[11], retc; 593 int msg_len, c; 594 struct tty *tp = &dtop_tty[0]; 595 596 /* 597 * Fiddle about emulating an lk201 keyboard. The lk501 598 * designers carefully ensured that keyboard handlers could be 599 * stateless, then we turn around and use lots of state to 600 * emulate the stateful lk201, since the X11R5 X servers 601 * only know about the lk201... (oh well) 602 */ 603 if (event != DTOP_EVENT_RECEIVE_PACKET) { 604 switch (event) { 605 case DTOP_EVENT_POLL: 606 { 607 register unsigned int t, t0; 608 609 /* 610 * Note we will always have at least the 611 * end-of-list marker present (a zero) 612 * Here stop and trigger of autorepeat. 613 * Do not repeat shift keys, either. 614 */ 615 { 616 register unsigned char uc, i = 0; 617 618 rpt_char: 619 uc = dev->keyboard.last_codes[i]; 620 621 if (uc == DTOP_KBD_EMPTY) { 622 dev->keyboard.k_ar_state = K_AR_OFF; 623 return 0; 624 } 625 if ((uc >= KEY_R_SHIFT) && (uc <= KEY_R_ALT)) { 626 /* sometimes swapped. Grrr. */ 627 if (++i < dev->keyboard.last_codes_count) 628 goto rpt_char; 629 dev->keyboard.k_ar_state = K_AR_OFF; 630 return 0; 631 } 632 c = uc; 633 } 634 635 /* 636 * Got a char. See if enough time from stroke, 637 * or from last repeat. 638 */ 639 t0 = (dev->keyboard.k_ar_state == K_AR_TRIGGER) ? 30 : 500; 640 t = TO_MS(time); 641 if ((t - dev->keyboard.last_msec) < t0) 642 return 0; 643 644 dev->keyboard.k_ar_state = K_AR_TRIGGER; 645 646 if (dtopDivertXInput) { 647 (*dtopDivertXInput)(KEY_REPEAT); 648 return (0); 649 } 650 if ((outc = kbdMapChar(KEY_REPEAT)) >= 0) 651 (*linesw[tp->t_line].l_rint)(outc, tp); 652 return 0; 653 } 654 default: 655 printf("Unknown dtop keyb\n"); 656 } 657 return -1; 658 } 659 660 msg_len = msg->code.val.len; 661 662 /* Check for errors */ 663 c = msg->body[0]; 664 if ((c < DTOP_KBD_KEY_MIN) && (c != DTOP_KBD_EMPTY)) { 665 printf("Keyboard error: %x %x %x..\n", msg_len, c, msg->body[1]); 666 if (c != DTOP_KBD_OUT_ERR) return -1; 667 /* spec sez if scan list overflow still there is data */ 668 msg->body[0] = 0; 669 } 670 671 dev->keyboard.last_msec = TO_MS(time); 672 673 switch (dev->keyboard.k_ar_state) { 674 case K_AR_IDLE: 675 if (outc != 0xff) /* from debugger, might be too early */ 676 dtop_keyboard_autorepeat(dev); 677 /* fall through */ 678 case K_AR_TRIGGER: 679 dev->keyboard.k_ar_state = K_AR_ACTIVE; 680 break; 681 case K_AR_ACTIVE: 682 break; 683 case K_AR_OFF: 684 printf("dtop keyb off?\n"); 685 dev->keyboard.k_ar_state = K_AR_IDLE; 686 } 687 688 /* 689 * To make things readable, do a first pass cancelling out 690 * all keys that are still pressed, and a second one generating 691 * events. While generating events, do the upstrokes first 692 * from oldest to youngest, then the downstrokes from oldest 693 * to youngest. This copes with lost packets and provides 694 * a reasonable model even if scans are too slow. 695 */ 696 697 /* make a copy of new state first */ 698 if (msg_len == 1) 699 save[0] = msg->body[0]; 700 else if (msg_len > 0) 701 bcopy(msg->body, save, msg_len); 702 703 /* 704 * Cancel out any keys in both the last and current message as 705 * they are unchanged. 706 */ 707 if (msg_len > 0 && dev->keyboard.last_codes_count > 0) { 708 ls = dev->keyboard.last_codes; 709 le = &dev->keyboard.last_codes[dev->keyboard.last_codes_count]; 710 ne = &msg->body[msg_len]; 711 for (; ls < le; ls++) { 712 for (ns = msg->body; ns < ne; ns++) 713 if (*ls == *ns) { 714 *ls = *ns = 0; 715 break; 716 } 717 } 718 } 719 720 /* 721 * Now generate all upstrokes 722 */ 723 le = dev->keyboard.last_codes; 724 ls = &dev->keyboard.last_codes[dev->keyboard.last_codes_count - 1]; 725 for ( ; ls >= le; ls--) 726 if (c = *ls) { 727 /* 728 * If there are no other down/up keys currently down, we 729 * should actually generate a KEY_UP, but that would require 730 * a lot more state. 731 */ 732 (void) kbdMapChar(c); 733 734 if (outc == 0 && dtopDivertXInput) 735 (*dtopDivertXInput)(c); 736 } 737 /* 738 * And finally the downstrokes 739 */ 740 ne = (char*)msg->body; 741 ns = (char*)&msg->body[msg_len - 1]; 742 retc = 0; 743 for ( ; ns >= ne; ns--) 744 if (*ns) { 745 c = kbdMapChar(*ns); 746 if (outc == 0) { 747 if (dtopDivertXInput) { 748 (*dtopDivertXInput)(*ns); 749 c = -1; /* consumed by X */ 750 } else if (c >= 0) 751 (*linesw[tp->t_line].l_rint)(c, tp); 752 } 753 /* return the related keycode anyways */ 754 if ((c >= 0) && (retc == 0)) 755 retc = c; 756 } 757 outc = retc; 758 /* install new scan state */ 759 if (msg_len == 1) 760 dev->keyboard.last_codes[0] = save[0]; 761 else if (msg_len > 0) 762 bcopy(save, dev->keyboard.last_codes, msg_len); 763 dev->keyboard.last_codes_count = msg_len; 764 return (outc); 765 } 766 767 /* 768 * Polled operations: we must do autorepeat by hand. Sigh. 769 */ 770 void 771 dtop_keyboard_autorepeat(arg) 772 void *arg; 773 { 774 dtop_device_t dev = (dtop_device_t)arg; 775 int s; 776 777 s = spltty(); 778 if (dev->keyboard.k_ar_state != K_AR_IDLE) 779 (void)dtop_keyboard_handler(dev, 0, DTOP_EVENT_POLL, 0); 780 781 if (dev->keyboard.k_ar_state == K_AR_OFF) 782 dev->keyboard.k_ar_state = K_AR_IDLE; 783 else 784 timeout(dtop_keyboard_autorepeat, dev, dev->keyboard.poll_frequency); 785 786 splx(s); 787 } 788 #endif 789