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