1 /* $NetBSD: kbd.c,v 1.24 2003/02/04 21:32:03 leo Exp $ */ 2 3 /* 4 * Copyright (c) 1995 Leo Weppelman 5 * Copyright (c) 1982, 1986, 1990 The Regents of the University of California. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by the University of 19 * California, Berkeley and its contributors. 20 * 4. Neither the name of the University nor the names of its contributors 21 * may be used to endorse or promote products derived from this software 22 * without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 */ 36 37 #include "mouse.h" 38 #include "ite.h" 39 #include "wskbd.h" 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/conf.h> 48 #include <sys/file.h> 49 #include <sys/kernel.h> 50 #include <sys/signalvar.h> 51 #include <sys/syslog.h> 52 #include <dev/cons.h> 53 #include <machine/cpu.h> 54 #include <machine/iomap.h> 55 #include <machine/mfp.h> 56 #include <machine/acia.h> 57 #include <atari/dev/itevar.h> 58 #include <atari/dev/event_var.h> 59 #include <atari/dev/vuid_event.h> 60 #include <atari/dev/ym2149reg.h> 61 #include <atari/dev/kbdreg.h> 62 #include <atari/dev/kbdvar.h> 63 #include <atari/dev/kbdmap.h> 64 #include <atari/dev/msvar.h> 65 66 #if NWSKBD>0 67 #include <dev/wscons/wsconsio.h> 68 #include <dev/wscons/wskbdvar.h> 69 #include <dev/wscons/wsksymdef.h> 70 #include <dev/wscons/wsksymvar.h> 71 #include <atari/dev/wskbdmap_atari.h> 72 #endif 73 74 /* WSKBD */ 75 /* 76 * If NWSKBD>0 we try to attach an wskbd device to us. What follows 77 * is definitions of callback functions and structures that are passed 78 * to wscons when initializing. 79 */ 80 81 /* 82 * Now with wscons this driver exhibits some weird behaviour. 83 * It may act both as a driver of its own and the md part of the 84 * wskbd driver. Therefore it can be accessed through /dev/kbd 85 * and /dev/wskbd0 both. 86 * 87 * The data from they keyboard may end up in at least four different 88 * places: 89 * - If this driver has been opened (/dev/kbd) and the 90 * direct mode (TIOCDIRECT) has been set, data goes to 91 * the process who opened the device. Data will transmit itself 92 * as described by the firm_event structure. 93 * - If wskbd support is compiled in and a wskbd driver has been 94 * attached then the data is sent to it. Wskbd in turn may 95 * - Send the data in the wscons_event form to a process that 96 * has opened /dev/wskbd0 97 * - Feed the data to a virtual terminal. 98 * - If an ite is present the data may be fed to it. 99 */ 100 101 u_char kbd_modifier; /* Modifier mask */ 102 103 static u_char kbd_ring[KBD_RING_SIZE]; 104 static volatile u_int kbd_rbput = 0; /* 'put' index */ 105 static u_int kbd_rbget = 0; /* 'get' index */ 106 static u_char kbd_soft = 0; /* 1: Softint has been scheduled*/ 107 108 static struct kbd_softc kbd_softc; 109 110 /* {b,c}devsw[] function prototypes */ 111 dev_type_open(kbdopen); 112 dev_type_close(kbdclose); 113 dev_type_read(kbdread); 114 dev_type_ioctl(kbdioctl); 115 dev_type_poll(kbdpoll); 116 dev_type_kqfilter(kbdkqfilter); 117 118 /* Interrupt handler */ 119 void kbdintr __P((int)); 120 121 static void kbdsoft __P((void *, void *)); 122 static void kbdattach __P((struct device *, struct device *, void *)); 123 static int kbdmatch __P((struct device *, struct cfdata *, void *)); 124 #if NITE>0 125 static int kbd_do_modifier __P((u_char)); 126 #endif 127 static int kbd_write_poll __P((u_char *, int)); 128 static void kbd_pkg_start __P((struct kbd_softc *, u_char)); 129 130 CFATTACH_DECL(kbd, sizeof(struct device), 131 kbdmatch, kbdattach, NULL, NULL); 132 133 const struct cdevsw kbd_cdevsw = { 134 kbdopen, kbdclose, kbdread, nowrite, kbdioctl, 135 nostop, notty, kbdpoll, nommap, kbdkqfilter, 136 }; 137 138 #if NWSKBD>0 139 /* accessops */ 140 static int kbd_enable(void *, int); 141 static void kbd_set_leds(void *, int); 142 static int kbd_ioctl(void *, u_long, caddr_t, int, struct proc *); 143 144 /* console ops */ 145 static void kbd_getc(void *, u_int *, int *); 146 static void kbd_pollc(void *, int); 147 static void kbd_bell(void *, u_int, u_int, u_int); 148 149 static struct wskbd_accessops kbd_accessops = { 150 kbd_enable, 151 kbd_set_leds, 152 kbd_ioctl 153 }; 154 155 static struct wskbd_consops kbd_consops = { 156 kbd_getc, 157 kbd_pollc, 158 kbd_bell 159 }; 160 161 /* Pointer to keymaps. */ 162 static struct wskbd_mapdata kbd_mapdata = { 163 atarikbd_keydesctab, 164 KB_US 165 }; 166 #endif /* WSKBD */ 167 168 /*ARGSUSED*/ 169 static int 170 kbdmatch(pdp, cfp, auxp) 171 struct device *pdp; 172 struct cfdata *cfp; 173 void *auxp; 174 { 175 if (!strcmp((char *)auxp, "kbd")) 176 return (1); 177 return (0); 178 } 179 180 /*ARGSUSED*/ 181 static void 182 kbdattach(pdp, dp, auxp) 183 struct device *pdp, *dp; 184 void *auxp; 185 { 186 int timeout; 187 u_char kbd_rst[] = { 0x80, 0x01 }; 188 u_char kbd_icmd[] = { 0x12, 0x15 }; 189 190 /* 191 * Disable keyboard interrupts from MFP 192 */ 193 MFP->mf_ierb &= ~IB_AINT; 194 195 /* 196 * Reset ACIA and intialize to: 197 * divide by 16, 8 data, 1 stop, no parity, enable RX interrupts 198 */ 199 KBD->ac_cs = A_RESET; 200 delay(100); /* XXX: enough? */ 201 KBD->ac_cs = kbd_softc.k_soft_cs = KBD_INIT | A_RXINT; 202 203 /* 204 * Clear error conditions 205 */ 206 while (KBD->ac_cs & (A_IRQ|A_RXRDY)) 207 timeout = KBD->ac_da; 208 209 /* 210 * Now send the reset string, and read+ignore it's response 211 */ 212 if (!kbd_write_poll(kbd_rst, 2)) 213 printf("kbd: error cannot reset keyboard\n"); 214 for (timeout = 1000; timeout > 0; timeout--) { 215 if (KBD->ac_cs & (A_IRQ|A_RXRDY)) { 216 timeout = KBD->ac_da; 217 timeout = 100; 218 } 219 delay(100); 220 } 221 /* 222 * Send init command: disable mice & joysticks 223 */ 224 kbd_write_poll(kbd_icmd, sizeof(kbd_icmd)); 225 226 printf("\n"); 227 228 #if NWSKBD>0 229 if (dp != NULL) { 230 /* 231 * Try to attach the wskbd. 232 */ 233 struct wskbddev_attach_args waa; 234 235 /* Maybe should be done before this?... */ 236 wskbd_cnattach(&kbd_consops, NULL, &kbd_mapdata); 237 238 waa.console = 1; 239 waa.keymap = &kbd_mapdata; 240 waa.accessops = &kbd_accessops; 241 waa.accesscookie = NULL; 242 kbd_softc.k_wskbddev = config_found(dp, &waa, wskbddevprint); 243 244 kbd_softc.k_pollingmode = 0; 245 246 kbdenable(); 247 } 248 #endif /* WSKBD */ 249 } 250 251 void 252 kbdenable() 253 { 254 int s, code; 255 256 s = spltty(); 257 258 /* 259 * Clear error conditions... 260 */ 261 while (KBD->ac_cs & (A_IRQ|A_RXRDY)) 262 code = KBD->ac_da; 263 /* 264 * Enable interrupts from MFP 265 */ 266 MFP->mf_iprb = (u_int8_t)~IB_AINT; 267 MFP->mf_ierb |= IB_AINT; 268 MFP->mf_imrb |= IB_AINT; 269 270 kbd_softc.k_event_mode = 0; 271 kbd_softc.k_events.ev_io = 0; 272 kbd_softc.k_pkg_size = 0; 273 splx(s); 274 } 275 276 int kbdopen(dev_t dev, int flags, int mode, struct proc *p) 277 { 278 if (kbd_softc.k_events.ev_io) 279 return EBUSY; 280 281 kbd_softc.k_events.ev_io = p; 282 ev_init(&kbd_softc.k_events); 283 return (0); 284 } 285 286 int 287 kbdclose(dev_t dev, int flags, int mode, struct proc *p) 288 { 289 /* Turn off event mode, dump the queue */ 290 kbd_softc.k_event_mode = 0; 291 ev_fini(&kbd_softc.k_events); 292 kbd_softc.k_events.ev_io = NULL; 293 return (0); 294 } 295 296 int 297 kbdread(dev_t dev, struct uio *uio, int flags) 298 { 299 return ev_read(&kbd_softc.k_events, uio, flags); 300 } 301 302 int 303 kbdioctl(dev_t dev,u_long cmd,register caddr_t data,int flag,struct proc *p) 304 { 305 register struct kbd_softc *k = &kbd_softc; 306 struct kbdbell *kb; 307 308 switch (cmd) { 309 case KIOCTRANS: 310 if (*(int *)data == TR_UNTRANS_EVENT) 311 return 0; 312 break; 313 314 case KIOCGTRANS: 315 /* 316 * Get translation mode 317 */ 318 *(int *)data = TR_UNTRANS_EVENT; 319 return 0; 320 321 case KIOCSDIRECT: 322 k->k_event_mode = *(int *)data; 323 return 0; 324 325 case KIOCRINGBELL: 326 kb = (struct kbdbell *)data; 327 if (kb) 328 kbd_bell_sparms(kb->volume, kb->pitch, 329 kb->duration); 330 kbdbell(); 331 return 0; 332 333 case FIONBIO: /* we will remove this someday (soon???) */ 334 return 0; 335 336 case FIOASYNC: 337 k->k_events.ev_async = *(int *)data != 0; 338 return 0; 339 340 case TIOCSPGRP: 341 if (*(int *)data != k->k_events.ev_io->p_pgid) 342 return EPERM; 343 return 0; 344 345 default: 346 return ENOTTY; 347 } 348 349 /* 350 * We identified the ioctl, but we do not handle it. 351 */ 352 return EOPNOTSUPP; /* misuse, but what the heck */ 353 } 354 355 int 356 kbdpoll (dev_t dev, int events, struct proc *p) 357 { 358 return ev_poll (&kbd_softc.k_events, events, p); 359 } 360 361 int 362 kbdkqfilter(dev_t dev, struct knote *kn) 363 { 364 365 return (ev_kqfilter(&kbd_softc.k_events, kn)); 366 } 367 368 /* 369 * Keyboard interrupt handler called straight from MFP at spl6. 370 */ 371 void 372 kbdintr(sr) 373 int sr; /* sr at time of interrupt */ 374 { 375 int code; 376 int got_char = 0; 377 378 /* 379 * There may be multiple keys available. Read them all. 380 */ 381 while (KBD->ac_cs & (A_RXRDY|A_OE|A_PE)) { 382 got_char = 1; 383 if (KBD->ac_cs & (A_OE|A_PE)) { 384 code = KBD->ac_da; /* Silently ignore errors */ 385 continue; 386 } 387 kbd_ring[kbd_rbput++ & KBD_RING_MASK] = KBD->ac_da; 388 } 389 390 /* 391 * If characters are waiting for transmit, send them. 392 */ 393 if ((kbd_softc.k_soft_cs & A_TXINT) && (KBD->ac_cs & A_TXRDY)) { 394 if (kbd_softc.k_sendp != NULL) 395 KBD->ac_da = *kbd_softc.k_sendp++; 396 if (--kbd_softc.k_send_cnt <= 0) { 397 /* 398 * The total package has been transmitted, 399 * wakeup anyone waiting for it. 400 */ 401 KBD->ac_cs = (kbd_softc.k_soft_cs &= ~A_TXINT); 402 kbd_softc.k_sendp = NULL; 403 kbd_softc.k_send_cnt = 0; 404 wakeup((caddr_t)&kbd_softc.k_send_cnt); 405 } 406 } 407 408 /* 409 * Activate software-level to handle possible input. 410 */ 411 if (got_char) { 412 if (!BASEPRI(sr)) { 413 if (!kbd_soft++) 414 add_sicallback(kbdsoft, 0, 0); 415 } else { 416 spl1(); 417 kbdsoft(NULL, NULL); 418 } 419 } 420 } 421 422 /* 423 * Keyboard soft interrupt handler 424 */ 425 void 426 kbdsoft(junk1, junk2) 427 void *junk1, *junk2; 428 { 429 int s; 430 u_char code; 431 struct kbd_softc *k = &kbd_softc; 432 struct firm_event *fe; 433 int put; 434 int n, get; 435 436 kbd_soft = 0; 437 get = kbd_rbget; 438 439 for (;;) { 440 n = kbd_rbput; 441 if (get == n) /* We're done */ 442 break; 443 n -= get; 444 if (n > KBD_RING_SIZE) { /* Ring buffer overflow */ 445 get += n - KBD_RING_SIZE; 446 n = KBD_RING_SIZE; 447 } 448 while (--n >= 0) { 449 code = kbd_ring[get++ & KBD_RING_MASK]; 450 451 /* 452 * If collecting a package, stuff it in and 453 * continue. 454 */ 455 if (k->k_pkg_size && (k->k_pkg_idx < k->k_pkg_size)) { 456 k->k_package[k->k_pkg_idx++] = code; 457 if (k->k_pkg_idx == k->k_pkg_size) { 458 /* 459 * Package is complete. 460 */ 461 switch(k->k_pkg_type) { 462 #if NMOUSE > 0 463 case KBD_AMS_PKG: 464 case KBD_RMS_PKG: 465 case KBD_JOY1_PKG: 466 mouse_soft((REL_MOUSE *)k->k_package, 467 k->k_pkg_size, k->k_pkg_type); 468 #endif /* NMOUSE */ 469 } 470 k->k_pkg_size = 0; 471 } 472 continue; 473 } 474 /* 475 * If this is a package header, init pkg. handling. 476 */ 477 if (!KBD_IS_KEY(code)) { 478 kbd_pkg_start(k, code); 479 continue; 480 } 481 #if NWSKBD>0 482 /* 483 * If we have attached a wskbd and not in polling mode and 484 * nobody has opened us directly, then send the keystroke 485 * to the wskbd. 486 */ 487 488 if (kbd_softc.k_pollingmode == 0 489 && kbd_softc.k_wskbddev != NULL 490 && k->k_event_mode == 0) { 491 wskbd_input(kbd_softc.k_wskbddev, 492 KBD_RELEASED(code) ? 493 WSCONS_EVENT_KEY_UP : 494 WSCONS_EVENT_KEY_DOWN, 495 KBD_SCANCODE(code)); 496 continue; 497 } 498 #endif /* NWSKBD */ 499 #if NITE>0 500 if (kbd_do_modifier(code) && !k->k_event_mode) 501 continue; 502 #endif 503 504 /* 505 * if not in event mode, deliver straight to ite to 506 * process key stroke 507 */ 508 if (!k->k_event_mode) { 509 /* Gets to spltty() by itself */ 510 #if NITE>0 511 ite_filter(code, ITEFILT_TTY); 512 #endif 513 continue; 514 } 515 516 /* 517 * Keyboard is generating events. Turn this keystroke 518 * into an event and put it in the queue. If the queue 519 * is full, the keystroke is lost (sorry!). 520 */ 521 s = spltty(); 522 put = k->k_events.ev_put; 523 fe = &k->k_events.ev_q[put]; 524 put = (put + 1) % EV_QSIZE; 525 if (put == k->k_events.ev_get) { 526 log(LOG_WARNING, 527 "keyboard event queue overflow\n"); 528 splx(s); 529 continue; 530 } 531 fe->id = KBD_SCANCODE(code); 532 fe->value = KBD_RELEASED(code) ? VKEY_UP : VKEY_DOWN; 533 fe->time = time; 534 k->k_events.ev_put = put; 535 EV_WAKEUP(&k->k_events); 536 splx(s); 537 } 538 kbd_rbget = get; 539 } 540 } 541 542 static u_char sound[] = { 543 0xA8,0x01,0xA9,0x01,0xAA,0x01,0x00, 544 0xF8,0x10,0x10,0x10,0x00,0x20,0x03 545 }; 546 547 void 548 kbdbell() 549 { 550 register int i, sps; 551 552 sps = splhigh(); 553 for (i = 0; i < sizeof(sound); i++) { 554 YM2149->sd_selr = i; 555 YM2149->sd_wdat = sound[i]; 556 } 557 splx(sps); 558 } 559 560 561 /* 562 * Set the parameters of the 'default' beep. 563 */ 564 565 #define KBDBELLCLOCK 125000 /* 2MHz / 16 */ 566 #define KBDBELLDURATION 128 /* 256 / 2MHz */ 567 568 void 569 kbd_bell_gparms(volume, pitch, duration) 570 u_int *volume, *pitch, *duration; 571 { 572 u_int tmp; 573 574 tmp = sound[11] | (sound[12] << 8); 575 *duration = (tmp * KBDBELLDURATION) / 1000; 576 577 tmp = sound[0] | (sound[1] << 8); 578 *pitch = KBDBELLCLOCK / tmp; 579 580 *volume = 0; 581 } 582 583 void 584 kbd_bell_sparms(volume, pitch, duration) 585 u_int volume, pitch, duration; 586 { 587 u_int f, t; 588 589 f = pitch > 10 ? pitch : 10; /* minimum pitch */ 590 if (f > 20000) 591 f = 20000; /* maximum pitch */ 592 593 f = KBDBELLCLOCK / f; 594 595 t = (duration * 1000) / KBDBELLDURATION; 596 597 sound[ 0] = f & 0xff; 598 sound[ 1] = (f >> 8) & 0xf; 599 f -= 1; 600 sound[ 2] = f & 0xff; 601 sound[ 3] = (f >> 8) & 0xf; 602 f += 2; 603 sound[ 4] = f & 0xff; 604 sound[ 5] = (f >> 8) & 0xf; 605 606 sound[11] = t & 0xff; 607 sound[12] = (t >> 8) & 0xff; 608 609 sound[13] = 0x03; 610 } 611 612 int 613 kbdgetcn() 614 { 615 u_char code; 616 int s = spltty(); 617 int ints_active; 618 619 ints_active = 0; 620 if (MFP->mf_imrb & IB_AINT) { 621 ints_active = 1; 622 MFP->mf_imrb &= ~IB_AINT; 623 } 624 for (;;) { 625 while (!((KBD->ac_cs & (A_IRQ|A_RXRDY)) == (A_IRQ|A_RXRDY))) 626 ; /* Wait for key */ 627 if (KBD->ac_cs & (A_OE|A_PE)) { 628 code = KBD->ac_da; /* Silently ignore errors */ 629 continue; 630 } 631 code = KBD->ac_da; 632 #if NITE>0 633 if (!kbd_do_modifier(code)) 634 #endif 635 break; 636 } 637 638 if (ints_active) { 639 MFP->mf_iprb = (u_int8_t)~IB_AINT; 640 MFP->mf_imrb |= IB_AINT; 641 } 642 643 splx (s); 644 return code; 645 } 646 647 /* 648 * Write a command to the keyboard in 'polled' mode. 649 */ 650 static int 651 kbd_write_poll(cmd, len) 652 u_char *cmd; 653 int len; 654 { 655 int timeout; 656 657 while (len-- > 0) { 658 KBD->ac_da = *cmd++; 659 for (timeout = 100; !(KBD->ac_cs & A_TXRDY); timeout--) 660 delay(10); 661 if (!(KBD->ac_cs & A_TXRDY)) 662 return (0); 663 } 664 return (1); 665 } 666 667 /* 668 * Write a command to the keyboard. Return when command is send. 669 */ 670 void 671 kbd_write(cmd, len) 672 u_char *cmd; 673 int len; 674 { 675 struct kbd_softc *k = &kbd_softc; 676 int sps; 677 678 /* 679 * Get to splhigh, 'real' interrupts arrive at spl6! 680 */ 681 sps = splhigh(); 682 683 /* 684 * Make sure any privious write has ended... 685 */ 686 while (k->k_sendp != NULL) 687 tsleep((caddr_t)&k->k_sendp, TTOPRI, "kbd_write1", 0); 688 689 /* 690 * If the KBD-acia is not currently busy, send the first 691 * character now. 692 */ 693 KBD->ac_cs = (k->k_soft_cs |= A_TXINT); 694 if (KBD->ac_cs & A_TXRDY) { 695 KBD->ac_da = *cmd++; 696 len--; 697 } 698 699 /* 700 * If we're not yet done, wait until all characters are send. 701 */ 702 if (len > 0) { 703 k->k_sendp = cmd; 704 k->k_send_cnt = len; 705 tsleep((caddr_t)&k->k_send_cnt, TTOPRI, "kbd_write2", 0); 706 } 707 splx(sps); 708 709 /* 710 * Wakeup all procs waiting for us. 711 */ 712 wakeup((caddr_t)&k->k_sendp); 713 } 714 715 /* 716 * Setup softc-fields to assemble a keyboard package. 717 */ 718 static void 719 kbd_pkg_start(kp, msg_start) 720 struct kbd_softc *kp; 721 u_char msg_start; 722 { 723 kp->k_pkg_idx = 1; 724 kp->k_package[0] = msg_start; 725 switch (msg_start) { 726 case 0xf6: 727 kp->k_pkg_type = KBD_MEM_PKG; 728 kp->k_pkg_size = 8; 729 break; 730 case 0xf7: 731 kp->k_pkg_type = KBD_AMS_PKG; 732 kp->k_pkg_size = 6; 733 break; 734 case 0xf8: 735 case 0xf9: 736 case 0xfa: 737 case 0xfb: 738 kp->k_pkg_type = KBD_RMS_PKG; 739 kp->k_pkg_size = 3; 740 break; 741 case 0xfc: 742 kp->k_pkg_type = KBD_CLK_PKG; 743 kp->k_pkg_size = 7; 744 break; 745 case 0xfe: 746 kp->k_pkg_type = KBD_JOY0_PKG; 747 kp->k_pkg_size = 2; 748 break; 749 case 0xff: 750 kp->k_pkg_type = KBD_JOY1_PKG; 751 kp->k_pkg_size = 2; 752 break; 753 default: 754 printf("kbd: Unknown packet 0x%x\n", msg_start); 755 break; 756 } 757 } 758 759 #if NITE>0 760 /* 761 * Modifier processing 762 */ 763 static int 764 kbd_do_modifier(code) 765 u_char code; 766 { 767 u_char up, mask; 768 769 up = KBD_RELEASED(code); 770 mask = 0; 771 772 switch(KBD_SCANCODE(code)) { 773 case KBD_LEFT_SHIFT: 774 mask = KBD_MOD_LSHIFT; 775 break; 776 case KBD_RIGHT_SHIFT: 777 mask = KBD_MOD_RSHIFT; 778 break; 779 case KBD_CTRL: 780 mask = KBD_MOD_CTRL; 781 break; 782 case KBD_ALT: 783 mask = KBD_MOD_ALT; 784 break; 785 case KBD_CAPS_LOCK: 786 /* CAPSLOCK is a toggle */ 787 if(!up) 788 kbd_modifier ^= KBD_MOD_CAPS; 789 return 1; 790 } 791 if(mask) { 792 if(up) 793 kbd_modifier &= ~mask; 794 else 795 kbd_modifier |= mask; 796 return 1; 797 } 798 return 0; 799 } 800 #endif 801 802 #if NWSKBD>0 803 /* 804 * These are the callback functions that are passed to wscons. 805 * They really don't do anything worth noting, just call the 806 * other functions above. 807 */ 808 809 static int 810 kbd_enable(void *c, int on) 811 { 812 /* Wonder what this is supposed to do... */ 813 return 0; 814 } 815 816 static void 817 kbd_set_leds(void *c, int leds) 818 { 819 /* we can not set the leds */ 820 } 821 822 static int 823 kbd_ioctl(void *c, u_long cmd, caddr_t data, int flag, struct proc *p) 824 { 825 struct wskbd_bell_data *kd; 826 827 switch (cmd) 828 { 829 case WSKBDIO_COMPLEXBELL: 830 kd = (struct wskbd_bell_data *)data; 831 kbd_bell(0, kd->pitch, kd->period, kd->volume); 832 return 0; 833 case WSKBDIO_SETLEDS: 834 return 0; 835 case WSKBDIO_GETLEDS: 836 *(int*)data = 0; 837 return 0; 838 case WSKBDIO_GTYPE: 839 *(u_int*)data = WSKBD_TYPE_ATARI; 840 return 0; 841 } 842 843 /* 844 * We are supposed to return EPASSTHROUGH to wscons if we didn't 845 * understand. 846 */ 847 return (EPASSTHROUGH); 848 } 849 850 static void 851 kbd_getc(void *c, u_int *type, int *data) 852 { 853 int key; 854 key = kbdgetcn(); 855 856 *data = KBD_SCANCODE(key); 857 *type = KBD_RELEASED(key) ? WSCONS_EVENT_KEY_UP : WSCONS_EVENT_KEY_DOWN; 858 } 859 860 static void 861 kbd_pollc(void *c, int on) 862 { 863 kbd_softc.k_pollingmode = on; 864 } 865 866 static void 867 kbd_bell(void *v, u_int pitch, u_int duration, u_int volume) 868 { 869 kbd_bell_sparms(volume, pitch, duration); 870 kbdbell(); 871 } 872 #endif /* NWSKBD */ 873