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