1/*- 2 * Copyright (c) 1999 FreeBSD(98) port team. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer as 10 * the first lines of this file unmodified. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. The name of the author may not be used to endorse or promote products 15 * derived from this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * $FreeBSD$ 29 */ 30 31#include "opt_compat.h" 32#include "opt_kbd.h" 33 34#include <sys/param.h> 35#include <sys/systm.h> 36#include <sys/kernel.h> 37#include <sys/module.h> 38#include <sys/bus.h> 39#include <machine/bus.h> 40#include <sys/rman.h> 41#include <sys/kbio.h> 42 43#include <machine/resource.h> 44 45#include <dev/kbd/kbdreg.h> 46 47#include <pc98/cbus/cbus.h> 48#include <isa/isavar.h> 49 50#define DRIVER_NAME "pckbd" 51 52/* device configuration flags */ 53#define KB_CONF_FAIL_IF_NO_KBD (1 << 0) /* don't install if no kbd is found */ 54 55typedef caddr_t KBDC; 56 57typedef struct pckbd_state { 58 KBDC kbdc; /* keyboard controller */ 59 int ks_mode; /* input mode (K_XLATE,K_RAW,K_CODE) */ 60 int ks_flags; /* flags */ 61#define COMPOSE (1 << 0) 62 int ks_state; /* shift/lock key state */ 63 int ks_accents; /* accent key index (> 0) */ 64 u_int ks_composed_char; /* composed char code (> 0) */ 65 struct callout ks_timer; 66} pckbd_state_t; 67 68static devclass_t pckbd_devclass; 69 70static int pckbdprobe(device_t dev); 71static int pckbdattach(device_t dev); 72static int pckbdresume(device_t dev); 73static void pckbd_isa_intr(void *arg); 74 75static device_method_t pckbd_methods[] = { 76 /* Device interface */ 77 DEVMETHOD(device_probe, pckbdprobe), 78 DEVMETHOD(device_attach, pckbdattach), 79 DEVMETHOD(device_resume, pckbdresume), 80 { 0, 0 } 81}; 82 83static driver_t pckbd_driver = { 84 DRIVER_NAME, 85 pckbd_methods, 86 1, 87}; 88 89DRIVER_MODULE(pckbd, isa, pckbd_driver, pckbd_devclass, 0, 0); 90 91static bus_addr_t pckbd_iat[] = {0, 2}; 92 93static int pckbd_probe_unit(device_t dev, int port, int irq, 94 int flags); 95static int pckbd_attach_unit(device_t dev, keyboard_t **kbd, 96 int port, int irq, int flags); 97static timeout_t pckbd_timeout; 98 99 100static int 101pckbdprobe(device_t dev) 102{ 103 struct resource *res; 104 int error, rid; 105 106 /* Check isapnp ids */ 107 if (isa_get_vendorid(dev)) 108 return (ENXIO); 109 110 device_set_desc(dev, "PC-98 Keyboard"); 111 112 rid = 0; 113 res = isa_alloc_resourcev(dev, SYS_RES_IOPORT, &rid, pckbd_iat, 2, 114 RF_ACTIVE); 115 if (res == NULL) 116 return ENXIO; 117 isa_load_resourcev(res, pckbd_iat, 2); 118 119 error = pckbd_probe_unit(dev, 120 isa_get_port(dev), 121 (1 << isa_get_irq(dev)), 122 device_get_flags(dev)); 123 124 bus_release_resource(dev, SYS_RES_IOPORT, rid, res); 125 126 return (error); 127} 128 129static int 130pckbdattach(device_t dev) 131{ 132 keyboard_t *kbd; 133 void *ih; 134 struct resource *res; 135 int error, rid; 136 137 rid = 0; 138 res = isa_alloc_resourcev(dev, SYS_RES_IOPORT, &rid, pckbd_iat, 2, 139 RF_ACTIVE); 140 if (res == NULL) 141 return ENXIO; 142 isa_load_resourcev(res, pckbd_iat, 2); 143 144 error = pckbd_attach_unit(dev, &kbd, 145 isa_get_port(dev), 146 (1 << isa_get_irq(dev)), 147 device_get_flags(dev)); 148 149 rid = 0; 150 res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE); 151 if (res == NULL) 152 return ENXIO; 153 bus_setup_intr(dev, res, INTR_TYPE_TTY, NULL, pckbd_isa_intr, kbd, &ih); 154 155 return 0; 156} 157 158static int 159pckbdresume(device_t dev) 160{ 161 keyboard_t *kbd; 162 163 kbd = kbd_get_keyboard(kbd_find_keyboard(DRIVER_NAME, 164 device_get_unit(dev))); 165 if (kbd) 166 kbdd_clear_state(kbd); 167 168 return (0); 169} 170 171static void 172pckbd_isa_intr(void *arg) 173{ 174 keyboard_t *kbd = arg; 175 176 kbdd_intr(kbd, NULL); 177} 178 179static int 180pckbd_probe_unit(device_t dev, int port, int irq, int flags) 181{ 182 keyboard_switch_t *sw; 183 int args[2]; 184 int error; 185 186 sw = kbd_get_switch(DRIVER_NAME); 187 if (sw == NULL) 188 return ENXIO; 189 190 args[0] = port; 191 args[1] = irq; 192 error = (*sw->probe)(device_get_unit(dev), args, flags); 193 if (error) 194 return error; 195 return 0; 196} 197 198static int 199pckbd_attach_unit(device_t dev, keyboard_t **kbd, int port, int irq, int flags) 200{ 201 keyboard_switch_t *sw; 202 pckbd_state_t *state; 203 int args[2]; 204 int error; 205 int unit; 206 207 sw = kbd_get_switch(DRIVER_NAME); 208 if (sw == NULL) 209 return ENXIO; 210 211 /* reset, initialize and enable the device */ 212 unit = device_get_unit(dev); 213 args[0] = port; 214 args[1] = irq; 215 *kbd = NULL; 216 error = (*sw->probe)(unit, args, flags); 217 if (error) 218 return error; 219 error = (*sw->init)(unit, kbd, args, flags); 220 if (error) 221 return error; 222 (*sw->enable)(*kbd); 223 224#ifdef KBD_INSTALL_CDEV 225 /* attach a virtual keyboard cdev */ 226 error = kbd_attach(*kbd); 227 if (error) 228 return error; 229#endif /* KBD_INSTALL_CDEV */ 230 231 /* 232 * This is a kludge to compensate for lost keyboard interrupts. 233 * A similar code used to be in syscons. See below. XXX 234 */ 235 state = (pckbd_state_t *)(*kbd)->kb_data; 236 callout_init(&state->ks_timer, 0); 237 pckbd_timeout(*kbd); 238 239 if (bootverbose) 240 (*sw->diag)(*kbd, bootverbose); 241 242 return 0; 243} 244 245static void 246pckbd_timeout(void *arg) 247{ 248 pckbd_state_t *state; 249 keyboard_t *kbd; 250 int s; 251 252 /* The following comments are extracted from syscons.c (1.287) */ 253 /* 254 * With release 2.1 of the Xaccel server, the keyboard is left 255 * hanging pretty often. Apparently an interrupt from the 256 * keyboard is lost, and I don't know why (yet). 257 * This ugly hack calls scintr if input is ready for the keyboard 258 * and conveniently hides the problem. XXX 259 */ 260 /* 261 * Try removing anything stuck in the keyboard controller; whether 262 * it's a keyboard scan code or mouse data. `scintr()' doesn't 263 * read the mouse data directly, but `kbdio' routines will, as a 264 * side effect. 265 */ 266 s = spltty(); 267 kbd = (keyboard_t *)arg; 268 if (kbdd_lock(kbd, TRUE)) { 269 /* 270 * We have seen the lock flag is not set. Let's reset 271 * the flag early, otherwise the LED update routine fails 272 * which may want the lock during the interrupt routine. 273 */ 274 kbdd_lock(kbd, FALSE); 275 if (kbdd_check_char(kbd)) 276 kbdd_intr(kbd, NULL); 277 } 278 splx(s); 279 state = (pckbd_state_t *)kbd->kb_data; 280 callout_reset(&state->ks_timer, hz / 10, pckbd_timeout, arg); 281} 282 283/* LOW-LEVEL */ 284 285#include <sys/limits.h> 286 287#define PC98KBD_DEFAULT 0 288 289/* keyboard driver declaration */ 290static int pckbd_configure(int flags); 291static kbd_probe_t pckbd_probe; 292static kbd_init_t pckbd_init; 293static kbd_term_t pckbd_term; 294static kbd_intr_t pckbd_intr; 295static kbd_test_if_t pckbd_test_if; 296static kbd_enable_t pckbd_enable; 297static kbd_disable_t pckbd_disable; 298static kbd_read_t pckbd_read; 299static kbd_check_t pckbd_check; 300static kbd_read_char_t pckbd_read_char; 301static kbd_check_char_t pckbd_check_char; 302static kbd_ioctl_t pckbd_ioctl; 303static kbd_lock_t pckbd_lock; 304static kbd_clear_state_t pckbd_clear_state; 305static kbd_get_state_t pckbd_get_state; 306static kbd_set_state_t pckbd_set_state; 307static kbd_poll_mode_t pckbd_poll; 308 309keyboard_switch_t pckbdsw = { 310 pckbd_probe, 311 pckbd_init, 312 pckbd_term, 313 pckbd_intr, 314 pckbd_test_if, 315 pckbd_enable, 316 pckbd_disable, 317 pckbd_read, 318 pckbd_check, 319 pckbd_read_char, 320 pckbd_check_char, 321 pckbd_ioctl, 322 pckbd_lock, 323 pckbd_clear_state, 324 pckbd_get_state, 325 pckbd_set_state, 326 genkbd_get_fkeystr, 327 pckbd_poll, 328 genkbd_diag, 329}; 330 331KEYBOARD_DRIVER(pckbd, pckbdsw, pckbd_configure); 332 333struct kbdc_softc { 334 int port; /* base port address */ 335 int lock; /* FIXME: XXX not quite a semaphore... */ 336}; 337 338/* local functions */ 339static int probe_keyboard(KBDC kbdc, int flags); 340static int init_keyboard(KBDC kbdc, int *type, int flags); 341static KBDC kbdc_open(int port); 342static int kbdc_lock(KBDC kbdc, int lock); 343static int kbdc_data_ready(KBDC kbdc); 344static int read_kbd_data(KBDC kbdc); 345static int read_kbd_data_no_wait(KBDC kbdc); 346static int wait_for_kbd_data(struct kbdc_softc *kbdc); 347 348/* local variables */ 349 350/* the initial key map, accent map and fkey strings */ 351#include <pc98/cbus/pckbdtables.h> 352 353/* structures for the default keyboard */ 354static keyboard_t default_kbd; 355static pckbd_state_t default_kbd_state; 356static keymap_t default_keymap; 357static accentmap_t default_accentmap; 358static fkeytab_t default_fkeytab[NUM_FKEYS]; 359 360/* 361 * The back door to the keyboard driver! 362 * This function is called by the console driver, via the kbdio module, 363 * to tickle keyboard drivers when the low-level console is being initialized. 364 * Almost nothing in the kernel has been initialied yet. Try to probe 365 * keyboards if possible. 366 * NOTE: because of the way the low-level conole is initialized, this routine 367 * may be called more than once!! 368 */ 369static int 370pckbd_configure(int flags) 371{ 372 keyboard_t *kbd; 373 int arg[2]; 374 int i; 375 376 /* XXX: a kludge to obtain the device configuration flags */ 377 if (resource_int_value(DRIVER_NAME, 0, "flags", &i) == 0) { 378 flags |= i; 379 /* if the driver is disabled, unregister the keyboard if any */ 380 if (resource_disabled(DRIVER_NAME, 0)) { 381 i = kbd_find_keyboard(DRIVER_NAME, PC98KBD_DEFAULT); 382 if (i >= 0) { 383 kbd = kbd_get_keyboard(i); 384 kbd_unregister(kbd); 385 kbd->kb_flags &= ~KB_REGISTERED; 386 return 0; 387 } 388 } 389 } 390 391 /* probe the default keyboard */ 392 arg[0] = -1; 393 arg[1] = -1; 394 kbd = NULL; 395 if (pckbd_probe(PC98KBD_DEFAULT, arg, flags)) 396 return 0; 397 if (pckbd_init(PC98KBD_DEFAULT, &kbd, arg, flags)) 398 return 0; 399 400 /* return the number of found keyboards */ 401 return 1; 402} 403 404/* low-level functions */ 405 406/* detect a keyboard */ 407static int 408pckbd_probe(int unit, void *arg, int flags) 409{ 410 KBDC kbdc; 411 int *data = (int *)arg; 412 413 if (unit != PC98KBD_DEFAULT) 414 return ENXIO; 415 if (KBD_IS_PROBED(&default_kbd)) 416 return 0; 417 418 kbdc = kbdc_open(data[0]); 419 if (kbdc == NULL) 420 return ENXIO; 421 if (probe_keyboard(kbdc, flags)) { 422 if (flags & KB_CONF_FAIL_IF_NO_KBD) 423 return ENXIO; 424 } 425 return 0; 426} 427 428/* reset and initialize the device */ 429static int 430pckbd_init(int unit, keyboard_t **kbdp, void *arg, int flags) 431{ 432 keyboard_t *kbd; 433 pckbd_state_t *state; 434 keymap_t *keymap; 435 accentmap_t *accmap; 436 fkeytab_t *fkeymap; 437 int fkeymap_size; 438 int *data = (int *)arg; 439 440 if (unit != PC98KBD_DEFAULT) /* shouldn't happen */ 441 return ENXIO; 442 443 *kbdp = kbd = &default_kbd; 444 state = &default_kbd_state; 445 if (!KBD_IS_PROBED(kbd)) { 446 keymap = &default_keymap; 447 accmap = &default_accentmap; 448 fkeymap = default_fkeytab; 449 fkeymap_size = nitems(default_fkeytab); 450 451 state->kbdc = kbdc_open(data[0]); 452 if (state->kbdc == NULL) 453 return ENXIO; 454 kbd_init_struct(kbd, DRIVER_NAME, KB_OTHER, unit, flags, 455 data[0], IO_KBDSIZE); 456 bcopy(&key_map, keymap, sizeof(key_map)); 457 bcopy(&accent_map, accmap, sizeof(accent_map)); 458 bcopy(fkey_tab, fkeymap, 459 imin(fkeymap_size*sizeof(fkeymap[0]), sizeof(fkey_tab))); 460 kbd_set_maps(kbd, keymap, accmap, fkeymap, fkeymap_size); 461 kbd->kb_data = (void *)state; 462 463 if (probe_keyboard(state->kbdc, flags)) {/* shouldn't happen */ 464 if (flags & KB_CONF_FAIL_IF_NO_KBD) 465 return ENXIO; 466 } else { 467 KBD_FOUND_DEVICE(kbd); 468 } 469 pckbd_clear_state(kbd); 470 state->ks_mode = K_XLATE; 471 KBD_PROBE_DONE(kbd); 472 } 473 if (!KBD_IS_INITIALIZED(kbd) && !(flags & KB_CONF_PROBE_ONLY)) { 474 if (KBD_HAS_DEVICE(kbd) 475 && init_keyboard(state->kbdc, &kbd->kb_type, kbd->kb_config) 476 && (kbd->kb_config & KB_CONF_FAIL_IF_NO_KBD)) 477 return ENXIO; 478 pckbd_ioctl(kbd, KDSETLED, (caddr_t)&state->ks_state); 479 KBD_INIT_DONE(kbd); 480 } 481 if (!KBD_IS_CONFIGURED(kbd)) { 482 if (kbd_register(kbd) < 0) 483 return ENXIO; 484 KBD_CONFIG_DONE(kbd); 485 } 486 487 return 0; 488} 489 490/* finish using this keyboard */ 491static int 492pckbd_term(keyboard_t *kbd) 493{ 494 pckbd_state_t *state = (pckbd_state_t *)kbd->kb_data; 495 496 kbd_unregister(kbd); 497 callout_drain(&state->ks_timer); 498 return 0; 499} 500 501/* keyboard interrupt routine */ 502static int 503pckbd_intr(keyboard_t *kbd, void *arg) 504{ 505 int c; 506 507 if (KBD_IS_ACTIVE(kbd) && KBD_IS_BUSY(kbd)) { 508 /* let the callback function to process the input */ 509 (*kbd->kb_callback.kc_func)(kbd, KBDIO_KEYINPUT, 510 kbd->kb_callback.kc_arg); 511 } else { 512 /* read and discard the input; no one is waiting for input */ 513 do { 514 c = pckbd_read_char(kbd, FALSE); 515 } while (c != NOKEY); 516 } 517 return 0; 518} 519 520/* test the interface to the device */ 521static int 522pckbd_test_if(keyboard_t *kbd) 523{ 524 return 0; 525} 526 527/* 528 * Enable the access to the device; until this function is called, 529 * the client cannot read from the keyboard. 530 */ 531static int 532pckbd_enable(keyboard_t *kbd) 533{ 534 int s; 535 536 s = spltty(); 537 KBD_ACTIVATE(kbd); 538 splx(s); 539 return 0; 540} 541 542/* disallow the access to the device */ 543static int 544pckbd_disable(keyboard_t *kbd) 545{ 546 int s; 547 548 s = spltty(); 549 KBD_DEACTIVATE(kbd); 550 splx(s); 551 return 0; 552} 553 554/* read one byte from the keyboard if it's allowed */ 555static int 556pckbd_read(keyboard_t *kbd, int wait) 557{ 558 int c; 559 560 if (wait) 561 c = read_kbd_data(((pckbd_state_t *)kbd->kb_data)->kbdc); 562 else 563 c = read_kbd_data_no_wait(((pckbd_state_t *)kbd->kb_data)->kbdc); 564 if (c != -1) 565 ++kbd->kb_count; 566 return (KBD_IS_ACTIVE(kbd) ? c : -1); 567} 568 569/* check if data is waiting */ 570static int 571pckbd_check(keyboard_t *kbd) 572{ 573 if (!KBD_IS_ACTIVE(kbd)) 574 return FALSE; 575 return kbdc_data_ready(((pckbd_state_t *)kbd->kb_data)->kbdc); 576} 577 578/* read char from the keyboard */ 579static u_int 580pckbd_read_char(keyboard_t *kbd, int wait) 581{ 582 pckbd_state_t *state; 583 u_int action; 584 int scancode; 585 int keycode; 586 587 state = (pckbd_state_t *)kbd->kb_data; 588next_code: 589 /* do we have a composed char to return? */ 590 if (!(state->ks_flags & COMPOSE) && (state->ks_composed_char > 0)) { 591 action = state->ks_composed_char; 592 state->ks_composed_char = 0; 593 if (action > UCHAR_MAX) 594 return ERRKEY; 595 return action; 596 } 597 598 /* see if there is something in the keyboard port */ 599 if (wait) { 600 do { 601 scancode = read_kbd_data(state->kbdc); 602 } while (scancode == -1); 603 } else { 604 scancode = read_kbd_data_no_wait(state->kbdc); 605 if (scancode == -1) 606 return NOKEY; 607 } 608 ++kbd->kb_count; 609 610#if 0 611 printf("pckbd_read_char(): scancode:0x%x\n", scancode); 612#endif 613 614 /* return the byte as is for the K_RAW mode */ 615 if (state->ks_mode == K_RAW) 616 return scancode; 617 618 /* translate the scan code into a keycode */ 619 keycode = scancode & 0x7F; 620 switch(scancode) { 621 case 0xF3: /* GRPH (compose key) released */ 622 if (state->ks_flags & COMPOSE) { 623 state->ks_flags &= ~COMPOSE; 624 if (state->ks_composed_char > UCHAR_MAX) 625 state->ks_composed_char = 0; 626 } 627 break; 628 case 0x73: /* GRPH (compose key) pressed */ 629 if (!(state->ks_flags & COMPOSE)) { 630 state->ks_flags |= COMPOSE; 631 state->ks_composed_char = 0; 632 } 633 break; 634 } 635 636 /* return the key code in the K_CODE mode */ 637 if (state->ks_mode == K_CODE) 638 return (keycode | (scancode & 0x80)); 639 640 /* compose a character code */ 641 if (state->ks_flags & COMPOSE) { 642 switch (scancode) { 643 /* key pressed, process it */ 644 case 0x42: case 0x43: case 0x44: /* keypad 7,8,9 */ 645 state->ks_composed_char *= 10; 646 state->ks_composed_char += scancode - 0x3B; 647 if (state->ks_composed_char > UCHAR_MAX) 648 return ERRKEY; 649 goto next_code; 650 case 0x46: case 0x47: case 0x48: /* keypad 4,5,6 */ 651 state->ks_composed_char *= 10; 652 state->ks_composed_char += scancode - 0x42; 653 if (state->ks_composed_char > UCHAR_MAX) 654 return ERRKEY; 655 goto next_code; 656 case 0x4A: case 0x4B: case 0x4C: /* keypad 1,2,3 */ 657 state->ks_composed_char *= 10; 658 state->ks_composed_char += scancode - 0x49; 659 if (state->ks_composed_char > UCHAR_MAX) 660 return ERRKEY; 661 goto next_code; 662 case 0x4E: /* keypad 0 */ 663 state->ks_composed_char *= 10; 664 if (state->ks_composed_char > UCHAR_MAX) 665 return ERRKEY; 666 goto next_code; 667 668 /* key released, no interest here */ 669 case 0xC2: case 0xC3: case 0xC4: /* keypad 7,8,9 */ 670 case 0xC6: case 0xC7: case 0xC8: /* keypad 4,5,6 */ 671 case 0xCA: case 0xCB: case 0xCC: /* keypad 1,2,3 */ 672 case 0xCE: /* keypad 0 */ 673 goto next_code; 674 675 case 0x73: /* GRPH key */ 676 break; 677 678 default: 679 if (state->ks_composed_char > 0) { 680 state->ks_flags &= ~COMPOSE; 681 state->ks_composed_char = 0; 682 return ERRKEY; 683 } 684 break; 685 } 686 } 687 688 /* keycode to key action */ 689 action = genkbd_keyaction(kbd, keycode, scancode & 0x80, 690 &state->ks_state, &state->ks_accents); 691 if (action == NOKEY) 692 goto next_code; 693 else 694 return action; 695} 696 697/* check if char is waiting */ 698static int 699pckbd_check_char(keyboard_t *kbd) 700{ 701 pckbd_state_t *state; 702 703 if (!KBD_IS_ACTIVE(kbd)) 704 return FALSE; 705 state = (pckbd_state_t *)kbd->kb_data; 706 if (!(state->ks_flags & COMPOSE) && (state->ks_composed_char > 0)) 707 return TRUE; 708 return kbdc_data_ready(state->kbdc); 709} 710 711/* some useful control functions */ 712static int 713pckbd_ioctl(keyboard_t *kbd, u_long cmd, caddr_t arg) 714{ 715 pckbd_state_t *state = kbd->kb_data; 716 int s; 717 int i; 718#if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5) || \ 719 defined(COMPAT_FREEBSD4) || defined(COMPAT_43) 720 int ival; 721#endif 722 723 s = spltty(); 724 switch (cmd) { 725 726 case KDGKBMODE: /* get keyboard mode */ 727 *(int *)arg = state->ks_mode; 728 break; 729#if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5) || \ 730 defined(COMPAT_FREEBSD4) || defined(COMPAT_43) 731 case _IO('K', 7): 732 ival = IOCPARM_IVAL(arg); 733 arg = (caddr_t)&ival; 734 /* FALLTHROUGH */ 735#endif 736 case KDSKBMODE: /* set keyboard mode */ 737 switch (*(int *)arg) { 738 case K_XLATE: 739 if (state->ks_mode != K_XLATE) { 740 /* make lock key state and LED state match */ 741 state->ks_state &= ~LOCK_MASK; 742 state->ks_state |= KBD_LED_VAL(kbd); 743 } 744 /* FALLTHROUGH */ 745 case K_RAW: 746 case K_CODE: 747 if (state->ks_mode != *(int *)arg) { 748 pckbd_clear_state(kbd); 749 state->ks_mode = *(int *)arg; 750 } 751 break; 752 default: 753 splx(s); 754 return EINVAL; 755 } 756 break; 757 758 case KDGETLED: /* get keyboard LED */ 759 *(int *)arg = KBD_LED_VAL(kbd); 760 break; 761#if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5) || \ 762 defined(COMPAT_FREEBSD4) || defined(COMPAT_43) 763 case _IO('K', 66): 764 ival = IOCPARM_IVAL(arg); 765 arg = (caddr_t)&ival; 766 /* FALLTHROUGH */ 767#endif 768 case KDSETLED: /* set keyboard LED */ 769 /* NOTE: lock key state in ks_state won't be changed */ 770 if (*(int *)arg & ~LOCK_MASK) { 771 splx(s); 772 return EINVAL; 773 } 774 i = *(int *)arg; 775 /* replace CAPS LED with ALTGR LED for ALTGR keyboards */ 776 if (kbd->kb_keymap->n_keys > ALTGR_OFFSET) { 777 if (i & ALKED) 778 i |= CLKED; 779 else 780 i &= ~CLKED; 781 } 782 KBD_LED_VAL(kbd) = *(int *)arg; 783 break; 784 785 case KDGKBSTATE: /* get lock key state */ 786 *(int *)arg = state->ks_state & LOCK_MASK; 787 break; 788#if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5) || \ 789 defined(COMPAT_FREEBSD4) || defined(COMPAT_43) 790 case _IO('K', 20): 791 ival = IOCPARM_IVAL(arg); 792 arg = (caddr_t)&ival; 793 /* FALLTHROUGH */ 794#endif 795 case KDSKBSTATE: /* set lock key state */ 796 if (*(int *)arg & ~LOCK_MASK) { 797 splx(s); 798 return EINVAL; 799 } 800 state->ks_state &= ~LOCK_MASK; 801 state->ks_state |= *(int *)arg; 802 splx(s); 803 /* set LEDs and quit */ 804 return pckbd_ioctl(kbd, KDSETLED, arg); 805 806 case KDSETRAD: /* set keyboard repeat rate (old interface)*/ 807 break; 808 case KDSETREPEAT: /* set keyboard repeat rate (new interface) */ 809 break; 810 811 case PIO_KEYMAP: /* set keyboard translation table */ 812 case OPIO_KEYMAP: /* set keyboard translation table (compat) */ 813 case PIO_KEYMAPENT: /* set keyboard translation table entry */ 814 case PIO_DEADKEYMAP: /* set accent key translation table */ 815 state->ks_accents = 0; 816 /* FALLTHROUGH */ 817 default: 818 splx(s); 819 return genkbd_commonioctl(kbd, cmd, arg); 820 } 821 822 splx(s); 823 return 0; 824} 825 826/* lock the access to the keyboard */ 827static int 828pckbd_lock(keyboard_t *kbd, int lock) 829{ 830 return kbdc_lock(((pckbd_state_t *)kbd->kb_data)->kbdc, lock); 831} 832 833/* clear the internal state of the keyboard */ 834static void 835pckbd_clear_state(keyboard_t *kbd) 836{ 837 pckbd_state_t *state; 838 839 state = (pckbd_state_t *)kbd->kb_data; 840 state->ks_flags = 0; 841 state->ks_state &= LOCK_MASK; /* preserve locking key state */ 842 state->ks_accents = 0; 843 state->ks_composed_char = 0; 844} 845 846/* save the internal state */ 847static int 848pckbd_get_state(keyboard_t *kbd, void *buf, size_t len) 849{ 850 if (len == 0) 851 return sizeof(pckbd_state_t); 852 if (len < sizeof(pckbd_state_t)) 853 return -1; 854 bcopy(kbd->kb_data, buf, sizeof(pckbd_state_t)); 855 return 0; 856} 857 858/* set the internal state */ 859static int 860pckbd_set_state(keyboard_t *kbd, void *buf, size_t len) 861{ 862 if (len < sizeof(pckbd_state_t)) 863 return ENOMEM; 864 if (((pckbd_state_t *)kbd->kb_data)->kbdc 865 != ((pckbd_state_t *)buf)->kbdc) 866 return ENOMEM; 867 bcopy(buf, kbd->kb_data, sizeof(pckbd_state_t)); 868 return 0; 869} 870 871/* set polling mode */ 872static int 873pckbd_poll(keyboard_t *kbd, int on) 874{ 875 return 0; 876} 877 878/* local functions */ 879 880static int 881probe_keyboard(KBDC kbdc, int flags) 882{ 883 return 0; 884} 885 886static int 887init_keyboard(KBDC kbdc, int *type, int flags) 888{ 889 *type = KB_OTHER; 890 return 0; 891} 892 893/* keyboard I/O routines */ 894 895/* retry count */ 896#ifndef KBD_MAXRETRY 897#define KBD_MAXRETRY 3 898#endif 899 900/* timing parameters */ 901#ifndef KBD_RESETDELAY 902#define KBD_RESETDELAY 200 /* wait 200msec after kbd/mouse reset */ 903#endif 904#ifndef KBD_MAXWAIT 905#define KBD_MAXWAIT 5 /* wait 5 times at most after reset */ 906#endif 907 908/* I/O recovery time */ 909#define KBDC_DELAYTIME 37 910#define KBDD_DELAYTIME 37 911 912/* I/O ports */ 913#define KBD_STATUS_PORT 2 /* status port, read */ 914#define KBD_DATA_PORT 0 /* data port, read */ 915 916/* status bits (KBD_STATUS_PORT) */ 917#define KBDS_BUFFER_FULL 0x0002 918 919/* macros */ 920 921#define kbdcp(p) ((struct kbdc_softc *)(p)) 922 923/* local variables */ 924 925static struct kbdc_softc kbdc_softc[1] = { { 0 }, }; 926 927/* associate a port number with a KBDC */ 928 929static KBDC 930kbdc_open(int port) 931{ 932 if (port <= 0) 933 port = IO_KBD; 934 935 /* PC-98 has only one keyboard I/F */ 936 kbdc_softc[0].port = port; 937 kbdc_softc[0].lock = FALSE; 938 return (KBDC)&kbdc_softc[0]; 939} 940 941/* set/reset polling lock */ 942static int 943kbdc_lock(KBDC p, int lock) 944{ 945 int prevlock; 946 947 prevlock = kbdcp(p)->lock; 948 kbdcp(p)->lock = lock; 949 950 return (prevlock != lock); 951} 952 953/* check if any data is waiting to be processed */ 954static int 955kbdc_data_ready(KBDC p) 956{ 957 return (inb(kbdcp(p)->port + KBD_STATUS_PORT) & KBDS_BUFFER_FULL); 958} 959 960/* wait for data from the keyboard */ 961static int 962wait_for_kbd_data(struct kbdc_softc *kbdc) 963{ 964 /* CPU will stay inside the loop for 200msec at most */ 965 int retry = 10000; 966 int port = kbdc->port; 967 968 while (!(inb(port + KBD_STATUS_PORT) & KBDS_BUFFER_FULL)) { 969 DELAY(KBDD_DELAYTIME); 970 DELAY(KBDC_DELAYTIME); 971 if (--retry < 0) 972 return 0; 973 } 974 DELAY(KBDD_DELAYTIME); 975 return 1; 976} 977 978/* read one byte from the keyboard */ 979static int 980read_kbd_data(KBDC p) 981{ 982 if (!wait_for_kbd_data(kbdcp(p))) 983 return -1; /* timeout */ 984 DELAY(KBDC_DELAYTIME); 985 return inb(kbdcp(p)->port + KBD_DATA_PORT); 986} 987 988/* read one byte from the keyboard, but return immediately if 989 * no data is waiting 990 */ 991static int 992read_kbd_data_no_wait(KBDC p) 993{ 994 if (inb(kbdcp(p)->port + KBD_STATUS_PORT) & KBDS_BUFFER_FULL) { 995 DELAY(KBDD_DELAYTIME); 996 return inb(kbdcp(p)->port + KBD_DATA_PORT); 997 } 998 return -1; /* no data */ 999} 1000