atkbd.c revision 162711
1193326Sed/*- 2193326Sed * Copyright (c) 1999 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp> 3193326Sed * All rights reserved. 4193326Sed * 5193326Sed * Redistribution and use in source and binary forms, with or without 6193326Sed * modification, are permitted provided that the following conditions 7193326Sed * are met: 8193326Sed * 1. Redistributions of source code must retain the above copyright 9193326Sed * notice, this list of conditions and the following disclaimer as 10193326Sed * the first lines of this file unmodified. 11193326Sed * 2. Redistributions in binary form must reproduce the above copyright 12193326Sed * notice, this list of conditions and the following disclaimer in the 13193326Sed * documentation and/or other materials provided with the distribution. 14193326Sed * 15193326Sed * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR 16193326Sed * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17193326Sed * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18193326Sed * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, 19193326Sed * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20193326Sed * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21193326Sed * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22193326Sed * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23193326Sed * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24193326Sed * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25193326Sed * 26193326Sed */ 27193326Sed 28193326Sed#include <sys/cdefs.h> 29193326Sed__FBSDID("$FreeBSD: head/sys/dev/atkbdc/atkbd.c 162711 2006-09-27 19:57:02Z ru $"); 30193326Sed 31193326Sed#include "opt_compat.h" 32193326Sed#include "opt_kbd.h" 33193326Sed#include "opt_atkbd.h" 34193326Sed 35193326Sed#include <sys/param.h> 36193326Sed#include <sys/systm.h> 37193326Sed#include <sys/kernel.h> 38193326Sed#include <sys/bus.h> 39193326Sed#include <sys/eventhandler.h> 40193326Sed#include <sys/proc.h> 41193326Sed#include <sys/limits.h> 42193326Sed#include <sys/malloc.h> 43193326Sed 44193326Sed#include <machine/bus.h> 45193326Sed#include <machine/resource.h> 46193326Sed 47193326Sed#ifdef __i386__ 48193326Sed#include <machine/md_var.h> 49193326Sed#include <machine/psl.h> 50193326Sed#include <machine/vm86.h> 51193326Sed#include <machine/pc/bios.h> 52193326Sed 53193326Sed#include <vm/vm.h> 54193326Sed#include <vm/pmap.h> 55193326Sed#include <vm/vm_param.h> 56193326Sed 57193326Sed#include <isa/isareg.h> 58193326Sed#endif /* __i386__ */ 59193326Sed 60193326Sed#include <sys/kbio.h> 61193326Sed#include <dev/kbd/kbdreg.h> 62193326Sed#include <dev/atkbdc/atkbdreg.h> 63193326Sed#include <dev/atkbdc/atkbdcreg.h> 64193326Sed 65193326Sedstatic timeout_t atkbd_timeout; 66193326Sedstatic void atkbd_shutdown_final(void *v); 67193326Sed 68193326Sedint 69193326Sedatkbd_probe_unit(int unit, int ctlr, int irq, int flags) 70193326Sed{ 71193326Sed keyboard_switch_t *sw; 72193326Sed int args[2]; 73193326Sed int error; 74193326Sed 75193326Sed sw = kbd_get_switch(ATKBD_DRIVER_NAME); 76193326Sed if (sw == NULL) 77193326Sed return ENXIO; 78193326Sed 79193326Sed args[0] = ctlr; 80193326Sed args[1] = irq; 81193326Sed error = (*sw->probe)(unit, args, flags); 82193326Sed if (error) 83193326Sed return error; 84193326Sed return 0; 85193326Sed} 86193326Sed 87193326Sedint 88193326Sedatkbd_attach_unit(int unit, keyboard_t **kbd, int ctlr, int irq, int flags) 89193326Sed{ 90193326Sed keyboard_switch_t *sw; 91193326Sed int args[2]; 92193326Sed int error; 93193326Sed 94193326Sed sw = kbd_get_switch(ATKBD_DRIVER_NAME); 95193326Sed if (sw == NULL) 96193326Sed return ENXIO; 97193326Sed 98193326Sed /* reset, initialize and enable the device */ 99193326Sed args[0] = ctlr; 100193326Sed args[1] = irq; 101193326Sed *kbd = NULL; 102193326Sed error = (*sw->probe)(unit, args, flags); 103193326Sed if (error) 104193326Sed return error; 105193326Sed error = (*sw->init)(unit, kbd, args, flags); 106193326Sed if (error) 107193326Sed return error; 108193326Sed (*sw->enable)(*kbd); 109193326Sed 110194711Sed#ifdef KBD_INSTALL_CDEV 111194711Sed /* attach a virtual keyboard cdev */ 112194711Sed error = kbd_attach(*kbd); 113193326Sed if (error) 114194179Sed return error; 115194179Sed#endif 116193326Sed 117193326Sed /* 118193326Sed * This is a kludge to compensate for lost keyboard interrupts. 119193326Sed * A similar code used to be in syscons. See below. XXX 120193326Sed */ 121193326Sed atkbd_timeout(*kbd); 122193326Sed 123193326Sed if (bootverbose) 124193326Sed (*sw->diag)(*kbd, bootverbose); 125193326Sed 126193326Sed EVENTHANDLER_REGISTER(shutdown_final, atkbd_shutdown_final, *kbd, 127193326Sed SHUTDOWN_PRI_DEFAULT); 128193326Sed 129193326Sed return 0; 130193326Sed} 131193326Sed 132193326Sedstatic void 133193326Sedatkbd_timeout(void *arg) 134193326Sed{ 135193326Sed keyboard_t *kbd; 136193326Sed int s; 137193326Sed 138193326Sed /* 139193326Sed * The original text of the following comments are extracted 140193326Sed * from syscons.c (1.287) 141193326Sed * 142193326Sed * With release 2.1 of the Xaccel server, the keyboard is left 143193326Sed * hanging pretty often. Apparently an interrupt from the 144193326Sed * keyboard is lost, and I don't know why (yet). 145193326Sed * This ugly hack calls the low-level interrupt routine if input 146193326Sed * is ready for the keyboard and conveniently hides the problem. XXX 147193326Sed * 148193326Sed * Try removing anything stuck in the keyboard controller; whether 149193326Sed * it's a keyboard scan code or mouse data. The low-level 150193326Sed * interrupt routine doesn't read the mouse data directly, 151193326Sed * but the keyboard controller driver will, as a side effect. 152193326Sed */ 153194613Sed /* 154194613Sed * And here is bde's original comment about this: 155194613Sed * 156193326Sed * This is necessary to handle edge triggered interrupts - if we 157194613Sed * returned when our IRQ is high due to unserviced input, then there 158193326Sed * would be no more keyboard IRQs until the keyboard is reset by 159193326Sed * external powers. 160193326Sed * 161193326Sed * The keyboard apparently unwedges the irq in most cases. 162193326Sed */ 163193326Sed s = spltty(); 164193326Sed kbd = (keyboard_t *)arg; 165194179Sed if ((*kbdsw[kbd->kb_index]->lock)(kbd, TRUE)) { 166194179Sed /* 167194711Sed * We have seen the lock flag is not set. Let's reset 168194711Sed * the flag early, otherwise the LED update routine fails 169194711Sed * which may want the lock during the interrupt routine. 170193326Sed */ 171193326Sed (*kbdsw[kbd->kb_index]->lock)(kbd, FALSE); 172193326Sed if ((*kbdsw[kbd->kb_index]->check_char)(kbd)) 173194179Sed (*kbdsw[kbd->kb_index]->intr)(kbd, NULL); 174194179Sed } 175193326Sed splx(s); 176193326Sed timeout(atkbd_timeout, arg, hz/10); 177193326Sed} 178193326Sed 179193326Sed/* LOW-LEVEL */ 180194711Sed 181194711Sed#define ATKBD_DEFAULT 0 182194711Sed 183194179Sedtypedef struct atkbd_state { 184194179Sed KBDC kbdc; /* keyboard controller */ 185194179Sed int ks_mode; /* input mode (K_XLATE,K_RAW,K_CODE) */ 186194179Sed int ks_flags; /* flags */ 187194179Sed#define COMPOSE (1 << 0) 188193326Sed int ks_polling; 189193326Sed int ks_state; /* shift/lock key state */ 190193326Sed int ks_accents; /* accent key index (> 0) */ 191193326Sed u_int ks_composed_char; /* composed char code (> 0) */ 192193326Sed u_char ks_prefix; /* AT scan code prefix */ 193193326Sed} atkbd_state_t; 194193326Sed 195193326Sed/* keyboard driver declaration */ 196193326Sedstatic int atkbd_configure(int flags); 197193326Sedstatic kbd_probe_t atkbd_probe; 198193326Sedstatic kbd_init_t atkbd_init; 199193326Sedstatic kbd_term_t atkbd_term; 200193326Sedstatic kbd_intr_t atkbd_intr; 201193326Sedstatic kbd_test_if_t atkbd_test_if; 202193326Sedstatic kbd_enable_t atkbd_enable; 203193326Sedstatic kbd_disable_t atkbd_disable; 204193326Sedstatic kbd_read_t atkbd_read; 205193326Sedstatic kbd_check_t atkbd_check; 206193326Sedstatic kbd_read_char_t atkbd_read_char; 207193326Sedstatic kbd_check_char_t atkbd_check_char; 208193326Sedstatic kbd_ioctl_t atkbd_ioctl; 209193326Sedstatic kbd_lock_t atkbd_lock; 210193326Sedstatic kbd_clear_state_t atkbd_clear_state; 211193326Sedstatic kbd_get_state_t atkbd_get_state; 212193326Sedstatic kbd_set_state_t atkbd_set_state; 213193326Sedstatic kbd_poll_mode_t atkbd_poll; 214193326Sed 215193326Sedstatic keyboard_switch_t atkbdsw = { 216193326Sed atkbd_probe, 217193326Sed atkbd_init, 218193326Sed atkbd_term, 219193326Sed atkbd_intr, 220193326Sed atkbd_test_if, 221193326Sed atkbd_enable, 222193326Sed atkbd_disable, 223193326Sed atkbd_read, 224193326Sed atkbd_check, 225193326Sed atkbd_read_char, 226193326Sed atkbd_check_char, 227193326Sed atkbd_ioctl, 228193326Sed atkbd_lock, 229193326Sed atkbd_clear_state, 230193326Sed atkbd_get_state, 231193326Sed atkbd_set_state, 232193326Sed genkbd_get_fkeystr, 233193326Sed atkbd_poll, 234193326Sed genkbd_diag, 235193326Sed}; 236193326Sed 237193326SedKEYBOARD_DRIVER(atkbd, atkbdsw, atkbd_configure); 238193326Sed 239193326Sed/* local functions */ 240193326Sedstatic int get_typematic(keyboard_t *kbd); 241193326Sedstatic int setup_kbd_port(KBDC kbdc, int port, int intr); 242193326Sedstatic int get_kbd_echo(KBDC kbdc); 243193326Sedstatic int probe_keyboard(KBDC kbdc, int flags); 244193326Sedstatic int init_keyboard(KBDC kbdc, int *type, int flags); 245193326Sedstatic int write_kbd(KBDC kbdc, int command, int data); 246193326Sedstatic int get_kbd_id(KBDC kbdc); 247193326Sedstatic int typematic(int delay, int rate); 248193326Sedstatic int typematic_delay(int delay); 249193326Sedstatic int typematic_rate(int rate); 250193326Sed 251193326Sed/* local variables */ 252193326Sed 253193326Sed/* the initial key map, accent map and fkey strings */ 254193326Sed#ifdef ATKBD_DFLT_KEYMAP 255193326Sed#define KBD_DFLT_KEYMAP 256193326Sed#include "atkbdmap.h" 257193326Sed#endif 258193326Sed#include <dev/kbd/kbdtables.h> 259193326Sed 260193326Sed/* structures for the default keyboard */ 261195341Sedstatic keyboard_t default_kbd; 262195341Sedstatic atkbd_state_t default_kbd_state; 263195341Sedstatic keymap_t default_keymap; 264195341Sedstatic accentmap_t default_accentmap; 265195341Sedstatic fkeytab_t default_fkeytab[NUM_FKEYS]; 266195341Sed 267193326Sed/* 268193326Sed * The back door to the keyboard driver! 269193326Sed * This function is called by the console driver, via the kbdio module, 270193326Sed * to tickle keyboard drivers when the low-level console is being initialized. 271193326Sed * Almost nothing in the kernel has been initialied yet. Try to probe 272193326Sed * keyboards if possible. 273193326Sed * NOTE: because of the way the low-level console is initialized, this routine 274193326Sed * may be called more than once!! 275193326Sed */ 276193326Sedstatic int 277193326Sedatkbd_configure(int flags) 278193326Sed{ 279193326Sed keyboard_t *kbd; 280193326Sed int arg[2]; 281193326Sed int i; 282193326Sed 283193326Sed /* 284193326Sed * Probe the keyboard controller, if not present or if the driver 285193326Sed * is disabled, unregister the keyboard if any. 286193326Sed */ 287193326Sed if (atkbdc_configure() != 0 || 288193326Sed resource_disabled("atkbd", ATKBD_DEFAULT)) { 289193326Sed i = kbd_find_keyboard(ATKBD_DRIVER_NAME, ATKBD_DEFAULT); 290193326Sed if (i >= 0) { 291193326Sed kbd = kbd_get_keyboard(i); 292193326Sed kbd_unregister(kbd); 293193326Sed kbd->kb_flags &= ~KB_REGISTERED; 294193326Sed } 295193326Sed return 0; 296193326Sed } 297193326Sed 298193326Sed /* XXX: a kludge to obtain the device configuration flags */ 299193326Sed if (resource_int_value("atkbd", ATKBD_DEFAULT, "flags", &i) == 0) 300193326Sed flags |= i; 301193326Sed 302193326Sed /* probe the default keyboard */ 303193326Sed arg[0] = -1; 304193326Sed arg[1] = -1; 305193326Sed kbd = NULL; 306193326Sed if (atkbd_probe(ATKBD_DEFAULT, arg, flags)) 307193326Sed return 0; 308193326Sed if (atkbd_init(ATKBD_DEFAULT, &kbd, arg, flags)) 309193326Sed return 0; 310193326Sed 311193326Sed /* return the number of found keyboards */ 312193326Sed return 1; 313193326Sed} 314193326Sed 315194179Sed/* low-level functions */ 316193326Sed 317193326Sed/* detect a keyboard */ 318193326Sedstatic int 319193326Sedatkbd_probe(int unit, void *arg, int flags) 320193326Sed{ 321193326Sed KBDC kbdc; 322193326Sed int *data = (int *)arg; /* data[0]: controller, data[1]: irq */ 323193326Sed 324193326Sed /* XXX */ 325193326Sed if (unit == ATKBD_DEFAULT) { 326193326Sed if (KBD_IS_PROBED(&default_kbd)) 327193326Sed return 0; 328193326Sed } 329193326Sed 330193326Sed kbdc = atkbdc_open(data[0]); 331193326Sed if (kbdc == NULL) 332193326Sed return ENXIO; 333193326Sed if (probe_keyboard(kbdc, flags)) { 334193326Sed if (flags & KB_CONF_FAIL_IF_NO_KBD) 335193326Sed return ENXIO; 336193326Sed } 337193326Sed return 0; 338193326Sed} 339193326Sed 340193326Sed/* reset and initialize the device */ 341193326Sedstatic int 342193326Sedatkbd_init(int unit, keyboard_t **kbdp, void *arg, int flags) 343193326Sed{ 344193326Sed keyboard_t *kbd; 345193326Sed atkbd_state_t *state; 346193326Sed keymap_t *keymap; 347193326Sed accentmap_t *accmap; 348193326Sed fkeytab_t *fkeymap; 349193326Sed int fkeymap_size; 350193326Sed int delay[2]; 351193326Sed int *data = (int *)arg; /* data[0]: controller, data[1]: irq */ 352193326Sed int error, needfree; 353193326Sed 354193326Sed /* XXX */ 355193326Sed if (unit == ATKBD_DEFAULT) { 356193326Sed *kbdp = kbd = &default_kbd; 357193326Sed if (KBD_IS_INITIALIZED(kbd) && KBD_IS_CONFIGURED(kbd)) 358193326Sed return 0; 359193326Sed state = &default_kbd_state; 360193326Sed keymap = &default_keymap; 361193326Sed accmap = &default_accentmap; 362193326Sed fkeymap = default_fkeytab; 363193326Sed fkeymap_size = 364193326Sed sizeof(default_fkeytab)/sizeof(default_fkeytab[0]); 365193326Sed needfree = 0; 366193326Sed } else if (*kbdp == NULL) { 367193326Sed *kbdp = kbd = malloc(sizeof(*kbd), M_DEVBUF, M_NOWAIT | M_ZERO); 368193326Sed state = malloc(sizeof(*state), M_DEVBUF, M_NOWAIT | M_ZERO); 369193326Sed /* NB: these will always be initialized 'cuz !KBD_IS_PROBED */ 370193326Sed keymap = malloc(sizeof(key_map), M_DEVBUF, M_NOWAIT); 371193326Sed accmap = malloc(sizeof(accent_map), M_DEVBUF, M_NOWAIT); 372193326Sed fkeymap = malloc(sizeof(fkey_tab), M_DEVBUF, M_NOWAIT); 373193326Sed fkeymap_size = sizeof(fkey_tab)/sizeof(fkey_tab[0]); 374193326Sed needfree = 1; 375193326Sed if ((kbd == NULL) || (state == NULL) || (keymap == NULL) 376193326Sed || (accmap == NULL) || (fkeymap == NULL)) { 377193326Sed error = ENOMEM; 378193326Sed goto bad; 379193326Sed } 380193326Sed } else if (KBD_IS_INITIALIZED(*kbdp) && KBD_IS_CONFIGURED(*kbdp)) { 381193326Sed return 0; 382193326Sed } else { 383193326Sed kbd = *kbdp; 384193326Sed state = (atkbd_state_t *)kbd->kb_data; 385193326Sed bzero(state, sizeof(*state)); 386193326Sed keymap = kbd->kb_keymap; 387193326Sed accmap = kbd->kb_accentmap; 388193326Sed fkeymap = kbd->kb_fkeytab; 389193326Sed fkeymap_size = kbd->kb_fkeytab_size; 390193326Sed needfree = 0; 391193326Sed } 392193326Sed 393193326Sed if (!KBD_IS_PROBED(kbd)) { 394193326Sed state->kbdc = atkbdc_open(data[0]); 395193326Sed if (state->kbdc == NULL) { 396193326Sed error = ENXIO; 397193326Sed goto bad; 398193326Sed } 399193326Sed kbd_init_struct(kbd, ATKBD_DRIVER_NAME, KB_OTHER, unit, flags, 400193326Sed 0, 0); 401193326Sed bcopy(&key_map, keymap, sizeof(key_map)); 402193326Sed bcopy(&accent_map, accmap, sizeof(accent_map)); 403193326Sed bcopy(fkey_tab, fkeymap, 404193326Sed imin(fkeymap_size*sizeof(fkeymap[0]), sizeof(fkey_tab))); 405193326Sed kbd_set_maps(kbd, keymap, accmap, fkeymap, fkeymap_size); 406193326Sed kbd->kb_data = (void *)state; 407193326Sed 408193326Sed if (probe_keyboard(state->kbdc, flags)) { /* shouldn't happen */ 409193326Sed if (flags & KB_CONF_FAIL_IF_NO_KBD) { 410193326Sed error = ENXIO; 411193326Sed goto bad; 412193326Sed } 413193326Sed } else { 414193326Sed KBD_FOUND_DEVICE(kbd); 415193326Sed } 416193326Sed atkbd_clear_state(kbd); 417193326Sed state->ks_mode = K_XLATE; 418193326Sed /* 419193326Sed * FIXME: set the initial value for lock keys in ks_state 420193326Sed * according to the BIOS data? 421193326Sed */ 422193326Sed KBD_PROBE_DONE(kbd); 423193326Sed } 424193326Sed if (!KBD_IS_INITIALIZED(kbd) && !(flags & KB_CONF_PROBE_ONLY)) { 425193326Sed kbd->kb_config = flags & ~KB_CONF_PROBE_ONLY; 426193326Sed if (KBD_HAS_DEVICE(kbd) 427193326Sed && init_keyboard(state->kbdc, &kbd->kb_type, kbd->kb_config) 428193326Sed && (kbd->kb_config & KB_CONF_FAIL_IF_NO_KBD)) { 429193326Sed kbd_unregister(kbd); 430193326Sed error = ENXIO; 431193326Sed goto bad; 432193326Sed } 433194711Sed atkbd_ioctl(kbd, KDSETLED, (caddr_t)&state->ks_state); 434194711Sed get_typematic(kbd); 435194711Sed delay[0] = kbd->kb_delay1; 436193326Sed delay[1] = kbd->kb_delay2; 437193326Sed atkbd_ioctl(kbd, KDSETREPEAT, (caddr_t)delay); 438193326Sed KBD_INIT_DONE(kbd); 439193326Sed } 440193326Sed if (!KBD_IS_CONFIGURED(kbd)) { 441193326Sed if (kbd_register(kbd) < 0) { 442193326Sed error = ENXIO; 443193326Sed goto bad; 444193326Sed } 445193326Sed KBD_CONFIG_DONE(kbd); 446193326Sed } 447193326Sed 448193326Sed return 0; 449193326Sedbad: 450193326Sed if (needfree) { 451193326Sed if (state != NULL) 452193326Sed free(state, M_DEVBUF); 453193326Sed if (keymap != NULL) 454193326Sed free(keymap, M_DEVBUF); 455193326Sed if (accmap != NULL) 456193326Sed free(accmap, M_DEVBUF); 457193326Sed if (fkeymap != NULL) 458193326Sed free(fkeymap, M_DEVBUF); 459193326Sed if (kbd != NULL) { 460193326Sed free(kbd, M_DEVBUF); 461193326Sed *kbdp = NULL; /* insure ref doesn't leak to caller */ 462193326Sed } 463193326Sed } 464193326Sed return error; 465193326Sed} 466193326Sed 467193326Sed/* finish using this keyboard */ 468193326Sedstatic int 469193326Sedatkbd_term(keyboard_t *kbd) 470193326Sed{ 471193326Sed kbd_unregister(kbd); 472193326Sed return 0; 473193326Sed} 474193326Sed 475193326Sed/* keyboard interrupt routine */ 476193326Sedstatic int 477193326Sedatkbd_intr(keyboard_t *kbd, void *arg) 478193326Sed{ 479193326Sed atkbd_state_t *state; 480193326Sed int delay[2]; 481193326Sed int c; 482193326Sed 483193326Sed if (KBD_IS_ACTIVE(kbd) && KBD_IS_BUSY(kbd)) { 484193326Sed /* let the callback function to process the input */ 485193326Sed (*kbd->kb_callback.kc_func)(kbd, KBDIO_KEYINPUT, 486193326Sed kbd->kb_callback.kc_arg); 487193326Sed } else { 488193326Sed /* read and discard the input; no one is waiting for input */ 489193326Sed do { 490195341Sed c = atkbd_read_char(kbd, FALSE); 491193326Sed } while (c != NOKEY); 492193326Sed 493193326Sed if (!KBD_HAS_DEVICE(kbd)) { 494193326Sed /* 495193326Sed * The keyboard was not detected before; 496193326Sed * it must have been reconnected! 497193326Sed */ 498193326Sed state = (atkbd_state_t *)kbd->kb_data; 499193326Sed init_keyboard(state->kbdc, &kbd->kb_type, 500193326Sed kbd->kb_config); 501193326Sed atkbd_ioctl(kbd, KDSETLED, (caddr_t)&state->ks_state); 502193326Sed get_typematic(kbd); 503193326Sed delay[0] = kbd->kb_delay1; 504193326Sed delay[1] = kbd->kb_delay2; 505193326Sed atkbd_ioctl(kbd, KDSETREPEAT, (caddr_t)delay); 506193326Sed KBD_FOUND_DEVICE(kbd); 507193326Sed } 508193326Sed } 509193326Sed return 0; 510193326Sed} 511193326Sed 512193326Sed/* test the interface to the device */ 513193326Sedstatic int 514193326Sedatkbd_test_if(keyboard_t *kbd) 515193326Sed{ 516193326Sed int error; 517193326Sed int s; 518193326Sed 519193326Sed error = 0; 520193326Sed empty_both_buffers(((atkbd_state_t *)kbd->kb_data)->kbdc, 10); 521193326Sed s = spltty(); 522193326Sed if (!test_controller(((atkbd_state_t *)kbd->kb_data)->kbdc)) 523193326Sed error = EIO; 524193326Sed else if (test_kbd_port(((atkbd_state_t *)kbd->kb_data)->kbdc) != 0) 525193326Sed error = EIO; 526193326Sed splx(s); 527193326Sed 528193326Sed return error; 529193326Sed} 530193326Sed 531193326Sed/* 532193326Sed * Enable the access to the device; until this function is called, 533193326Sed * the client cannot read from the keyboard. 534193326Sed */ 535193326Sedstatic int 536193326Sedatkbd_enable(keyboard_t *kbd) 537193326Sed{ 538193326Sed int s; 539193326Sed 540193326Sed s = spltty(); 541193326Sed KBD_ACTIVATE(kbd); 542193326Sed splx(s); 543193326Sed return 0; 544193326Sed} 545193326Sed 546193326Sed/* disallow the access to the device */ 547193326Sedstatic int 548193326Sedatkbd_disable(keyboard_t *kbd) 549193326Sed{ 550193326Sed int s; 551193326Sed 552193326Sed s = spltty(); 553193326Sed KBD_DEACTIVATE(kbd); 554193326Sed splx(s); 555193326Sed return 0; 556193326Sed} 557193326Sed 558193326Sed/* read one byte from the keyboard if it's allowed */ 559193326Sedstatic int 560193326Sedatkbd_read(keyboard_t *kbd, int wait) 561193326Sed{ 562193326Sed int c; 563193326Sed 564193326Sed if (wait) 565193326Sed c = read_kbd_data(((atkbd_state_t *)kbd->kb_data)->kbdc); 566193326Sed else 567193326Sed c = read_kbd_data_no_wait(((atkbd_state_t *)kbd->kb_data)->kbdc); 568193326Sed if (c != -1) 569193326Sed ++kbd->kb_count; 570193326Sed return (KBD_IS_ACTIVE(kbd) ? c : -1); 571193326Sed} 572193326Sed 573193326Sed/* check if data is waiting */ 574193326Sedstatic int 575193326Sedatkbd_check(keyboard_t *kbd) 576193326Sed{ 577193326Sed if (!KBD_IS_ACTIVE(kbd)) 578193326Sed return FALSE; 579193326Sed return kbdc_data_ready(((atkbd_state_t *)kbd->kb_data)->kbdc); 580193326Sed} 581193326Sed 582193326Sed/* read char from the keyboard */ 583193326Sedstatic u_int 584193326Sedatkbd_read_char(keyboard_t *kbd, int wait) 585193326Sed{ 586193326Sed atkbd_state_t *state; 587193326Sed u_int action; 588193326Sed int scancode; 589193326Sed int keycode; 590193326Sed 591193326Sed state = (atkbd_state_t *)kbd->kb_data; 592193326Sednext_code: 593193326Sed /* do we have a composed char to return? */ 594193326Sed if (!(state->ks_flags & COMPOSE) && (state->ks_composed_char > 0)) { 595193326Sed action = state->ks_composed_char; 596193326Sed state->ks_composed_char = 0; 597193326Sed if (action > UCHAR_MAX) 598193326Sed return ERRKEY; 599193326Sed return action; 600193326Sed } 601193326Sed 602193326Sed /* see if there is something in the keyboard port */ 603193326Sed if (wait) { 604193326Sed do { 605193326Sed scancode = read_kbd_data(state->kbdc); 606193326Sed } while (scancode == -1); 607193326Sed } else { 608193326Sed scancode = read_kbd_data_no_wait(state->kbdc); 609193326Sed if (scancode == -1) 610193326Sed return NOKEY; 611193326Sed } 612193326Sed ++kbd->kb_count; 613193326Sed 614193326Sed#if KBDIO_DEBUG >= 10 615193326Sed printf("atkbd_read_char(): scancode:0x%x\n", scancode); 616193326Sed#endif 617193326Sed 618193326Sed /* return the byte as is for the K_RAW mode */ 619193326Sed if (state->ks_mode == K_RAW) 620193326Sed return scancode; 621193326Sed 622193326Sed /* translate the scan code into a keycode */ 623193326Sed keycode = scancode & 0x7F; 624193326Sed switch (state->ks_prefix) { 625193326Sed case 0x00: /* normal scancode */ 626193326Sed switch(scancode) { 627193326Sed case 0xB8: /* left alt (compose key) released */ 628193326Sed if (state->ks_flags & COMPOSE) { 629193326Sed state->ks_flags &= ~COMPOSE; 630193326Sed if (state->ks_composed_char > UCHAR_MAX) 631193326Sed state->ks_composed_char = 0; 632193326Sed } 633193326Sed break; 634193326Sed case 0x38: /* left alt (compose key) pressed */ 635193326Sed if (!(state->ks_flags & COMPOSE)) { 636193326Sed state->ks_flags |= COMPOSE; 637193326Sed state->ks_composed_char = 0; 638193326Sed } 639193326Sed break; 640193326Sed case 0xE0: 641193326Sed case 0xE1: 642193326Sed state->ks_prefix = scancode; 643193326Sed goto next_code; 644193326Sed } 645193326Sed break; 646193326Sed case 0xE0: /* 0xE0 prefix */ 647193326Sed state->ks_prefix = 0; 648193326Sed switch (keycode) { 649193326Sed case 0x1C: /* right enter key */ 650193326Sed keycode = 0x59; 651193326Sed break; 652193326Sed case 0x1D: /* right ctrl key */ 653193326Sed keycode = 0x5A; 654193326Sed break; 655195341Sed case 0x35: /* keypad divide key */ 656193326Sed keycode = 0x5B; 657195341Sed break; 658193326Sed case 0x37: /* print scrn key */ 659193326Sed keycode = 0x5C; 660193326Sed break; 661193326Sed case 0x38: /* right alt key (alt gr) */ 662193326Sed keycode = 0x5D; 663194711Sed break; 664194711Sed case 0x46: /* ctrl-pause/break on AT 101 (see below) */ 665194711Sed keycode = 0x68; 666193326Sed break; 667193326Sed case 0x47: /* grey home key */ 668193326Sed keycode = 0x5E; 669193326Sed break; 670193326Sed case 0x48: /* grey up arrow key */ 671193326Sed keycode = 0x5F; 672193326Sed break; 673193326Sed case 0x49: /* grey page up key */ 674193326Sed keycode = 0x60; 675193326Sed break; 676193326Sed case 0x4B: /* grey left arrow key */ 677193326Sed keycode = 0x61; 678193326Sed break; 679193326Sed case 0x4D: /* grey right arrow key */ 680193326Sed keycode = 0x62; 681193326Sed break; 682193326Sed case 0x4F: /* grey end key */ 683193326Sed keycode = 0x63; 684193326Sed break; 685193326Sed case 0x50: /* grey down arrow key */ 686193326Sed keycode = 0x64; 687193326Sed break; 688195341Sed case 0x51: /* grey page down key */ 689195341Sed keycode = 0x65; 690195341Sed break; 691195341Sed case 0x52: /* grey insert key */ 692195341Sed keycode = 0x66; 693195341Sed break; 694195341Sed case 0x53: /* grey delete key */ 695193326Sed keycode = 0x67; 696195341Sed break; 697193326Sed /* the following 3 are only used on the MS "Natural" keyboard */ 698195341Sed case 0x5b: /* left Window key */ 699195341Sed keycode = 0x69; 700195341Sed break; 701195341Sed case 0x5c: /* right Window key */ 702195341Sed keycode = 0x6a; 703193326Sed break; 704193326Sed case 0x5d: /* menu key */ 705195341Sed keycode = 0x6b; 706195341Sed break; 707193326Sed case 0x5e: /* power key */ 708193326Sed keycode = 0x6d; 709193326Sed break; 710193326Sed case 0x5f: /* sleep key */ 711193326Sed keycode = 0x6e; 712195341Sed break; 713193326Sed case 0x63: /* wake key */ 714193326Sed keycode = 0x6f; 715193326Sed break; 716193326Sed default: /* ignore everything else */ 717193326Sed goto next_code; 718193326Sed } 719193326Sed break; 720193326Sed case 0xE1: /* 0xE1 prefix */ 721193326Sed /* 722193326Sed * The pause/break key on the 101 keyboard produces: 723193326Sed * E1-1D-45 E1-9D-C5 724193326Sed * Ctrl-pause/break produces: 725193326Sed * E0-46 E0-C6 (See above.) 726193326Sed */ 727193326Sed state->ks_prefix = 0; 728193326Sed if (keycode == 0x1D) 729193326Sed state->ks_prefix = 0x1D; 730193326Sed goto next_code; 731193326Sed /* NOT REACHED */ 732193326Sed case 0x1D: /* pause / break */ 733193326Sed state->ks_prefix = 0; 734193326Sed if (keycode != 0x45) 735193326Sed goto next_code; 736193326Sed keycode = 0x68; 737193326Sed break; 738193326Sed } 739193326Sed 740193326Sed if (kbd->kb_type == KB_84) { 741193326Sed switch (keycode) { 742193326Sed case 0x37: /* *(numpad)/print screen */ 743193326Sed if (state->ks_flags & SHIFTS) 744193326Sed keycode = 0x5c; /* print screen */ 745193326Sed break; 746193326Sed case 0x45: /* num lock/pause */ 747193326Sed if (state->ks_flags & CTLS) 748193326Sed keycode = 0x68; /* pause */ 749193326Sed break; 750193326Sed case 0x46: /* scroll lock/break */ 751193326Sed if (state->ks_flags & CTLS) 752193326Sed keycode = 0x6c; /* break */ 753193326Sed break; 754193326Sed } 755193326Sed } else if (kbd->kb_type == KB_101) { 756193326Sed switch (keycode) { 757193326Sed case 0x5c: /* print screen */ 758193326Sed if (state->ks_flags & ALTS) 759193326Sed keycode = 0x54; /* sysrq */ 760193326Sed break; 761193326Sed case 0x68: /* pause/break */ 762193326Sed if (state->ks_flags & CTLS) 763195341Sed keycode = 0x6c; /* break */ 764195341Sed break; 765195341Sed } 766195341Sed } 767195341Sed 768195341Sed /* return the key code in the K_CODE mode */ 769195341Sed if (state->ks_mode == K_CODE) 770195341Sed return (keycode | (scancode & 0x80)); 771195341Sed 772193326Sed /* compose a character code */ 773195341Sed if (state->ks_flags & COMPOSE) { 774195341Sed switch (keycode | (scancode & 0x80)) { 775193326Sed /* key pressed, process it */ 776193326Sed case 0x47: case 0x48: case 0x49: /* keypad 7,8,9 */ 777193326Sed state->ks_composed_char *= 10; 778193326Sed state->ks_composed_char += keycode - 0x40; 779193326Sed if (state->ks_composed_char > UCHAR_MAX) 780194711Sed return ERRKEY; 781194711Sed goto next_code; 782193326Sed case 0x4B: case 0x4C: case 0x4D: /* keypad 4,5,6 */ 783194711Sed state->ks_composed_char *= 10; 784194711Sed state->ks_composed_char += keycode - 0x47; 785194711Sed if (state->ks_composed_char > UCHAR_MAX) 786193326Sed return ERRKEY; 787193326Sed goto next_code; 788193326Sed case 0x4F: case 0x50: case 0x51: /* keypad 1,2,3 */ 789193326Sed state->ks_composed_char *= 10; 790195341Sed state->ks_composed_char += keycode - 0x4E; 791195341Sed if (state->ks_composed_char > UCHAR_MAX) 792195341Sed return ERRKEY; 793195341Sed goto next_code; 794195341Sed case 0x52: /* keypad 0 */ 795195341Sed state->ks_composed_char *= 10; 796195341Sed if (state->ks_composed_char > UCHAR_MAX) 797195341Sed return ERRKEY; 798195341Sed goto next_code; 799195341Sed 800195341Sed /* key released, no interest here */ 801195341Sed case 0xC7: case 0xC8: case 0xC9: /* keypad 7,8,9 */ 802195341Sed case 0xCB: case 0xCC: case 0xCD: /* keypad 4,5,6 */ 803195341Sed case 0xCF: case 0xD0: case 0xD1: /* keypad 1,2,3 */ 804195341Sed case 0xD2: /* keypad 0 */ 805195341Sed goto next_code; 806195341Sed 807195341Sed case 0x38: /* left alt key */ 808195341Sed break; 809195341Sed 810195341Sed default: 811195341Sed if (state->ks_composed_char > 0) { 812195341Sed state->ks_flags &= ~COMPOSE; 813195341Sed state->ks_composed_char = 0; 814195341Sed return ERRKEY; 815195341Sed } 816195341Sed break; 817195341Sed } 818195341Sed } 819195341Sed 820195341Sed /* keycode to key action */ 821195341Sed action = genkbd_keyaction(kbd, keycode, scancode & 0x80, 822195341Sed &state->ks_state, &state->ks_accents); 823195341Sed if (action == NOKEY) 824195341Sed goto next_code; 825195341Sed else 826193326Sed return action; 827193326Sed} 828193326Sed 829193326Sed/* check if char is waiting */ 830193326Sedstatic int 831193326Sedatkbd_check_char(keyboard_t *kbd) 832193326Sed{ 833193326Sed atkbd_state_t *state; 834193326Sed 835193326Sed if (!KBD_IS_ACTIVE(kbd)) 836193326Sed return FALSE; 837193326Sed state = (atkbd_state_t *)kbd->kb_data; 838193326Sed if (!(state->ks_flags & COMPOSE) && (state->ks_composed_char > 0)) 839193326Sed return TRUE; 840193326Sed return kbdc_data_ready(state->kbdc); 841193326Sed} 842193326Sed 843193326Sed/* some useful control functions */ 844193326Sedstatic int 845193326Sedatkbd_ioctl(keyboard_t *kbd, u_long cmd, caddr_t arg) 846193326Sed{ 847193326Sed /* translate LED_XXX bits into the device specific bits */ 848193326Sed static u_char ledmap[8] = { 849193326Sed 0, 4, 2, 6, 1, 5, 3, 7, 850193326Sed }; 851193326Sed atkbd_state_t *state = kbd->kb_data; 852193326Sed int error; 853193326Sed int s; 854193326Sed int i; 855193326Sed#if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5) || \ 856193326Sed defined(COMPAT_FREEBSD4) || defined(COMPAT_43) 857193326Sed int ival; 858193326Sed#endif 859193326Sed 860193326Sed s = spltty(); 861193326Sed switch (cmd) { 862193326Sed 863193326Sed case KDGKBMODE: /* get keyboard mode */ 864193326Sed *(int *)arg = state->ks_mode; 865193326Sed break; 866193326Sed#if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5) || \ 867193326Sed defined(COMPAT_FREEBSD4) || defined(COMPAT_43) 868193326Sed case _IO('K', 7): 869193326Sed ival = IOCPARM_IVAL(arg); 870193326Sed arg = (caddr_t)&ival; 871193326Sed /* FALLTHROUGH */ 872193326Sed#endif 873193326Sed case KDSKBMODE: /* set keyboard mode */ 874193326Sed switch (*(int *)arg) { 875193326Sed case K_XLATE: 876193326Sed if (state->ks_mode != K_XLATE) { 877193326Sed /* make lock key state and LED state match */ 878193326Sed state->ks_state &= ~LOCK_MASK; 879193326Sed state->ks_state |= KBD_LED_VAL(kbd); 880193326Sed } 881195341Sed /* FALLTHROUGH */ 882193326Sed case K_RAW: 883193326Sed case K_CODE: 884193326Sed if (state->ks_mode != *(int *)arg) { 885193326Sed atkbd_clear_state(kbd); 886193326Sed state->ks_mode = *(int *)arg; 887193326Sed } 888193326Sed break; 889193326Sed default: 890193326Sed splx(s); 891193326Sed return EINVAL; 892193326Sed } 893193326Sed break; 894193326Sed 895193326Sed case KDGETLED: /* get keyboard LED */ 896193326Sed *(int *)arg = KBD_LED_VAL(kbd); 897193326Sed break; 898193326Sed#if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5) || \ 899193326Sed defined(COMPAT_FREEBSD4) || defined(COMPAT_43) 900193326Sed case _IO('K', 66): 901193326Sed ival = IOCPARM_IVAL(arg); 902193326Sed arg = (caddr_t)&ival; 903193326Sed /* FALLTHROUGH */ 904193326Sed#endif 905193326Sed case KDSETLED: /* set keyboard LED */ 906193326Sed /* NOTE: lock key state in ks_state won't be changed */ 907193326Sed if (*(int *)arg & ~LOCK_MASK) { 908193326Sed splx(s); 909193326Sed return EINVAL; 910193326Sed } 911193326Sed i = *(int *)arg; 912193326Sed /* replace CAPS LED with ALTGR LED for ALTGR keyboards */ 913193326Sed if (state->ks_mode == K_XLATE && 914193326Sed kbd->kb_keymap->n_keys > ALTGR_OFFSET) { 915193326Sed if (i & ALKED) 916193326Sed i |= CLKED; 917193326Sed else 918193326Sed i &= ~CLKED; 919193326Sed } 920193326Sed if (KBD_HAS_DEVICE(kbd)) { 921193326Sed error = write_kbd(state->kbdc, KBDC_SET_LEDS, 922193326Sed ledmap[i & LED_MASK]); 923193326Sed if (error) { 924193326Sed splx(s); 925193326Sed return error; 926193326Sed } 927193326Sed } 928193326Sed KBD_LED_VAL(kbd) = *(int *)arg; 929193326Sed break; 930193326Sed 931193326Sed case KDGKBSTATE: /* get lock key state */ 932193326Sed *(int *)arg = state->ks_state & LOCK_MASK; 933193326Sed break; 934193326Sed#if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5) || \ 935193326Sed defined(COMPAT_FREEBSD4) || defined(COMPAT_43) 936193326Sed case _IO('K', 20): 937193326Sed ival = IOCPARM_IVAL(arg); 938193326Sed arg = (caddr_t)&ival; 939193326Sed /* FALLTHROUGH */ 940193326Sed#endif 941193326Sed case KDSKBSTATE: /* set lock key state */ 942193326Sed if (*(int *)arg & ~LOCK_MASK) { 943193326Sed splx(s); 944193326Sed return EINVAL; 945193326Sed } 946193326Sed state->ks_state &= ~LOCK_MASK; 947193326Sed state->ks_state |= *(int *)arg; 948193326Sed splx(s); 949193326Sed /* set LEDs and quit */ 950193326Sed return atkbd_ioctl(kbd, KDSETLED, arg); 951193326Sed 952193326Sed case KDSETREPEAT: /* set keyboard repeat rate (new interface) */ 953193326Sed splx(s); 954193326Sed if (!KBD_HAS_DEVICE(kbd)) 955193326Sed return 0; 956193326Sed i = typematic(((int *)arg)[0], ((int *)arg)[1]); 957193326Sed error = write_kbd(state->kbdc, KBDC_SET_TYPEMATIC, i); 958193326Sed if (error == 0) { 959193326Sed kbd->kb_delay1 = typematic_delay(i); 960193326Sed kbd->kb_delay2 = typematic_rate(i); 961193326Sed } 962193326Sed return error; 963193326Sed 964193326Sed#if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5) || \ 965193326Sed defined(COMPAT_FREEBSD4) || defined(COMPAT_43) 966193326Sed case _IO('K', 67): 967193326Sed ival = IOCPARM_IVAL(arg); 968193326Sed arg = (caddr_t)&ival; 969193326Sed /* FALLTHROUGH */ 970193326Sed#endif 971193326Sed case KDSETRAD: /* set keyboard repeat rate (old interface) */ 972193326Sed splx(s); 973193326Sed if (!KBD_HAS_DEVICE(kbd)) 974193326Sed return 0; 975193326Sed error = write_kbd(state->kbdc, KBDC_SET_TYPEMATIC, *(int *)arg); 976193326Sed if (error == 0) { 977193326Sed kbd->kb_delay1 = typematic_delay(*(int *)arg); 978195341Sed kbd->kb_delay2 = typematic_rate(*(int *)arg); 979195341Sed } 980193326Sed return error; 981193326Sed 982193326Sed case PIO_KEYMAP: /* set keyboard translation table */ 983193326Sed case PIO_KEYMAPENT: /* set keyboard translation table entry */ 984193326Sed case PIO_DEADKEYMAP: /* set accent key translation table */ 985193326Sed state->ks_accents = 0; 986193326Sed /* FALLTHROUGH */ 987193326Sed default: 988193326Sed splx(s); 989193326Sed return genkbd_commonioctl(kbd, cmd, arg); 990193326Sed } 991193326Sed 992193326Sed splx(s); 993193326Sed return 0; 994193326Sed} 995193326Sed 996193326Sed/* lock the access to the keyboard */ 997193326Sedstatic int 998193326Sedatkbd_lock(keyboard_t *kbd, int lock) 999193326Sed{ 1000193326Sed return kbdc_lock(((atkbd_state_t *)kbd->kb_data)->kbdc, lock); 1001193326Sed} 1002193326Sed 1003193326Sed/* clear the internal state of the keyboard */ 1004193326Sedstatic void 1005193326Sedatkbd_clear_state(keyboard_t *kbd) 1006193326Sed{ 1007193326Sed atkbd_state_t *state; 1008193326Sed 1009193326Sed state = (atkbd_state_t *)kbd->kb_data; 1010193326Sed state->ks_flags = 0; 1011193326Sed state->ks_polling = 0; 1012193326Sed state->ks_state &= LOCK_MASK; /* preserve locking key state */ 1013193326Sed state->ks_accents = 0; 1014193326Sed state->ks_composed_char = 0; 1015193326Sed#if 0 1016193326Sed state->ks_prefix = 0; /* XXX */ 1017193326Sed#endif 1018193326Sed} 1019193326Sed 1020193326Sed/* save the internal state */ 1021193326Sedstatic int 1022193326Sedatkbd_get_state(keyboard_t *kbd, void *buf, size_t len) 1023193326Sed{ 1024193326Sed if (len == 0) 1025193326Sed return sizeof(atkbd_state_t); 1026193326Sed if (len < sizeof(atkbd_state_t)) 1027193326Sed return -1; 1028193326Sed bcopy(kbd->kb_data, buf, sizeof(atkbd_state_t)); 1029193326Sed return 0; 1030193326Sed} 1031193326Sed 1032193326Sed/* set the internal state */ 1033193326Sedstatic int 1034194711Sedatkbd_set_state(keyboard_t *kbd, void *buf, size_t len) 1035194711Sed{ 1036194711Sed if (len < sizeof(atkbd_state_t)) 1037193326Sed return ENOMEM; 1038193326Sed if (((atkbd_state_t *)kbd->kb_data)->kbdc 1039193326Sed != ((atkbd_state_t *)buf)->kbdc) 1040193326Sed return ENOMEM; 1041193326Sed bcopy(buf, kbd->kb_data, sizeof(atkbd_state_t)); 1042193326Sed return 0; 1043193326Sed} 1044193326Sed 1045193326Sedstatic int 1046193326Sedatkbd_poll(keyboard_t *kbd, int on) 1047193326Sed{ 1048193326Sed atkbd_state_t *state; 1049193326Sed int s; 1050193326Sed 1051193326Sed state = (atkbd_state_t *)kbd->kb_data; 1052193326Sed s = spltty(); 1053193326Sed if (on) 1054193326Sed ++state->ks_polling; 1055195341Sed else 1056195341Sed --state->ks_polling; 1057193326Sed splx(s); 1058193326Sed return 0; 1059193326Sed} 1060193326Sed 1061193326Sedstatic void 1062193326Sedatkbd_shutdown_final(void *v) 1063193326Sed{ 1064193326Sed#ifdef __sparc64__ 1065193326Sed keyboard_t *kbd = v; 1066193326Sed KBDC kbdc = ((atkbd_state_t *)kbd->kb_data)->kbdc; 1067193326Sed 1068193326Sed /* 1069193326Sed * Turn off the translation in preparation for handing the keyboard 1070193326Sed * over to the OFW as the OBP driver doesn't use translation and 1071193326Sed * also doesn't disable it itself resulting in a broken keymap at 1072193326Sed * the boot prompt. Also disable the aux port and the interrupts as 1073193326Sed * the OBP driver doesn't use them, i.e. polls the keyboard. Not 1074193326Sed * disabling the interrupts doesn't cause real problems but the 1075193326Sed * responsiveness is a bit better when they are turned off. 1076193326Sed */ 1077193326Sed send_kbd_command(kbdc, KBDC_DISABLE_KBD); 1078193326Sed set_controller_command_byte(kbdc, 1079193326Sed KBD_AUX_CONTROL_BITS | KBD_KBD_CONTROL_BITS | KBD_TRANSLATION, 1080193326Sed KBD_DISABLE_AUX_PORT | KBD_DISABLE_KBD_INT | KBD_ENABLE_KBD_PORT); 1081193326Sed send_kbd_command(kbdc, KBDC_ENABLE_KBD); 1082193326Sed#endif 1083193326Sed} 1084193326Sed 1085193326Sed/* local functions */ 1086193326Sed 1087193326Sedstatic int 1088193326Sedget_typematic(keyboard_t *kbd) 1089193326Sed{ 1090193326Sed#ifdef __i386__ 1091193326Sed /* 1092193326Sed * Only some systems allow us to retrieve the keyboard repeat 1093193326Sed * rate previously set via the BIOS... 1094193326Sed */ 1095193326Sed struct vm86frame vmf; 1096193326Sed u_int32_t p; 1097193326Sed 1098193326Sed bzero(&vmf, sizeof(vmf)); 1099193326Sed vmf.vmf_ax = 0xc000; 1100193326Sed vm86_intcall(0x15, &vmf); 1101193326Sed if ((vmf.vmf_eflags & PSL_C) || vmf.vmf_ah) 1102193326Sed return ENODEV; 1103193326Sed p = BIOS_PADDRTOVADDR(((u_int32_t)vmf.vmf_es << 4) + vmf.vmf_bx); 1104193326Sed if ((readb(p + 6) & 0x40) == 0) /* int 16, function 0x09 supported? */ 1105193326Sed return ENODEV; 1106193326Sed vmf.vmf_ax = 0x0900; 1107193326Sed vm86_intcall(0x16, &vmf); 1108193326Sed if ((vmf.vmf_al & 0x08) == 0) /* int 16, function 0x0306 supported? */ 1109193326Sed return ENODEV; 1110193326Sed vmf.vmf_ax = 0x0306; 1111193326Sed vm86_intcall(0x16, &vmf); 1112193326Sed kbd->kb_delay1 = typematic_delay(vmf.vmf_bh << 5); 1113195341Sed kbd->kb_delay2 = typematic_rate(vmf.vmf_bl); 1114193326Sed return 0; 1115193326Sed#else 1116193326Sed return ENODEV; 1117193326Sed#endif /* __i386__ */ 1118193326Sed} 1119193326Sed 1120193326Sedstatic int 1121193326Sedsetup_kbd_port(KBDC kbdc, int port, int intr) 1122193326Sed{ 1123193326Sed if (!set_controller_command_byte(kbdc, 1124193326Sed KBD_KBD_CONTROL_BITS, 1125193326Sed ((port) ? KBD_ENABLE_KBD_PORT : KBD_DISABLE_KBD_PORT) 1126193326Sed | ((intr) ? KBD_ENABLE_KBD_INT : KBD_DISABLE_KBD_INT))) 1127193326Sed return 1; 1128193326Sed return 0; 1129193326Sed} 1130193326Sed 1131193326Sedstatic int 1132193326Sedget_kbd_echo(KBDC kbdc) 1133193326Sed{ 1134193326Sed /* enable the keyboard port, but disable the keyboard intr. */ 1135193326Sed if (setup_kbd_port(kbdc, TRUE, FALSE)) 1136193326Sed /* CONTROLLER ERROR: there is very little we can do... */ 1137193326Sed return ENXIO; 1138193326Sed 1139193326Sed /* see if something is present */ 1140193326Sed write_kbd_command(kbdc, KBDC_ECHO); 1141193326Sed if (read_kbd_data(kbdc) != KBD_ECHO) { 1142193326Sed empty_both_buffers(kbdc, 10); 1143193326Sed test_controller(kbdc); 1144193326Sed test_kbd_port(kbdc); 1145195341Sed return ENXIO; 1146195341Sed } 1147193326Sed 1148193326Sed /* enable the keyboard port and intr. */ 1149193326Sed if (setup_kbd_port(kbdc, TRUE, TRUE)) { 1150193326Sed /* 1151193326Sed * CONTROLLER ERROR 1152193326Sed * This is serious; the keyboard intr is left disabled! 1153193326Sed */ 1154193326Sed return ENXIO; 1155193326Sed } 1156193326Sed 1157193326Sed return 0; 1158193326Sed} 1159193326Sed 1160193326Sedstatic int 1161193326Sedprobe_keyboard(KBDC kbdc, int flags) 1162193326Sed{ 1163193326Sed /* 1164193326Sed * Don't try to print anything in this function. The low-level 1165193326Sed * console may not have been initialized yet... 1166193326Sed */ 1167193326Sed int err; 1168193326Sed int c; 1169193326Sed int m; 1170193326Sed 1171193326Sed if (!kbdc_lock(kbdc, TRUE)) { 1172193326Sed /* driver error? */ 1173193326Sed return ENXIO; 1174193326Sed } 1175193326Sed 1176193326Sed /* temporarily block data transmission from the keyboard */ 1177193326Sed write_controller_command(kbdc, KBDC_DISABLE_KBD_PORT); 1178193326Sed 1179193326Sed /* flush any noise in the buffer */ 1180193326Sed empty_both_buffers(kbdc, 100); 1181193326Sed 1182193326Sed /* save the current keyboard controller command byte */ 1183193326Sed m = kbdc_get_device_mask(kbdc) & ~KBD_KBD_CONTROL_BITS; 1184193326Sed c = get_controller_command_byte(kbdc); 1185193326Sed if (c == -1) { 1186193326Sed /* CONTROLLER ERROR */ 1187193326Sed kbdc_set_device_mask(kbdc, m); 1188193326Sed kbdc_lock(kbdc, FALSE); 1189193326Sed return ENXIO; 1190195341Sed } 1191193326Sed 1192193326Sed /* 1193193326Sed * The keyboard may have been screwed up by the boot block. 1194193326Sed * We may just be able to recover from error by testing the controller 1195193326Sed * and the keyboard port. The controller command byte needs to be 1196193326Sed * saved before this recovery operation, as some controllers seem 1197193326Sed * to set the command byte to particular values. 1198193326Sed */ 1199193326Sed test_controller(kbdc); 1200193326Sed if (!(flags & KB_CONF_NO_PROBE_TEST)) 1201193326Sed test_kbd_port(kbdc); 1202193326Sed 1203193326Sed err = get_kbd_echo(kbdc); 1204193326Sed 1205193326Sed /* 1206193326Sed * Even if the keyboard doesn't seem to be present (err != 0), 1207193326Sed * we shall enable the keyboard port and interrupt so that 1208193326Sed * the driver will be operable when the keyboard is attached 1209193326Sed * to the system later. It is NOT recommended to hot-plug 1210193326Sed * the AT keyboard, but many people do so... 1211193326Sed */ 1212193326Sed kbdc_set_device_mask(kbdc, m | KBD_KBD_CONTROL_BITS); 1213193326Sed setup_kbd_port(kbdc, TRUE, TRUE); 1214193326Sed#if 0 1215193326Sed if (err == 0) { 1216193326Sed kbdc_set_device_mask(kbdc, m | KBD_KBD_CONTROL_BITS); 1217193326Sed } else { 1218193326Sed /* try to restore the command byte as before */ 1219193326Sed set_controller_command_byte(kbdc, 0xff, c); 1220193326Sed kbdc_set_device_mask(kbdc, m); 1221193326Sed } 1222193326Sed#endif 1223193326Sed 1224195341Sed kbdc_lock(kbdc, FALSE); 1225195341Sed return err; 1226193326Sed} 1227193326Sed 1228193326Sedstatic int 1229193326Sedinit_keyboard(KBDC kbdc, int *type, int flags) 1230193326Sed{ 1231193326Sed int codeset; 1232193326Sed int id; 1233193326Sed int c; 1234193326Sed 1235193326Sed if (!kbdc_lock(kbdc, TRUE)) { 1236193326Sed /* driver error? */ 1237193326Sed return EIO; 1238193326Sed } 1239193326Sed 1240193326Sed /* temporarily block data transmission from the keyboard */ 1241193326Sed write_controller_command(kbdc, KBDC_DISABLE_KBD_PORT); 1242193326Sed 1243193326Sed /* save the current controller command byte */ 1244193326Sed empty_both_buffers(kbdc, 200); 1245193326Sed c = get_controller_command_byte(kbdc); 1246193326Sed if (c == -1) { 1247193326Sed /* CONTROLLER ERROR */ 1248193326Sed kbdc_lock(kbdc, FALSE); 1249193326Sed printf("atkbd: unable to get the current command byte value.\n"); 1250193326Sed return EIO; 1251193326Sed } 1252193326Sed if (bootverbose) 1253193326Sed printf("atkbd: the current kbd controller command byte %04x\n", 1254193326Sed c); 1255193326Sed#if 0 1256193326Sed /* override the keyboard lock switch */ 1257193326Sed c |= KBD_OVERRIDE_KBD_LOCK; 1258193326Sed#endif 1259193326Sed 1260193326Sed /* enable the keyboard port, but disable the keyboard intr. */ 1261193326Sed if (setup_kbd_port(kbdc, TRUE, FALSE)) { 1262193326Sed /* CONTROLLER ERROR: there is very little we can do... */ 1263193326Sed printf("atkbd: unable to set the command byte.\n"); 1264193326Sed kbdc_lock(kbdc, FALSE); 1265193326Sed return EIO; 1266193326Sed } 1267193326Sed 1268193326Sed /* 1269195341Sed * Check if we have an XT keyboard before we attempt to reset it. 1270193326Sed * The procedure assumes that the keyboard and the controller have 1271193326Sed * been set up properly by BIOS and have not been messed up 1272193326Sed * during the boot process. 1273193326Sed */ 1274193326Sed codeset = -1; 1275193326Sed if (flags & KB_CONF_ALT_SCANCODESET) 1276193326Sed /* the user says there is a XT keyboard */ 1277193326Sed codeset = 1; 1278193326Sed#ifdef KBD_DETECT_XT_KEYBOARD 1279193326Sed else if ((c & KBD_TRANSLATION) == 0) { 1280193326Sed /* SET_SCANCODE_SET is not always supported; ignore error */ 1281193326Sed if (send_kbd_command_and_data(kbdc, KBDC_SET_SCANCODE_SET, 0) 1282193326Sed == KBD_ACK) 1283193326Sed codeset = read_kbd_data(kbdc); 1284193326Sed } 1285193326Sed if (bootverbose) 1286193326Sed printf("atkbd: scancode set %d\n", codeset); 1287193326Sed#endif /* KBD_DETECT_XT_KEYBOARD */ 1288195341Sed 1289193326Sed *type = KB_OTHER; 1290193326Sed id = get_kbd_id(kbdc); 1291193326Sed switch(id) { 1292193326Sed case 0x41ab: /* 101/102/... Enhanced */ 1293193326Sed case 0x83ab: /* ditto */ 1294193326Sed case 0x54ab: /* SpaceSaver */ 1295193326Sed case 0x84ab: /* ditto */ 1296193326Sed#if 0 1297193326Sed case 0x90ab: /* 'G' */ 1298193326Sed case 0x91ab: /* 'P' */ 1299193326Sed case 0x92ab: /* 'A' */ 1300193326Sed#endif 1301193326Sed *type = KB_101; 1302193326Sed break; 1303193326Sed case -1: /* AT 84 keyboard doesn't return ID */ 1304193326Sed *type = KB_84; 1305193326Sed break; 1306193326Sed default: 1307193326Sed break; 1308193326Sed } 1309193326Sed if (bootverbose) 1310193326Sed printf("atkbd: keyboard ID 0x%x (%d)\n", id, *type); 1311193326Sed 1312193326Sed /* reset keyboard hardware */ 1313193326Sed if (!(flags & KB_CONF_NO_RESET) && !reset_kbd(kbdc)) { 1314193326Sed /* 1315193326Sed * KEYBOARD ERROR 1316193326Sed * Keyboard reset may fail either because the keyboard 1317193326Sed * doen't exist, or because the keyboard doesn't pass 1318194711Sed * the self-test, or the keyboard controller on the 1319194711Sed * motherboard and the keyboard somehow fail to shake hands. 1320194711Sed * It is just possible, particularly in the last case, 1321193326Sed * that the keyboard controller may be left in a hung state. 1322193326Sed * test_controller() and test_kbd_port() appear to bring 1323193326Sed * the keyboard controller back (I don't know why and how, 1324193326Sed * though.) 1325193326Sed */ 1326193326Sed empty_both_buffers(kbdc, 10); 1327193326Sed test_controller(kbdc); 1328193326Sed test_kbd_port(kbdc); 1329193326Sed /* 1330193326Sed * We could disable the keyboard port and interrupt... but, 1331193326Sed * the keyboard may still exist (see above). 1332193326Sed */ 1333193326Sed set_controller_command_byte(kbdc, 0xff, c); 1334193326Sed kbdc_lock(kbdc, FALSE); 1335193326Sed if (bootverbose) 1336194711Sed printf("atkbd: failed to reset the keyboard.\n"); 1337194711Sed return EIO; 1338194711Sed } 1339193326Sed 1340193326Sed /* 1341193326Sed * Allow us to set the XT_KEYBD flag so that keyboards 1342193326Sed * such as those on the IBM ThinkPad laptop computers can be used 1343193326Sed * with the standard console driver. 1344193326Sed */ 1345193326Sed if (codeset == 1) { 1346193326Sed if (send_kbd_command_and_data(kbdc, 1347193326Sed KBDC_SET_SCANCODE_SET, codeset) == KBD_ACK) { 1348193326Sed /* XT kbd doesn't need scan code translation */ 1349193326Sed c &= ~KBD_TRANSLATION; 1350193326Sed } else { 1351193326Sed /* 1352193326Sed * KEYBOARD ERROR 1353193326Sed * The XT kbd isn't usable unless the proper scan 1354193326Sed * code set is selected. 1355193326Sed */ 1356193326Sed set_controller_command_byte(kbdc, 0xff, c); 1357193326Sed kbdc_lock(kbdc, FALSE); 1358194711Sed printf("atkbd: unable to set the XT keyboard mode.\n"); 1359194711Sed return EIO; 1360194711Sed } 1361193326Sed } 1362193326Sed 1363193326Sed#if defined(__sparc64__) 1364193326Sed if (send_kbd_command_and_data( 1365193326Sed kbdc, KBDC_SET_SCANCODE_SET, 2) != KBD_ACK) { 1366193326Sed printf("atkbd: can't set translation.\n"); 1367193326Sed } 1368193326Sed c |= KBD_TRANSLATION; 1369193326Sed#endif 1370193326Sed 1371193326Sed /* enable the keyboard port and intr. */ 1372193326Sed if (!set_controller_command_byte(kbdc, 1373193326Sed KBD_KBD_CONTROL_BITS | KBD_TRANSLATION | KBD_OVERRIDE_KBD_LOCK, 1374193326Sed (c & (KBD_TRANSLATION | KBD_OVERRIDE_KBD_LOCK)) 1375193326Sed | KBD_ENABLE_KBD_PORT | KBD_ENABLE_KBD_INT)) { 1376193326Sed /* 1377193326Sed * CONTROLLER ERROR 1378193326Sed * This is serious; we are left with the disabled 1379193326Sed * keyboard intr. 1380193326Sed */ 1381193326Sed set_controller_command_byte(kbdc, 0xff, c); 1382193326Sed kbdc_lock(kbdc, FALSE); 1383193326Sed printf("atkbd: unable to enable the keyboard port and intr.\n"); 1384193326Sed return EIO; 1385193326Sed } 1386193326Sed 1387193326Sed kbdc_lock(kbdc, FALSE); 1388193326Sed return 0; 1389193326Sed} 1390193326Sed 1391193326Sedstatic int 1392193326Sedwrite_kbd(KBDC kbdc, int command, int data) 1393193326Sed{ 1394193326Sed int s; 1395193326Sed 1396193326Sed /* prevent the timeout routine from polling the keyboard */ 1397193326Sed if (!kbdc_lock(kbdc, TRUE)) 1398193326Sed return EBUSY; 1399193326Sed 1400193326Sed /* disable the keyboard and mouse interrupt */ 1401193326Sed s = spltty(); 1402193326Sed#if 0 1403193326Sed c = get_controller_command_byte(kbdc); 1404193326Sed if ((c == -1) 1405193326Sed || !set_controller_command_byte(kbdc, 1406193326Sed kbdc_get_device_mask(kbdc), 1407193326Sed KBD_DISABLE_KBD_PORT | KBD_DISABLE_KBD_INT 1408193326Sed | KBD_DISABLE_AUX_PORT | KBD_DISABLE_AUX_INT)) { 1409193326Sed /* CONTROLLER ERROR */ 1410193326Sed kbdc_lock(kbdc, FALSE); 1411193326Sed splx(s); 1412193326Sed return EIO; 1413193326Sed } 1414193326Sed /* 1415193326Sed * Now that the keyboard controller is told not to generate 1416193326Sed * the keyboard and mouse interrupts, call `splx()' to allow 1417193326Sed * the other tty interrupts. The clock interrupt may also occur, 1418193326Sed * but the timeout routine (`scrn_timer()') will be blocked 1419193326Sed * by the lock flag set via `kbdc_lock()' 1420193326Sed */ 1421193326Sed splx(s); 1422193326Sed#endif 1423193326Sed 1424193326Sed if (send_kbd_command_and_data(kbdc, command, data) != KBD_ACK) 1425193326Sed send_kbd_command(kbdc, KBDC_ENABLE_KBD); 1426193326Sed 1427193326Sed#if 0 1428193326Sed /* restore the interrupts */ 1429193326Sed if (!set_controller_command_byte(kbdc, 1430193326Sed kbdc_get_device_mask(kbdc), 1431193326Sed c & (KBD_KBD_CONTROL_BITS | KBD_AUX_CONTROL_BITS))) { 1432193326Sed /* CONTROLLER ERROR */ 1433193326Sed } 1434193326Sed#else 1435193326Sed splx(s); 1436193326Sed#endif 1437193326Sed kbdc_lock(kbdc, FALSE); 1438193326Sed 1439193326Sed return 0; 1440193326Sed} 1441193326Sed 1442193326Sedstatic int 1443193326Sedget_kbd_id(KBDC kbdc) 1444193326Sed{ 1445193326Sed int id1, id2; 1446193326Sed 1447193326Sed empty_both_buffers(kbdc, 10); 1448193326Sed id1 = id2 = -1; 1449193326Sed if (send_kbd_command(kbdc, KBDC_SEND_DEV_ID) != KBD_ACK) 1450193326Sed return -1; 1451193326Sed 1452193326Sed DELAY(10000); /* 10 msec delay */ 1453193576Sed id1 = read_kbd_data(kbdc); 1454193326Sed if (id1 != -1) 1455193326Sed id2 = read_kbd_data(kbdc); 1456193326Sed 1457193326Sed if ((id1 == -1) || (id2 == -1)) { 1458193326Sed empty_both_buffers(kbdc, 10); 1459193326Sed test_controller(kbdc); 1460193326Sed test_kbd_port(kbdc); 1461193326Sed return -1; 1462193326Sed } 1463193326Sed return ((id2 << 8) | id1); 1464193326Sed} 1465193326Sed 1466193326Sedstatic int delays[] = { 250, 500, 750, 1000 }; 1467193326Sedstatic int rates[] = { 34, 38, 42, 46, 50, 55, 59, 63, 1468193326Sed 68, 76, 84, 92, 100, 110, 118, 126, 1469193326Sed 136, 152, 168, 184, 200, 220, 236, 252, 1470193326Sed 272, 304, 336, 368, 400, 440, 472, 504 }; 1471193326Sed 1472193326Sedstatic int 1473193326Sedtypematic_delay(int i) 1474193326Sed{ 1475193326Sed return delays[(i >> 5) & 3]; 1476193326Sed} 1477193326Sed 1478193326Sedstatic int 1479193326Sedtypematic_rate(int i) 1480193326Sed{ 1481193326Sed return rates[i & 0x1f]; 1482193326Sed} 1483193326Sed 1484193326Sedstatic int 1485193326Sedtypematic(int delay, int rate) 1486193326Sed{ 1487193326Sed int value; 1488193326Sed int i; 1489193326Sed 1490193326Sed for (i = sizeof(delays)/sizeof(delays[0]) - 1; i > 0; --i) { 1491193326Sed if (delay >= delays[i]) 1492193326Sed break; 1493193326Sed } 1494193326Sed value = i << 5; 1495193326Sed for (i = sizeof(rates)/sizeof(rates[0]) - 1; i > 0; --i) { 1496193326Sed if (rate >= rates[i]) 1497193326Sed break; 1498193326Sed } 1499193326Sed value |= i; 1500193326Sed return value; 1501193326Sed} 1502193326Sed