atkbd.c revision 158041
142421Syokota/*- 242421Syokota * Copyright (c) 1999 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp> 342421Syokota * All rights reserved. 442421Syokota * 542421Syokota * Redistribution and use in source and binary forms, with or without 642421Syokota * modification, are permitted provided that the following conditions 742421Syokota * are met: 842421Syokota * 1. Redistributions of source code must retain the above copyright 942421Syokota * notice, this list of conditions and the following disclaimer as 1042421Syokota * the first lines of this file unmodified. 1142421Syokota * 2. Redistributions in binary form must reproduce the above copyright 1242421Syokota * notice, this list of conditions and the following disclaimer in the 1342421Syokota * documentation and/or other materials provided with the distribution. 1442421Syokota * 1542421Syokota * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR 1642421Syokota * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1742421Syokota * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 1842421Syokota * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, 1942421Syokota * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2042421Syokota * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2142421Syokota * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2242421Syokota * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2342421Syokota * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2442421Syokota * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2542421Syokota * 2642421Syokota */ 2742421Syokota 28119418Sobrien#include <sys/cdefs.h> 29119418Sobrien__FBSDID("$FreeBSD: head/sys/dev/atkbdc/atkbd.c 158041 2006-04-26 06:05:16Z sobomax $"); 30119418Sobrien 3142421Syokota#include "opt_kbd.h" 3244628Syokota#include "opt_atkbd.h" 3342421Syokota 3442421Syokota#include <sys/param.h> 3542421Syokota#include <sys/systm.h> 3642421Syokota#include <sys/kernel.h> 3747336Syokota#include <sys/bus.h> 38147271Smarius#include <sys/eventhandler.h> 3942421Syokota#include <sys/proc.h> 40114216Skan#include <sys/limits.h> 4142421Syokota#include <sys/malloc.h> 4242421Syokota 4358271Syokota#include <machine/bus.h> 4458271Syokota#include <machine/resource.h> 4558271Syokota 4655731Syokota#ifdef __i386__ 4755731Syokota#include <machine/md_var.h> 4855731Syokota#include <machine/psl.h> 4955731Syokota#include <machine/vm86.h> 5055731Syokota#include <machine/pc/bios.h> 5155731Syokota 5255731Syokota#include <vm/vm.h> 5355731Syokota#include <vm/pmap.h> 54130312Sjhb#include <vm/vm_param.h> 55147271Smarius 56147271Smarius#include <isa/isareg.h> 5755731Syokota#endif /* __i386__ */ 5855731Syokota 5980040Syokota#include <sys/kbio.h> 6042421Syokota#include <dev/kbd/kbdreg.h> 61147271Smarius#include <dev/atkbdc/atkbdreg.h> 62147271Smarius#include <dev/atkbdc/atkbdcreg.h> 6342421Syokota 6442421Syokotastatic timeout_t atkbd_timeout; 65147271Smariusstatic void atkbd_shutdown_final(void *v); 6642421Syokota 6742421Syokotaint 6858271Syokotaatkbd_probe_unit(int unit, int ctlr, int irq, int flags) 6942421Syokota{ 7042421Syokota keyboard_switch_t *sw; 7142421Syokota int args[2]; 7244628Syokota int error; 7342421Syokota 7442421Syokota sw = kbd_get_switch(ATKBD_DRIVER_NAME); 7542421Syokota if (sw == NULL) 7642421Syokota return ENXIO; 7742421Syokota 7858271Syokota args[0] = ctlr; 7942421Syokota args[1] = irq; 8044628Syokota error = (*sw->probe)(unit, args, flags); 8144628Syokota if (error) 8244628Syokota return error; 8344628Syokota return 0; 8442421Syokota} 8542421Syokota 8642421Syokotaint 8758271Syokotaatkbd_attach_unit(int unit, keyboard_t **kbd, int ctlr, int irq, int flags) 8842421Syokota{ 8942421Syokota keyboard_switch_t *sw; 9044628Syokota int args[2]; 9142421Syokota int error; 9242421Syokota 9342421Syokota sw = kbd_get_switch(ATKBD_DRIVER_NAME); 9442421Syokota if (sw == NULL) 9542421Syokota return ENXIO; 9642421Syokota 9742421Syokota /* reset, initialize and enable the device */ 9858271Syokota args[0] = ctlr; 9944628Syokota args[1] = irq; 10050154Syokota *kbd = NULL; 10144628Syokota error = (*sw->probe)(unit, args, flags); 10242421Syokota if (error) 10344628Syokota return error; 10450154Syokota error = (*sw->init)(unit, kbd, args, flags); 10544628Syokota if (error) 10644628Syokota return error; 10750154Syokota (*sw->enable)(*kbd); 10842421Syokota 10942421Syokota#ifdef KBD_INSTALL_CDEV 11042421Syokota /* attach a virtual keyboard cdev */ 11150154Syokota error = kbd_attach(*kbd); 11242421Syokota if (error) 11342421Syokota return error; 11442421Syokota#endif 11542421Syokota 11642421Syokota /* 11742421Syokota * This is a kludge to compensate for lost keyboard interrupts. 11842421Syokota * A similar code used to be in syscons. See below. XXX 11942421Syokota */ 12050154Syokota atkbd_timeout(*kbd); 12142421Syokota 12242421Syokota if (bootverbose) 12350154Syokota (*sw->diag)(*kbd, bootverbose); 124147271Smarius 125147271Smarius EVENTHANDLER_REGISTER(shutdown_final, atkbd_shutdown_final, *kbd, 126147271Smarius SHUTDOWN_PRI_DEFAULT); 127147271Smarius 12842421Syokota return 0; 12942421Syokota} 13042421Syokota 13142421Syokotastatic void 13242421Syokotaatkbd_timeout(void *arg) 13342421Syokota{ 13442421Syokota keyboard_t *kbd; 13542421Syokota int s; 13642421Syokota 13756334Syokota /* 13856334Syokota * The original text of the following comments are extracted 13956334Syokota * from syscons.c (1.287) 14056334Syokota * 14142421Syokota * With release 2.1 of the Xaccel server, the keyboard is left 14242421Syokota * hanging pretty often. Apparently an interrupt from the 14342421Syokota * keyboard is lost, and I don't know why (yet). 14456334Syokota * This ugly hack calls the low-level interrupt routine if input 14556334Syokota * is ready for the keyboard and conveniently hides the problem. XXX 14656334Syokota * 14756334Syokota * Try removing anything stuck in the keyboard controller; whether 14856334Syokota * it's a keyboard scan code or mouse data. The low-level 14956334Syokota * interrupt routine doesn't read the mouse data directly, 15056334Syokota * but the keyboard controller driver will, as a side effect. 15142421Syokota */ 15242421Syokota /* 15356334Syokota * And here is bde's original comment about this: 15456334Syokota * 15556334Syokota * This is necessary to handle edge triggered interrupts - if we 15656334Syokota * returned when our IRQ is high due to unserviced input, then there 15756334Syokota * would be no more keyboard IRQs until the keyboard is reset by 15856334Syokota * external powers. 15956334Syokota * 16056334Syokota * The keyboard apparently unwedges the irq in most cases. 16142421Syokota */ 16242421Syokota s = spltty(); 16342421Syokota kbd = (keyboard_t *)arg; 16442421Syokota if ((*kbdsw[kbd->kb_index]->lock)(kbd, TRUE)) { 16542421Syokota /* 16642421Syokota * We have seen the lock flag is not set. Let's reset 16742421Syokota * the flag early, otherwise the LED update routine fails 16842421Syokota * which may want the lock during the interrupt routine. 16942421Syokota */ 17042421Syokota (*kbdsw[kbd->kb_index]->lock)(kbd, FALSE); 17142421Syokota if ((*kbdsw[kbd->kb_index]->check_char)(kbd)) 17244628Syokota (*kbdsw[kbd->kb_index]->intr)(kbd, NULL); 17342421Syokota } 17442421Syokota splx(s); 17542421Syokota timeout(atkbd_timeout, arg, hz/10); 17642421Syokota} 17742421Syokota 17842421Syokota/* LOW-LEVEL */ 17942421Syokota 18042421Syokota#define ATKBD_DEFAULT 0 18142421Syokota 18242421Syokotatypedef struct atkbd_state { 18342421Syokota KBDC kbdc; /* keyboard controller */ 18442421Syokota /* XXX: don't move this field; pcvt 18542421Syokota * expects `kbdc' to be the first 18642421Syokota * field in this structure. */ 18742421Syokota int ks_mode; /* input mode (K_XLATE,K_RAW,K_CODE) */ 18842421Syokota int ks_flags; /* flags */ 18942421Syokota#define COMPOSE (1 << 0) 19044628Syokota int ks_polling; 19142421Syokota int ks_state; /* shift/lock key state */ 19242421Syokota int ks_accents; /* accent key index (> 0) */ 19342421Syokota u_int ks_composed_char; /* composed char code (> 0) */ 19442421Syokota u_char ks_prefix; /* AT scan code prefix */ 19542421Syokota} atkbd_state_t; 19642421Syokota 19742421Syokota/* keyboard driver declaration */ 19842421Syokotastatic int atkbd_configure(int flags); 19942421Syokotastatic kbd_probe_t atkbd_probe; 20042421Syokotastatic kbd_init_t atkbd_init; 20142421Syokotastatic kbd_term_t atkbd_term; 20242421Syokotastatic kbd_intr_t atkbd_intr; 20342421Syokotastatic kbd_test_if_t atkbd_test_if; 20442421Syokotastatic kbd_enable_t atkbd_enable; 20542421Syokotastatic kbd_disable_t atkbd_disable; 20642421Syokotastatic kbd_read_t atkbd_read; 20742421Syokotastatic kbd_check_t atkbd_check; 20842421Syokotastatic kbd_read_char_t atkbd_read_char; 20942421Syokotastatic kbd_check_char_t atkbd_check_char; 21042421Syokotastatic kbd_ioctl_t atkbd_ioctl; 21142421Syokotastatic kbd_lock_t atkbd_lock; 21242421Syokotastatic kbd_clear_state_t atkbd_clear_state; 21342421Syokotastatic kbd_get_state_t atkbd_get_state; 21442421Syokotastatic kbd_set_state_t atkbd_set_state; 21544628Syokotastatic kbd_poll_mode_t atkbd_poll; 21642421Syokota 217114293Smarkmstatic keyboard_switch_t atkbdsw = { 21842421Syokota atkbd_probe, 21942421Syokota atkbd_init, 22042421Syokota atkbd_term, 22142421Syokota atkbd_intr, 22242421Syokota atkbd_test_if, 22342421Syokota atkbd_enable, 22442421Syokota atkbd_disable, 22542421Syokota atkbd_read, 22642421Syokota atkbd_check, 22742421Syokota atkbd_read_char, 22842421Syokota atkbd_check_char, 22942421Syokota atkbd_ioctl, 23042421Syokota atkbd_lock, 23142421Syokota atkbd_clear_state, 23242421Syokota atkbd_get_state, 23342421Syokota atkbd_set_state, 23442421Syokota genkbd_get_fkeystr, 23544628Syokota atkbd_poll, 23642421Syokota genkbd_diag, 23742421Syokota}; 23842421Syokota 23942421SyokotaKEYBOARD_DRIVER(atkbd, atkbdsw, atkbd_configure); 24042421Syokota 24142421Syokota/* local functions */ 24255731Syokotastatic int get_typematic(keyboard_t *kbd); 24342421Syokotastatic int setup_kbd_port(KBDC kbdc, int port, int intr); 24442421Syokotastatic int get_kbd_echo(KBDC kbdc); 24542421Syokotastatic int probe_keyboard(KBDC kbdc, int flags); 24642421Syokotastatic int init_keyboard(KBDC kbdc, int *type, int flags); 24742421Syokotastatic int write_kbd(KBDC kbdc, int command, int data); 24842421Syokotastatic int get_kbd_id(KBDC kbdc); 24944628Syokotastatic int typematic(int delay, int rate); 25054543Syokotastatic int typematic_delay(int delay); 25154543Syokotastatic int typematic_rate(int rate); 25242421Syokota 25342421Syokota/* local variables */ 25442421Syokota 25542421Syokota/* the initial key map, accent map and fkey strings */ 25644628Syokota#ifdef ATKBD_DFLT_KEYMAP 25744628Syokota#define KBD_DFLT_KEYMAP 25844628Syokota#include "atkbdmap.h" 25944628Syokota#endif 26042831Syokota#include <dev/kbd/kbdtables.h> 26142421Syokota 26242421Syokota/* structures for the default keyboard */ 26342421Syokotastatic keyboard_t default_kbd; 26442421Syokotastatic atkbd_state_t default_kbd_state; 26542421Syokotastatic keymap_t default_keymap; 26642421Syokotastatic accentmap_t default_accentmap; 26742421Syokotastatic fkeytab_t default_fkeytab[NUM_FKEYS]; 26842421Syokota 26942421Syokota/* 27042421Syokota * The back door to the keyboard driver! 27142421Syokota * This function is called by the console driver, via the kbdio module, 27242421Syokota * to tickle keyboard drivers when the low-level console is being initialized. 27342421Syokota * Almost nothing in the kernel has been initialied yet. Try to probe 27442421Syokota * keyboards if possible. 27594228Sasmodai * NOTE: because of the way the low-level console is initialized, this routine 27642421Syokota * may be called more than once!! 27742421Syokota */ 27842421Syokotastatic int 27942421Syokotaatkbd_configure(int flags) 28042421Syokota{ 28142421Syokota keyboard_t *kbd; 28242421Syokota int arg[2]; 28344628Syokota int i; 28442421Syokota 285158041Ssobomax /* 286158041Ssobomax * Probe the keyboard controller, if not present or if the driver 287158041Ssobomax * is disabled, unregister the keyboard if any. 288158041Ssobomax */ 289158041Ssobomax if (atkbdc_configure() != 0 || 290158041Ssobomax resource_disabled("atkbd", ATKBD_DEFAULT)) { 29146764Syokota i = kbd_find_keyboard(ATKBD_DRIVER_NAME, ATKBD_DEFAULT); 29246764Syokota if (i >= 0) { 29346764Syokota kbd = kbd_get_keyboard(i); 29446764Syokota kbd_unregister(kbd); 29546764Syokota kbd->kb_flags &= ~KB_REGISTERED; 29644628Syokota } 29748878Syokota return 0; 29844628Syokota } 29945720Speter 30046764Syokota /* XXX: a kludge to obtain the device configuration flags */ 30146764Syokota if (resource_int_value("atkbd", ATKBD_DEFAULT, "flags", &i) == 0) 30246764Syokota flags |= i; 30346764Syokota 30442421Syokota /* probe the default keyboard */ 30542421Syokota arg[0] = -1; 30642421Syokota arg[1] = -1; 30744628Syokota kbd = NULL; 30844628Syokota if (atkbd_probe(ATKBD_DEFAULT, arg, flags)) 30942421Syokota return 0; 31044628Syokota if (atkbd_init(ATKBD_DEFAULT, &kbd, arg, flags)) 31144628Syokota return 0; 31242421Syokota 31344628Syokota /* return the number of found keyboards */ 31444628Syokota return 1; 31544628Syokota} 31644628Syokota 31744628Syokota/* low-level functions */ 31844628Syokota 31944628Syokota/* detect a keyboard */ 32044628Syokotastatic int 32144628Syokotaatkbd_probe(int unit, void *arg, int flags) 32244628Syokota{ 32344628Syokota KBDC kbdc; 32458271Syokota int *data = (int *)arg; /* data[0]: controller, data[1]: irq */ 32544628Syokota 32644628Syokota /* XXX */ 32744628Syokota if (unit == ATKBD_DEFAULT) { 32844628Syokota if (KBD_IS_PROBED(&default_kbd)) 32942421Syokota return 0; 33042421Syokota } 33142421Syokota 33258271Syokota kbdc = atkbdc_open(data[0]); 33344628Syokota if (kbdc == NULL) 33444628Syokota return ENXIO; 33544628Syokota if (probe_keyboard(kbdc, flags)) { 33644628Syokota if (flags & KB_CONF_FAIL_IF_NO_KBD) 33744628Syokota return ENXIO; 33842421Syokota } 33944628Syokota return 0; 34042421Syokota} 34142421Syokota 34244628Syokota/* reset and initialize the device */ 34342421Syokotastatic int 34444628Syokotaatkbd_init(int unit, keyboard_t **kbdp, void *arg, int flags) 34542421Syokota{ 34642421Syokota keyboard_t *kbd; 34742421Syokota atkbd_state_t *state; 34842421Syokota keymap_t *keymap; 34942421Syokota accentmap_t *accmap; 35042421Syokota fkeytab_t *fkeymap; 35142421Syokota int fkeymap_size; 35255731Syokota int delay[2]; 35358271Syokota int *data = (int *)arg; /* data[0]: controller, data[1]: irq */ 354142569Ssam int error, needfree; 35542421Syokota 35642421Syokota /* XXX */ 35742421Syokota if (unit == ATKBD_DEFAULT) { 35842421Syokota *kbdp = kbd = &default_kbd; 35944628Syokota if (KBD_IS_INITIALIZED(kbd) && KBD_IS_CONFIGURED(kbd)) 36042421Syokota return 0; 36142421Syokota state = &default_kbd_state; 36242421Syokota keymap = &default_keymap; 36342421Syokota accmap = &default_accentmap; 36442421Syokota fkeymap = default_fkeytab; 36542421Syokota fkeymap_size = 36642421Syokota sizeof(default_fkeytab)/sizeof(default_fkeytab[0]); 367142569Ssam needfree = 0; 36842421Syokota } else if (*kbdp == NULL) { 36969781Sdwmalone *kbdp = kbd = malloc(sizeof(*kbd), M_DEVBUF, M_NOWAIT | M_ZERO); 37069781Sdwmalone state = malloc(sizeof(*state), M_DEVBUF, M_NOWAIT | M_ZERO); 371142569Ssam /* NB: these will always be initialized 'cuz !KBD_IS_PROBED */ 37242421Syokota keymap = malloc(sizeof(key_map), M_DEVBUF, M_NOWAIT); 37342421Syokota accmap = malloc(sizeof(accent_map), M_DEVBUF, M_NOWAIT); 37442421Syokota fkeymap = malloc(sizeof(fkey_tab), M_DEVBUF, M_NOWAIT); 37542421Syokota fkeymap_size = sizeof(fkey_tab)/sizeof(fkey_tab[0]); 376142569Ssam needfree = 1; 37769781Sdwmalone if ((kbd == NULL) || (state == NULL) || (keymap == NULL) 37869781Sdwmalone || (accmap == NULL) || (fkeymap == NULL)) { 379142569Ssam error = ENOMEM; 380142569Ssam goto bad; 38142421Syokota } 38244628Syokota } else if (KBD_IS_INITIALIZED(*kbdp) && KBD_IS_CONFIGURED(*kbdp)) { 38342421Syokota return 0; 38442421Syokota } else { 38542421Syokota kbd = *kbdp; 38642421Syokota state = (atkbd_state_t *)kbd->kb_data; 38742421Syokota bzero(state, sizeof(*state)); 38842421Syokota keymap = kbd->kb_keymap; 38942421Syokota accmap = kbd->kb_accentmap; 39042421Syokota fkeymap = kbd->kb_fkeytab; 39142421Syokota fkeymap_size = kbd->kb_fkeytab_size; 392142569Ssam needfree = 0; 39342421Syokota } 39442421Syokota 39544628Syokota if (!KBD_IS_PROBED(kbd)) { 39658271Syokota state->kbdc = atkbdc_open(data[0]); 397142569Ssam if (state->kbdc == NULL) { 398142569Ssam error = ENXIO; 399142569Ssam goto bad; 400142569Ssam } 40144628Syokota kbd_init_struct(kbd, ATKBD_DRIVER_NAME, KB_OTHER, unit, flags, 40258271Syokota 0, 0); 40344628Syokota bcopy(&key_map, keymap, sizeof(key_map)); 40444628Syokota bcopy(&accent_map, accmap, sizeof(accent_map)); 40544628Syokota bcopy(fkey_tab, fkeymap, 40644628Syokota imin(fkeymap_size*sizeof(fkeymap[0]), sizeof(fkey_tab))); 40744628Syokota kbd_set_maps(kbd, keymap, accmap, fkeymap, fkeymap_size); 40844628Syokota kbd->kb_data = (void *)state; 40944628Syokota 41044628Syokota if (probe_keyboard(state->kbdc, flags)) { /* shouldn't happen */ 411142569Ssam if (flags & KB_CONF_FAIL_IF_NO_KBD) { 412142569Ssam error = ENXIO; 413142569Ssam goto bad; 414142569Ssam } 41544628Syokota } else { 41644628Syokota KBD_FOUND_DEVICE(kbd); 41744628Syokota } 41844628Syokota atkbd_clear_state(kbd); 41944628Syokota state->ks_mode = K_XLATE; 42044628Syokota /* 42144628Syokota * FIXME: set the initial value for lock keys in ks_state 42244628Syokota * according to the BIOS data? 42344628Syokota */ 42444628Syokota KBD_PROBE_DONE(kbd); 42542421Syokota } 42644628Syokota if (!KBD_IS_INITIALIZED(kbd) && !(flags & KB_CONF_PROBE_ONLY)) { 42749820Syokota kbd->kb_config = flags & ~KB_CONF_PROBE_ONLY; 42842421Syokota if (KBD_HAS_DEVICE(kbd) 42944628Syokota && init_keyboard(state->kbdc, &kbd->kb_type, kbd->kb_config) 430117513Ssimokawa && (kbd->kb_config & KB_CONF_FAIL_IF_NO_KBD)) { 431117513Ssimokawa kbd_unregister(kbd); 432142569Ssam error = ENXIO; 433142569Ssam goto bad; 434117513Ssimokawa } 43544628Syokota atkbd_ioctl(kbd, KDSETLED, (caddr_t)&state->ks_state); 43655731Syokota get_typematic(kbd); 43755731Syokota delay[0] = kbd->kb_delay1; 43855731Syokota delay[1] = kbd->kb_delay2; 43955731Syokota atkbd_ioctl(kbd, KDSETREPEAT, (caddr_t)delay); 44042421Syokota KBD_INIT_DONE(kbd); 44142421Syokota } 44242421Syokota if (!KBD_IS_CONFIGURED(kbd)) { 443142569Ssam if (kbd_register(kbd) < 0) { 444142569Ssam error = ENXIO; 445142569Ssam goto bad; 446142569Ssam } 44742421Syokota KBD_CONFIG_DONE(kbd); 44842421Syokota } 44942421Syokota 45042421Syokota return 0; 451142569Ssambad: 452142569Ssam if (needfree) { 453142569Ssam if (state != NULL) 454142569Ssam free(state, M_DEVBUF); 455142569Ssam if (keymap != NULL) 456142569Ssam free(keymap, M_DEVBUF); 457142569Ssam if (accmap != NULL) 458142569Ssam free(accmap, M_DEVBUF); 459142569Ssam if (fkeymap != NULL) 460142569Ssam free(fkeymap, M_DEVBUF); 461142569Ssam if (kbd != NULL) { 462142569Ssam free(kbd, M_DEVBUF); 463142569Ssam *kbdp = NULL; /* insure ref doesn't leak to caller */ 464142569Ssam } 465142569Ssam } 466142569Ssam return error; 46742421Syokota} 46842421Syokota 46942421Syokota/* finish using this keyboard */ 47042421Syokotastatic int 47142421Syokotaatkbd_term(keyboard_t *kbd) 47242421Syokota{ 47342421Syokota kbd_unregister(kbd); 47442421Syokota return 0; 47542421Syokota} 47642421Syokota 47742421Syokota/* keyboard interrupt routine */ 47842421Syokotastatic int 47944628Syokotaatkbd_intr(keyboard_t *kbd, void *arg) 48042421Syokota{ 48142421Syokota atkbd_state_t *state; 48255731Syokota int delay[2]; 48342421Syokota int c; 48442421Syokota 48542421Syokota if (KBD_IS_ACTIVE(kbd) && KBD_IS_BUSY(kbd)) { 48642421Syokota /* let the callback function to process the input */ 48742421Syokota (*kbd->kb_callback.kc_func)(kbd, KBDIO_KEYINPUT, 48842421Syokota kbd->kb_callback.kc_arg); 48942421Syokota } else { 49042421Syokota /* read and discard the input; no one is waiting for input */ 49142421Syokota do { 49242421Syokota c = atkbd_read_char(kbd, FALSE); 49342421Syokota } while (c != NOKEY); 49442421Syokota 49542421Syokota if (!KBD_HAS_DEVICE(kbd)) { 49642421Syokota /* 49742421Syokota * The keyboard was not detected before; 49842421Syokota * it must have been reconnected! 49942421Syokota */ 50042421Syokota state = (atkbd_state_t *)kbd->kb_data; 50142421Syokota init_keyboard(state->kbdc, &kbd->kb_type, 50242421Syokota kbd->kb_config); 50342421Syokota atkbd_ioctl(kbd, KDSETLED, (caddr_t)&state->ks_state); 50455731Syokota get_typematic(kbd); 50555731Syokota delay[0] = kbd->kb_delay1; 50655731Syokota delay[1] = kbd->kb_delay2; 50755731Syokota atkbd_ioctl(kbd, KDSETREPEAT, (caddr_t)delay); 50842421Syokota KBD_FOUND_DEVICE(kbd); 50942421Syokota } 51042421Syokota } 51142421Syokota return 0; 51242421Syokota} 51342421Syokota 51442421Syokota/* test the interface to the device */ 51542421Syokotastatic int 51642421Syokotaatkbd_test_if(keyboard_t *kbd) 51742421Syokota{ 51842421Syokota int error; 51942421Syokota int s; 52042421Syokota 52142421Syokota error = 0; 52242421Syokota empty_both_buffers(((atkbd_state_t *)kbd->kb_data)->kbdc, 10); 52342421Syokota s = spltty(); 52442421Syokota if (!test_controller(((atkbd_state_t *)kbd->kb_data)->kbdc)) 52542421Syokota error = EIO; 52642421Syokota else if (test_kbd_port(((atkbd_state_t *)kbd->kb_data)->kbdc) != 0) 52742421Syokota error = EIO; 52842421Syokota splx(s); 52942421Syokota 53042421Syokota return error; 53142421Syokota} 53242421Syokota 53342421Syokota/* 53442421Syokota * Enable the access to the device; until this function is called, 53542421Syokota * the client cannot read from the keyboard. 53642421Syokota */ 53742421Syokotastatic int 53842421Syokotaatkbd_enable(keyboard_t *kbd) 53942421Syokota{ 54042421Syokota int s; 54142421Syokota 54242421Syokota s = spltty(); 54342421Syokota KBD_ACTIVATE(kbd); 54442421Syokota splx(s); 54542421Syokota return 0; 54642421Syokota} 54742421Syokota 54842421Syokota/* disallow the access to the device */ 54942421Syokotastatic int 55042421Syokotaatkbd_disable(keyboard_t *kbd) 55142421Syokota{ 55242421Syokota int s; 55342421Syokota 55442421Syokota s = spltty(); 55542421Syokota KBD_DEACTIVATE(kbd); 55642421Syokota splx(s); 55742421Syokota return 0; 55842421Syokota} 55942421Syokota 56042421Syokota/* read one byte from the keyboard if it's allowed */ 56142421Syokotastatic int 56242421Syokotaatkbd_read(keyboard_t *kbd, int wait) 56342421Syokota{ 56442421Syokota int c; 56542421Syokota 56642421Syokota if (wait) 56742421Syokota c = read_kbd_data(((atkbd_state_t *)kbd->kb_data)->kbdc); 56842421Syokota else 56942421Syokota c = read_kbd_data_no_wait(((atkbd_state_t *)kbd->kb_data)->kbdc); 57054382Syokota if (c != -1) 57154382Syokota ++kbd->kb_count; 57242421Syokota return (KBD_IS_ACTIVE(kbd) ? c : -1); 57342421Syokota} 57442421Syokota 57542421Syokota/* check if data is waiting */ 57642421Syokotastatic int 57742421Syokotaatkbd_check(keyboard_t *kbd) 57842421Syokota{ 57942421Syokota if (!KBD_IS_ACTIVE(kbd)) 58042421Syokota return FALSE; 58142421Syokota return kbdc_data_ready(((atkbd_state_t *)kbd->kb_data)->kbdc); 58242421Syokota} 58342421Syokota 58442421Syokota/* read char from the keyboard */ 58542421Syokotastatic u_int 58642421Syokotaatkbd_read_char(keyboard_t *kbd, int wait) 58742421Syokota{ 58842421Syokota atkbd_state_t *state; 58942421Syokota u_int action; 59042421Syokota int scancode; 59142421Syokota int keycode; 59242421Syokota 59342421Syokota state = (atkbd_state_t *)kbd->kb_data; 59442421Syokotanext_code: 59542421Syokota /* do we have a composed char to return? */ 59642421Syokota if (!(state->ks_flags & COMPOSE) && (state->ks_composed_char > 0)) { 59742421Syokota action = state->ks_composed_char; 59842421Syokota state->ks_composed_char = 0; 59942421Syokota if (action > UCHAR_MAX) 60042421Syokota return ERRKEY; 60142421Syokota return action; 60242421Syokota } 60342421Syokota 60442421Syokota /* see if there is something in the keyboard port */ 60542421Syokota if (wait) { 60642421Syokota do { 60742421Syokota scancode = read_kbd_data(state->kbdc); 60842421Syokota } while (scancode == -1); 60942421Syokota } else { 61042421Syokota scancode = read_kbd_data_no_wait(state->kbdc); 61142421Syokota if (scancode == -1) 61242421Syokota return NOKEY; 61342421Syokota } 61454382Syokota ++kbd->kb_count; 61542421Syokota 61654382Syokota#if KBDIO_DEBUG >= 10 61754382Syokota printf("atkbd_read_char(): scancode:0x%x\n", scancode); 61854382Syokota#endif 61954382Syokota 62042421Syokota /* return the byte as is for the K_RAW mode */ 62142421Syokota if (state->ks_mode == K_RAW) 62242421Syokota return scancode; 62342421Syokota 62442421Syokota /* translate the scan code into a keycode */ 62542421Syokota keycode = scancode & 0x7F; 62642421Syokota switch (state->ks_prefix) { 62742421Syokota case 0x00: /* normal scancode */ 62842421Syokota switch(scancode) { 62942421Syokota case 0xB8: /* left alt (compose key) released */ 63042421Syokota if (state->ks_flags & COMPOSE) { 63142421Syokota state->ks_flags &= ~COMPOSE; 63242421Syokota if (state->ks_composed_char > UCHAR_MAX) 63342421Syokota state->ks_composed_char = 0; 63442421Syokota } 63542421Syokota break; 63642421Syokota case 0x38: /* left alt (compose key) pressed */ 63742421Syokota if (!(state->ks_flags & COMPOSE)) { 63842421Syokota state->ks_flags |= COMPOSE; 63942421Syokota state->ks_composed_char = 0; 64042421Syokota } 64142421Syokota break; 64242421Syokota case 0xE0: 64342421Syokota case 0xE1: 64442421Syokota state->ks_prefix = scancode; 64542421Syokota goto next_code; 64642421Syokota } 64742421Syokota break; 64842421Syokota case 0xE0: /* 0xE0 prefix */ 64942421Syokota state->ks_prefix = 0; 65042421Syokota switch (keycode) { 65142421Syokota case 0x1C: /* right enter key */ 65242421Syokota keycode = 0x59; 65342421Syokota break; 65442421Syokota case 0x1D: /* right ctrl key */ 65542421Syokota keycode = 0x5A; 65642421Syokota break; 65742421Syokota case 0x35: /* keypad divide key */ 65842421Syokota keycode = 0x5B; 65942421Syokota break; 66042421Syokota case 0x37: /* print scrn key */ 66142421Syokota keycode = 0x5C; 66242421Syokota break; 66342421Syokota case 0x38: /* right alt key (alt gr) */ 66442421Syokota keycode = 0x5D; 66542421Syokota break; 66643337Syokota case 0x46: /* ctrl-pause/break on AT 101 (see below) */ 66743337Syokota keycode = 0x68; 66843337Syokota break; 66942421Syokota case 0x47: /* grey home key */ 67042421Syokota keycode = 0x5E; 67142421Syokota break; 67242421Syokota case 0x48: /* grey up arrow key */ 67342421Syokota keycode = 0x5F; 67442421Syokota break; 67542421Syokota case 0x49: /* grey page up key */ 67642421Syokota keycode = 0x60; 67742421Syokota break; 67842421Syokota case 0x4B: /* grey left arrow key */ 67942421Syokota keycode = 0x61; 68042421Syokota break; 68142421Syokota case 0x4D: /* grey right arrow key */ 68242421Syokota keycode = 0x62; 68342421Syokota break; 68442421Syokota case 0x4F: /* grey end key */ 68542421Syokota keycode = 0x63; 68642421Syokota break; 68742421Syokota case 0x50: /* grey down arrow key */ 68842421Syokota keycode = 0x64; 68942421Syokota break; 69042421Syokota case 0x51: /* grey page down key */ 69142421Syokota keycode = 0x65; 69242421Syokota break; 69342421Syokota case 0x52: /* grey insert key */ 69442421Syokota keycode = 0x66; 69542421Syokota break; 69642421Syokota case 0x53: /* grey delete key */ 69742421Syokota keycode = 0x67; 69842421Syokota break; 69942421Syokota /* the following 3 are only used on the MS "Natural" keyboard */ 70042421Syokota case 0x5b: /* left Window key */ 70142421Syokota keycode = 0x69; 70242421Syokota break; 70342421Syokota case 0x5c: /* right Window key */ 70442421Syokota keycode = 0x6a; 70542421Syokota break; 70642421Syokota case 0x5d: /* menu key */ 70742421Syokota keycode = 0x6b; 70842421Syokota break; 709120875Sfjoe case 0x5e: /* power key */ 710120875Sfjoe keycode = 0x6d; 711120875Sfjoe break; 712120875Sfjoe case 0x5f: /* sleep key */ 713120875Sfjoe keycode = 0x6e; 714120875Sfjoe break; 715120875Sfjoe case 0x63: /* wake key */ 716120875Sfjoe keycode = 0x6f; 717120875Sfjoe break; 71842421Syokota default: /* ignore everything else */ 71942421Syokota goto next_code; 72042421Syokota } 72142421Syokota break; 72242421Syokota case 0xE1: /* 0xE1 prefix */ 72343337Syokota /* 72443337Syokota * The pause/break key on the 101 keyboard produces: 72543337Syokota * E1-1D-45 E1-9D-C5 72643337Syokota * Ctrl-pause/break produces: 72743337Syokota * E0-46 E0-C6 (See above.) 72843337Syokota */ 72942421Syokota state->ks_prefix = 0; 73042421Syokota if (keycode == 0x1D) 73142421Syokota state->ks_prefix = 0x1D; 73242421Syokota goto next_code; 73342421Syokota /* NOT REACHED */ 73442421Syokota case 0x1D: /* pause / break */ 73542421Syokota state->ks_prefix = 0; 73642421Syokota if (keycode != 0x45) 73743337Syokota goto next_code; 73842421Syokota keycode = 0x68; 73942421Syokota break; 74042421Syokota } 74142421Syokota 74243337Syokota if (kbd->kb_type == KB_84) { 74343337Syokota switch (keycode) { 74443337Syokota case 0x37: /* *(numpad)/print screen */ 74543337Syokota if (state->ks_flags & SHIFTS) 74643337Syokota keycode = 0x5c; /* print screen */ 74743337Syokota break; 74843337Syokota case 0x45: /* num lock/pause */ 74943337Syokota if (state->ks_flags & CTLS) 75043337Syokota keycode = 0x68; /* pause */ 75143337Syokota break; 75243337Syokota case 0x46: /* scroll lock/break */ 75343337Syokota if (state->ks_flags & CTLS) 75443337Syokota keycode = 0x6c; /* break */ 75543337Syokota break; 75643337Syokota } 75743337Syokota } else if (kbd->kb_type == KB_101) { 75843337Syokota switch (keycode) { 75943337Syokota case 0x5c: /* print screen */ 76043337Syokota if (state->ks_flags & ALTS) 76143337Syokota keycode = 0x54; /* sysrq */ 76243337Syokota break; 76343337Syokota case 0x68: /* pause/break */ 76443337Syokota if (state->ks_flags & CTLS) 76543337Syokota keycode = 0x6c; /* break */ 76643337Syokota break; 76743337Syokota } 76843337Syokota } 76943337Syokota 77042421Syokota /* return the key code in the K_CODE mode */ 77142421Syokota if (state->ks_mode == K_CODE) 77242421Syokota return (keycode | (scancode & 0x80)); 77342421Syokota 77442421Syokota /* compose a character code */ 77542421Syokota if (state->ks_flags & COMPOSE) { 77647293Syokota switch (keycode | (scancode & 0x80)) { 77742421Syokota /* key pressed, process it */ 77842421Syokota case 0x47: case 0x48: case 0x49: /* keypad 7,8,9 */ 77942421Syokota state->ks_composed_char *= 10; 78046765Syokota state->ks_composed_char += keycode - 0x40; 78142421Syokota if (state->ks_composed_char > UCHAR_MAX) 78242421Syokota return ERRKEY; 78342421Syokota goto next_code; 78442421Syokota case 0x4B: case 0x4C: case 0x4D: /* keypad 4,5,6 */ 78542421Syokota state->ks_composed_char *= 10; 78646765Syokota state->ks_composed_char += keycode - 0x47; 78742421Syokota if (state->ks_composed_char > UCHAR_MAX) 78842421Syokota return ERRKEY; 78942421Syokota goto next_code; 79042421Syokota case 0x4F: case 0x50: case 0x51: /* keypad 1,2,3 */ 79142421Syokota state->ks_composed_char *= 10; 79246765Syokota state->ks_composed_char += keycode - 0x4E; 79342421Syokota if (state->ks_composed_char > UCHAR_MAX) 79442421Syokota return ERRKEY; 79542421Syokota goto next_code; 79642421Syokota case 0x52: /* keypad 0 */ 79742421Syokota state->ks_composed_char *= 10; 79842421Syokota if (state->ks_composed_char > UCHAR_MAX) 79942421Syokota return ERRKEY; 80042421Syokota goto next_code; 80142421Syokota 80242421Syokota /* key released, no interest here */ 80342421Syokota case 0xC7: case 0xC8: case 0xC9: /* keypad 7,8,9 */ 80442421Syokota case 0xCB: case 0xCC: case 0xCD: /* keypad 4,5,6 */ 80542421Syokota case 0xCF: case 0xD0: case 0xD1: /* keypad 1,2,3 */ 80642421Syokota case 0xD2: /* keypad 0 */ 80742421Syokota goto next_code; 80842421Syokota 80942421Syokota case 0x38: /* left alt key */ 81042421Syokota break; 81142421Syokota 81242421Syokota default: 81342421Syokota if (state->ks_composed_char > 0) { 81442421Syokota state->ks_flags &= ~COMPOSE; 81542421Syokota state->ks_composed_char = 0; 81642421Syokota return ERRKEY; 81742421Syokota } 81842421Syokota break; 81942421Syokota } 82042421Syokota } 82142421Syokota 82242421Syokota /* keycode to key action */ 82342421Syokota action = genkbd_keyaction(kbd, keycode, scancode & 0x80, 82442421Syokota &state->ks_state, &state->ks_accents); 82542421Syokota if (action == NOKEY) 82642421Syokota goto next_code; 82742421Syokota else 82842421Syokota return action; 82942421Syokota} 83042421Syokota 83142421Syokota/* check if char is waiting */ 83242421Syokotastatic int 83342421Syokotaatkbd_check_char(keyboard_t *kbd) 83442421Syokota{ 83542421Syokota atkbd_state_t *state; 83642421Syokota 83742421Syokota if (!KBD_IS_ACTIVE(kbd)) 83842421Syokota return FALSE; 83942421Syokota state = (atkbd_state_t *)kbd->kb_data; 84042421Syokota if (!(state->ks_flags & COMPOSE) && (state->ks_composed_char > 0)) 84142421Syokota return TRUE; 84242421Syokota return kbdc_data_ready(state->kbdc); 84342421Syokota} 84442421Syokota 84542421Syokota/* some useful control functions */ 84642421Syokotastatic int 84742421Syokotaatkbd_ioctl(keyboard_t *kbd, u_long cmd, caddr_t arg) 84842421Syokota{ 849147271Smarius /* translate LED_XXX bits into the device specific bits */ 85042421Syokota static u_char ledmap[8] = { 85142421Syokota 0, 4, 2, 6, 1, 5, 3, 7, 85242421Syokota }; 85342421Syokota atkbd_state_t *state = kbd->kb_data; 85442421Syokota int error; 85542421Syokota int s; 85642421Syokota int i; 85742421Syokota 85842421Syokota s = spltty(); 85942421Syokota switch (cmd) { 86042421Syokota 86142421Syokota case KDGKBMODE: /* get keyboard mode */ 86242421Syokota *(int *)arg = state->ks_mode; 86342421Syokota break; 86442421Syokota case KDSKBMODE: /* set keyboard mode */ 86542421Syokota switch (*(int *)arg) { 86642421Syokota case K_XLATE: 86742421Syokota if (state->ks_mode != K_XLATE) { 86842421Syokota /* make lock key state and LED state match */ 86942421Syokota state->ks_state &= ~LOCK_MASK; 87042421Syokota state->ks_state |= KBD_LED_VAL(kbd); 87142421Syokota } 872102412Scharnier /* FALLTHROUGH */ 87342421Syokota case K_RAW: 87442421Syokota case K_CODE: 87542421Syokota if (state->ks_mode != *(int *)arg) { 87642421Syokota atkbd_clear_state(kbd); 87742421Syokota state->ks_mode = *(int *)arg; 87842421Syokota } 87942421Syokota break; 88042421Syokota default: 88142421Syokota splx(s); 88242421Syokota return EINVAL; 88342421Syokota } 88442421Syokota break; 88542421Syokota 88642421Syokota case KDGETLED: /* get keyboard LED */ 88742421Syokota *(int *)arg = KBD_LED_VAL(kbd); 88842421Syokota break; 88942421Syokota case KDSETLED: /* set keyboard LED */ 89042421Syokota /* NOTE: lock key state in ks_state won't be changed */ 89142421Syokota if (*(int *)arg & ~LOCK_MASK) { 89242421Syokota splx(s); 89342421Syokota return EINVAL; 89442421Syokota } 89542421Syokota i = *(int *)arg; 89642421Syokota /* replace CAPS LED with ALTGR LED for ALTGR keyboards */ 89761004Sache if (state->ks_mode == K_XLATE && 89861004Sache kbd->kb_keymap->n_keys > ALTGR_OFFSET) { 89942421Syokota if (i & ALKED) 90042421Syokota i |= CLKED; 90142421Syokota else 90242421Syokota i &= ~CLKED; 90342421Syokota } 90442421Syokota if (KBD_HAS_DEVICE(kbd)) { 90542421Syokota error = write_kbd(state->kbdc, KBDC_SET_LEDS, 90642421Syokota ledmap[i & LED_MASK]); 90742421Syokota if (error) { 90842421Syokota splx(s); 90942421Syokota return error; 91042421Syokota } 91142421Syokota } 91242421Syokota KBD_LED_VAL(kbd) = *(int *)arg; 91342421Syokota break; 91442421Syokota 91542421Syokota case KDGKBSTATE: /* get lock key state */ 91642421Syokota *(int *)arg = state->ks_state & LOCK_MASK; 91742421Syokota break; 91842421Syokota case KDSKBSTATE: /* set lock key state */ 91942421Syokota if (*(int *)arg & ~LOCK_MASK) { 92042421Syokota splx(s); 92142421Syokota return EINVAL; 92242421Syokota } 92342421Syokota state->ks_state &= ~LOCK_MASK; 92442421Syokota state->ks_state |= *(int *)arg; 92542421Syokota splx(s); 92642421Syokota /* set LEDs and quit */ 92742421Syokota return atkbd_ioctl(kbd, KDSETLED, arg); 92842421Syokota 92944628Syokota case KDSETREPEAT: /* set keyboard repeat rate (new interface) */ 93042421Syokota splx(s); 93142421Syokota if (!KBD_HAS_DEVICE(kbd)) 93242421Syokota return 0; 93344628Syokota i = typematic(((int *)arg)[0], ((int *)arg)[1]); 93454543Syokota error = write_kbd(state->kbdc, KBDC_SET_TYPEMATIC, i); 93554543Syokota if (error == 0) { 93654543Syokota kbd->kb_delay1 = typematic_delay(i); 93754543Syokota kbd->kb_delay2 = typematic_rate(i); 93854543Syokota } 93954543Syokota return error; 94042421Syokota 94144628Syokota case KDSETRAD: /* set keyboard repeat rate (old interface) */ 94244628Syokota splx(s); 94344628Syokota if (!KBD_HAS_DEVICE(kbd)) 94444628Syokota return 0; 94554543Syokota error = write_kbd(state->kbdc, KBDC_SET_TYPEMATIC, *(int *)arg); 94654543Syokota if (error == 0) { 94754543Syokota kbd->kb_delay1 = typematic_delay(*(int *)arg); 94854543Syokota kbd->kb_delay2 = typematic_rate(*(int *)arg); 94954543Syokota } 95054543Syokota return error; 95144628Syokota 95242421Syokota case PIO_KEYMAP: /* set keyboard translation table */ 95342421Syokota case PIO_KEYMAPENT: /* set keyboard translation table entry */ 95442421Syokota case PIO_DEADKEYMAP: /* set accent key translation table */ 95542421Syokota state->ks_accents = 0; 956102412Scharnier /* FALLTHROUGH */ 95742421Syokota default: 95842421Syokota splx(s); 95942421Syokota return genkbd_commonioctl(kbd, cmd, arg); 96042421Syokota } 96142421Syokota 96242421Syokota splx(s); 96342421Syokota return 0; 96442421Syokota} 96542421Syokota 96642421Syokota/* lock the access to the keyboard */ 96742421Syokotastatic int 96842421Syokotaatkbd_lock(keyboard_t *kbd, int lock) 96942421Syokota{ 97042421Syokota return kbdc_lock(((atkbd_state_t *)kbd->kb_data)->kbdc, lock); 97142421Syokota} 97242421Syokota 97342421Syokota/* clear the internal state of the keyboard */ 97442421Syokotastatic void 97542421Syokotaatkbd_clear_state(keyboard_t *kbd) 97642421Syokota{ 97742421Syokota atkbd_state_t *state; 97842421Syokota 97942421Syokota state = (atkbd_state_t *)kbd->kb_data; 98042421Syokota state->ks_flags = 0; 98144628Syokota state->ks_polling = 0; 98242421Syokota state->ks_state &= LOCK_MASK; /* preserve locking key state */ 98342421Syokota state->ks_accents = 0; 98442421Syokota state->ks_composed_char = 0; 98542421Syokota#if 0 98642421Syokota state->ks_prefix = 0; /* XXX */ 98742421Syokota#endif 98842421Syokota} 98942421Syokota 99042421Syokota/* save the internal state */ 99142421Syokotastatic int 99242421Syokotaatkbd_get_state(keyboard_t *kbd, void *buf, size_t len) 99342421Syokota{ 99442421Syokota if (len == 0) 99542421Syokota return sizeof(atkbd_state_t); 99642421Syokota if (len < sizeof(atkbd_state_t)) 99742421Syokota return -1; 99842421Syokota bcopy(kbd->kb_data, buf, sizeof(atkbd_state_t)); 99942421Syokota return 0; 100042421Syokota} 100142421Syokota 100242421Syokota/* set the internal state */ 100342421Syokotastatic int 100442421Syokotaatkbd_set_state(keyboard_t *kbd, void *buf, size_t len) 100542421Syokota{ 100642421Syokota if (len < sizeof(atkbd_state_t)) 100742421Syokota return ENOMEM; 100842421Syokota if (((atkbd_state_t *)kbd->kb_data)->kbdc 100942421Syokota != ((atkbd_state_t *)buf)->kbdc) 101042421Syokota return ENOMEM; 101142421Syokota bcopy(buf, kbd->kb_data, sizeof(atkbd_state_t)); 101242421Syokota return 0; 101342421Syokota} 101442421Syokota 101544628Syokotastatic int 101644628Syokotaatkbd_poll(keyboard_t *kbd, int on) 101744628Syokota{ 101844628Syokota atkbd_state_t *state; 101944628Syokota int s; 102044628Syokota 102144628Syokota state = (atkbd_state_t *)kbd->kb_data; 102244628Syokota s = spltty(); 102344628Syokota if (on) 102444628Syokota ++state->ks_polling; 102544628Syokota else 102644628Syokota --state->ks_polling; 102744628Syokota splx(s); 102844628Syokota return 0; 102944628Syokota} 103044628Syokota 1031147271Smariusstatic void 1032147271Smariusatkbd_shutdown_final(void *v) 1033147271Smarius{ 1034147271Smarius#ifdef __sparc64__ 1035147271Smarius keyboard_t *kbd = v; 1036147271Smarius KBDC kbdc = ((atkbd_state_t *)kbd->kb_data)->kbdc; 1037147271Smarius 1038147271Smarius /* 1039147271Smarius * Turn off the translation in preparation for handing the keyboard 1040147271Smarius * over to the OFW as the OBP driver doesn't use translation and 1041147271Smarius * also doesn't disable it itself resulting in a broken keymap at 1042147271Smarius * the boot prompt. Also disable the aux port and the interrupts as 1043147271Smarius * the OBP driver doesn't use them, i.e. polls the keyboard. Not 1044147271Smarius * disabling the interrupts doesn't cause real problems but the 1045147271Smarius * responsiveness is a bit better when they are turned off. 1046147271Smarius */ 1047147271Smarius send_kbd_command(kbdc, KBDC_DISABLE_KBD); 1048147271Smarius set_controller_command_byte(kbdc, 1049147271Smarius KBD_AUX_CONTROL_BITS | KBD_KBD_CONTROL_BITS | KBD_TRANSLATION, 1050147271Smarius KBD_DISABLE_AUX_PORT | KBD_DISABLE_KBD_INT | KBD_ENABLE_KBD_PORT); 1051147271Smarius send_kbd_command(kbdc, KBDC_ENABLE_KBD); 1052147271Smarius#endif 1053147271Smarius} 1054147271Smarius 105542421Syokota/* local functions */ 105642421Syokota 105742421Syokotastatic int 105855731Syokotaget_typematic(keyboard_t *kbd) 105955731Syokota{ 106055731Syokota#ifdef __i386__ 106155731Syokota /* 106255731Syokota * Only some systems allow us to retrieve the keyboard repeat 106355731Syokota * rate previously set via the BIOS... 106455731Syokota */ 106555731Syokota struct vm86frame vmf; 106655731Syokota u_int32_t p; 106755731Syokota 106855731Syokota bzero(&vmf, sizeof(vmf)); 106955731Syokota vmf.vmf_ax = 0xc000; 107055731Syokota vm86_intcall(0x15, &vmf); 107155731Syokota if ((vmf.vmf_eflags & PSL_C) || vmf.vmf_ah) 107255731Syokota return ENODEV; 107355731Syokota p = BIOS_PADDRTOVADDR(((u_int32_t)vmf.vmf_es << 4) + vmf.vmf_bx); 107455731Syokota if ((readb(p + 6) & 0x40) == 0) /* int 16, function 0x09 supported? */ 107555731Syokota return ENODEV; 107655731Syokota vmf.vmf_ax = 0x0900; 107755731Syokota vm86_intcall(0x16, &vmf); 107855731Syokota if ((vmf.vmf_al & 0x08) == 0) /* int 16, function 0x0306 supported? */ 107955731Syokota return ENODEV; 108055731Syokota vmf.vmf_ax = 0x0306; 108155731Syokota vm86_intcall(0x16, &vmf); 108255731Syokota kbd->kb_delay1 = typematic_delay(vmf.vmf_bh << 5); 108355731Syokota kbd->kb_delay2 = typematic_rate(vmf.vmf_bl); 108455731Syokota return 0; 108555731Syokota#else 108655731Syokota return ENODEV; 108755731Syokota#endif /* __i386__ */ 108855731Syokota} 108955731Syokota 109055731Syokotastatic int 109142421Syokotasetup_kbd_port(KBDC kbdc, int port, int intr) 109242421Syokota{ 109342421Syokota if (!set_controller_command_byte(kbdc, 109442421Syokota KBD_KBD_CONTROL_BITS, 109542421Syokota ((port) ? KBD_ENABLE_KBD_PORT : KBD_DISABLE_KBD_PORT) 109642421Syokota | ((intr) ? KBD_ENABLE_KBD_INT : KBD_DISABLE_KBD_INT))) 109742421Syokota return 1; 109842421Syokota return 0; 109942421Syokota} 110042421Syokota 110142421Syokotastatic int 110242421Syokotaget_kbd_echo(KBDC kbdc) 110342421Syokota{ 110442421Syokota /* enable the keyboard port, but disable the keyboard intr. */ 110542421Syokota if (setup_kbd_port(kbdc, TRUE, FALSE)) 110642421Syokota /* CONTROLLER ERROR: there is very little we can do... */ 110742421Syokota return ENXIO; 110842421Syokota 110942421Syokota /* see if something is present */ 111042421Syokota write_kbd_command(kbdc, KBDC_ECHO); 111142421Syokota if (read_kbd_data(kbdc) != KBD_ECHO) { 111242421Syokota empty_both_buffers(kbdc, 10); 111342421Syokota test_controller(kbdc); 111442421Syokota test_kbd_port(kbdc); 111542421Syokota return ENXIO; 111642421Syokota } 111742421Syokota 111842421Syokota /* enable the keyboard port and intr. */ 111942421Syokota if (setup_kbd_port(kbdc, TRUE, TRUE)) { 112042421Syokota /* 112142421Syokota * CONTROLLER ERROR 112242421Syokota * This is serious; the keyboard intr is left disabled! 112342421Syokota */ 112442421Syokota return ENXIO; 112542421Syokota } 112642421Syokota 112742421Syokota return 0; 112842421Syokota} 112942421Syokota 113042421Syokotastatic int 113142421Syokotaprobe_keyboard(KBDC kbdc, int flags) 113242421Syokota{ 113342421Syokota /* 113442421Syokota * Don't try to print anything in this function. The low-level 113542421Syokota * console may not have been initialized yet... 113642421Syokota */ 113742421Syokota int err; 113842421Syokota int c; 113942421Syokota int m; 114042421Syokota 114142421Syokota if (!kbdc_lock(kbdc, TRUE)) { 114242421Syokota /* driver error? */ 114342421Syokota return ENXIO; 114442421Syokota } 114542421Syokota 114657131Syokota /* temporarily block data transmission from the keyboard */ 114757131Syokota write_controller_command(kbdc, KBDC_DISABLE_KBD_PORT); 114857131Syokota 114942421Syokota /* flush any noise in the buffer */ 115057131Syokota empty_both_buffers(kbdc, 100); 115142421Syokota 115242421Syokota /* save the current keyboard controller command byte */ 115342421Syokota m = kbdc_get_device_mask(kbdc) & ~KBD_KBD_CONTROL_BITS; 115442421Syokota c = get_controller_command_byte(kbdc); 115542421Syokota if (c == -1) { 115642421Syokota /* CONTROLLER ERROR */ 115742421Syokota kbdc_set_device_mask(kbdc, m); 115842421Syokota kbdc_lock(kbdc, FALSE); 115942421Syokota return ENXIO; 116042421Syokota } 116142421Syokota 116242421Syokota /* 116342421Syokota * The keyboard may have been screwed up by the boot block. 116442421Syokota * We may just be able to recover from error by testing the controller 116542421Syokota * and the keyboard port. The controller command byte needs to be 116642421Syokota * saved before this recovery operation, as some controllers seem 116742421Syokota * to set the command byte to particular values. 116842421Syokota */ 116942421Syokota test_controller(kbdc); 1170138900Sjhb if (!(flags & KB_CONF_NO_PROBE_TEST)) 1171138900Sjhb test_kbd_port(kbdc); 117242421Syokota 117342421Syokota err = get_kbd_echo(kbdc); 117457902Syokota 117557902Syokota /* 117657902Syokota * Even if the keyboard doesn't seem to be present (err != 0), 117757902Syokota * we shall enable the keyboard port and interrupt so that 117857902Syokota * the driver will be operable when the keyboard is attached 117957902Syokota * to the system later. It is NOT recommended to hot-plug 118057902Syokota * the AT keyboard, but many people do so... 118157902Syokota */ 118257902Syokota kbdc_set_device_mask(kbdc, m | KBD_KBD_CONTROL_BITS); 118357902Syokota setup_kbd_port(kbdc, TRUE, TRUE); 118457902Syokota#if 0 118542421Syokota if (err == 0) { 118642421Syokota kbdc_set_device_mask(kbdc, m | KBD_KBD_CONTROL_BITS); 118742421Syokota } else { 118857131Syokota /* try to restore the command byte as before */ 118957131Syokota set_controller_command_byte(kbdc, 0xff, c); 119042421Syokota kbdc_set_device_mask(kbdc, m); 119142421Syokota } 119257902Syokota#endif 119342421Syokota 119442421Syokota kbdc_lock(kbdc, FALSE); 119542421Syokota return err; 119642421Syokota} 119742421Syokota 119842421Syokotastatic int 119942421Syokotainit_keyboard(KBDC kbdc, int *type, int flags) 120042421Syokota{ 120142421Syokota int codeset; 120242421Syokota int id; 120342421Syokota int c; 120442421Syokota 120542421Syokota if (!kbdc_lock(kbdc, TRUE)) { 120642421Syokota /* driver error? */ 120742421Syokota return EIO; 120842421Syokota } 120942421Syokota 121057131Syokota /* temporarily block data transmission from the keyboard */ 121157131Syokota write_controller_command(kbdc, KBDC_DISABLE_KBD_PORT); 121257131Syokota 121342421Syokota /* save the current controller command byte */ 121454382Syokota empty_both_buffers(kbdc, 200); 121542421Syokota c = get_controller_command_byte(kbdc); 121642421Syokota if (c == -1) { 121742421Syokota /* CONTROLLER ERROR */ 121842421Syokota kbdc_lock(kbdc, FALSE); 121942421Syokota printf("atkbd: unable to get the current command byte value.\n"); 122042421Syokota return EIO; 122142421Syokota } 122242421Syokota if (bootverbose) 122342421Syokota printf("atkbd: the current kbd controller command byte %04x\n", 122442421Syokota c); 122542421Syokota#if 0 122642421Syokota /* override the keyboard lock switch */ 122742421Syokota c |= KBD_OVERRIDE_KBD_LOCK; 122842421Syokota#endif 122942421Syokota 123042421Syokota /* enable the keyboard port, but disable the keyboard intr. */ 123142421Syokota if (setup_kbd_port(kbdc, TRUE, FALSE)) { 123242421Syokota /* CONTROLLER ERROR: there is very little we can do... */ 123342421Syokota printf("atkbd: unable to set the command byte.\n"); 123442421Syokota kbdc_lock(kbdc, FALSE); 123542421Syokota return EIO; 123642421Syokota } 123742421Syokota 123842421Syokota /* 123942421Syokota * Check if we have an XT keyboard before we attempt to reset it. 124042421Syokota * The procedure assumes that the keyboard and the controller have 124142421Syokota * been set up properly by BIOS and have not been messed up 124242421Syokota * during the boot process. 124342421Syokota */ 124442421Syokota codeset = -1; 124542421Syokota if (flags & KB_CONF_ALT_SCANCODESET) 124642421Syokota /* the user says there is a XT keyboard */ 124742421Syokota codeset = 1; 124842421Syokota#ifdef KBD_DETECT_XT_KEYBOARD 124942421Syokota else if ((c & KBD_TRANSLATION) == 0) { 125042421Syokota /* SET_SCANCODE_SET is not always supported; ignore error */ 125142421Syokota if (send_kbd_command_and_data(kbdc, KBDC_SET_SCANCODE_SET, 0) 125242421Syokota == KBD_ACK) 125342421Syokota codeset = read_kbd_data(kbdc); 125442421Syokota } 125542421Syokota if (bootverbose) 125642421Syokota printf("atkbd: scancode set %d\n", codeset); 125742421Syokota#endif /* KBD_DETECT_XT_KEYBOARD */ 125842421Syokota 125942421Syokota *type = KB_OTHER; 126042421Syokota id = get_kbd_id(kbdc); 126142421Syokota switch(id) { 126255730Syokota case 0x41ab: /* 101/102/... Enhanced */ 126355730Syokota case 0x83ab: /* ditto */ 126455730Syokota case 0x54ab: /* SpaceSaver */ 126555730Syokota case 0x84ab: /* ditto */ 126655730Syokota#if 0 126755730Syokota case 0x90ab: /* 'G' */ 126855730Syokota case 0x91ab: /* 'P' */ 126955730Syokota case 0x92ab: /* 'A' */ 127055730Syokota#endif 127142421Syokota *type = KB_101; 127242421Syokota break; 127342421Syokota case -1: /* AT 84 keyboard doesn't return ID */ 127442421Syokota *type = KB_84; 127542421Syokota break; 127642421Syokota default: 127742421Syokota break; 127842421Syokota } 127942421Syokota if (bootverbose) 128042421Syokota printf("atkbd: keyboard ID 0x%x (%d)\n", id, *type); 128142421Syokota 128242421Syokota /* reset keyboard hardware */ 128342421Syokota if (!(flags & KB_CONF_NO_RESET) && !reset_kbd(kbdc)) { 128442421Syokota /* 128542421Syokota * KEYBOARD ERROR 128642421Syokota * Keyboard reset may fail either because the keyboard 128742421Syokota * doen't exist, or because the keyboard doesn't pass 128842421Syokota * the self-test, or the keyboard controller on the 128942421Syokota * motherboard and the keyboard somehow fail to shake hands. 129042421Syokota * It is just possible, particularly in the last case, 1291110398Scharnier * that the keyboard controller may be left in a hung state. 129242421Syokota * test_controller() and test_kbd_port() appear to bring 129342421Syokota * the keyboard controller back (I don't know why and how, 129442421Syokota * though.) 129542421Syokota */ 129642421Syokota empty_both_buffers(kbdc, 10); 129742421Syokota test_controller(kbdc); 129842421Syokota test_kbd_port(kbdc); 129942421Syokota /* 130042421Syokota * We could disable the keyboard port and interrupt... but, 130142421Syokota * the keyboard may still exist (see above). 130242421Syokota */ 130342421Syokota set_controller_command_byte(kbdc, 0xff, c); 130442421Syokota kbdc_lock(kbdc, FALSE); 130542421Syokota if (bootverbose) 130642421Syokota printf("atkbd: failed to reset the keyboard.\n"); 130742421Syokota return EIO; 130842421Syokota } 130942421Syokota 131042421Syokota /* 131194275Sphk * Allow us to set the XT_KEYBD flag so that keyboards 131242421Syokota * such as those on the IBM ThinkPad laptop computers can be used 131342421Syokota * with the standard console driver. 131442421Syokota */ 131542421Syokota if (codeset == 1) { 131642421Syokota if (send_kbd_command_and_data(kbdc, 131742421Syokota KBDC_SET_SCANCODE_SET, codeset) == KBD_ACK) { 131842421Syokota /* XT kbd doesn't need scan code translation */ 131942421Syokota c &= ~KBD_TRANSLATION; 132042421Syokota } else { 132142421Syokota /* 132242421Syokota * KEYBOARD ERROR 132342421Syokota * The XT kbd isn't usable unless the proper scan 132442421Syokota * code set is selected. 132542421Syokota */ 132642421Syokota set_controller_command_byte(kbdc, 0xff, c); 132742421Syokota kbdc_lock(kbdc, FALSE); 132842421Syokota printf("atkbd: unable to set the XT keyboard mode.\n"); 132942421Syokota return EIO; 133042421Syokota } 133142421Syokota } 133242421Syokota 1333147271Smarius#if defined(__alpha__) || defined(__sparc64__) 133442831Syokota if (send_kbd_command_and_data( 133542831Syokota kbdc, KBDC_SET_SCANCODE_SET, 2) != KBD_ACK) { 133642831Syokota printf("atkbd: can't set translation.\n"); 133742831Syokota } 133842831Syokota c |= KBD_TRANSLATION; 133942831Syokota#endif 134042831Syokota 134142421Syokota /* enable the keyboard port and intr. */ 134242421Syokota if (!set_controller_command_byte(kbdc, 134342421Syokota KBD_KBD_CONTROL_BITS | KBD_TRANSLATION | KBD_OVERRIDE_KBD_LOCK, 134442421Syokota (c & (KBD_TRANSLATION | KBD_OVERRIDE_KBD_LOCK)) 134542421Syokota | KBD_ENABLE_KBD_PORT | KBD_ENABLE_KBD_INT)) { 134642421Syokota /* 134742421Syokota * CONTROLLER ERROR 134842421Syokota * This is serious; we are left with the disabled 134942421Syokota * keyboard intr. 135042421Syokota */ 135142421Syokota set_controller_command_byte(kbdc, 0xff, c); 135242421Syokota kbdc_lock(kbdc, FALSE); 135342421Syokota printf("atkbd: unable to enable the keyboard port and intr.\n"); 135442421Syokota return EIO; 135542421Syokota } 135642421Syokota 135742421Syokota kbdc_lock(kbdc, FALSE); 135842421Syokota return 0; 135942421Syokota} 136042421Syokota 136142421Syokotastatic int 136242421Syokotawrite_kbd(KBDC kbdc, int command, int data) 136342421Syokota{ 136442421Syokota int s; 136542421Syokota 136642421Syokota /* prevent the timeout routine from polling the keyboard */ 136742421Syokota if (!kbdc_lock(kbdc, TRUE)) 136842421Syokota return EBUSY; 136942421Syokota 137042421Syokota /* disable the keyboard and mouse interrupt */ 137142421Syokota s = spltty(); 137242421Syokota#if 0 137342421Syokota c = get_controller_command_byte(kbdc); 137442421Syokota if ((c == -1) 137542421Syokota || !set_controller_command_byte(kbdc, 137642421Syokota kbdc_get_device_mask(kbdc), 137742421Syokota KBD_DISABLE_KBD_PORT | KBD_DISABLE_KBD_INT 137842421Syokota | KBD_DISABLE_AUX_PORT | KBD_DISABLE_AUX_INT)) { 137942421Syokota /* CONTROLLER ERROR */ 138042421Syokota kbdc_lock(kbdc, FALSE); 138142421Syokota splx(s); 138242421Syokota return EIO; 138342421Syokota } 138442421Syokota /* 138542421Syokota * Now that the keyboard controller is told not to generate 138642421Syokota * the keyboard and mouse interrupts, call `splx()' to allow 138742421Syokota * the other tty interrupts. The clock interrupt may also occur, 138842421Syokota * but the timeout routine (`scrn_timer()') will be blocked 138942421Syokota * by the lock flag set via `kbdc_lock()' 139042421Syokota */ 139142421Syokota splx(s); 139242421Syokota#endif 139342421Syokota 139442421Syokota if (send_kbd_command_and_data(kbdc, command, data) != KBD_ACK) 139542421Syokota send_kbd_command(kbdc, KBDC_ENABLE_KBD); 139642421Syokota 139742421Syokota#if 0 139842421Syokota /* restore the interrupts */ 139942421Syokota if (!set_controller_command_byte(kbdc, 140042421Syokota kbdc_get_device_mask(kbdc), 140142421Syokota c & (KBD_KBD_CONTROL_BITS | KBD_AUX_CONTROL_BITS))) { 140242421Syokota /* CONTROLLER ERROR */ 140342421Syokota } 140442421Syokota#else 140542421Syokota splx(s); 140642421Syokota#endif 140742421Syokota kbdc_lock(kbdc, FALSE); 140842421Syokota 140942421Syokota return 0; 141042421Syokota} 141142421Syokota 141242421Syokotastatic int 141342421Syokotaget_kbd_id(KBDC kbdc) 141442421Syokota{ 141542421Syokota int id1, id2; 141642421Syokota 141742421Syokota empty_both_buffers(kbdc, 10); 141842421Syokota id1 = id2 = -1; 141942421Syokota if (send_kbd_command(kbdc, KBDC_SEND_DEV_ID) != KBD_ACK) 142042421Syokota return -1; 142142421Syokota 142242421Syokota DELAY(10000); /* 10 msec delay */ 142342421Syokota id1 = read_kbd_data(kbdc); 142442421Syokota if (id1 != -1) 142542421Syokota id2 = read_kbd_data(kbdc); 142642421Syokota 142742421Syokota if ((id1 == -1) || (id2 == -1)) { 142842421Syokota empty_both_buffers(kbdc, 10); 142942421Syokota test_controller(kbdc); 143042421Syokota test_kbd_port(kbdc); 143142421Syokota return -1; 143242421Syokota } 143342421Syokota return ((id2 << 8) | id1); 143442421Syokota} 143542421Syokota 143654543Syokotastatic int delays[] = { 250, 500, 750, 1000 }; 143754543Syokotastatic int rates[] = { 34, 38, 42, 46, 50, 55, 59, 63, 143854543Syokota 68, 76, 84, 92, 100, 110, 118, 126, 143954543Syokota 136, 152, 168, 184, 200, 220, 236, 252, 144054543Syokota 272, 304, 336, 368, 400, 440, 472, 504 }; 144154543Syokota 144244628Syokotastatic int 144354543Syokotatypematic_delay(int i) 144454543Syokota{ 144554543Syokota return delays[(i >> 5) & 3]; 144654543Syokota} 144754543Syokota 144854543Syokotastatic int 144954543Syokotatypematic_rate(int i) 145054543Syokota{ 145154543Syokota return rates[i & 0x1f]; 145254543Syokota} 145354543Syokota 145454543Syokotastatic int 145544628Syokotatypematic(int delay, int rate) 145644628Syokota{ 145744628Syokota int value; 145844628Syokota int i; 145944628Syokota 146044628Syokota for (i = sizeof(delays)/sizeof(delays[0]) - 1; i > 0; --i) { 146144628Syokota if (delay >= delays[i]) 146244628Syokota break; 146344628Syokota } 146444628Syokota value = i << 5; 146544628Syokota for (i = sizeof(rates)/sizeof(rates[0]) - 1; i > 0; --i) { 146644628Syokota if (rate >= rates[i]) 146744628Syokota break; 146844628Syokota } 146944628Syokota value |= i; 147044628Syokota return value; 147144628Syokota} 1472