1 /* $NetBSD: kbd.c,v 1.50 2007/12/28 20:49:49 joerg Exp $ */ 2 3 /* 4 * Copyright (c) 1982, 1986, 1990 The Regents of the University of California. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of the University nor the names of its contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 * 31 * kbd.c 32 */ 33 34 #include <sys/cdefs.h> 35 __KERNEL_RCSID(0, "$NetBSD: kbd.c,v 1.50 2007/12/28 20:49:49 joerg Exp $"); 36 37 #include <sys/param.h> 38 #include <sys/systm.h> 39 #include <sys/device.h> 40 #include <sys/ioctl.h> 41 #include <sys/tty.h> 42 #include <sys/proc.h> 43 #include <sys/file.h> 44 #include <sys/kernel.h> 45 #include <sys/syslog.h> 46 #include <sys/signalvar.h> 47 #include <sys/conf.h> 48 #include <dev/cons.h> 49 #include <machine/cpu.h> 50 #include <amiga/amiga/device.h> 51 #include <amiga/amiga/custom.h> 52 #ifdef DRACO 53 #include <m68k/asm_single.h> 54 #include <amiga/amiga/drcustom.h> 55 #endif 56 #include <amiga/amiga/cia.h> 57 #include <amiga/dev/itevar.h> 58 #include <amiga/dev/kbdreg.h> 59 #include <amiga/dev/kbdmap.h> 60 #include <amiga/dev/kbdvar.h> 61 #include <amiga/dev/event_var.h> 62 #include <amiga/dev/vuid_event.h> 63 64 #include "kbd.h" 65 #include "ite.h" 66 67 /* WSKBD */ 68 69 /* 70 * If NWSKBD>0 we try to attach an wskbd device to us. What follows 71 * is definitions of callback functions and structures that are passed 72 * to wscons when initializing. 73 */ 74 75 /* 76 * Now with wscons this driver exhibits some weird behaviour. 77 * It may act both as a driver of its own and the md part of the 78 * wskbd driver. Therefore it can be accessed through /dev/kbd 79 * and /dev/wskbd0 both. 80 * 81 * The data from they keyboard may end up in at least four different 82 * places: 83 * - If this driver has been opened (/dev/kbd) and the 84 * direct mode (TIOCDIRECT) has been set, data goes to 85 * the process who opened the device. Data will transmit itself 86 * as described by the firm_event structure. 87 * - If wskbd support is compiled in and a wskbd driver has been 88 * attached then the data is sent to it. Wskbd in turn may 89 * - Send the data in the wscons_event form to a process that 90 * has opened /dev/wskbd0 91 * - Feed the data to a virtual terminal. 92 * - If an ite is present the data may be fed to it. 93 */ 94 95 #include "wskbd.h" 96 97 #if NWSKBD>0 98 #include <dev/wscons/wsconsio.h> 99 #include <dev/wscons/wskbdvar.h> 100 #include <dev/wscons/wsksymdef.h> 101 #include <dev/wscons/wsksymvar.h> 102 #include <amiga/dev/wskbdmap_amiga.h> 103 104 /* accessops */ 105 int kbd_enable(void *, int); 106 void kbd_set_leds(void *, int); 107 int kbd_ioctl(void *, u_long, void *, int, struct lwp *); 108 109 /* console ops */ 110 void kbd_getc(void *, u_int *, int *); 111 void kbd_pollc(void *, int); 112 void kbd_bell(void *, u_int, u_int, u_int); 113 114 static struct wskbd_accessops kbd_accessops = { 115 kbd_enable, 116 kbd_set_leds, 117 kbd_ioctl 118 }; 119 120 static struct wskbd_consops kbd_consops = { 121 kbd_getc, 122 kbd_pollc, 123 kbd_bell 124 }; 125 126 /* 127 * Pointer to keymaps. They are defined in wskbdmap_amiga.c. 128 */ 129 static struct wskbd_mapdata kbd_mapdata = { 130 amigakbd_keydesctab, 131 KB_US 132 }; 133 134 #endif /* WSKBD */ 135 136 struct kbd_softc { 137 int k_event_mode; /* if true, collect events, else pass to ite */ 138 struct evvar k_events; /* event queue state */ 139 #ifdef DRACO 140 u_char k_rlprfx; /* MF-II rel. prefix has been seen */ 141 u_char k_mf2; 142 #endif 143 144 int k_console; /* true if used as console keyboard */ 145 #if NWSKBD>0 146 struct device *k_wskbddev; /* pointer to wskbd for sending strokes */ 147 int k_pollingmode; /* polling mode on? whatever it isss... */ 148 #endif 149 }; 150 struct kbd_softc kbd_softc; 151 152 int kbdmatch(struct device *, struct cfdata *, void *); 153 void kbdattach(struct device *, struct device *, void *); 154 void kbdintr(int); 155 void kbdstuffchar(u_char); 156 157 int drkbdgetc(void); 158 int drkbdrputc(u_int8_t); 159 int drkbdputc(u_int8_t); 160 int drkbdputc2(u_int8_t, u_int8_t); 161 int drkbdwaitfor(int); 162 163 CFATTACH_DECL(kbd, sizeof(struct device), 164 kbdmatch, kbdattach, NULL, NULL); 165 166 dev_type_open(kbdopen); 167 dev_type_close(kbdclose); 168 dev_type_read(kbdread); 169 dev_type_ioctl(kbdioctl); 170 dev_type_poll(kbdpoll); 171 dev_type_kqfilter(kbdkqfilter); 172 173 const struct cdevsw kbd_cdevsw = { 174 kbdopen, kbdclose, kbdread, nowrite, kbdioctl, 175 nostop, notty, kbdpoll, nommap, kbdkqfilter, 176 }; 177 178 /*ARGSUSED*/ 179 int 180 kbdmatch(struct device *pdp, struct cfdata *cfp, void *auxp) 181 { 182 183 if (matchname((char *)auxp, "kbd")) 184 return(1); 185 return(0); 186 } 187 188 /*ARGSUSED*/ 189 void 190 kbdattach(struct device *pdp, struct device *dp, void *auxp) 191 { 192 #ifdef DRACO 193 kbdenable(); 194 if (kbd_softc.k_mf2) 195 printf(": QuickLogic type MF-II\n"); 196 else 197 printf(": CIA A type Amiga\n"); 198 #else 199 printf(": CIA A type Amiga\n"); 200 #endif 201 202 #if NWSKBD>0 203 if (dp != NULL) { 204 /* 205 * Try to attach the wskbd. 206 */ 207 struct wskbddev_attach_args waa; 208 waa.console = kbd_softc.k_console; 209 waa.keymap = &kbd_mapdata; 210 waa.accessops = &kbd_accessops; 211 waa.accesscookie = NULL; 212 kbd_softc.k_wskbddev = config_found(dp, &waa, wskbddevprint); 213 214 kbd_softc.k_pollingmode = 0; 215 } 216 kbdenable(); 217 #endif /* WSKBD */ 218 } 219 220 /* 221 * This is called when somebody wants to use kbd as the console keyboard. 222 */ 223 void 224 kbd_cnattach(void) 225 { 226 #if NWSKBD>0 227 wskbd_cnattach(&kbd_consops, NULL, &kbd_mapdata); 228 kbd_softc.k_console = 1; 229 #endif 230 } 231 232 /* definitions for amiga keyboard encoding. */ 233 #define KEY_CODE(c) ((c) & 0x7f) 234 #define KEY_UP(c) ((c) & 0x80) 235 236 #define DATLO single_inst_bclr_b(draco_ioct->io_control, DRCNTRL_KBDDATOUT) 237 #define DATHI single_inst_bset_b(draco_ioct->io_control, DRCNTRL_KBDDATOUT) 238 239 #define CLKLO single_inst_bclr_b(draco_ioct->io_control, DRCNTRL_KBDCLKOUT) 240 #define CLKHI single_inst_bset_b(draco_ioct->io_control, DRCNTRL_KBDCLKOUT) 241 242 void 243 kbdenable(void) 244 { 245 static int kbd_inited = 0; 246 247 int s; 248 249 #ifdef DRACO 250 int id; 251 #endif 252 /* 253 * collides with external ints from SCSI, watch out for this when 254 * enabling/disabling interrupts there !! 255 */ 256 s = splhigh(); /* don't lower; might be called from early ddb */ 257 if (kbd_inited) { 258 splx(s); 259 return; 260 } 261 kbd_inited = 1; 262 #ifdef DRACO 263 if (is_draco()) { 264 265 CLKLO; 266 delay(5000); 267 draco_ioct->io_kbdrst = 0; 268 269 if (drkbdputc(0xf2)) 270 goto LnoMFII; 271 272 id = drkbdgetc() << 8; 273 id |= drkbdgetc(); 274 275 if (id != 0xab83) 276 goto LnoMFII; 277 278 if (drkbdputc2(0xf0, 3)) /* mode 3 */ 279 goto LnoMFII; 280 281 if (drkbdputc(0xf8)) /* make/break, no typematic */ 282 goto LnoMFII; 283 284 if (drkbdputc(0xf4)) /* enable */ 285 goto LnoMFII; 286 kbd_softc.k_mf2 = 1; 287 single_inst_bclr_b(draco_ioct->io_control, DRCNTRL_KBDINTENA); 288 289 ciaa.icr = CIA_ICR_SP; /* CIA SP interrupt disable */ 290 ciaa.cra &= ~(1<<6); /* serial line == input */ 291 splx(s); 292 return; 293 294 LnoMFII: 295 kbd_softc.k_mf2 = 0; 296 single_inst_bset_b(*draco_intena, DRIRQ_INT2); 297 ciaa.icr = CIA_ICR_IR_SC | CIA_ICR_SP; 298 /* SP interrupt enable */ 299 ciaa.cra &= ~(1<<6); /* serial line == input */ 300 splx(s); 301 return; 302 303 } else { 304 #endif 305 custom.intena = INTF_SETCLR | INTF_PORTS; 306 ciaa.icr = CIA_ICR_IR_SC | CIA_ICR_SP; /* SP interrupt enable */ 307 ciaa.cra &= ~(1<<6); /* serial line == input */ 308 #ifdef DRACO 309 } 310 #endif 311 kbd_softc.k_event_mode = 0; 312 kbd_softc.k_events.ev_io = 0; 313 splx(s); 314 } 315 316 #ifdef DRACO 317 /* 318 * call this with kbd interrupt blocked 319 */ 320 321 int 322 drkbdgetc(void) 323 { 324 u_int8_t in; 325 326 while ((draco_ioct->io_status & DRSTAT_KBDRECV) == 0); 327 in = draco_ioct->io_kbddata; 328 draco_ioct->io_kbdrst = 0; 329 330 return in; 331 } 332 333 #define WAIT0 if (drkbdwaitfor(0)) goto Ltimeout 334 #define WAIT1 if (drkbdwaitfor(DRSTAT_KBDCLKIN)) goto Ltimeout 335 336 int 337 drkbdwaitfor(int bit) 338 { 339 int i; 340 341 342 343 i = 60000; /* about 50 ms max */ 344 345 do { 346 if ((draco_ioct->io_status & DRSTAT_KBDCLKIN) == bit) 347 return 0; 348 349 } while (--i >= 0); 350 351 return 1; 352 } 353 354 /* 355 * Output a raw byte to the keyboard (+ parity and stop bit). 356 * return 0 on success, 1 on timeout. 357 */ 358 int 359 drkbdrputc(u_int8_t c) 360 { 361 u_int8_t parity; 362 int bitcnt; 363 364 DATLO; CLKHI; WAIT1; 365 parity = 0; 366 367 for (bitcnt=7; bitcnt >= 0; bitcnt--) { 368 WAIT0; 369 if (c & 1) { 370 DATHI; 371 } else { 372 ++parity; 373 DATLO; 374 } 375 c >>= 1; 376 WAIT1; 377 } 378 WAIT0; 379 /* parity bit */ 380 if (parity & 1) { 381 DATLO; 382 } else { 383 DATHI; 384 } 385 WAIT1; 386 /* stop bit */ 387 WAIT0; DATHI; WAIT1; 388 389 WAIT0; /* XXX should check the ack bit here... */ 390 WAIT1; 391 draco_ioct->io_kbdrst = 0; 392 return 0; 393 394 Ltimeout: 395 DATHI; 396 draco_ioct->io_kbdrst = 0; 397 return 1; 398 } 399 400 /* 401 * Output one cooked byte to the keyboard, with wait for ACK or RESEND, 402 * and retry if necessary. 0 == success, 1 == timeout 403 */ 404 int 405 drkbdputc(u_int8_t c) 406 { 407 int rc; 408 409 do { 410 if (drkbdrputc(c)) 411 return(-1); 412 413 rc = drkbdgetc(); 414 } while (rc == 0xfe); 415 return (!(rc == 0xfa)); 416 } 417 418 /* 419 * same for twobyte sequence 420 */ 421 422 int 423 drkbdputc2(u_int8_t c1, u_int8_t c2) 424 { 425 int rc; 426 427 do { 428 do { 429 if (drkbdrputc(c1)) 430 return(-1); 431 432 rc = drkbdgetc(); 433 } while (rc == 0xfe); 434 if (rc != 0xfa) 435 return (-1); 436 437 if (drkbdrputc(c2)) 438 return(-1); 439 440 rc = drkbdgetc(); 441 } while (rc == 0xfe); 442 return (!(rc == 0xfa)); 443 } 444 #endif 445 446 int 447 kbdopen(dev_t dev, int flags, int mode, struct lwp *l) 448 { 449 450 kbdenable(); 451 if (kbd_softc.k_events.ev_io) 452 return EBUSY; 453 454 kbd_softc.k_events.ev_io = l->l_proc; 455 ev_init(&kbd_softc.k_events); 456 return (0); 457 } 458 459 int 460 kbdclose(dev_t dev, int flags, int mode, struct lwp *l) 461 { 462 463 /* Turn off event mode, dump the queue */ 464 kbd_softc.k_event_mode = 0; 465 ev_fini(&kbd_softc.k_events); 466 kbd_softc.k_events.ev_io = NULL; 467 return (0); 468 } 469 470 int 471 kbdread(dev_t dev, struct uio *uio, int flags) 472 { 473 return ev_read (&kbd_softc.k_events, uio, flags); 474 } 475 476 int 477 kbdioctl(dev_t dev, u_long cmd, register void *data, int flag, 478 struct lwp *l) 479 { 480 register struct kbd_softc *k = &kbd_softc; 481 482 switch (cmd) { 483 case KIOCTRANS: 484 if (*(int *)data == TR_UNTRANS_EVENT) 485 return 0; 486 break; 487 488 case KIOCGTRANS: 489 /* Get translation mode */ 490 *(int *)data = TR_UNTRANS_EVENT; 491 return 0; 492 493 case KIOCSDIRECT: 494 k->k_event_mode = *(int *)data; 495 return 0; 496 497 case FIONBIO: /* we will remove this someday (soon???) */ 498 return 0; 499 500 case FIOASYNC: 501 k->k_events.ev_async = *(int *)data != 0; 502 return 0; 503 504 case FIOSETOWN: 505 if (-*(int *)data != k->k_events.ev_io->p_pgid 506 && *(int *)data != k->k_events.ev_io->p_pid) 507 return EPERM; 508 return 0; 509 510 case TIOCSPGRP: 511 if (*(int *)data != k->k_events.ev_io->p_pgid) 512 return EPERM; 513 return 0; 514 515 default: 516 return ENOTTY; 517 } 518 519 /* We identified the ioctl, but we do not handle it. */ 520 return EOPNOTSUPP; /* misuse, but what the heck */ 521 } 522 523 int 524 kbdpoll(dev_t dev, int events, struct lwp *l) 525 { 526 return ev_poll (&kbd_softc.k_events, events, l); 527 } 528 529 int 530 kbdkqfilter(dev, kn) 531 dev_t dev; 532 struct knote *kn; 533 { 534 535 return (ev_kqfilter(&kbd_softc.k_events, kn)); 536 } 537 538 void 539 kbdintr(int mask) 540 { 541 u_char c; 542 #ifdef KBDRESET 543 static int reset_warn; 544 #endif 545 546 /* 547 * now only invoked from generic CIA interrupt handler if there *is* 548 * a keyboard interrupt pending 549 */ 550 551 c = ~ciaa.sdr; /* keyboard data is inverted */ 552 /* ack */ 553 ciaa.cra |= (1 << 6); /* serial line output */ 554 #ifdef KBDRESET 555 if (reset_warn && c == 0xf0) { 556 #ifdef DEBUG 557 printf ("kbdintr: !!!! Reset Warning !!!!\n"); 558 #endif 559 bootsync(); 560 reset_warn = 0; 561 DELAY(30000000); 562 } 563 #endif 564 /* wait 200 microseconds (for bloody Cherry keyboards..) */ 565 DELAY(2000); /* fudge delay a bit for some keyboards */ 566 ciaa.cra &= ~(1 << 6); 567 568 /* process the character */ 569 c = (c >> 1) | (c << 7); /* rotate right once */ 570 571 #ifdef KBDRESET 572 if (c == 0x78) { 573 #ifdef DEBUG 574 printf ("kbdintr: Reset Warning started\n"); 575 #endif 576 ++reset_warn; 577 return; 578 } 579 #endif 580 kbdstuffchar(c); 581 } 582 583 #ifdef DRACO 584 /* maps MF-II keycodes to Amiga keycodes */ 585 586 const u_char drkbdtab[] = { 587 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x50, 588 0x45, 0xff, 0xff, 0xff, 0xff, 0x42, 0x00, 0x51, 589 590 0xff, 0x64, 0x60, 0x30, 0x63, 0x10, 0x01, 0x52, 591 0xff, 0x66, 0x31, 0x21, 0x20, 0x11, 0x02, 0x53, 592 593 0xff, 0x33, 0x32, 0x22, 0x12, 0x04, 0x03, 0x54, 594 0xff, 0x40, 0x34, 0x23, 0x14, 0x13, 0x05, 0x55, 595 596 0xff, 0x36, 0x35, 0x25, 0x24, 0x15, 0x06, 0x56, 597 0xff, 0x67, 0x37, 0x26, 0x16, 0x07, 0x08, 0x57, 598 /* --- */ 599 0xff, 0x38, 0x27, 0x17, 0x18, 0x0a, 0x09, 0x58, 600 0xff, 0x39, 0x3a, 0x28, 0x29, 0x19, 0x0b, 0x59, 601 602 0xff, 0xff, 0x2a, 0x2b, 0x1a, 0x0c, 0x4b, 0xff, 603 0x65, 0x61, 0x44, 0x1b, 0xff, 0xff, 0x6f, 0xff, 604 605 0x4d, 0x4f, 0xff, 0x4c, 0x0d, 0xff, 0x41, 0x46, 606 0xff, 0x1d, 0x4e, 0x2d, 0x3d, 0x4a, 0x5f, 0x62, 607 608 0x0f, 0x3c, 0x1e, 0x2e, 0x2f, 0x3e, 0x5a, 0x5b, 609 0xff, 0x43, 0x1f, 0xff, 0x5e, 0x3f, 0x5c, 0xff, 610 /* --- */ 611 0xff, 0xff, 0xff, 0xff, 0x5d 612 }; 613 #endif 614 615 616 int 617 kbdgetcn(void) 618 { 619 int s; 620 u_char ints, mask, c, in; 621 622 #ifdef DRACO 623 if (is_draco() && kbd_softc.k_mf2) { 624 do { 625 c = 0; 626 s = spltty (); 627 while ((draco_ioct->io_status & DRSTAT_KBDRECV) == 0); 628 in = draco_ioct->io_kbddata; 629 draco_ioct->io_kbdrst = 0; 630 if (in == 0xF0) { /* release prefix */ 631 c = 0x80; 632 while ((draco_ioct->io_status & 633 DRSTAT_KBDRECV) == 0); 634 in = draco_ioct->io_kbddata; 635 draco_ioct->io_kbdrst = 0; 636 } 637 splx(s); 638 #ifdef DRACORAWKEYDEBUG 639 printf("<%02x>", in); 640 #endif 641 c |= in>=sizeof(drkbdtab) ? 0xff : drkbdtab[in]; 642 } while (c == 0xff); 643 return (c); 644 } 645 #endif 646 s = spltty(); 647 for (ints = 0; ! ((mask = ciaa.icr) & CIA_ICR_SP); 648 ints |= mask) ; 649 650 in = ciaa.sdr; 651 c = ~in; 652 653 /* ack */ 654 ciaa.cra |= (1 << 6); /* serial line output */ 655 ciaa.sdr = 0xff; /* ack */ 656 /* wait 200 microseconds */ 657 DELAY(2000); /* XXXX only works as long as DELAY doesn't 658 * use a timer and waits.. */ 659 ciaa.cra &= ~(1 << 6); 660 ciaa.sdr = in; 661 662 splx (s); 663 c = (c >> 1) | (c << 7); 664 665 /* take care that no CIA-interrupts are lost */ 666 if (ints) 667 dispatch_cia_ints (0, ints); 668 669 return c; 670 } 671 672 void 673 kbdstuffchar(u_char c) 674 { 675 struct firm_event *fe; 676 struct kbd_softc *k = &kbd_softc; 677 int put; 678 679 #if NWSKBD>0 680 /* 681 * If we have attached a wskbd and not in polling mode and 682 * nobody has opened us directly, then send the keystroke 683 * to the wskbd. 684 */ 685 686 if (kbd_softc.k_pollingmode == 0 687 && kbd_softc.k_wskbddev != NULL 688 && k->k_event_mode == 0) { 689 wskbd_input(kbd_softc.k_wskbddev, 690 KEY_UP(c) ? 691 WSCONS_EVENT_KEY_UP : 692 WSCONS_EVENT_KEY_DOWN, 693 KEY_CODE(c)); 694 return; 695 } 696 697 #endif /* NWSKBD */ 698 699 /* 700 * If not in event mode, deliver straight to ite to process 701 * key stroke 702 */ 703 704 if (! k->k_event_mode) { 705 #if NITE>0 706 ite_filter (c, ITEFILT_TTY); 707 #endif 708 return; 709 } 710 711 /* 712 * Keyboard is generating events. Turn this keystroke into an 713 * event and put it in the queue. If the queue is full, the 714 * keystroke is lost (sorry!). 715 */ 716 717 put = k->k_events.ev_put; 718 fe = &k->k_events.ev_q[put]; 719 put = (put + 1) % EV_QSIZE; 720 if (put == k->k_events.ev_get) { 721 log(LOG_WARNING, "keyboard event queue overflow\n"); 722 /* ??? */ 723 return; 724 } 725 fe->id = KEY_CODE(c); 726 fe->value = KEY_UP(c) ? VKEY_UP : VKEY_DOWN; 727 getmicrotime(&fe->time); 728 k->k_events.ev_put = put; 729 EV_WAKEUP(&k->k_events); 730 } 731 732 733 #ifdef DRACO 734 void 735 drkbdintr(void) 736 { 737 u_char in; 738 struct kbd_softc *k = &kbd_softc; 739 740 in = draco_ioct->io_kbddata; 741 draco_ioct->io_kbdrst = 0; 742 743 if (in == 0xF0) 744 k->k_rlprfx = 0x80; 745 else { 746 kbdstuffchar(in>=sizeof(drkbdtab) ? 0xff : 747 drkbdtab[in] | k->k_rlprfx); 748 k->k_rlprfx = 0; 749 } 750 } 751 752 #endif 753 754 755 #if NWSKBD>0 756 /* 757 * These are the callback functions that are passed to wscons. 758 * They really don't do anything worth noting, just call the 759 * other functions above. 760 */ 761 762 int 763 kbd_enable(void *c, int on) 764 { 765 /* Wonder what this is supposed to do... */ 766 return (0); 767 } 768 769 void 770 kbd_set_leds(void *c, int leds) 771 { 772 } 773 774 int 775 kbd_ioctl(void *c, u_long cmd, void *data, int flag, struct lwp *l) 776 { 777 switch (cmd) 778 { 779 case WSKBDIO_COMPLEXBELL: 780 return 0; 781 case WSKBDIO_SETLEDS: 782 return 0; 783 case WSKBDIO_GETLEDS: 784 *(int*)data = 0; 785 return 0; 786 case WSKBDIO_GTYPE: 787 *(u_int*)data = WSKBD_TYPE_AMIGA; 788 return 0; 789 } 790 791 /* 792 * We are supposed to return EPASSTHROUGH to wscons if we didn't 793 * understand. 794 */ 795 return (EPASSTHROUGH); 796 } 797 798 void 799 kbd_getc(void *c, u_int *type, int *data) 800 { 801 int key; 802 803 key = kbdgetcn(); 804 805 *data = KEY_CODE(key); 806 *type = KEY_UP(key) ? WSCONS_EVENT_KEY_UP : WSCONS_EVENT_KEY_DOWN; 807 } 808 809 void 810 kbd_pollc(void *c, int on) 811 { 812 kbd_softc.k_pollingmode = on; 813 } 814 815 void 816 kbd_bell(void *c, u_int x, u_int y, u_int z) 817 { 818 } 819 #endif /* WSKBD */ 820