atkbd.c revision 130312
1109864Sjeff/*- 2165762Sjeff * Copyright (c) 1999 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp> 3109864Sjeff * All rights reserved. 4109864Sjeff * 5109864Sjeff * Redistribution and use in source and binary forms, with or without 6109864Sjeff * modification, are permitted provided that the following conditions 7109864Sjeff * are met: 8109864Sjeff * 1. Redistributions of source code must retain the above copyright 9109864Sjeff * notice, this list of conditions and the following disclaimer as 10109864Sjeff * the first lines of this file unmodified. 11109864Sjeff * 2. Redistributions in binary form must reproduce the above copyright 12109864Sjeff * notice, this list of conditions and the following disclaimer in the 13109864Sjeff * documentation and/or other materials provided with the distribution. 14109864Sjeff * 15109864Sjeff * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR 16109864Sjeff * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17109864Sjeff * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18109864Sjeff * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, 19109864Sjeff * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20109864Sjeff * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21109864Sjeff * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22109864Sjeff * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23109864Sjeff * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24109864Sjeff * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25109864Sjeff * 26109864Sjeff */ 27171482Sjeff 28171482Sjeff#include <sys/cdefs.h> 29171482Sjeff__FBSDID("$FreeBSD: head/sys/dev/atkbdc/atkbd.c 130312 2004-06-10 20:31:00Z jhb $"); 30171482Sjeff 31171482Sjeff#include "opt_kbd.h" 32171482Sjeff#include "opt_atkbd.h" 33172293Sjeff 34171482Sjeff#include <sys/param.h> 35171482Sjeff#include <sys/systm.h> 36171482Sjeff#include <sys/kernel.h> 37171482Sjeff#include <sys/bus.h> 38116182Sobrien#include <sys/proc.h> 39191645Sjeff#include <sys/limits.h> 40116182Sobrien#include <sys/malloc.h> 41147565Speter 42179297Sjb#include <machine/bus.h> 43147565Speter#include <machine/resource.h> 44134649Sscottl 45109864Sjeff#ifdef __i386__ 46109864Sjeff#include <machine/md_var.h> 47131929Smarcel#include <machine/psl.h> 48109864Sjeff#include <machine/vm86.h> 49109864Sjeff#include <machine/pc/bios.h> 50109864Sjeff 51109864Sjeff#include <vm/vm.h> 52109864Sjeff#include <vm/pmap.h> 53112966Sjeff#include <vm/vm_param.h> 54122038Sjeff#endif /* __i386__ */ 55109864Sjeff 56109864Sjeff#include <sys/kbio.h> 57109864Sjeff#include <dev/kbd/kbdreg.h> 58109864Sjeff#include <dev/kbd/atkbdreg.h> 59109864Sjeff#include <dev/kbd/atkbdcreg.h> 60139453Sjhb 61161599Sdavidxu#include <isa/isareg.h> 62109864Sjeff 63176735Sjeffstatic timeout_t atkbd_timeout; 64184439Sivoras 65109864Sjeffint 66109864Sjeffatkbd_probe_unit(int unit, int ctlr, int irq, int flags) 67109864Sjeff{ 68109864Sjeff keyboard_switch_t *sw; 69109864Sjeff int args[2]; 70145256Sjkoshy int error; 71145256Sjkoshy 72145256Sjkoshy sw = kbd_get_switch(ATKBD_DRIVER_NAME); 73145256Sjkoshy if (sw == NULL) 74179297Sjb return ENXIO; 75179297Sjb 76179297Sjb args[0] = ctlr; 77179297Sjb args[1] = irq; 78179297Sjb error = (*sw->probe)(unit, args, flags); 79179297Sjb if (error) 80109864Sjeff return error; 81121790Sjeff return 0; 82109864Sjeff} 83208165Srrs 84172345Sjeffint 85166190Sjeffatkbd_attach_unit(int unit, keyboard_t **kbd, int ctlr, int irq, int flags) 86166190Sjeff{ 87171482Sjeff keyboard_switch_t *sw; 88166137Sjeff int args[2]; 89187679Sjeff int error; 90187679Sjeff 91187357Sjeff sw = kbd_get_switch(ATKBD_DRIVER_NAME); 92187357Sjeff if (sw == NULL) 93166137Sjeff return ENXIO; 94171482Sjeff 95171482Sjeff /* reset, initialize and enable the device */ 96146954Sjeff args[0] = ctlr; 97164936Sjulian args[1] = irq; 98171482Sjeff *kbd = NULL; 99171482Sjeff error = (*sw->probe)(unit, args, flags); 100164936Sjulian if (error) 101177009Sjeff return error; 102171482Sjeff error = (*sw->init)(unit, kbd, args, flags); 103171482Sjeff if (error) 104171482Sjeff return error; 105164936Sjulian (*sw->enable)(*kbd); 106199764Sivoras 107164936Sjulian#ifdef KBD_INSTALL_CDEV 108164936Sjulian /* attach a virtual keyboard cdev */ 109187357Sjeff error = kbd_attach(*kbd); 110187357Sjeff if (error) 111187357Sjeff return error; 112134791Sjulian#endif 113164936Sjulian 114166108Sjeff /* 115166108Sjeff * This is a kludge to compensate for lost keyboard interrupts. 116121790Sjeff * A similar code used to be in syscons. See below. XXX 117164936Sjulian */ 118109864Sjeff atkbd_timeout(*kbd); 119176735Sjeff 120176735Sjeff if (bootverbose) 121176735Sjeff (*sw->diag)(*kbd, bootverbose); 122176735Sjeff return 0; 123109864Sjeff} 124165762Sjeff 125111857Sjeffstatic void 126165762Sjeffatkbd_timeout(void *arg) 127165762Sjeff{ 128165796Sjeff keyboard_t *kbd; 129165762Sjeff int s; 130165762Sjeff 131165762Sjeff /* 132165762Sjeff * The original text of the following comments are extracted 133165762Sjeff * from syscons.c (1.287) 134165762Sjeff * 135165796Sjeff * With release 2.1 of the Xaccel server, the keyboard is left 136165762Sjeff * hanging pretty often. Apparently an interrupt from the 137165762Sjeff * keyboard is lost, and I don't know why (yet). 138165830Sjeff * This ugly hack calls the low-level interrupt routine if input 139165762Sjeff * is ready for the keyboard and conveniently hides the problem. XXX 140165762Sjeff * 141165762Sjeff * Try removing anything stuck in the keyboard controller; whether 142165762Sjeff * it's a keyboard scan code or mouse data. The low-level 143165762Sjeff * interrupt routine doesn't read the mouse data directly, 144165762Sjeff * but the keyboard controller driver will, as a side effect. 145165762Sjeff */ 146165762Sjeff /* 147165762Sjeff * And here is bde's original comment about this: 148116642Sjeff * 149165762Sjeff * This is necessary to handle edge triggered interrupts - if we 150165762Sjeff * returned when our IRQ is high due to unserviced input, then there 151109864Sjeff * would be no more keyboard IRQs until the keyboard is reset by 152165762Sjeff * external powers. 153121869Sjeff * 154165762Sjeff * The keyboard apparently unwedges the irq in most cases. 155165762Sjeff */ 156170787Sjeff s = spltty(); 157165762Sjeff kbd = (keyboard_t *)arg; 158165762Sjeff if ((*kbdsw[kbd->kb_index]->lock)(kbd, TRUE)) { 159165827Sjeff /* 160165762Sjeff * We have seen the lock flag is not set. Let's reset 161109864Sjeff * the flag early, otherwise the LED update routine fails 162109864Sjeff * which may want the lock during the interrupt routine. 163165762Sjeff */ 164165762Sjeff (*kbdsw[kbd->kb_index]->lock)(kbd, FALSE); 165165762Sjeff if ((*kbdsw[kbd->kb_index]->check_char)(kbd)) 166165762Sjeff (*kbdsw[kbd->kb_index]->intr)(kbd, NULL); 167109864Sjeff } 168110645Sjeff splx(s); 169110645Sjeff timeout(atkbd_timeout, arg, hz/10); 170121868Sjeff} 171116365Sjeff 172111857Sjeff/* LOW-LEVEL */ 173109864Sjeff 174165762Sjeff#define ATKBD_DEFAULT 0 175165762Sjeff 176116365Sjefftypedef struct atkbd_state { 177116365Sjeff KBDC kbdc; /* keyboard controller */ 178121126Sjeff /* XXX: don't move this field; pcvt 179111857Sjeff * expects `kbdc' to be the first 180109864Sjeff * field in this structure. */ 181165762Sjeff int ks_mode; /* input mode (K_XLATE,K_RAW,K_CODE) */ 182165762Sjeff int ks_flags; /* flags */ 183165762Sjeff#define COMPOSE (1 << 0) 184165762Sjeff int ks_polling; 185165762Sjeff int ks_state; /* shift/lock key state */ 186171482Sjeff int ks_accents; /* accent key index (> 0) */ 187109864Sjeff u_int ks_composed_char; /* composed char code (> 0) */ 188165762Sjeff u_char ks_prefix; /* AT scan code prefix */ 189165762Sjeff} atkbd_state_t; 190165762Sjeff 191177009Sjeff/* keyboard driver declaration */ 192172345Sjeffstatic int atkbd_configure(int flags); 193172345Sjeffstatic kbd_probe_t atkbd_probe; 194172345Sjeffstatic kbd_init_t atkbd_init; 195172345Sjeffstatic kbd_term_t atkbd_term; 196171482Sjeffstatic kbd_intr_t atkbd_intr; 197172345Sjeffstatic kbd_test_if_t atkbd_test_if; 198172345Sjeffstatic kbd_enable_t atkbd_enable; 199172345Sjeffstatic kbd_disable_t atkbd_disable; 200172345Sjeffstatic kbd_read_t atkbd_read; 201177903Sjeffstatic kbd_check_t atkbd_check; 202178277Sjeffstatic kbd_read_char_t atkbd_read_char; 203178277Sjeffstatic kbd_check_char_t atkbd_check_char; 204109864Sjeffstatic kbd_ioctl_t atkbd_ioctl; 205109864Sjeffstatic kbd_lock_t atkbd_lock; 206171482Sjeffstatic kbd_clear_state_t atkbd_clear_state; 207171482Sjeffstatic kbd_get_state_t atkbd_get_state; 208171482Sjeffstatic kbd_set_state_t atkbd_set_state; 209109864Sjeffstatic kbd_poll_mode_t atkbd_poll; 210164936Sjulian 211177009Sjeffstatic keyboard_switch_t atkbdsw = { 212177009Sjeff atkbd_probe, 213176735Sjeff atkbd_init, 214178277Sjeff atkbd_term, 215176735Sjeff atkbd_intr, 216177009Sjeff atkbd_test_if, 217178277Sjeff atkbd_enable, 218178277Sjeff atkbd_disable, 219177009Sjeff atkbd_read, 220177009Sjeff atkbd_check, 221166557Sjeff atkbd_read_char, 222166557Sjeff atkbd_check_char, 223177009Sjeff atkbd_ioctl, 224177009Sjeff atkbd_lock, 225177009Sjeff atkbd_clear_state, 226187357Sjeff atkbd_get_state, 227187357Sjeff atkbd_set_state, 228187357Sjeff genkbd_get_fkeystr, 229187357Sjeff atkbd_poll, 230171482Sjeff genkbd_diag, 231109864Sjeff}; 232178277Sjeff 233178277SjeffKEYBOARD_DRIVER(atkbd, atkbdsw, atkbd_configure); 234178277Sjeff 235166108Sjeff/* local functions */ 236123433Sjeffstatic int get_typematic(keyboard_t *kbd); 237184439Sivorasstatic int setup_kbd_port(KBDC kbdc, int port, int intr); 238123433Sjeffstatic int get_kbd_echo(KBDC kbdc); 239176735Sjeffstatic int probe_keyboard(KBDC kbdc, int flags); 240176735Sjeffstatic int init_keyboard(KBDC kbdc, int *type, int flags); 241166108Sjeffstatic int write_kbd(KBDC kbdc, int command, int data); 242123433Sjeffstatic int get_kbd_id(KBDC kbdc); 243166108Sjeffstatic int typematic(int delay, int rate); 244166108Sjeffstatic int typematic_delay(int delay); 245171506Sjeffstatic int typematic_rate(int rate); 246172409Sjeff 247166108Sjeff/* local variables */ 248172409Sjeff 249171506Sjeff/* the initial key map, accent map and fkey strings */ 250171506Sjeff#ifdef ATKBD_DFLT_KEYMAP 251166108Sjeff#define KBD_DFLT_KEYMAP 252166108Sjeff#include "atkbdmap.h" 253165620Sjeff#endif 254109864Sjeff#include <dev/kbd/kbdtables.h> 255164936Sjulian 256172409Sjeff/* structures for the default keyboard */ 257172409Sjeffstatic keyboard_t default_kbd; 258129982Sjeffstatic atkbd_state_t default_kbd_state; 259164936Sjulianstatic keymap_t default_keymap; 260164936Sjulianstatic accentmap_t default_accentmap; 261171713Sjeffstatic fkeytab_t default_fkeytab[NUM_FKEYS]; 262123433Sjeff 263164936Sjulian/* 264129982Sjeff * The back door to the keyboard driver! 265170315Sjeff * This function is called by the console driver, via the kbdio module, 266164936Sjulian * to tickle keyboard drivers when the low-level console is being initialized. 267164936Sjulian * Almost nothing in the kernel has been initialied yet. Try to probe 268110028Sjeff * keyboards if possible. 269109864Sjeff * NOTE: because of the way the low-level console is initialized, this routine 270171482Sjeff * may be called more than once!! 271171482Sjeff */ 272171482Sjeffstatic int 273171482Sjeffatkbd_configure(int flags) 274176735Sjeff{ 275171482Sjeff keyboard_t *kbd; 276163709Sjb int arg[2]; 277146954Sjeff int i; 278163709Sjb 279163709Sjb /* probe the keyboard controller */ 280163709Sjb atkbdc_configure(); 281164936Sjulian 282109864Sjeff /* if the driver is disabled, unregister the keyboard if any */ 283110267Sjeff if (resource_disabled("atkbd", ATKBD_DEFAULT)) { 284177435Sjeff i = kbd_find_keyboard(ATKBD_DRIVER_NAME, ATKBD_DEFAULT); 285164936Sjulian if (i >= 0) { 286177435Sjeff kbd = kbd_get_keyboard(i); 287177435Sjeff kbd_unregister(kbd); 288177435Sjeff kbd->kb_flags &= ~KB_REGISTERED; 289177435Sjeff } 290177005Sjeff return 0; 291164936Sjulian } 292165762Sjeff 293171482Sjeff /* XXX: a kludge to obtain the device configuration flags */ 294110267Sjeff if (resource_int_value("atkbd", ATKBD_DEFAULT, "flags", &i) == 0) 295176735Sjeff flags |= i; 296171482Sjeff 297177435Sjeff /* probe the default keyboard */ 298177435Sjeff arg[0] = -1; 299177435Sjeff arg[1] = -1; 300177435Sjeff kbd = NULL; 301172409Sjeff if (atkbd_probe(ATKBD_DEFAULT, arg, flags)) 302176735Sjeff return 0; 303177435Sjeff if (atkbd_init(ATKBD_DEFAULT, &kbd, arg, flags)) 304171482Sjeff return 0; 305171713Sjeff 306184439Sivoras /* return the number of found keyboards */ 307184439Sivoras return 1; 308184439Sivoras} 309121790Sjeff 310110028Sjeff/* low-level functions */ 311165762Sjeff 312177253Srwatson/* detect a keyboard */ 313165762Sjeffstatic int 314165762Sjeffatkbd_probe(int unit, void *arg, int flags) 315177253Srwatson{ 316177253Srwatson KBDC kbdc; 317165762Sjeff int *data = (int *)arg; /* data[0]: controller, data[1]: irq */ 318171482Sjeff 319171482Sjeff /* XXX */ 320171482Sjeff if (unit == ATKBD_DEFAULT) { 321165762Sjeff if (KBD_IS_PROBED(&default_kbd)) 322165762Sjeff return 0; 323165762Sjeff } 324165762Sjeff 325177435Sjeff kbdc = atkbdc_open(data[0]); 326165762Sjeff if (kbdc == NULL) 327165762Sjeff return ENXIO; 328165762Sjeff if (probe_keyboard(kbdc, flags)) { 329165762Sjeff if (flags & KB_CONF_FAIL_IF_NO_KBD) 330165762Sjeff return ENXIO; 331165762Sjeff } 332165762Sjeff return 0; 333165762Sjeff} 334165762Sjeff 335165762Sjeff/* reset and initialize the device */ 336165762Sjeffstatic int 337177435Sjeffatkbd_init(int unit, keyboard_t **kbdp, void *arg, int flags) 338165762Sjeff{ 339177435Sjeff keyboard_t *kbd; 340177435Sjeff atkbd_state_t *state; 341165762Sjeff keymap_t *keymap; 342165762Sjeff accentmap_t *accmap; 343165762Sjeff fkeytab_t *fkeymap; 344165762Sjeff int fkeymap_size; 345165762Sjeff int delay[2]; 346171482Sjeff int *data = (int *)arg; /* data[0]: controller, data[1]: irq */ 347171482Sjeff 348171482Sjeff /* XXX */ 349113357Sjeff if (unit == ATKBD_DEFAULT) { 350164936Sjulian *kbdp = kbd = &default_kbd; 351110267Sjeff if (KBD_IS_INITIALIZED(kbd) && KBD_IS_CONFIGURED(kbd)) 352164936Sjulian return 0; 353112994Sjeff state = &default_kbd_state; 354164936Sjulian keymap = &default_keymap; 355112994Sjeff accmap = &default_accentmap; 356171713Sjeff fkeymap = default_fkeytab; 357176735Sjeff fkeymap_size = 358176735Sjeff sizeof(default_fkeytab)/sizeof(default_fkeytab[0]); 359165620Sjeff } else if (*kbdp == NULL) { 360178277Sjeff *kbdp = kbd = malloc(sizeof(*kbd), M_DEVBUF, M_NOWAIT | M_ZERO); 361178277Sjeff state = malloc(sizeof(*state), M_DEVBUF, M_NOWAIT | M_ZERO); 362171482Sjeff keymap = malloc(sizeof(key_map), M_DEVBUF, M_NOWAIT); 363165766Sjeff accmap = malloc(sizeof(accent_map), M_DEVBUF, M_NOWAIT); 364178277Sjeff fkeymap = malloc(sizeof(fkey_tab), M_DEVBUF, M_NOWAIT); 365178277Sjeff fkeymap_size = sizeof(fkey_tab)/sizeof(fkey_tab[0]); 366165762Sjeff if ((kbd == NULL) || (state == NULL) || (keymap == NULL) 367165762Sjeff || (accmap == NULL) || (fkeymap == NULL)) { 368165762Sjeff if (state != NULL) 369165762Sjeff free(state, M_DEVBUF); 370165762Sjeff if (keymap != NULL) 371165762Sjeff free(keymap, M_DEVBUF); 372113357Sjeff if (accmap != NULL) 373112994Sjeff free(accmap, M_DEVBUF); 374177005Sjeff if (fkeymap != NULL) 375177005Sjeff free(fkeymap, M_DEVBUF); 376177005Sjeff if (kbd != NULL) 377177005Sjeff free(kbd, M_DEVBUF); 378177005Sjeff return ENOMEM; 379177005Sjeff } 380177005Sjeff } else if (KBD_IS_INITIALIZED(*kbdp) && KBD_IS_CONFIGURED(*kbdp)) { 381177005Sjeff return 0; 382177005Sjeff } else { 383177005Sjeff kbd = *kbdp; 384177005Sjeff state = (atkbd_state_t *)kbd->kb_data; 385177005Sjeff bzero(state, sizeof(*state)); 386177005Sjeff keymap = kbd->kb_keymap; 387177005Sjeff accmap = kbd->kb_accentmap; 388177005Sjeff fkeymap = kbd->kb_fkeytab; 389177005Sjeff fkeymap_size = kbd->kb_fkeytab_size; 390177005Sjeff } 391177005Sjeff 392177005Sjeff if (!KBD_IS_PROBED(kbd)) { 393177005Sjeff state->kbdc = atkbdc_open(data[0]); 394177005Sjeff if (state->kbdc == NULL) 395177005Sjeff return ENXIO; 396177005Sjeff kbd_init_struct(kbd, ATKBD_DRIVER_NAME, KB_OTHER, unit, flags, 397177005Sjeff 0, 0); 398177005Sjeff bcopy(&key_map, keymap, sizeof(key_map)); 399177005Sjeff bcopy(&accent_map, accmap, sizeof(accent_map)); 400177005Sjeff bcopy(fkey_tab, fkeymap, 401177005Sjeff imin(fkeymap_size*sizeof(fkeymap[0]), sizeof(fkey_tab))); 402177005Sjeff kbd_set_maps(kbd, keymap, accmap, fkeymap, fkeymap_size); 403177005Sjeff kbd->kb_data = (void *)state; 404177005Sjeff 405177005Sjeff if (probe_keyboard(state->kbdc, flags)) { /* shouldn't happen */ 406177005Sjeff if (flags & KB_CONF_FAIL_IF_NO_KBD) 407171482Sjeff return ENXIO; 408171482Sjeff } else { 409171482Sjeff KBD_FOUND_DEVICE(kbd); 410171482Sjeff } 411171482Sjeff atkbd_clear_state(kbd); 412171482Sjeff state->ks_mode = K_XLATE; 413122744Sjeff /* 414177435Sjeff * FIXME: set the initial value for lock keys in ks_state 415122744Sjeff * according to the BIOS data? 416177435Sjeff */ 417177042Sjeff KBD_PROBE_DONE(kbd); 418177042Sjeff } 419171482Sjeff if (!KBD_IS_INITIALIZED(kbd) && !(flags & KB_CONF_PROBE_ONLY)) { 420177435Sjeff kbd->kb_config = flags & ~KB_CONF_PROBE_ONLY; 421177009Sjeff if (KBD_HAS_DEVICE(kbd) 422177435Sjeff && init_keyboard(state->kbdc, &kbd->kb_type, kbd->kb_config) 423177435Sjeff && (kbd->kb_config & KB_CONF_FAIL_IF_NO_KBD)) { 424177435Sjeff kbd_unregister(kbd); 425177435Sjeff return ENXIO; 426165620Sjeff } 427164936Sjulian atkbd_ioctl(kbd, KDSETLED, (caddr_t)&state->ks_state); 428123433Sjeff get_typematic(kbd); 429177042Sjeff delay[0] = kbd->kb_delay1; 430177042Sjeff delay[1] = kbd->kb_delay2; 431177042Sjeff atkbd_ioctl(kbd, KDSETREPEAT, (caddr_t)delay); 432177042Sjeff KBD_INIT_DONE(kbd); 433165762Sjeff } 434165762Sjeff if (!KBD_IS_CONFIGURED(kbd)) { 435165762Sjeff if (kbd_register(kbd) < 0) 436165762Sjeff return ENXIO; 437165762Sjeff KBD_CONFIG_DONE(kbd); 438165762Sjeff } 439171713Sjeff 440165762Sjeff return 0; 441165762Sjeff} 442165766Sjeff 443165766Sjeff/* finish using this keyboard */ 444165766Sjeffstatic int 445165766Sjeffatkbd_term(keyboard_t *kbd) 446165766Sjeff{ 447165766Sjeff kbd_unregister(kbd); 448165766Sjeff return 0; 449167664Sjeff} 450165762Sjeff 451165766Sjeff/* keyboard interrupt routine */ 452177435Sjeffstatic int 453177042Sjeffatkbd_intr(keyboard_t *kbd, void *arg) 454165762Sjeff{ 455177009Sjeff atkbd_state_t *state; 456177435Sjeff int delay[2]; 457177009Sjeff int c; 458177009Sjeff 459171482Sjeff if (KBD_IS_ACTIVE(kbd) && KBD_IS_BUSY(kbd)) { 460171482Sjeff /* let the callback function to process the input */ 461171482Sjeff (*kbd->kb_callback.kc_func)(kbd, KBDIO_KEYINPUT, 462171482Sjeff kbd->kb_callback.kc_arg); 463171482Sjeff } else { 464122744Sjeff /* read and discard the input; no one is waiting for input */ 465177435Sjeff do { 466122744Sjeff c = atkbd_read_char(kbd, FALSE); 467177435Sjeff } while (c != NOKEY); 468177435Sjeff 469177435Sjeff if (!KBD_HAS_DEVICE(kbd)) { 470171482Sjeff /* 471171482Sjeff * The keyboard was not detected before; 472177435Sjeff * it must have been reconnected! 473164936Sjulian */ 474165620Sjeff state = (atkbd_state_t *)kbd->kb_data; 475164936Sjulian init_keyboard(state->kbdc, &kbd->kb_type, 476123433Sjeff kbd->kb_config); 477165766Sjeff atkbd_ioctl(kbd, KDSETLED, (caddr_t)&state->ks_state); 478165766Sjeff get_typematic(kbd); 479177435Sjeff delay[0] = kbd->kb_delay1; 480165766Sjeff delay[1] = kbd->kb_delay2; 481177435Sjeff atkbd_ioctl(kbd, KDSETREPEAT, (caddr_t)delay); 482165766Sjeff KBD_FOUND_DEVICE(kbd); 483177435Sjeff } 484122744Sjeff } 485122744Sjeff return 0; 486171482Sjeff} 487171482Sjeff 488171482Sjeff/* test the interface to the device */ 489171482Sjeffstatic int 490113357Sjeffatkbd_test_if(keyboard_t *kbd) 491177435Sjeff{ 492113357Sjeff int error; 493171482Sjeff int s; 494171482Sjeff 495177435Sjeff error = 0; 496177902Sjeff empty_both_buffers(((atkbd_state_t *)kbd->kb_data)->kbdc, 10); 497165620Sjeff s = spltty(); 498198854Sattilio if (!test_controller(((atkbd_state_t *)kbd->kb_data)->kbdc)) 499177902Sjeff error = EIO; 500187357Sjeff else if (test_kbd_port(((atkbd_state_t *)kbd->kb_data)->kbdc) != 0) 501110267Sjeff error = EIO; 502113357Sjeff splx(s); 503171482Sjeff 504171482Sjeff return error; 505171482Sjeff} 506171482Sjeff 507112994Sjeff/* 508177435Sjeff * Enable the access to the device; until this function is called, 509110267Sjeff * the client cannot read from the keyboard. 510171482Sjeff */ 511177435Sjeffstatic int 512171482Sjeffatkbd_enable(keyboard_t *kbd) 513171482Sjeff{ 514171713Sjeff int s; 515177902Sjeff 516165620Sjeff s = spltty(); 517198854Sattilio KBD_ACTIVATE(kbd); 518177902Sjeff splx(s); 519187357Sjeff return 0; 520110267Sjeff} 521110267Sjeff 522176735Sjeff/* disallow the access to the device */ 523176735Sjeffstatic int 524176735Sjeffatkbd_disable(keyboard_t *kbd) 525176735Sjeff{ 526176735Sjeff int s; 527176735Sjeff 528176735Sjeff s = spltty(); 529176735Sjeff KBD_DEACTIVATE(kbd); 530176735Sjeff splx(s); 531176735Sjeff return 0; 532176735Sjeff} 533176735Sjeff 534177435Sjeff/* read one byte from the keyboard if it's allowed */ 535177435Sjeffstatic int 536176735Sjeffatkbd_read(keyboard_t *kbd, int wait) 537176735Sjeff{ 538176735Sjeff int c; 539176735Sjeff 540176735Sjeff if (wait) 541113357Sjeff c = read_kbd_data(((atkbd_state_t *)kbd->kb_data)->kbdc); 542176735Sjeff else 543194779Sjeff c = read_kbd_data_no_wait(((atkbd_state_t *)kbd->kb_data)->kbdc); 544176735Sjeff if (c != -1) 545176735Sjeff ++kbd->kb_count; 546176735Sjeff return (KBD_IS_ACTIVE(kbd) ? c : -1); 547176735Sjeff} 548176735Sjeff 549176735Sjeff/* check if data is waiting */ 550176735Sjeffstatic int 551176735Sjeffatkbd_check(keyboard_t *kbd) 552176735Sjeff{ 553194779Sjeff if (!KBD_IS_ACTIVE(kbd)) 554194779Sjeff return FALSE; 555176735Sjeff return kbdc_data_ready(((atkbd_state_t *)kbd->kb_data)->kbdc); 556176735Sjeff} 557177169Sjhb 558176735Sjeff/* read char from the keyboard */ 559176735Sjeffstatic u_int 560176735Sjeffatkbd_read_char(keyboard_t *kbd, int wait) 561176735Sjeff{ 562176735Sjeff atkbd_state_t *state; 563176735Sjeff u_int action; 564116069Sjeff int scancode; 565176735Sjeff int keycode; 566176735Sjeff 567176735Sjeff state = (atkbd_state_t *)kbd->kb_data; 568176735Sjeffnext_code: 569176735Sjeff /* do we have a composed char to return? */ 570176735Sjeff if (!(state->ks_flags & COMPOSE) && (state->ks_composed_char > 0)) { 571176735Sjeff action = state->ks_composed_char; 572176735Sjeff state->ks_composed_char = 0; 573176735Sjeff if (action > UCHAR_MAX) 574176735Sjeff return ERRKEY; 575176735Sjeff return action; 576176735Sjeff } 577194779Sjeff 578176735Sjeff /* see if there is something in the keyboard port */ 579176735Sjeff if (wait) { 580176735Sjeff do { 581176735Sjeff scancode = read_kbd_data(state->kbdc); 582176735Sjeff } while (scancode == -1); 583176735Sjeff } else { 584194779Sjeff scancode = read_kbd_data_no_wait(state->kbdc); 585176735Sjeff if (scancode == -1) 586176735Sjeff return NOKEY; 587176735Sjeff } 588176735Sjeff ++kbd->kb_count; 589176735Sjeff 590176735Sjeff#if KBDIO_DEBUG >= 10 591176735Sjeff printf("atkbd_read_char(): scancode:0x%x\n", scancode); 592176735Sjeff#endif 593176735Sjeff 594176735Sjeff /* return the byte as is for the K_RAW mode */ 595176735Sjeff if (state->ks_mode == K_RAW) 596176735Sjeff return scancode; 597176735Sjeff 598176735Sjeff /* translate the scan code into a keycode */ 599176735Sjeff keycode = scancode & 0x7F; 600116069Sjeff switch (state->ks_prefix) { 601176735Sjeff case 0x00: /* normal scancode */ 602176735Sjeff switch(scancode) { 603176735Sjeff case 0xB8: /* left alt (compose key) released */ 604116069Sjeff if (state->ks_flags & COMPOSE) { 605177169Sjhb state->ks_flags &= ~COMPOSE; 606176735Sjeff if (state->ks_composed_char > UCHAR_MAX) 607176735Sjeff state->ks_composed_char = 0; 608176735Sjeff } 609176735Sjeff break; 610176735Sjeff case 0x38: /* left alt (compose key) pressed */ 611176735Sjeff if (!(state->ks_flags & COMPOSE)) { 612176735Sjeff state->ks_flags |= COMPOSE; 613176735Sjeff state->ks_composed_char = 0; 614176735Sjeff } 615176735Sjeff break; 616176735Sjeff case 0xE0: 617176735Sjeff case 0xE1: 618176735Sjeff state->ks_prefix = scancode; 619176735Sjeff goto next_code; 620176735Sjeff } 621176735Sjeff break; 622176735Sjeff case 0xE0: /* 0xE0 prefix */ 623176735Sjeff state->ks_prefix = 0; 624176735Sjeff switch (keycode) { 625176735Sjeff case 0x1C: /* right enter key */ 626176735Sjeff keycode = 0x59; 627176735Sjeff break; 628176735Sjeff case 0x1D: /* right ctrl key */ 629176735Sjeff keycode = 0x5A; 630176735Sjeff break; 631176735Sjeff case 0x35: /* keypad divide key */ 632176735Sjeff keycode = 0x5B; 633176735Sjeff break; 634176735Sjeff case 0x37: /* print scrn key */ 635176735Sjeff keycode = 0x5C; 636176735Sjeff break; 637176735Sjeff case 0x38: /* right alt key (alt gr) */ 638176735Sjeff keycode = 0x5D; 639176735Sjeff break; 640176735Sjeff case 0x46: /* ctrl-pause/break on AT 101 (see below) */ 641176735Sjeff keycode = 0x68; 642176735Sjeff break; 643176735Sjeff case 0x47: /* grey home key */ 644176735Sjeff keycode = 0x5E; 645176735Sjeff break; 646176735Sjeff case 0x48: /* grey up arrow key */ 647176735Sjeff keycode = 0x5F; 648176735Sjeff break; 649176735Sjeff case 0x49: /* grey page up key */ 650176735Sjeff keycode = 0x60; 651176735Sjeff break; 652176735Sjeff case 0x4B: /* grey left arrow key */ 653176735Sjeff keycode = 0x61; 654176735Sjeff break; 655176735Sjeff case 0x4D: /* grey right arrow key */ 656176735Sjeff keycode = 0x62; 657176735Sjeff break; 658176735Sjeff case 0x4F: /* grey end key */ 659194779Sjeff keycode = 0x63; 660176735Sjeff break; 661176735Sjeff case 0x50: /* grey down arrow key */ 662176735Sjeff keycode = 0x64; 663176735Sjeff break; 664176735Sjeff case 0x51: /* grey page down key */ 665176735Sjeff keycode = 0x65; 666176735Sjeff break; 667176735Sjeff case 0x52: /* grey insert key */ 668176735Sjeff keycode = 0x66; 669176735Sjeff break; 670176735Sjeff case 0x53: /* grey delete key */ 671176735Sjeff keycode = 0x67; 672176735Sjeff break; 673176735Sjeff /* the following 3 are only used on the MS "Natural" keyboard */ 674176735Sjeff case 0x5b: /* left Window key */ 675176735Sjeff keycode = 0x69; 676176735Sjeff break; 677176735Sjeff case 0x5c: /* right Window key */ 678176735Sjeff keycode = 0x6a; 679176735Sjeff break; 680176735Sjeff case 0x5d: /* menu key */ 681176735Sjeff keycode = 0x6b; 682176735Sjeff break; 683176735Sjeff case 0x5e: /* power key */ 684176735Sjeff keycode = 0x6d; 685176735Sjeff break; 686176735Sjeff case 0x5f: /* sleep key */ 687176735Sjeff keycode = 0x6e; 688176735Sjeff break; 689176735Sjeff case 0x63: /* wake key */ 690176735Sjeff keycode = 0x6f; 691176735Sjeff break; 692176735Sjeff default: /* ignore everything else */ 693176735Sjeff goto next_code; 694194779Sjeff } 695176735Sjeff break; 696176735Sjeff case 0xE1: /* 0xE1 prefix */ 697176735Sjeff /* 698176735Sjeff * The pause/break key on the 101 keyboard produces: 699176735Sjeff * E1-1D-45 E1-9D-C5 700176735Sjeff * Ctrl-pause/break produces: 701176735Sjeff * E0-46 E0-C6 (See above.) 702176735Sjeff */ 703176735Sjeff state->ks_prefix = 0; 704176735Sjeff if (keycode == 0x1D) 705176735Sjeff state->ks_prefix = 0x1D; 706176735Sjeff goto next_code; 707176735Sjeff /* NOT REACHED */ 708176735Sjeff case 0x1D: /* pause / break */ 709176735Sjeff state->ks_prefix = 0; 710194779Sjeff if (keycode != 0x45) 711176735Sjeff goto next_code; 712176735Sjeff keycode = 0x68; 713176735Sjeff break; 714176735Sjeff } 715176735Sjeff 716176735Sjeff if (kbd->kb_type == KB_84) { 717176735Sjeff switch (keycode) { 718176735Sjeff case 0x37: /* *(numpad)/print screen */ 719176735Sjeff if (state->ks_flags & SHIFTS) 720176735Sjeff keycode = 0x5c; /* print screen */ 721176735Sjeff break; 722176735Sjeff case 0x45: /* num lock/pause */ 723176735Sjeff if (state->ks_flags & CTLS) 724176735Sjeff keycode = 0x68; /* pause */ 725176735Sjeff break; 726176735Sjeff case 0x46: /* scroll lock/break */ 727194779Sjeff if (state->ks_flags & CTLS) 728176735Sjeff keycode = 0x6c; /* break */ 729176735Sjeff break; 730176735Sjeff } 731176735Sjeff } else if (kbd->kb_type == KB_101) { 732176735Sjeff switch (keycode) { 733176735Sjeff case 0x5c: /* print screen */ 734176735Sjeff if (state->ks_flags & ALTS) 735176735Sjeff keycode = 0x54; /* sysrq */ 736176735Sjeff break; 737176735Sjeff case 0x68: /* pause/break */ 738176735Sjeff if (state->ks_flags & CTLS) 739176735Sjeff keycode = 0x6c; /* break */ 740176735Sjeff break; 741176735Sjeff } 742176735Sjeff } 743176735Sjeff 744176735Sjeff /* return the key code in the K_CODE mode */ 745176735Sjeff if (state->ks_mode == K_CODE) 746121790Sjeff return (keycode | (scancode & 0x80)); 747176735Sjeff 748116069Sjeff /* compose a character code */ 749194779Sjeff if (state->ks_flags & COMPOSE) { 750176735Sjeff switch (keycode | (scancode & 0x80)) { 751176735Sjeff /* key pressed, process it */ 752123487Sjeff case 0x47: case 0x48: case 0x49: /* keypad 7,8,9 */ 753123487Sjeff state->ks_composed_char *= 10; 754194779Sjeff state->ks_composed_char += keycode - 0x40; 755176735Sjeff if (state->ks_composed_char > UCHAR_MAX) 756176735Sjeff return ERRKEY; 757176735Sjeff goto next_code; 758176735Sjeff case 0x4B: case 0x4C: case 0x4D: /* keypad 4,5,6 */ 759176735Sjeff state->ks_composed_char *= 10; 760176735Sjeff state->ks_composed_char += keycode - 0x47; 761123487Sjeff if (state->ks_composed_char > UCHAR_MAX) 762176735Sjeff return ERRKEY; 763176735Sjeff goto next_code; 764176735Sjeff case 0x4F: case 0x50: case 0x51: /* keypad 1,2,3 */ 765176735Sjeff state->ks_composed_char *= 10; 766194779Sjeff state->ks_composed_char += keycode - 0x4E; 767176735Sjeff if (state->ks_composed_char > UCHAR_MAX) 768194779Sjeff return ERRKEY; 769123487Sjeff goto next_code; 770176735Sjeff case 0x52: /* keypad 0 */ 771176735Sjeff state->ks_composed_char *= 10; 772176735Sjeff if (state->ks_composed_char > UCHAR_MAX) 773123487Sjeff return ERRKEY; 774123487Sjeff goto next_code; 775123487Sjeff 776201148Sed /* key released, no interest here */ 777123487Sjeff case 0xC7: case 0xC8: case 0xC9: /* keypad 7,8,9 */ 778172409Sjeff case 0xCB: case 0xCC: case 0xCD: /* keypad 4,5,6 */ 779123487Sjeff case 0xCF: case 0xD0: case 0xD1: /* keypad 1,2,3 */ 780172409Sjeff case 0xD2: /* keypad 0 */ 781172409Sjeff goto next_code; 782172409Sjeff 783172409Sjeff case 0x38: /* left alt key */ 784176735Sjeff break; 785176735Sjeff 786171482Sjeff default: 787171482Sjeff if (state->ks_composed_char > 0) { 788172409Sjeff state->ks_flags &= ~COMPOSE; 789172409Sjeff state->ks_composed_char = 0; 790176735Sjeff return ERRKEY; 791172409Sjeff } 792123487Sjeff break; 793123487Sjeff } 794171482Sjeff } 795171482Sjeff 796171482Sjeff /* keycode to key action */ 797123487Sjeff action = genkbd_keyaction(kbd, keycode, scancode & 0x80, 798171482Sjeff &state->ks_state, &state->ks_accents); 799171482Sjeff if (action == NOKEY) 800171482Sjeff goto next_code; 801171482Sjeff else 802171482Sjeff return action; 803171482Sjeff} 804171482Sjeff 805171482Sjeff/* check if char is waiting */ 806171482Sjeffstatic int 807171482Sjeffatkbd_check_char(keyboard_t *kbd) 808171482Sjeff{ 809171482Sjeff atkbd_state_t *state; 810172409Sjeff 811172409Sjeff if (!KBD_IS_ACTIVE(kbd)) 812172409Sjeff return FALSE; 813172409Sjeff state = (atkbd_state_t *)kbd->kb_data; 814172409Sjeff if (!(state->ks_flags & COMPOSE) && (state->ks_composed_char > 0)) 815172409Sjeff return TRUE; 816172409Sjeff return kbdc_data_ready(state->kbdc); 817172409Sjeff} 818172409Sjeff 819172409Sjeff/* some useful control functions */ 820171482Sjeffstatic int 821171482Sjeffatkbd_ioctl(keyboard_t *kbd, u_long cmd, caddr_t arg) 822176735Sjeff{ 823164936Sjulian /* trasnlate LED_XXX bits into the device specific bits */ 824123487Sjeff static u_char ledmap[8] = { 825123433Sjeff 0, 4, 2, 6, 1, 5, 3, 7, 826116069Sjeff }; 827116069Sjeff atkbd_state_t *state = kbd->kb_data; 828176735Sjeff int error; 829116069Sjeff int s; 830116069Sjeff int i; 831116069Sjeff 832116069Sjeff s = spltty(); 833171482Sjeff switch (cmd) { 834176735Sjeff 835176735Sjeff case KDGKBMODE: /* get keyboard mode */ 836176735Sjeff *(int *)arg = state->ks_mode; 837176735Sjeff break; 838116069Sjeff case KDSKBMODE: /* set keyboard mode */ 839122744Sjeff switch (*(int *)arg) { 840165620Sjeff case K_XLATE: 841122744Sjeff if (state->ks_mode != K_XLATE) { 842171482Sjeff /* make lock key state and LED state match */ 843171482Sjeff state->ks_state &= ~LOCK_MASK; 844171482Sjeff state->ks_state |= KBD_LED_VAL(kbd); 845171482Sjeff } 846171482Sjeff /* FALLTHROUGH */ 847171482Sjeff case K_RAW: 848171482Sjeff case K_CODE: 849176735Sjeff if (state->ks_mode != *(int *)arg) { 850172293Sjeff atkbd_clear_state(kbd); 851172293Sjeff state->ks_mode = *(int *)arg; 852172293Sjeff } 853172293Sjeff break; 854172293Sjeff default: 855171482Sjeff splx(s); 856172409Sjeff return EINVAL; 857176735Sjeff } 858116069Sjeff break; 859116069Sjeff 860171482Sjeff case KDGETLED: /* get keyboard LED */ 861171482Sjeff *(int *)arg = KBD_LED_VAL(kbd); 862171482Sjeff break; 863176735Sjeff case KDSETLED: /* set keyboard LED */ 864171482Sjeff /* NOTE: lock key state in ks_state won't be changed */ 865116069Sjeff if (*(int *)arg & ~LOCK_MASK) { 866171482Sjeff splx(s); 867171482Sjeff return EINVAL; 868164936Sjulian } 869171482Sjeff i = *(int *)arg; 870116069Sjeff /* replace CAPS LED with ALTGR LED for ALTGR keyboards */ 871172409Sjeff if (state->ks_mode == K_XLATE && 872172409Sjeff kbd->kb_keymap->n_keys > ALTGR_OFFSET) { 873172409Sjeff if (i & ALKED) 874164936Sjulian i |= CLKED; 875171482Sjeff else 876177435Sjeff i &= ~CLKED; 877177435Sjeff } 878176735Sjeff if (KBD_HAS_DEVICE(kbd)) { 879177435Sjeff error = write_kbd(state->kbdc, KBDC_SET_LEDS, 880171482Sjeff ledmap[i & LED_MASK]); 881171482Sjeff if (error) { 882172409Sjeff splx(s); 883171482Sjeff return error; 884171482Sjeff } 885172409Sjeff } 886171482Sjeff KBD_LED_VAL(kbd) = *(int *)arg; 887171482Sjeff break; 888166108Sjeff 889171482Sjeff case KDGKBSTATE: /* get lock key state */ 890171482Sjeff *(int *)arg = state->ks_state & LOCK_MASK; 891176735Sjeff break; 892116069Sjeff case KDSKBSTATE: /* set lock key state */ 893110267Sjeff if (*(int *)arg & ~LOCK_MASK) { 894171482Sjeff splx(s); 895171482Sjeff return EINVAL; 896171482Sjeff } 897171482Sjeff state->ks_state &= ~LOCK_MASK; 898123433Sjeff state->ks_state |= *(int *)arg; 899164936Sjulian splx(s); 900121790Sjeff /* set LEDs and quit */ 901176735Sjeff return atkbd_ioctl(kbd, KDSETLED, arg); 902164936Sjulian 903194779Sjeff case KDSETREPEAT: /* set keyboard repeat rate (new interface) */ 904176735Sjeff splx(s); 905171482Sjeff if (!KBD_HAS_DEVICE(kbd)) 906123433Sjeff return 0; 907172484Sjeff i = typematic(((int *)arg)[0], ((int *)arg)[1]); 908172484Sjeff error = write_kbd(state->kbdc, KBDC_SET_TYPEMATIC, i); 909194779Sjeff if (error == 0) { 910194779Sjeff kbd->kb_delay1 = typematic_delay(i); 911176735Sjeff kbd->kb_delay2 = typematic_rate(i); 912171482Sjeff } 913176735Sjeff return error; 914191643Sjeff 915176735Sjeff case KDSETRAD: /* set keyboard repeat rate (old interface) */ 916176735Sjeff splx(s); 917176735Sjeff if (!KBD_HAS_DEVICE(kbd)) 918176735Sjeff return 0; 919176735Sjeff error = write_kbd(state->kbdc, KBDC_SET_TYPEMATIC, *(int *)arg); 920176735Sjeff if (error == 0) { 921176735Sjeff kbd->kb_delay1 = typematic_delay(*(int *)arg); 922166108Sjeff kbd->kb_delay2 = typematic_rate(*(int *)arg); 923176735Sjeff } 924194779Sjeff return error; 925176735Sjeff 926176735Sjeff case PIO_KEYMAP: /* set keyboard translation table */ 927176735Sjeff case PIO_KEYMAPENT: /* set keyboard translation table entry */ 928176735Sjeff case PIO_DEADKEYMAP: /* set accent key translation table */ 929171482Sjeff state->ks_accents = 0; 930176735Sjeff /* FALLTHROUGH */ 931176735Sjeff default: 932176735Sjeff splx(s); 933176735Sjeff return genkbd_commonioctl(kbd, cmd, arg); 934176735Sjeff } 935176735Sjeff 936176735Sjeff splx(s); 937176735Sjeff return 0; 938176735Sjeff} 939176735Sjeff 940176735Sjeff/* lock the access to the keyboard */ 941176735Sjeffstatic int 942178272Sjeffatkbd_lock(keyboard_t *kbd, int lock) 943176735Sjeff{ 944176735Sjeff return kbdc_lock(((atkbd_state_t *)kbd->kb_data)->kbdc, lock); 945176735Sjeff} 946123433Sjeff 947171482Sjeff/* clear the internal state of the keyboard */ 948123433Sjeffstatic void 949121790Sjeffatkbd_clear_state(keyboard_t *kbd) 950121790Sjeff{ 951171482Sjeff atkbd_state_t *state; 952171482Sjeff 953171482Sjeff state = (atkbd_state_t *)kbd->kb_data; 954121790Sjeff state->ks_flags = 0; 955177435Sjeff state->ks_polling = 0; 956121790Sjeff state->ks_state &= LOCK_MASK; /* preserve locking key state */ 957185047Sjhb state->ks_accents = 0; 958166247Sjeff state->ks_composed_char = 0; 959166108Sjeff#if 0 960121790Sjeff state->ks_prefix = 0; /* XXX */ 961177005Sjeff#endif 962177005Sjeff} 963177435Sjeff 964177435Sjeff/* save the internal state */ 965185047Sjhbstatic int 966185047Sjhbatkbd_get_state(keyboard_t *kbd, void *buf, size_t len) 967166137Sjeff{ 968185047Sjhb if (len == 0) 969178277Sjeff return sizeof(atkbd_state_t); 970178471Sjeff if (len < sizeof(atkbd_state_t)) 971178471Sjeff return -1; 972178471Sjeff bcopy(kbd->kb_data, buf, sizeof(atkbd_state_t)); 973178471Sjeff return 0; 974178471Sjeff} 975178277Sjeff 976177005Sjeff/* set the internal state */ 977171482Sjeffstatic int 978121790Sjeffatkbd_set_state(keyboard_t *kbd, void *buf, size_t len) 979121790Sjeff{ 980171482Sjeff if (len < sizeof(atkbd_state_t)) 981171482Sjeff return ENOMEM; 982171482Sjeff if (((atkbd_state_t *)kbd->kb_data)->kbdc 983171482Sjeff != ((atkbd_state_t *)buf)->kbdc) 984177435Sjeff return ENOMEM; 985176735Sjeff bcopy(buf, kbd->kb_data, sizeof(atkbd_state_t)); 986171482Sjeff return 0; 987171482Sjeff} 988171482Sjeff 989177435Sjeffstatic int 990171482Sjeffatkbd_poll(keyboard_t *kbd, int on) 991171482Sjeff{ 992171482Sjeff atkbd_state_t *state; 993171482Sjeff int s; 994171482Sjeff 995171482Sjeff state = (atkbd_state_t *)kbd->kb_data; 996171482Sjeff s = spltty(); 997171482Sjeff if (on) 998171482Sjeff ++state->ks_polling; 999171482Sjeff else 1000171482Sjeff --state->ks_polling; 1001171482Sjeff splx(s); 1002171482Sjeff return 0; 1003171482Sjeff} 1004171482Sjeff 1005171482Sjeff/* local functions */ 1006171482Sjeff 1007171482Sjeffstatic int 1008171482Sjeffget_typematic(keyboard_t *kbd) 1009171482Sjeff{ 1010171482Sjeff#ifdef __i386__ 1011171482Sjeff /* 1012171482Sjeff * Only some systems allow us to retrieve the keyboard repeat 1013177435Sjeff * rate previously set via the BIOS... 1014177435Sjeff */ 1015177435Sjeff struct vm86frame vmf; 1016177435Sjeff u_int32_t p; 1017171482Sjeff 1018171482Sjeff bzero(&vmf, sizeof(vmf)); 1019171482Sjeff vmf.vmf_ax = 0xc000; 1020171482Sjeff vm86_intcall(0x15, &vmf); 1021171482Sjeff if ((vmf.vmf_eflags & PSL_C) || vmf.vmf_ah) 1022171482Sjeff return ENODEV; 1023171482Sjeff p = BIOS_PADDRTOVADDR(((u_int32_t)vmf.vmf_es << 4) + vmf.vmf_bx); 1024171482Sjeff if ((readb(p + 6) & 0x40) == 0) /* int 16, function 0x09 supported? */ 1025171482Sjeff return ENODEV; 1026171482Sjeff vmf.vmf_ax = 0x0900; 1027171482Sjeff vm86_intcall(0x16, &vmf); 1028171482Sjeff if ((vmf.vmf_al & 0x08) == 0) /* int 16, function 0x0306 supported? */ 1029171482Sjeff return ENODEV; 1030171482Sjeff vmf.vmf_ax = 0x0306; 1031177435Sjeff vm86_intcall(0x16, &vmf); 1032176735Sjeff kbd->kb_delay1 = typematic_delay(vmf.vmf_bh << 5); 1033121790Sjeff kbd->kb_delay2 = typematic_rate(vmf.vmf_bl); 1034121790Sjeff return 0; 1035121790Sjeff#else 1036177435Sjeff return ENODEV; 1037121790Sjeff#endif /* __i386__ */ 1038121790Sjeff} 1039121790Sjeff 1040121790Sjeffstatic int 1041121790Sjeffsetup_kbd_port(KBDC kbdc, int port, int intr) 1042121790Sjeff{ 1043121790Sjeff if (!set_controller_command_byte(kbdc, 1044121790Sjeff KBD_KBD_CONTROL_BITS, 1045123231Speter ((port) ? KBD_ENABLE_KBD_PORT : KBD_DISABLE_KBD_PORT) 1046121790Sjeff | ((intr) ? KBD_ENABLE_KBD_INT : KBD_DISABLE_KBD_INT))) 1047121790Sjeff return 1; 1048177435Sjeff return 0; 1049177435Sjeff} 1050177435Sjeff 1051177435Sjeffstatic int 1052121790Sjeffget_kbd_echo(KBDC kbdc) 1053121790Sjeff{ 1054121790Sjeff /* enable the keyboard port, but disable the keyboard intr. */ 1055121790Sjeff if (setup_kbd_port(kbdc, TRUE, FALSE)) 1056121790Sjeff /* CONTROLLER ERROR: there is very little we can do... */ 1057171482Sjeff return ENXIO; 1058171482Sjeff 1059171482Sjeff /* see if something is present */ 1060177435Sjeff write_kbd_command(kbdc, KBDC_ECHO); 1061176735Sjeff if (read_kbd_data(kbdc) != KBD_ECHO) { 1062121790Sjeff empty_both_buffers(kbdc, 10); 1063177435Sjeff test_controller(kbdc); 1064121790Sjeff test_kbd_port(kbdc); 1065171482Sjeff return ENXIO; 1066177435Sjeff } 1067177435Sjeff 1068177435Sjeff /* enable the keyboard port and intr. */ 1069177435Sjeff if (setup_kbd_port(kbdc, TRUE, TRUE)) { 1070177435Sjeff /* 1071176735Sjeff * CONTROLLER ERROR 1072121790Sjeff * This is serious; the keyboard intr is left disabled! 1073123433Sjeff */ 1074171482Sjeff return ENXIO; 1075171482Sjeff } 1076172409Sjeff 1077171482Sjeff return 0; 1078171482Sjeff} 1079177435Sjeff 1080123433Sjeffstatic int 1081177435Sjeffprobe_keyboard(KBDC kbdc, int flags) 1082171482Sjeff{ 1083123433Sjeff /* 1084177435Sjeff * Don't try to print anything in this function. The low-level 1085171482Sjeff * console may not have been initialized yet... 1086177435Sjeff */ 1087177435Sjeff int err; 1088177435Sjeff int c; 1089177435Sjeff int m; 1090171482Sjeff 1091171482Sjeff if (!kbdc_lock(kbdc, TRUE)) { 1092171482Sjeff /* driver error? */ 1093123433Sjeff return ENXIO; 1094172293Sjeff } 1095171482Sjeff 1096171482Sjeff /* temporarily block data transmission from the keyboard */ 1097123685Sjeff write_controller_command(kbdc, KBDC_DISABLE_KBD_PORT); 1098171482Sjeff 1099171482Sjeff /* flush any noise in the buffer */ 1100171482Sjeff empty_both_buffers(kbdc, 100); 1101171482Sjeff 1102171482Sjeff /* save the current keyboard controller command byte */ 1103171482Sjeff m = kbdc_get_device_mask(kbdc) & ~KBD_KBD_CONTROL_BITS; 1104166108Sjeff c = get_controller_command_byte(kbdc); 1105171482Sjeff if (c == -1) { 1106171482Sjeff /* CONTROLLER ERROR */ 1107166108Sjeff kbdc_set_device_mask(kbdc, m); 1108202889Sattilio kbdc_lock(kbdc, FALSE); 1109171482Sjeff return ENXIO; 1110171482Sjeff } 1111171713Sjeff 1112202889Sattilio /* 1113171482Sjeff * The keyboard may have been screwed up by the boot block. 1114166108Sjeff * We may just be able to recover from error by testing the controller 1115166108Sjeff * and the keyboard port. The controller command byte needs to be 1116178272Sjeff * saved before this recovery operation, as some controllers seem 1117178272Sjeff * to set the command byte to particular values. 1118178272Sjeff */ 1119178272Sjeff test_controller(kbdc); 1120178272Sjeff test_kbd_port(kbdc); 1121178272Sjeff 1122178272Sjeff err = get_kbd_echo(kbdc); 1123166108Sjeff 1124177435Sjeff /* 1125171482Sjeff * Even if the keyboard doesn't seem to be present (err != 0), 1126176735Sjeff * we shall enable the keyboard port and interrupt so that 1127177435Sjeff * the driver will be operable when the keyboard is attached 1128171482Sjeff * to the system later. It is NOT recommended to hot-plug 1129194779Sjeff * the AT keyboard, but many people do so... 1130166108Sjeff */ 1131166108Sjeff kbdc_set_device_mask(kbdc, m | KBD_KBD_CONTROL_BITS); 1132166108Sjeff setup_kbd_port(kbdc, TRUE, TRUE); 1133166108Sjeff#if 0 1134176735Sjeff if (err == 0) { 1135177435Sjeff kbdc_set_device_mask(kbdc, m | KBD_KBD_CONTROL_BITS); 1136166108Sjeff } else { 1137166108Sjeff /* try to restore the command byte as before */ 1138171506Sjeff set_controller_command_byte(kbdc, 0xff, c); 1139171506Sjeff kbdc_set_device_mask(kbdc, m); 1140171506Sjeff } 1141176735Sjeff#endif 1142176735Sjeff 1143166108Sjeff kbdc_lock(kbdc, FALSE); 1144176735Sjeff return err; 1145176735Sjeff} 1146166108Sjeff 1147176735Sjeffstatic int 1148178272Sjeffinit_keyboard(KBDC kbdc, int *type, int flags) 1149178272Sjeff{ 1150176735Sjeff int codeset; 1151178272Sjeff int id; 1152166108Sjeff int c; 1153176735Sjeff 1154176735Sjeff if (!kbdc_lock(kbdc, TRUE)) { 1155166108Sjeff /* driver error? */ 1156176735Sjeff return EIO; 1157176735Sjeff } 1158176735Sjeff 1159178272Sjeff /* temporarily block data transmission from the keyboard */ 1160178272Sjeff write_controller_command(kbdc, KBDC_DISABLE_KBD_PORT); 1161176735Sjeff 1162178272Sjeff /* save the current controller command byte */ 1163178272Sjeff empty_both_buffers(kbdc, 200); 1164178272Sjeff c = get_controller_command_byte(kbdc); 1165176735Sjeff if (c == -1) { 1166178272Sjeff /* CONTROLLER ERROR */ 1167139334Sjeff kbdc_lock(kbdc, FALSE); 1168123433Sjeff printf("atkbd: unable to get the current command byte value.\n"); 1169176735Sjeff return EIO; 1170123433Sjeff } 1171176735Sjeff if (bootverbose) 1172176735Sjeff printf("atkbd: the current kbd controller command byte %04x\n", 1173176735Sjeff c); 1174176735Sjeff#if 0 1175176735Sjeff /* override the keyboard lock switch */ 1176194779Sjeff c |= KBD_OVERRIDE_KBD_LOCK; 1177176735Sjeff#endif 1178176735Sjeff 1179176735Sjeff /* enable the keyboard port, but disable the keyboard intr. */ 1180176735Sjeff if (setup_kbd_port(kbdc, TRUE, FALSE)) { 1181171506Sjeff /* CONTROLLER ERROR: there is very little we can do... */ 1182176735Sjeff printf("atkbd: unable to set the command byte.\n"); 1183171506Sjeff kbdc_lock(kbdc, FALSE); 1184177005Sjeff return EIO; 1185178272Sjeff } 1186178272Sjeff 1187177005Sjeff /* 1188178272Sjeff * Check if we have an XT keyboard before we attempt to reset it. 1189178272Sjeff * The procedure assumes that the keyboard and the controller have 1190178272Sjeff * been set up properly by BIOS and have not been messed up 1191178272Sjeff * during the boot process. 1192177005Sjeff */ 1193171482Sjeff codeset = -1; 1194123433Sjeff if (flags & KB_CONF_ALT_SCANCODESET) 1195176735Sjeff /* the user says there is a XT keyboard */ 1196123433Sjeff codeset = 1; 1197117326Sjeff#ifdef KBD_DETECT_XT_KEYBOARD 1198121790Sjeff else if ((c & KBD_TRANSLATION) == 0) { 1199117326Sjeff /* SET_SCANCODE_SET is not always supported; ignore error */ 1200177435Sjeff if (send_kbd_command_and_data(kbdc, KBDC_SET_SCANCODE_SET, 0) 1201164936Sjulian == KBD_ACK) 1202110267Sjeff codeset = read_kbd_data(kbdc); 1203177435Sjeff } 1204110267Sjeff if (bootverbose) 1205171482Sjeff printf("atkbd: scancode set %d\n", codeset); 1206177435Sjeff#endif /* KBD_DETECT_XT_KEYBOARD */ 1207177435Sjeff 1208177435Sjeff *type = KB_OTHER; 1209177435Sjeff id = get_kbd_id(kbdc); 1210177435Sjeff switch(id) { 1211177435Sjeff case 0x41ab: /* 101/102/... Enhanced */ 1212165762Sjeff case 0x83ab: /* ditto */ 1213177435Sjeff case 0x54ab: /* SpaceSaver */ 1214177435Sjeff case 0x84ab: /* ditto */ 1215165762Sjeff#if 0 1216177435Sjeff case 0x90ab: /* 'G' */ 1217177435Sjeff case 0x91ab: /* 'P' */ 1218177435Sjeff case 0x92ab: /* 'A' */ 1219165762Sjeff#endif 1220177435Sjeff *type = KB_101; 1221177435Sjeff break; 1222165762Sjeff case -1: /* AT 84 keyboard doesn't return ID */ 1223165762Sjeff *type = KB_84; 1224165762Sjeff break; 1225110267Sjeff default: 1226110267Sjeff break; 1227171482Sjeff } 1228171482Sjeff if (bootverbose) 1229171482Sjeff printf("atkbd: keyboard ID 0x%x (%d)\n", id, *type); 1230109864Sjeff 1231164936Sjulian /* reset keyboard hardware */ 1232110028Sjeff if (!(flags & KB_CONF_NO_RESET) && !reset_kbd(kbdc)) { 1233171482Sjeff /* 1234171713Sjeff * KEYBOARD ERROR 1235171713Sjeff * Keyboard reset may fail either because the keyboard 1236165762Sjeff * doen't exist, or because the keyboard doesn't pass 1237165762Sjeff * the self-test, or the keyboard controller on the 1238165620Sjeff * motherboard and the keyboard somehow fail to shake hands. 1239176735Sjeff * It is just possible, particularly in the last case, 1240176735Sjeff * that the keyboard controller may be left in a hung state. 1241176735Sjeff * test_controller() and test_kbd_port() appear to bring 1242176735Sjeff * the keyboard controller back (I don't know why and how, 1243187357Sjeff * though.) 1244187357Sjeff */ 1245187357Sjeff empty_both_buffers(kbdc, 10); 1246187357Sjeff test_controller(kbdc); 1247110028Sjeff test_kbd_port(kbdc); 1248110028Sjeff /* 1249171713Sjeff * We could disable the keyboard port and interrupt... but, 1250110028Sjeff * the keyboard may still exist (see above). 1251171713Sjeff */ 1252171713Sjeff set_controller_command_byte(kbdc, 0xff, c); 1253171713Sjeff kbdc_lock(kbdc, FALSE); 1254171713Sjeff if (bootverbose) 1255171713Sjeff printf("atkbd: failed to reset the keyboard.\n"); 1256176735Sjeff return EIO; 1257176735Sjeff } 1258171713Sjeff 1259171713Sjeff /* 1260176735Sjeff * Allow us to set the XT_KEYBD flag so that keyboards 1261171713Sjeff * such as those on the IBM ThinkPad laptop computers can be used 1262176735Sjeff * with the standard console driver. 1263176735Sjeff */ 1264176735Sjeff if (codeset == 1) { 1265123433Sjeff if (send_kbd_command_and_data(kbdc, 1266176735Sjeff KBDC_SET_SCANCODE_SET, codeset) == KBD_ACK) { 1267176735Sjeff /* XT kbd doesn't need scan code translation */ 1268171713Sjeff c &= ~KBD_TRANSLATION; 1269171713Sjeff } else { 1270171713Sjeff /* 1271171713Sjeff * KEYBOARD ERROR 1272171713Sjeff * The XT kbd isn't usable unless the proper scan 1273171713Sjeff * code set is selected. 1274171713Sjeff */ 1275171713Sjeff set_controller_command_byte(kbdc, 0xff, c); 1276171713Sjeff kbdc_lock(kbdc, FALSE); 1277171713Sjeff printf("atkbd: unable to set the XT keyboard mode.\n"); 1278171713Sjeff return EIO; 1279171713Sjeff } 1280171713Sjeff } 1281171713Sjeff 1282176734Sjeff#ifdef __alpha__ 1283117237Sjeff if (send_kbd_command_and_data( 1284171713Sjeff kbdc, KBDC_SET_SCANCODE_SET, 2) != KBD_ACK) { 1285116069Sjeff printf("atkbd: can't set translation.\n"); 1286171482Sjeff 1287171482Sjeff } 1288171482Sjeff c |= KBD_TRANSLATION; 1289171482Sjeff#endif 1290171482Sjeff 1291171482Sjeff /* enable the keyboard port and intr. */ 1292171482Sjeff if (!set_controller_command_byte(kbdc, 1293171482Sjeff KBD_KBD_CONTROL_BITS | KBD_TRANSLATION | KBD_OVERRIDE_KBD_LOCK, 1294171482Sjeff (c & (KBD_TRANSLATION | KBD_OVERRIDE_KBD_LOCK)) 1295171482Sjeff | KBD_ENABLE_KBD_PORT | KBD_ENABLE_KBD_INT)) { 1296171713Sjeff /* 1297177435Sjeff * CONTROLLER ERROR 1298176735Sjeff * This is serious; we are left with the disabled 1299171482Sjeff * keyboard intr. 1300109864Sjeff */ 1301109864Sjeff set_controller_command_byte(kbdc, 0xff, c); 1302171482Sjeff kbdc_lock(kbdc, FALSE); 1303171482Sjeff printf("atkbd: unable to enable the keyboard port and intr.\n"); 1304171482Sjeff return EIO; 1305153533Sdavidxu } 1306153533Sdavidxu 1307153533Sdavidxu kbdc_lock(kbdc, FALSE); 1308153533Sdavidxu return 0; 1309171482Sjeff} 1310171482Sjeff 1311153533Sdavidxustatic int 1312166229Sjeffwrite_kbd(KBDC kbdc, int command, int data) 1313153533Sdavidxu{ 1314153533Sdavidxu int s; 1315165762Sjeff 1316165766Sjeff /* prevent the timeout routine from polling the keyboard */ 1317153533Sdavidxu if (!kbdc_lock(kbdc, TRUE)) 1318171482Sjeff return EBUSY; 1319165762Sjeff 1320165762Sjeff /* disable the keyboard and mouse interrupt */ 1321165762Sjeff s = spltty(); 1322165762Sjeff#if 0 1323171482Sjeff c = get_controller_command_byte(kbdc); 1324171482Sjeff if ((c == -1) 1325171482Sjeff || !set_controller_command_byte(kbdc, 1326166108Sjeff kbdc_get_device_mask(kbdc), 1327171899Sjeff KBD_DISABLE_KBD_PORT | KBD_DISABLE_KBD_INT 1328172409Sjeff | KBD_DISABLE_AUX_PORT | KBD_DISABLE_AUX_INT)) { 1329172409Sjeff /* CONTROLLER ERROR */ 1330172409Sjeff kbdc_lock(kbdc, FALSE); 1331172409Sjeff splx(s); 1332172409Sjeff return EIO; 1333189787Sjeff } 1334189787Sjeff /* 1335189787Sjeff * Now that the keyboard controller is told not to generate 1336171899Sjeff * the keyboard and mouse interrupts, call `splx()' to allow 1337189787Sjeff * the other tty interrupts. The clock interrupt may also occur, 1338166108Sjeff * but the timeout routine (`scrn_timer()') will be blocked 1339166108Sjeff * by the lock flag set via `kbdc_lock()' 1340153533Sdavidxu */ 1341153533Sdavidxu splx(s); 1342153533Sdavidxu#endif 1343109864Sjeff 1344171482Sjeff if (send_kbd_command_and_data(kbdc, command, data) != KBD_ACK) 1345171482Sjeff send_kbd_command(kbdc, KBDC_ENABLE_KBD); 1346171482Sjeff 1347171482Sjeff#if 0 1348171482Sjeff /* restore the interrupts */ 1349171482Sjeff if (!set_controller_command_byte(kbdc, 1350171482Sjeff kbdc_get_device_mask(kbdc), 1351171482Sjeff c & (KBD_KBD_CONTROL_BITS | KBD_AUX_CONTROL_BITS))) { 1352171482Sjeff /* CONTROLLER ERROR */ 1353171482Sjeff } 1354171482Sjeff#else 1355171482Sjeff splx(s); 1356171482Sjeff#endif 1357171482Sjeff kbdc_lock(kbdc, FALSE); 1358171482Sjeff 1359171482Sjeff return 0; 1360171482Sjeff} 1361171482Sjeff 1362171482Sjeffstatic int 1363171482Sjeffget_kbd_id(KBDC kbdc) 1364171482Sjeff{ 1365171482Sjeff int id1, id2; 1366171482Sjeff 1367171482Sjeff empty_both_buffers(kbdc, 10); 1368171482Sjeff id1 = id2 = -1; 1369171482Sjeff if (send_kbd_command(kbdc, KBDC_SEND_DEV_ID) != KBD_ACK) 1370171482Sjeff return -1; 1371171482Sjeff 1372171482Sjeff DELAY(10000); /* 10 msec delay */ 1373171482Sjeff id1 = read_kbd_data(kbdc); 1374171482Sjeff if (id1 != -1) 1375171482Sjeff id2 = read_kbd_data(kbdc); 1376171482Sjeff 1377171482Sjeff if ((id1 == -1) || (id2 == -1)) { 1378171482Sjeff empty_both_buffers(kbdc, 10); 1379171482Sjeff test_controller(kbdc); 1380171482Sjeff test_kbd_port(kbdc); 1381171482Sjeff return -1; 1382171482Sjeff } 1383171482Sjeff return ((id2 << 8) | id1); 1384171482Sjeff} 1385171482Sjeff 1386171482Sjeffstatic int delays[] = { 250, 500, 750, 1000 }; 1387109864Sjeffstatic int rates[] = { 34, 38, 42, 46, 50, 55, 59, 63, 1388109864Sjeff 68, 76, 84, 92, 100, 110, 118, 126, 1389109864Sjeff 136, 152, 168, 184, 200, 220, 236, 252, 1390113357Sjeff 272, 304, 336, 368, 400, 440, 472, 504 }; 1391163709Sjb 1392109864Sjeffstatic int 1393165762Sjefftypematic_delay(int i) 1394109864Sjeff{ 1395109864Sjeff return delays[(i >> 5) & 3]; 1396163709Sjb} 1397113357Sjeff 1398112966Sjeffstatic int 1399165762Sjefftypematic_rate(int i) 1400165762Sjeff{ 1401165762Sjeff return rates[i & 0x1f]; 1402112966Sjeff} 1403171482Sjeff 1404165762Sjeffstatic int 1405165762Sjefftypematic(int delay, int rate) 1406172293Sjeff{ 1407172293Sjeff int value; 1408172293Sjeff int i; 1409172293Sjeff 1410112966Sjeff for (i = sizeof(delays)/sizeof(delays[0]) - 1; i > 0; --i) { 1411198126Sjhb if (delay >= delays[i]) 1412165762Sjeff break; 1413165762Sjeff } 1414165762Sjeff value = i << 5; 1415165762Sjeff for (i = sizeof(rates)/sizeof(rates[0]) - 1; i > 0; --i) { 1416165762Sjeff if (rate >= rates[i]) 1417166208Sjeff break; 1418166208Sjeff } 1419165762Sjeff value |= i; 1420165762Sjeff return value; 1421165762Sjeff} 1422165762Sjeff