1 /* $NetBSD: kbd.c,v 1.42 2002/10/02 04:55:52 thorpej 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.42 2002/10/02 04:55:52 thorpej 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 174 const struct cdevsw kbd_cdevsw = { 175 kbdopen, kbdclose, kbdread, nowrite, kbdioctl, 176 nostop, notty, kbdpoll, nommap, 177 }; 178 179 /*ARGSUSED*/ 180 int 181 kbdmatch(struct device *pdp, struct cfdata *cfp, void *auxp) 182 { 183 184 if (matchname((char *)auxp, "kbd")) 185 return(1); 186 return(0); 187 } 188 189 /*ARGSUSED*/ 190 void 191 kbdattach(struct device *pdp, struct device *dp, void *auxp) 192 { 193 #ifdef DRACO 194 kbdenable(); 195 if (kbd_softc.k_mf2) 196 printf(": QuickLogic type MF-II\n"); 197 else 198 printf(": CIA A type Amiga\n"); 199 #else 200 printf(": CIA A type Amiga\n"); 201 #endif 202 203 #if NWSKBD>0 204 if (dp != NULL) { 205 /* 206 * Try to attach the wskbd. 207 */ 208 struct wskbddev_attach_args waa; 209 210 /* Maybe should be done before this?... */ 211 wskbd_cnattach(&kbd_consops, NULL, &kbd_mapdata); 212 213 waa.console = 1; 214 waa.keymap = &kbd_mapdata; 215 waa.accessops = &kbd_accessops; 216 waa.accesscookie = NULL; 217 kbd_softc.k_wskbddev = config_found(dp, &waa, wskbddevprint); 218 219 kbd_softc.k_pollingmode = 0; 220 } 221 kbdenable(); 222 #endif /* WSKBD */ 223 } 224 225 /* definitions for amiga keyboard encoding. */ 226 #define KEY_CODE(c) ((c) & 0x7f) 227 #define KEY_UP(c) ((c) & 0x80) 228 229 #define DATLO single_inst_bclr_b(draco_ioct->io_control, DRCNTRL_KBDDATOUT) 230 #define DATHI single_inst_bset_b(draco_ioct->io_control, DRCNTRL_KBDDATOUT) 231 232 #define CLKLO single_inst_bclr_b(draco_ioct->io_control, DRCNTRL_KBDCLKOUT) 233 #define CLKHI single_inst_bset_b(draco_ioct->io_control, DRCNTRL_KBDCLKOUT) 234 235 void 236 kbdenable(void) 237 { 238 static int kbd_inited = 0; 239 240 int s; 241 242 #ifdef DRACO 243 int id; 244 #endif 245 /* 246 * collides with external ints from SCSI, watch out for this when 247 * enabling/disabling interrupts there !! 248 */ 249 s = splhigh(); /* don't lower; might be called from early ddb */ 250 if (kbd_inited) { 251 splx(s); 252 return; 253 } 254 kbd_inited = 1; 255 #ifdef DRACO 256 if (is_draco()) { 257 258 CLKLO; 259 delay(5000); 260 draco_ioct->io_kbdrst = 0; 261 262 if (drkbdputc(0xf2)) 263 goto LnoMFII; 264 265 id = drkbdgetc() << 8; 266 id |= drkbdgetc(); 267 268 if (id != 0xab83) 269 goto LnoMFII; 270 271 if (drkbdputc2(0xf0, 3)) /* mode 3 */ 272 goto LnoMFII; 273 274 if (drkbdputc(0xf8)) /* make/break, no typematic */ 275 goto LnoMFII; 276 277 if (drkbdputc(0xf4)) /* enable */ 278 goto LnoMFII; 279 kbd_softc.k_mf2 = 1; 280 single_inst_bclr_b(draco_ioct->io_control, DRCNTRL_KBDINTENA); 281 282 ciaa.icr = CIA_ICR_SP; /* CIA SP interrupt disable */ 283 ciaa.cra &= ~(1<<6); /* serial line == input */ 284 splx(s); 285 return; 286 287 LnoMFII: 288 kbd_softc.k_mf2 = 0; 289 single_inst_bset_b(*draco_intena, DRIRQ_INT2); 290 ciaa.icr = CIA_ICR_IR_SC | CIA_ICR_SP; 291 /* SP interrupt enable */ 292 ciaa.cra &= ~(1<<6); /* serial line == input */ 293 splx(s); 294 return; 295 296 } else { 297 #endif 298 custom.intena = INTF_SETCLR | INTF_PORTS; 299 ciaa.icr = CIA_ICR_IR_SC | CIA_ICR_SP; /* SP interrupt enable */ 300 ciaa.cra &= ~(1<<6); /* serial line == input */ 301 #ifdef DRACO 302 } 303 #endif 304 kbd_softc.k_event_mode = 0; 305 kbd_softc.k_events.ev_io = 0; 306 splx(s); 307 } 308 309 #ifdef DRACO 310 /* 311 * call this with kbd interupt blocked 312 */ 313 314 int 315 drkbdgetc(void) 316 { 317 u_int8_t in; 318 319 while ((draco_ioct->io_status & DRSTAT_KBDRECV) == 0); 320 in = draco_ioct->io_kbddata; 321 draco_ioct->io_kbdrst = 0; 322 323 return in; 324 } 325 326 #define WAIT0 if (drkbdwaitfor(0)) goto Ltimeout 327 #define WAIT1 if (drkbdwaitfor(DRSTAT_KBDCLKIN)) goto Ltimeout 328 329 int 330 drkbdwaitfor(int bit) 331 { 332 int i; 333 334 335 336 i = 60000; /* about 50 ms max */ 337 338 do { 339 if ((draco_ioct->io_status & DRSTAT_KBDCLKIN) == bit) 340 return 0; 341 342 } while (--i >= 0); 343 344 return 1; 345 } 346 347 /* 348 * Output a raw byte to the keyboard (+ parity and stop bit). 349 * return 0 on success, 1 on timeout. 350 */ 351 int 352 drkbdrputc(u_int8_t c) 353 { 354 u_int8_t parity; 355 int bitcnt; 356 357 DATLO; CLKHI; WAIT1; 358 parity = 0; 359 360 for (bitcnt=7; bitcnt >= 0; bitcnt--) { 361 WAIT0; 362 if (c & 1) { 363 DATHI; 364 } else { 365 ++parity; 366 DATLO; 367 } 368 c >>= 1; 369 WAIT1; 370 } 371 WAIT0; 372 /* parity bit */ 373 if (parity & 1) { 374 DATLO; 375 } else { 376 DATHI; 377 } 378 WAIT1; 379 /* stop bit */ 380 WAIT0; DATHI; WAIT1; 381 382 WAIT0; /* XXX should check the ack bit here... */ 383 WAIT1; 384 draco_ioct->io_kbdrst = 0; 385 return 0; 386 387 Ltimeout: 388 DATHI; 389 draco_ioct->io_kbdrst = 0; 390 return 1; 391 } 392 393 /* 394 * Output one cooked byte to the keyboard, with wait for ACK or RESEND, 395 * and retry if necessary. 0 == success, 1 == timeout 396 */ 397 int 398 drkbdputc(u_int8_t c) 399 { 400 int rc; 401 402 do { 403 if (drkbdrputc(c)) 404 return(-1); 405 406 rc = drkbdgetc(); 407 } while (rc == 0xfe); 408 return (!(rc == 0xfa)); 409 } 410 411 /* 412 * same for twobyte sequence 413 */ 414 415 int 416 drkbdputc2(u_int8_t c1, u_int8_t c2) 417 { 418 int rc; 419 420 do { 421 do { 422 if (drkbdrputc(c1)) 423 return(-1); 424 425 rc = drkbdgetc(); 426 } while (rc == 0xfe); 427 if (rc != 0xfa) 428 return (-1); 429 430 if (drkbdrputc(c2)) 431 return(-1); 432 433 rc = drkbdgetc(); 434 } while (rc == 0xfe); 435 return (!(rc == 0xfa)); 436 } 437 #endif 438 439 int 440 kbdopen(dev_t dev, int flags, int mode, struct proc *p) 441 { 442 443 kbdenable(); 444 if (kbd_softc.k_events.ev_io) 445 return EBUSY; 446 447 kbd_softc.k_events.ev_io = p; 448 ev_init(&kbd_softc.k_events); 449 return (0); 450 } 451 452 int 453 kbdclose(dev_t dev, int flags, int mode, struct proc *p) 454 { 455 456 /* Turn off event mode, dump the queue */ 457 kbd_softc.k_event_mode = 0; 458 ev_fini(&kbd_softc.k_events); 459 kbd_softc.k_events.ev_io = NULL; 460 return (0); 461 } 462 463 int 464 kbdread(dev_t dev, struct uio *uio, int flags) 465 { 466 return ev_read (&kbd_softc.k_events, uio, flags); 467 } 468 469 int 470 kbdioctl(dev_t dev, u_long cmd, register caddr_t data, int flag, 471 struct proc *p) 472 { 473 register struct kbd_softc *k = &kbd_softc; 474 475 switch (cmd) { 476 case KIOCTRANS: 477 if (*(int *)data == TR_UNTRANS_EVENT) 478 return 0; 479 break; 480 481 case KIOCGTRANS: 482 /* Get translation mode */ 483 *(int *)data = TR_UNTRANS_EVENT; 484 return 0; 485 486 case KIOCSDIRECT: 487 k->k_event_mode = *(int *)data; 488 return 0; 489 490 case FIONBIO: /* we will remove this someday (soon???) */ 491 return 0; 492 493 case FIOASYNC: 494 k->k_events.ev_async = *(int *)data != 0; 495 return 0; 496 497 case TIOCSPGRP: 498 if (*(int *)data != k->k_events.ev_io->p_pgid) 499 return EPERM; 500 return 0; 501 502 default: 503 return ENOTTY; 504 } 505 506 /* We identified the ioctl, but we do not handle it. */ 507 return EOPNOTSUPP; /* misuse, but what the heck */ 508 } 509 510 int 511 kbdpoll(dev_t dev, int events, struct proc *p) 512 { 513 return ev_poll (&kbd_softc.k_events, events, p); 514 } 515 516 517 void 518 kbdintr(int mask) 519 { 520 u_char c; 521 #ifdef KBDRESET 522 static int reset_warn; 523 #endif 524 525 /* 526 * now only invoked from generic CIA interrupt handler if there *is* 527 * a keyboard interrupt pending 528 */ 529 530 c = ~ciaa.sdr; /* keyboard data is inverted */ 531 /* ack */ 532 ciaa.cra |= (1 << 6); /* serial line output */ 533 #ifdef KBDRESET 534 if (reset_warn && c == 0xf0) { 535 #ifdef DEBUG 536 printf ("kbdintr: !!!! Reset Warning !!!!\n"); 537 #endif 538 bootsync(); 539 reset_warn = 0; 540 DELAY(30000000); 541 } 542 #endif 543 /* wait 200 microseconds (for bloody Cherry keyboards..) */ 544 DELAY(2000); /* fudge delay a bit for some keyboards */ 545 ciaa.cra &= ~(1 << 6); 546 547 /* process the character */ 548 c = (c >> 1) | (c << 7); /* rotate right once */ 549 550 #ifdef KBDRESET 551 if (c == 0x78) { 552 #ifdef DEBUG 553 printf ("kbdintr: Reset Warning started\n"); 554 #endif 555 ++reset_warn; 556 return; 557 } 558 #endif 559 kbdstuffchar(c); 560 } 561 562 #ifdef DRACO 563 /* maps MF-II keycodes to Amiga keycodes */ 564 565 const u_char drkbdtab[] = { 566 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x50, 567 0x45, 0xff, 0xff, 0xff, 0xff, 0x42, 0x00, 0x51, 568 569 0xff, 0x64, 0x60, 0x30, 0x63, 0x10, 0x01, 0x52, 570 0xff, 0x66, 0x31, 0x21, 0x20, 0x11, 0x02, 0x53, 571 572 0xff, 0x33, 0x32, 0x22, 0x12, 0x04, 0x03, 0x54, 573 0xff, 0x40, 0x34, 0x23, 0x14, 0x13, 0x05, 0x55, 574 575 0xff, 0x36, 0x35, 0x25, 0x24, 0x15, 0x06, 0x56, 576 0xff, 0x67, 0x37, 0x26, 0x16, 0x07, 0x08, 0x57, 577 /* --- */ 578 0xff, 0x38, 0x27, 0x17, 0x18, 0x0a, 0x09, 0x58, 579 0xff, 0x39, 0x3a, 0x28, 0x29, 0x19, 0x0b, 0x59, 580 581 0xff, 0xff, 0x2a, 0x2b, 0x1a, 0x0c, 0x4b, 0xff, 582 0x65, 0x61, 0x44, 0x1b, 0xff, 0xff, 0x6f, 0xff, 583 584 0x4d, 0x4f, 0xff, 0x4c, 0x0d, 0xff, 0x41, 0x46, 585 0xff, 0x1d, 0x4e, 0x2d, 0x3d, 0x4a, 0x5f, 0x62, 586 587 0x0f, 0x3c, 0x1e, 0x2e, 0x2f, 0x3e, 0x5a, 0x5b, 588 0xff, 0x43, 0x1f, 0xff, 0x5e, 0x3f, 0x5c, 0xff, 589 /* --- */ 590 0xff, 0xff, 0xff, 0xff, 0x5d 591 }; 592 #endif 593 594 595 int 596 kbdgetcn(void) 597 { 598 int s; 599 u_char ints, mask, c, in; 600 601 #ifdef DRACO 602 if (is_draco() && kbd_softc.k_mf2) { 603 do { 604 c = 0; 605 s = spltty (); 606 while ((draco_ioct->io_status & DRSTAT_KBDRECV) == 0); 607 in = draco_ioct->io_kbddata; 608 draco_ioct->io_kbdrst = 0; 609 if (in == 0xF0) { /* release prefix */ 610 c = 0x80; 611 while ((draco_ioct->io_status & 612 DRSTAT_KBDRECV) == 0); 613 in = draco_ioct->io_kbddata; 614 draco_ioct->io_kbdrst = 0; 615 } 616 splx(s); 617 #ifdef DRACORAWKEYDEBUG 618 printf("<%02x>", in); 619 #endif 620 c |= in>=sizeof(drkbdtab) ? 0xff : drkbdtab[in]; 621 } while (c == 0xff); 622 return (c); 623 } 624 #endif 625 s = spltty(); 626 for (ints = 0; ! ((mask = ciaa.icr) & CIA_ICR_SP); 627 ints |= mask) ; 628 629 in = ciaa.sdr; 630 c = ~in; 631 632 /* ack */ 633 ciaa.cra |= (1 << 6); /* serial line output */ 634 ciaa.sdr = 0xff; /* ack */ 635 /* wait 200 microseconds */ 636 DELAY(2000); /* XXXX only works as long as DELAY doesn't 637 * use a timer and waits.. */ 638 ciaa.cra &= ~(1 << 6); 639 ciaa.sdr = in; 640 641 splx (s); 642 c = (c >> 1) | (c << 7); 643 644 /* take care that no CIA-interrupts are lost */ 645 if (ints) 646 dispatch_cia_ints (0, ints); 647 648 return c; 649 } 650 651 void 652 kbdstuffchar(u_char c) 653 { 654 struct firm_event *fe; 655 struct kbd_softc *k = &kbd_softc; 656 int put; 657 658 #if NWSKBD>0 659 /* 660 * If we have attached a wskbd and not in polling mode and 661 * nobody has opened us directly, then send the keystroke 662 * to the wskbd. 663 */ 664 665 if (kbd_softc.k_pollingmode == 0 666 && kbd_softc.k_wskbddev != NULL 667 && k->k_event_mode == 0) { 668 wskbd_input(kbd_softc.k_wskbddev, 669 KEY_UP(c) ? 670 WSCONS_EVENT_KEY_UP : 671 WSCONS_EVENT_KEY_DOWN, 672 KEY_CODE(c)); 673 return; 674 } 675 676 #endif /* NWSKBD */ 677 678 /* 679 * If not in event mode, deliver straight to ite to process 680 * key stroke 681 */ 682 683 if (! k->k_event_mode) { 684 #if NITE>0 685 ite_filter (c, ITEFILT_TTY); 686 #endif 687 return; 688 } 689 690 /* 691 * Keyboard is generating events. Turn this keystroke into an 692 * event and put it in the queue. If the queue is full, the 693 * keystroke is lost (sorry!). 694 */ 695 696 put = k->k_events.ev_put; 697 fe = &k->k_events.ev_q[put]; 698 put = (put + 1) % EV_QSIZE; 699 if (put == k->k_events.ev_get) { 700 log(LOG_WARNING, "keyboard event queue overflow\n"); 701 /* ??? */ 702 return; 703 } 704 fe->id = KEY_CODE(c); 705 fe->value = KEY_UP(c) ? VKEY_UP : VKEY_DOWN; 706 fe->time = time; 707 k->k_events.ev_put = put; 708 EV_WAKEUP(&k->k_events); 709 } 710 711 712 #ifdef DRACO 713 void 714 drkbdintr(void) 715 { 716 u_char in; 717 struct kbd_softc *k = &kbd_softc; 718 719 in = draco_ioct->io_kbddata; 720 draco_ioct->io_kbdrst = 0; 721 722 if (in == 0xF0) 723 k->k_rlprfx = 0x80; 724 else { 725 kbdstuffchar(in>=sizeof(drkbdtab) ? 0xff : 726 drkbdtab[in] | k->k_rlprfx); 727 k->k_rlprfx = 0; 728 } 729 } 730 731 #endif 732 733 734 #if NWSKBD>0 735 /* 736 * These are the callback functions that are passed to wscons. 737 * They really don't do anything worth noting, just call the 738 * other functions above. 739 */ 740 741 int 742 kbd_enable(void *c, int on) 743 { 744 /* Wonder what this is supposed to do... */ 745 return (0); 746 } 747 748 void 749 kbd_set_leds(void *c, int leds) 750 { 751 } 752 753 int 754 kbd_ioctl(void *c, u_long cmd, caddr_t data, int flag, struct proc *p) 755 { 756 switch (cmd) 757 { 758 case WSKBDIO_COMPLEXBELL: 759 return 0; 760 case WSKBDIO_SETLEDS: 761 return 0; 762 case WSKBDIO_GETLEDS: 763 *(int*)data = 0; 764 return 0; 765 case WSKBDIO_GTYPE: 766 *(u_int*)data = WSKBD_TYPE_AMIGA; 767 return 0; 768 } 769 770 /* 771 * We are supposed to return EPASSTHROUGH to wscons if we didn't 772 * understand. 773 */ 774 return (EPASSTHROUGH); 775 } 776 777 void 778 kbd_getc(void *c, u_int *type, int *data) 779 { 780 int key; 781 782 key = kbdgetcn(); 783 784 *data = KEY_CODE(key); 785 *type = KEY_UP(key) ? WSCONS_EVENT_KEY_UP : WSCONS_EVENT_KEY_DOWN; 786 } 787 788 void 789 kbd_pollc(void *c, int on) 790 { 791 kbd_softc.k_pollingmode = on; 792 } 793 794 void 795 kbd_bell(void *c, u_int x, u_int y, u_int z) 796 { 797 } 798 #endif /* WSKBD */ 799