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