1 /* $NetBSD: kbd.c,v 1.40 2002/09/06 13:18:43 gehenna 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.40 2002/09/06 13:18:43 gehenna 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 struct cfattach kbd_ca = { 166 sizeof(struct device), kbdmatch, kbdattach 167 }; 168 169 dev_type_open(kbdopen); 170 dev_type_close(kbdclose); 171 dev_type_read(kbdread); 172 dev_type_ioctl(kbdioctl); 173 dev_type_poll(kbdpoll); 174 175 const struct cdevsw kbd_cdevsw = { 176 kbdopen, kbdclose, kbdread, nowrite, kbdioctl, 177 nostop, notty, kbdpoll, nommap, 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 interupt 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 518 void 519 kbdintr(int mask) 520 { 521 u_char c; 522 #ifdef KBDRESET 523 static int reset_warn; 524 #endif 525 526 /* 527 * now only invoked from generic CIA interrupt handler if there *is* 528 * a keyboard interrupt pending 529 */ 530 531 c = ~ciaa.sdr; /* keyboard data is inverted */ 532 /* ack */ 533 ciaa.cra |= (1 << 6); /* serial line output */ 534 #ifdef KBDRESET 535 if (reset_warn && c == 0xf0) { 536 #ifdef DEBUG 537 printf ("kbdintr: !!!! Reset Warning !!!!\n"); 538 #endif 539 bootsync(); 540 reset_warn = 0; 541 DELAY(30000000); 542 } 543 #endif 544 /* wait 200 microseconds (for bloody Cherry keyboards..) */ 545 DELAY(2000); /* fudge delay a bit for some keyboards */ 546 ciaa.cra &= ~(1 << 6); 547 548 /* process the character */ 549 c = (c >> 1) | (c << 7); /* rotate right once */ 550 551 #ifdef KBDRESET 552 if (c == 0x78) { 553 #ifdef DEBUG 554 printf ("kbdintr: Reset Warning started\n"); 555 #endif 556 ++reset_warn; 557 return; 558 } 559 #endif 560 kbdstuffchar(c); 561 } 562 563 #ifdef DRACO 564 /* maps MF-II keycodes to Amiga keycodes */ 565 566 const u_char drkbdtab[] = { 567 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x50, 568 0x45, 0xff, 0xff, 0xff, 0xff, 0x42, 0x00, 0x51, 569 570 0xff, 0x64, 0x60, 0x30, 0x63, 0x10, 0x01, 0x52, 571 0xff, 0x66, 0x31, 0x21, 0x20, 0x11, 0x02, 0x53, 572 573 0xff, 0x33, 0x32, 0x22, 0x12, 0x04, 0x03, 0x54, 574 0xff, 0x40, 0x34, 0x23, 0x14, 0x13, 0x05, 0x55, 575 576 0xff, 0x36, 0x35, 0x25, 0x24, 0x15, 0x06, 0x56, 577 0xff, 0x67, 0x37, 0x26, 0x16, 0x07, 0x08, 0x57, 578 /* --- */ 579 0xff, 0x38, 0x27, 0x17, 0x18, 0x0a, 0x09, 0x58, 580 0xff, 0x39, 0x3a, 0x28, 0x29, 0x19, 0x0b, 0x59, 581 582 0xff, 0xff, 0x2a, 0x2b, 0x1a, 0x0c, 0x4b, 0xff, 583 0x65, 0x61, 0x44, 0x1b, 0xff, 0xff, 0x6f, 0xff, 584 585 0x4d, 0x4f, 0xff, 0x4c, 0x0d, 0xff, 0x41, 0x46, 586 0xff, 0x1d, 0x4e, 0x2d, 0x3d, 0x4a, 0x5f, 0x62, 587 588 0x0f, 0x3c, 0x1e, 0x2e, 0x2f, 0x3e, 0x5a, 0x5b, 589 0xff, 0x43, 0x1f, 0xff, 0x5e, 0x3f, 0x5c, 0xff, 590 /* --- */ 591 0xff, 0xff, 0xff, 0xff, 0x5d 592 }; 593 #endif 594 595 596 int 597 kbdgetcn(void) 598 { 599 int s; 600 u_char ints, mask, c, in; 601 602 #ifdef DRACO 603 if (is_draco() && kbd_softc.k_mf2) { 604 do { 605 c = 0; 606 s = spltty (); 607 while ((draco_ioct->io_status & DRSTAT_KBDRECV) == 0); 608 in = draco_ioct->io_kbddata; 609 draco_ioct->io_kbdrst = 0; 610 if (in == 0xF0) { /* release prefix */ 611 c = 0x80; 612 while ((draco_ioct->io_status & 613 DRSTAT_KBDRECV) == 0); 614 in = draco_ioct->io_kbddata; 615 draco_ioct->io_kbdrst = 0; 616 } 617 splx(s); 618 #ifdef DRACORAWKEYDEBUG 619 printf("<%02x>", in); 620 #endif 621 c |= in>=sizeof(drkbdtab) ? 0xff : drkbdtab[in]; 622 } while (c == 0xff); 623 return (c); 624 } 625 #endif 626 s = spltty(); 627 for (ints = 0; ! ((mask = ciaa.icr) & CIA_ICR_SP); 628 ints |= mask) ; 629 630 in = ciaa.sdr; 631 c = ~in; 632 633 /* ack */ 634 ciaa.cra |= (1 << 6); /* serial line output */ 635 ciaa.sdr = 0xff; /* ack */ 636 /* wait 200 microseconds */ 637 DELAY(2000); /* XXXX only works as long as DELAY doesn't 638 * use a timer and waits.. */ 639 ciaa.cra &= ~(1 << 6); 640 ciaa.sdr = in; 641 642 splx (s); 643 c = (c >> 1) | (c << 7); 644 645 /* take care that no CIA-interrupts are lost */ 646 if (ints) 647 dispatch_cia_ints (0, ints); 648 649 return c; 650 } 651 652 void 653 kbdstuffchar(u_char c) 654 { 655 struct firm_event *fe; 656 struct kbd_softc *k = &kbd_softc; 657 int put; 658 659 #if NWSKBD>0 660 /* 661 * If we have attached a wskbd and not in polling mode and 662 * nobody has opened us directly, then send the keystroke 663 * to the wskbd. 664 */ 665 666 if (kbd_softc.k_pollingmode == 0 667 && kbd_softc.k_wskbddev != NULL 668 && k->k_event_mode == 0) { 669 wskbd_input(kbd_softc.k_wskbddev, 670 KEY_UP(c) ? 671 WSCONS_EVENT_KEY_UP : 672 WSCONS_EVENT_KEY_DOWN, 673 KEY_CODE(c)); 674 return; 675 } 676 677 #endif /* NWSKBD */ 678 679 /* 680 * If not in event mode, deliver straight to ite to process 681 * key stroke 682 */ 683 684 if (! k->k_event_mode) { 685 #if NITE>0 686 ite_filter (c, ITEFILT_TTY); 687 #endif 688 return; 689 } 690 691 /* 692 * Keyboard is generating events. Turn this keystroke into an 693 * event and put it in the queue. If the queue is full, the 694 * keystroke is lost (sorry!). 695 */ 696 697 put = k->k_events.ev_put; 698 fe = &k->k_events.ev_q[put]; 699 put = (put + 1) % EV_QSIZE; 700 if (put == k->k_events.ev_get) { 701 log(LOG_WARNING, "keyboard event queue overflow\n"); 702 /* ??? */ 703 return; 704 } 705 fe->id = KEY_CODE(c); 706 fe->value = KEY_UP(c) ? VKEY_UP : VKEY_DOWN; 707 fe->time = time; 708 k->k_events.ev_put = put; 709 EV_WAKEUP(&k->k_events); 710 } 711 712 713 #ifdef DRACO 714 void 715 drkbdintr(void) 716 { 717 u_char in; 718 struct kbd_softc *k = &kbd_softc; 719 720 in = draco_ioct->io_kbddata; 721 draco_ioct->io_kbdrst = 0; 722 723 if (in == 0xF0) 724 k->k_rlprfx = 0x80; 725 else { 726 kbdstuffchar(in>=sizeof(drkbdtab) ? 0xff : 727 drkbdtab[in] | k->k_rlprfx); 728 k->k_rlprfx = 0; 729 } 730 } 731 732 #endif 733 734 735 #if NWSKBD>0 736 /* 737 * These are the callback functions that are passed to wscons. 738 * They really don't do anything worth noting, just call the 739 * other functions above. 740 */ 741 742 int 743 kbd_enable(void *c, int on) 744 { 745 /* Wonder what this is supposed to do... */ 746 return (0); 747 } 748 749 void 750 kbd_set_leds(void *c, int leds) 751 { 752 } 753 754 int 755 kbd_ioctl(void *c, u_long cmd, caddr_t data, int flag, struct proc *p) 756 { 757 switch (cmd) 758 { 759 case WSKBDIO_COMPLEXBELL: 760 return 0; 761 case WSKBDIO_SETLEDS: 762 return 0; 763 case WSKBDIO_GETLEDS: 764 *(int*)data = 0; 765 return 0; 766 case WSKBDIO_GTYPE: 767 *(u_int*)data = WSKBD_TYPE_AMIGA; 768 return 0; 769 } 770 771 /* 772 * We are supposed to return EPASSTHROUGH to wscons if we didn't 773 * understand. 774 */ 775 return (EPASSTHROUGH); 776 } 777 778 void 779 kbd_getc(void *c, u_int *type, int *data) 780 { 781 int key; 782 783 key = kbdgetcn(); 784 785 *data = KEY_CODE(key); 786 *type = KEY_UP(key) ? WSCONS_EVENT_KEY_UP : WSCONS_EVENT_KEY_DOWN; 787 } 788 789 void 790 kbd_pollc(void *c, int on) 791 { 792 kbd_softc.k_pollingmode = on; 793 } 794 795 void 796 kbd_bell(void *c, u_int x, u_int y, u_int z) 797 { 798 } 799 #endif /* WSKBD */ 800