1122470Sjake/*- 2122470Sjake * Copyright (c) 2003 Jake Burkholder. 3122470Sjake * All rights reserved. 4122470Sjake * 5122470Sjake * Redistribution and use in source and binary forms, with or without 6122470Sjake * modification, are permitted provided that the following conditions 7122470Sjake * are met: 8122470Sjake * 1. Redistributions of source code must retain the above copyright 9122470Sjake * notice, this list of conditions and the following disclaimer. 10122470Sjake * 2. Redistributions in binary form must reproduce the above copyright 11122470Sjake * notice, this list of conditions and the following disclaimer in the 12122470Sjake * documentation and/or other materials provided with the distribution. 13122470Sjake * 14122470Sjake * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15122470Sjake * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16122470Sjake * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17122470Sjake * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18122470Sjake * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19122470Sjake * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20122470Sjake * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21122470Sjake * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22122470Sjake * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23122470Sjake * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24122470Sjake * SUCH DAMAGE. 25122470Sjake */ 26122470Sjake 27146475Smarius#include <sys/cdefs.h> 28146475Smarius__FBSDID("$FreeBSD: releng/10.3/sys/dev/uart/uart_kbd_sun.c 224126 2011-07-17 08:19:19Z ed $"); 29146475Smarius 30162711Sru#include "opt_compat.h" 31122470Sjake#include "opt_kbd.h" 32163890Smarius#include "opt_sunkbd.h" 33122470Sjake 34163890Smarius#if (defined(SUNKBD_EMULATE_ATKBD) && defined(SUNKBD_DFLT_KEYMAP)) || \ 35163890Smarius !defined(SUNKBD_EMULATE_ATKBD) 36163890Smarius#define KBD_DFLT_KEYMAP 37163890Smarius#endif 38163890Smarius 39122470Sjake#include <sys/param.h> 40122470Sjake#include <sys/systm.h> 41122470Sjake#include <sys/bus.h> 42122470Sjake#include <sys/interrupt.h> 43122470Sjake#include <sys/kbio.h> 44122470Sjake#include <sys/kernel.h> 45163890Smarius#include <sys/limits.h> 46122470Sjake 47122470Sjake#include <machine/bus.h> 48122470Sjake 49122470Sjake#include <dev/kbd/kbdreg.h> 50163890Smarius#include <dev/kbd/kbdtables.h> 51122470Sjake 52122470Sjake#include <dev/uart/uart.h> 53122470Sjake#include <dev/uart/uart_bus.h> 54122470Sjake#include <dev/uart/uart_cpu.h> 55122470Sjake 56122470Sjake#include <dev/uart/uart_kbd_sun.h> 57163890Smarius#if !defined(SUNKBD_EMULATE_ATKBD) 58122470Sjake#include <dev/uart/uart_kbd_sun_tables.h> 59163890Smarius#endif 60122470Sjake 61163890Smarius#if defined(SUNKBD_EMULATE_ATKBD) && defined(SUNKBD_DFLT_KEYMAP) 62163890Smarius#include "sunkbdmap.h" 63163890Smarius#endif 64122470Sjake#include "uart_if.h" 65122470Sjake 66163890Smarius#define SUNKBD_DRIVER_NAME "sunkbd" 67122470Sjake 68122470Sjake#define TODO printf("%s: unimplemented", __func__) 69122470Sjake 70122470Sjakestruct sunkbd_softc { 71122470Sjake keyboard_t sc_kbd; 72122470Sjake struct uart_softc *sc_uart; 73122470Sjake struct uart_devinfo *sc_sysdev; 74122470Sjake 75122470Sjake struct callout sc_repeat_callout; 76122470Sjake int sc_repeat_key; 77122470Sjake 78122470Sjake int sc_accents; 79163890Smarius int sc_composed_char; 80163890Smarius int sc_flags; 81163890Smarius#define KPCOMPOSE (1 << 0) 82122470Sjake int sc_mode; 83122470Sjake int sc_polling; 84122470Sjake int sc_repeating; 85122470Sjake int sc_state; 86163890Smarius 87163890Smarius#if defined(SUNKBD_EMULATE_ATKBD) 88163890Smarius int sc_buffered_char[2]; 89163890Smarius#endif 90122470Sjake}; 91122470Sjake 92122470Sjakestatic int sunkbd_configure(int flags); 93122470Sjakestatic int sunkbd_probe_keyboard(struct uart_devinfo *di); 94122470Sjake 95122470Sjakestatic int sunkbd_probe(int unit, void *arg, int flags); 96122470Sjakestatic int sunkbd_init(int unit, keyboard_t **kbdp, void *arg, int flags); 97122470Sjakestatic int sunkbd_term(keyboard_t *kbd); 98122470Sjakestatic int sunkbd_intr(keyboard_t *kbd, void *arg); 99122470Sjakestatic int sunkbd_test_if(keyboard_t *kbd); 100122470Sjakestatic int sunkbd_enable(keyboard_t *kbd); 101122470Sjakestatic int sunkbd_disable(keyboard_t *kbd); 102122470Sjakestatic int sunkbd_read(keyboard_t *kbd, int wait); 103122470Sjakestatic int sunkbd_check(keyboard_t *kbd); 104122470Sjakestatic u_int sunkbd_read_char(keyboard_t *kbd, int wait); 105122470Sjakestatic int sunkbd_check_char(keyboard_t *kbd); 106122470Sjakestatic int sunkbd_ioctl(keyboard_t *kbd, u_long cmd, caddr_t data); 107122470Sjakestatic int sunkbd_lock(keyboard_t *kbd, int lock); 108122470Sjakestatic void sunkbd_clear_state(keyboard_t *kbd); 109122470Sjakestatic int sunkbd_get_state(keyboard_t *kbd, void *buf, size_t len); 110122470Sjakestatic int sunkbd_set_state(keyboard_t *kbd, void *buf, size_t len); 111122470Sjakestatic int sunkbd_poll_mode(keyboard_t *kbd, int on); 112122470Sjakestatic void sunkbd_diag(keyboard_t *kbd, int level); 113122470Sjake 114122470Sjakestatic void sunkbd_repeat(void *v); 115163890Smarius#if defined(SUNKBD_EMULATE_ATKBD) 116163890Smariusstatic int keycode2scancode(int keycode, int shift, int up); 117163890Smarius#endif 118122470Sjake 119122470Sjakestatic keyboard_switch_t sunkbdsw = { 120122470Sjake sunkbd_probe, 121122470Sjake sunkbd_init, 122122470Sjake sunkbd_term, 123122470Sjake sunkbd_intr, 124122470Sjake sunkbd_test_if, 125122470Sjake sunkbd_enable, 126122470Sjake sunkbd_disable, 127122470Sjake sunkbd_read, 128122470Sjake sunkbd_check, 129122470Sjake sunkbd_read_char, 130122470Sjake sunkbd_check_char, 131122470Sjake sunkbd_ioctl, 132122470Sjake sunkbd_lock, 133122470Sjake sunkbd_clear_state, 134122470Sjake sunkbd_get_state, 135122470Sjake sunkbd_set_state, 136122470Sjake genkbd_get_fkeystr, 137122470Sjake sunkbd_poll_mode, 138122470Sjake sunkbd_diag 139122470Sjake}; 140122470Sjake 141122470SjakeKEYBOARD_DRIVER(sunkbd, sunkbdsw, sunkbd_configure); 142122470Sjake 143122470Sjakestatic struct sunkbd_softc sunkbd_softc; 144122470Sjakestatic struct uart_devinfo uart_keyboard; 145122470Sjake 146163890Smarius#if defined(SUNKBD_EMULATE_ATKBD) 147163890Smarius 148163890Smarius#define SCAN_PRESS 0x000 149163890Smarius#define SCAN_RELEASE 0x080 150163890Smarius#define SCAN_PREFIX_E0 0x100 151163890Smarius#define SCAN_PREFIX_E1 0x200 152163890Smarius#define SCAN_PREFIX_CTL 0x400 153163890Smarius#define SCAN_PREFIX_SHIFT 0x800 154163890Smarius#define SCAN_PREFIX (SCAN_PREFIX_E0 | SCAN_PREFIX_E1 | \ 155163890Smarius SCAN_PREFIX_CTL | SCAN_PREFIX_SHIFT) 156163890Smarius 157163890Smarius#define NOTR 0x0 /* no translation */ 158163890Smarius 159163890Smariusstatic const uint8_t sunkbd_trtab[] = { 160163890Smarius NOTR, 0x6d, 0x78, 0x6e, 0x79, 0x3b, 0x3c, 0x44, /* 0x00 - 0x07 */ 161163890Smarius 0x3d, 0x57, 0x3e, 0x58, 0x3f, 0x5d, 0x40, NOTR, /* 0x08 - 0x0f */ 162163890Smarius 0x41, 0x42, 0x43, 0x38, 0x5f, 0x68, 0x5c, 0x46, /* 0x10 - 0x17 */ 163169173Smarius 0x61, 0x6f, 0x70, 0x64, 0x62, 0x01, 0x02, 0x03, /* 0x18 - 0x1f */ 164163890Smarius 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, /* 0x20 - 0x27 */ 165163890Smarius 0x0c, 0x0d, 0x29, 0x0e, 0x66, 0x77, 0x5b, 0x37, /* 0x28 - 0x2f */ 166169173Smarius 0x7a, 0x71, 0x53, 0x74, 0x5e, 0x0f, 0x10, 0x11, /* 0x30 - 0x37 */ 167163890Smarius 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, /* 0x38 - 0x3f */ 168163890Smarius 0x1a, 0x1b, 0x67, 0x6b, 0x47, 0x48, 0x49, 0x4a, /* 0x40 - 0x47 */ 169169173Smarius 0x73, 0x72, 0x63, NOTR, 0x1d, 0x1e, 0x1f, 0x20, /* 0x48 - 0x4f */ 170163890Smarius 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, /* 0x50 - 0x57 */ 171163890Smarius 0x2b, 0x1c, 0x59, 0x4b, 0x4c, 0x4d, 0x52, 0x75, /* 0x58 - 0x5f */ 172163890Smarius 0x60, 0x76, 0x45, 0x2a, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x60 - 0x67 */ 173163890Smarius 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, NOTR, /* 0x68 - 0x6f */ 174163890Smarius 0x4f, 0x50, 0x51, NOTR, NOTR, NOTR, 0x6c, 0x3a, /* 0x70 - 0x77 */ 175163890Smarius 0x69, 0x39, 0x6a, 0x65, 0x56, 0x4e, NOTR, NOTR /* 0x78 - 0x7f */ 176122470Sjake}; 177122470Sjake 178163890Smarius#endif 179163890Smarius 180122470Sjakestatic int 181122470Sjakesunkbd_probe_keyboard(struct uart_devinfo *di) 182122470Sjake{ 183163890Smarius int c, id, ltries, tries; 184122470Sjake 185122470Sjake for (tries = 5; tries != 0; tries--) { 186122470Sjake uart_putc(di, SKBD_CMD_RESET); 187122470Sjake for (ltries = 1000; ltries != 0; ltries--) { 188122470Sjake if (uart_poll(di) == SKBD_RSP_RESET) 189122470Sjake break; 190122470Sjake DELAY(1000); 191122470Sjake } 192122470Sjake if (ltries == 0) 193122470Sjake continue; 194163890Smarius id = -1; 195122470Sjake for (ltries = 1000; ltries != 0; ltries--) { 196163890Smarius switch (c = uart_poll(di)) { 197163890Smarius case -1: 198122470Sjake break; 199163890Smarius case SKBD_RSP_IDLE: 200163890Smarius return (id); 201163890Smarius default: 202163890Smarius id = c; 203163890Smarius } 204122470Sjake DELAY(1000); 205122470Sjake } 206122470Sjake } 207122470Sjake return (-1); 208122470Sjake} 209122470Sjake 210122470Sjakestatic int sunkbd_attach(struct uart_softc *sc); 211122470Sjakestatic void sunkbd_uart_intr(void *arg); 212122470Sjake 213122470Sjakestatic int 214122470Sjakesunkbd_configure(int flags) 215122470Sjake{ 216122470Sjake struct sunkbd_softc *sc; 217122470Sjake 218146975Smarius /* 219146975Smarius * We are only prepared to be used for the high-level console 220146975Smarius * when the keyboard is both configured and attached. 221146975Smarius */ 222146975Smarius if (!(flags & KB_CONF_PROBE_ONLY)) { 223146975Smarius if (KBD_IS_INITIALIZED(&sunkbd_softc.sc_kbd)) 224146975Smarius goto found; 225146975Smarius else 226146475Smarius return (0); 227146475Smarius } 228146475Smarius 229146975Smarius if (uart_cpu_getdev(UART_DEV_KEYBOARD, &uart_keyboard)) 230146975Smarius return (0); 231146975Smarius if (uart_probe(&uart_keyboard)) 232146975Smarius return (0); 233146975Smarius uart_init(&uart_keyboard); 234146975Smarius 235146975Smarius uart_keyboard.type = UART_DEV_KEYBOARD; 236146975Smarius uart_keyboard.attach = sunkbd_attach; 237146975Smarius uart_add_sysdev(&uart_keyboard); 238146975Smarius 239163890Smarius if (sunkbd_probe_keyboard(&uart_keyboard) != KB_SUN4) 240141081Smarcel return (0); 241141081Smarcel 242122470Sjake sc = &sunkbd_softc; 243122470Sjake callout_init(&sc->sc_repeat_callout, 0); 244163890Smarius sunkbd_clear_state(&sc->sc_kbd); 245122470Sjake 246163890Smarius#if defined(SUNKBD_EMULATE_ATKBD) 247163890Smarius kbd_init_struct(&sc->sc_kbd, SUNKBD_DRIVER_NAME, KB_101, 0, 0, 0, 0); 248163890Smarius kbd_set_maps(&sc->sc_kbd, &key_map, &accent_map, fkey_tab, 249163890Smarius sizeof(fkey_tab) / sizeof(fkey_tab[0])); 250163890Smarius#else 251163890Smarius kbd_init_struct(&sc->sc_kbd, SUNKBD_DRIVER_NAME, KB_OTHER, 0, 0, 0, 0); 252122470Sjake kbd_set_maps(&sc->sc_kbd, &keymap_sun_us_unix_kbd, 253122470Sjake &accentmap_sun_us_unix_kbd, fkey_tab, 254122470Sjake sizeof(fkey_tab) / sizeof(fkey_tab[0])); 255163890Smarius#endif 256122470Sjake sc->sc_mode = K_XLATE; 257122470Sjake kbd_register(&sc->sc_kbd); 258122470Sjake 259122470Sjake sc->sc_sysdev = &uart_keyboard; 260122470Sjake 261146475Smarius found: 262146475Smarius /* Return number of found keyboards. */ 263146475Smarius return (1); 264122470Sjake} 265122470Sjake 266122470Sjakestatic int 267122470Sjakesunkbd_attach(struct uart_softc *sc) 268122470Sjake{ 269122470Sjake 270141081Smarcel /* 271141081Smarcel * Don't attach if we didn't probe the keyboard. Note that 272141081Smarcel * the UART is still marked as a system device in that case. 273141081Smarcel */ 274141081Smarcel if (sunkbd_softc.sc_sysdev == NULL) { 275141081Smarcel device_printf(sc->sc_dev, "keyboard not present\n"); 276141081Smarcel return (0); 277141081Smarcel } 278141081Smarcel 279122470Sjake if (sc->sc_sysdev != NULL) { 280122470Sjake sunkbd_softc.sc_uart = sc; 281122470Sjake 282127740Smarcel#ifdef KBD_INSTALL_CDEV 283122470Sjake kbd_attach(&sunkbd_softc.sc_kbd); 284127740Smarcel#endif 285122470Sjake sunkbd_enable(&sunkbd_softc.sc_kbd); 286122470Sjake 287151658Sjhb swi_add(&tty_intr_event, uart_driver_name, sunkbd_uart_intr, 288122470Sjake &sunkbd_softc, SWI_TTY, INTR_TYPE_TTY, &sc->sc_softih); 289122470Sjake 290122470Sjake sc->sc_opened = 1; 291146975Smarius KBD_INIT_DONE(&sunkbd_softc.sc_kbd); 292122470Sjake } 293122470Sjake 294122470Sjake return (0); 295122470Sjake} 296122470Sjake 297122470Sjakestatic void 298122470Sjakesunkbd_uart_intr(void *arg) 299122470Sjake{ 300122470Sjake struct sunkbd_softc *sc = arg; 301122470Sjake int pend; 302122470Sjake 303122470Sjake if (sc->sc_uart->sc_leaving) 304122470Sjake return; 305122470Sjake 306122470Sjake pend = atomic_readandclear_32(&sc->sc_uart->sc_ttypend); 307155971Smarcel if (!(pend & SER_INT_MASK)) 308122470Sjake return; 309122470Sjake 310155971Smarcel if (pend & SER_INT_RXREADY) { 311122470Sjake if (KBD_IS_ACTIVE(&sc->sc_kbd) && KBD_IS_BUSY(&sc->sc_kbd)) { 312122470Sjake sc->sc_kbd.kb_callback.kc_func(&sc->sc_kbd, 313122470Sjake KBDIO_KEYINPUT, sc->sc_kbd.kb_callback.kc_arg); 314122470Sjake } 315122470Sjake } 316122470Sjake} 317122470Sjake 318122470Sjakestatic int 319122470Sjakesunkbd_probe(int unit, void *arg, int flags) 320122470Sjake{ 321163890Smarius 322122470Sjake TODO; 323122470Sjake return (0); 324122470Sjake} 325122470Sjake 326122470Sjakestatic int 327122470Sjakesunkbd_init(int unit, keyboard_t **kbdp, void *arg, int flags) 328122470Sjake{ 329163890Smarius 330122470Sjake TODO; 331122470Sjake return (0); 332122470Sjake} 333122470Sjake 334122470Sjakestatic int 335122470Sjakesunkbd_term(keyboard_t *kbd) 336122470Sjake{ 337163890Smarius 338122470Sjake TODO; 339122470Sjake return (0); 340122470Sjake} 341122470Sjake 342122470Sjakestatic int 343122470Sjakesunkbd_intr(keyboard_t *kbd, void *arg) 344122470Sjake{ 345163890Smarius 346122470Sjake TODO; 347122470Sjake return (0); 348122470Sjake} 349122470Sjake 350122470Sjakestatic int 351122470Sjakesunkbd_test_if(keyboard_t *kbd) 352122470Sjake{ 353163890Smarius 354122470Sjake TODO; 355122470Sjake return (0); 356122470Sjake} 357122470Sjake 358122470Sjakestatic int 359122470Sjakesunkbd_enable(keyboard_t *kbd) 360122470Sjake{ 361163890Smarius 362122470Sjake KBD_ACTIVATE(kbd); 363122470Sjake return (0); 364122470Sjake} 365122470Sjake 366122470Sjakestatic int 367122470Sjakesunkbd_disable(keyboard_t *kbd) 368122470Sjake{ 369163890Smarius 370122470Sjake KBD_DEACTIVATE(kbd); 371122470Sjake return (0); 372122470Sjake} 373122470Sjake 374122470Sjakestatic int 375122470Sjakesunkbd_read(keyboard_t *kbd, int wait) 376122470Sjake{ 377163890Smarius 378122470Sjake TODO; 379122470Sjake return (0); 380122470Sjake} 381122470Sjake 382122470Sjakestatic int 383122470Sjakesunkbd_check(keyboard_t *kbd) 384122470Sjake{ 385163890Smarius struct sunkbd_softc *sc; 386163890Smarius 387163890Smarius if (!KBD_IS_ACTIVE(kbd)) 388163890Smarius return (FALSE); 389163890Smarius 390163890Smarius sc = (struct sunkbd_softc *)kbd; 391163890Smarius 392163890Smarius#if defined(SUNKBD_EMULATE_ATKBD) 393163890Smarius if (sc->sc_buffered_char[0]) 394163890Smarius return (TRUE); 395163890Smarius#endif 396163890Smarius 397163890Smarius if (sc->sc_repeating) 398163890Smarius return (TRUE); 399163890Smarius 400163890Smarius if (sc->sc_uart != NULL && !uart_rx_empty(sc->sc_uart)) 401163890Smarius return (TRUE); 402163890Smarius 403163890Smarius if (sc->sc_polling != 0 && sc->sc_sysdev != NULL && 404166100Smarius uart_rxready(sc->sc_sysdev)) 405163890Smarius return (TRUE); 406163890Smarius 407163890Smarius return (FALSE); 408122470Sjake} 409122470Sjake 410122470Sjakestatic u_int 411122470Sjakesunkbd_read_char(keyboard_t *kbd, int wait) 412122470Sjake{ 413122470Sjake struct sunkbd_softc *sc; 414163890Smarius int key, release, repeated, suncode; 415122470Sjake 416122470Sjake sc = (struct sunkbd_softc *)kbd; 417163890Smarius 418163890Smarius#if defined(SUNKBD_EMULATE_ATKBD) 419163890Smarius if (sc->sc_mode == K_RAW && sc->sc_buffered_char[0]) { 420163890Smarius key = sc->sc_buffered_char[0]; 421163890Smarius if (key & SCAN_PREFIX) { 422163890Smarius sc->sc_buffered_char[0] = key & ~SCAN_PREFIX; 423163890Smarius return ((key & SCAN_PREFIX_E0) ? 0xe0 : 0xe1); 424163890Smarius } else { 425163890Smarius sc->sc_buffered_char[0] = sc->sc_buffered_char[1]; 426163890Smarius sc->sc_buffered_char[1] = 0; 427163890Smarius return (key); 428163890Smarius } 429163890Smarius } 430163890Smarius#endif 431163890Smarius 432163890Smarius repeated = 0; 433122470Sjake if (sc->sc_repeating) { 434163890Smarius repeated = 1; 435122470Sjake sc->sc_repeating = 0; 436122470Sjake callout_reset(&sc->sc_repeat_callout, hz / 10, 437122470Sjake sunkbd_repeat, sc); 438163890Smarius suncode = sc->sc_repeat_key; 439163890Smarius goto process_code; 440122470Sjake } 441122470Sjake 442122470Sjake for (;;) { 443163890Smarius next_code: 444163890Smarius if (!(sc->sc_flags & KPCOMPOSE) && (sc->sc_composed_char > 0)) { 445163890Smarius key = sc->sc_composed_char; 446163890Smarius sc->sc_composed_char = 0; 447163890Smarius if (key > UCHAR_MAX) 448163890Smarius return (ERRKEY); 449163890Smarius return (key); 450163890Smarius } 451122470Sjake 452122470Sjake if (sc->sc_uart != NULL && !uart_rx_empty(sc->sc_uart)) { 453163890Smarius suncode = uart_rx_get(sc->sc_uart); 454122470Sjake } else if (sc->sc_polling != 0 && sc->sc_sysdev != NULL) { 455122470Sjake if (wait) 456163890Smarius suncode = uart_getc(sc->sc_sysdev); 457163890Smarius else if ((suncode = uart_poll(sc->sc_sysdev)) == -1) 458122470Sjake return (NOKEY); 459122470Sjake } else { 460122470Sjake return (NOKEY); 461122470Sjake } 462122470Sjake 463163890Smarius switch (suncode) { 464122470Sjake case SKBD_RSP_IDLE: 465122470Sjake break; 466122470Sjake default: 467163890Smarius process_code: 468122470Sjake ++kbd->kb_count; 469163890Smarius key = SKBD_KEY_CHAR(suncode); 470163890Smarius release = suncode & SKBD_KEY_RELEASE; 471163890Smarius if (!repeated) { 472163890Smarius if (release == 0) { 473163890Smarius callout_reset(&sc->sc_repeat_callout, 474163890Smarius hz / 2, sunkbd_repeat, sc); 475163890Smarius sc->sc_repeat_key = suncode; 476163890Smarius } else if (sc->sc_repeat_key == key) { 477122470Sjake callout_stop(&sc->sc_repeat_callout); 478122470Sjake sc->sc_repeat_key = -1; 479122470Sjake } 480122470Sjake } 481122470Sjake 482163890Smarius#if defined(SUNKBD_EMULATE_ATKBD) 483163890Smarius key = sunkbd_trtab[key]; 484163890Smarius if (key == NOTR) 485163890Smarius return (NOKEY); 486163890Smarius 487163890Smarius if (!repeated) { 488163890Smarius switch (key) { 489163890Smarius case 0x1d: /* ctrl */ 490163890Smarius if (release != 0) 491163890Smarius sc->sc_flags &= ~CTLS; 492163890Smarius else 493163890Smarius sc->sc_flags |= CTLS; 494163890Smarius break; 495163890Smarius case 0x2a: /* left shift */ 496163890Smarius case 0x36: /* right shift */ 497163890Smarius if (release != 0) 498163890Smarius sc->sc_flags &= ~SHIFTS; 499163890Smarius else 500163890Smarius sc->sc_flags |= SHIFTS; 501163890Smarius break; 502163890Smarius case 0x38: /* alt */ 503163890Smarius case 0x5d: /* altgr */ 504163890Smarius if (release != 0) 505163890Smarius sc->sc_flags &= ~ALTS; 506163890Smarius else 507163890Smarius sc->sc_flags |= ALTS; 508163890Smarius break; 509163890Smarius } 510163890Smarius } 511163890Smarius if (sc->sc_mode == K_RAW) { 512163890Smarius key = keycode2scancode(key, sc->sc_flags, 513163890Smarius release); 514163890Smarius if (key & SCAN_PREFIX) { 515163890Smarius if (key & SCAN_PREFIX_CTL) { 516163890Smarius sc->sc_buffered_char[0] = 517163890Smarius 0x1d | (key & SCAN_RELEASE); 518163890Smarius sc->sc_buffered_char[1] = 519163890Smarius key & ~SCAN_PREFIX; 520163890Smarius } else if (key & SCAN_PREFIX_SHIFT) { 521163890Smarius sc->sc_buffered_char[0] = 522163890Smarius 0x2a | (key & SCAN_RELEASE); 523163890Smarius sc->sc_buffered_char[1] = 524163890Smarius key & ~SCAN_PREFIX_SHIFT; 525163890Smarius } else { 526163890Smarius sc->sc_buffered_char[0] = 527163890Smarius key & ~SCAN_PREFIX; 528163890Smarius sc->sc_buffered_char[1] = 0; 529163890Smarius } 530163890Smarius return ((key & SCAN_PREFIX_E0) ? 531163890Smarius 0xe0 : 0xe1); 532163890Smarius } 533122470Sjake return (key); 534163890Smarius } 535163890Smarius switch (key) { 536163890Smarius case 0x5c: /* print screen */ 537163890Smarius if (sc->sc_flags & ALTS) 538163890Smarius key = 0x54; /* sysrq */ 539163890Smarius break; 540163890Smarius case 0x68: /* pause/break */ 541163890Smarius if (sc->sc_flags & CTLS) 542163890Smarius key = 0x6c; /* break */ 543163890Smarius break; 544163890Smarius } 545122470Sjake 546163890Smarius if (sc->sc_mode == K_CODE) 547163890Smarius return (key | release); 548163890Smarius#else 549163890Smarius if (sc->sc_mode == K_RAW || sc->sc_mode == K_CODE) 550163890Smarius return (suncode); 551163890Smarius#endif 552163890Smarius 553163890Smarius#if defined(SUNKBD_EMULATE_ATKBD) 554163890Smarius if (key == 0x38) { /* left alt (KP compose key) */ 555163890Smarius#else 556163890Smarius if (key == 0x13) { /* left alt (KP compose key) */ 557163890Smarius#endif 558163890Smarius if (release != 0) { 559166100Smarius if (sc->sc_flags & KPCOMPOSE) { 560166100Smarius sc->sc_flags &= ~KPCOMPOSE; 561166100Smarius if (sc->sc_composed_char > 562166100Smarius UCHAR_MAX) 563166100Smarius sc->sc_composed_char = 564166100Smarius 0; 565163890Smarius } 566163890Smarius } else { 567163890Smarius if (!(sc->sc_flags & KPCOMPOSE)) { 568163890Smarius sc->sc_flags |= KPCOMPOSE; 569163890Smarius sc->sc_composed_char = 0; 570163890Smarius } 571163890Smarius } 572163890Smarius } 573163890Smarius if (sc->sc_flags & KPCOMPOSE) { 574163890Smarius switch (suncode) { 575163890Smarius case 0x44: /* KP 7 */ 576163890Smarius case 0x45: /* KP 8 */ 577163890Smarius case 0x46: /* KP 9 */ 578163890Smarius sc->sc_composed_char *= 10; 579163890Smarius sc->sc_composed_char += suncode - 0x3d; 580163890Smarius if (sc->sc_composed_char > UCHAR_MAX) 581163890Smarius return (ERRKEY); 582163890Smarius goto next_code; 583163890Smarius case 0x5b: /* KP 4 */ 584163890Smarius case 0x5c: /* KP 5 */ 585163890Smarius case 0x5d: /* KP 6 */ 586163890Smarius sc->sc_composed_char *= 10; 587163890Smarius sc->sc_composed_char += suncode - 0x58; 588163890Smarius if (sc->sc_composed_char > UCHAR_MAX) 589163890Smarius return (ERRKEY); 590163890Smarius goto next_code; 591163890Smarius case 0x70: /* KP 1 */ 592163890Smarius case 0x71: /* KP 2 */ 593163890Smarius case 0x72: /* KP 3 */ 594163890Smarius sc->sc_composed_char *= 10; 595163890Smarius sc->sc_composed_char += suncode - 0x6f; 596163890Smarius if (sc->sc_composed_char > UCHAR_MAX) 597163890Smarius return (ERRKEY); 598163890Smarius goto next_code; 599163890Smarius case 0x5e: /* KP 0 */ 600163890Smarius sc->sc_composed_char *= 10; 601163890Smarius if (sc->sc_composed_char > UCHAR_MAX) 602163890Smarius return (ERRKEY); 603163890Smarius goto next_code; 604163890Smarius 605163890Smarius case 0x44 | SKBD_KEY_RELEASE: /* KP 7 */ 606163890Smarius case 0x45 | SKBD_KEY_RELEASE: /* KP 8 */ 607163890Smarius case 0x46 | SKBD_KEY_RELEASE: /* KP 9 */ 608163890Smarius case 0x5b | SKBD_KEY_RELEASE: /* KP 4 */ 609163890Smarius case 0x5c | SKBD_KEY_RELEASE: /* KP 5 */ 610163890Smarius case 0x5d | SKBD_KEY_RELEASE: /* KP 6 */ 611163890Smarius case 0x70 | SKBD_KEY_RELEASE: /* KP 1 */ 612163890Smarius case 0x71 | SKBD_KEY_RELEASE: /* KP 2 */ 613163890Smarius case 0x72 | SKBD_KEY_RELEASE: /* KP 3 */ 614163890Smarius case 0x5e | SKBD_KEY_RELEASE: /* KP 0 */ 615163890Smarius goto next_code; 616163890Smarius default: 617163890Smarius if (sc->sc_composed_char > 0) { 618163890Smarius sc->sc_flags &= ~KPCOMPOSE; 619163890Smarius sc->sc_composed_char = 0; 620163890Smarius return (ERRKEY); 621163890Smarius } 622163890Smarius } 623163890Smarius } 624163890Smarius 625163890Smarius key = genkbd_keyaction(kbd, key, release, 626122470Sjake &sc->sc_state, &sc->sc_accents); 627163890Smarius if (key != NOKEY || repeated) 628163890Smarius return (key); 629122470Sjake } 630122470Sjake } 631122470Sjake return (0); 632122470Sjake} 633122470Sjake 634122470Sjakestatic int 635122470Sjakesunkbd_check_char(keyboard_t *kbd) 636122470Sjake{ 637163890Smarius struct sunkbd_softc *sc; 638163890Smarius 639163890Smarius if (!KBD_IS_ACTIVE(kbd)) 640163890Smarius return (FALSE); 641163890Smarius 642163890Smarius sc = (struct sunkbd_softc *)kbd; 643163890Smarius if (!(sc->sc_flags & KPCOMPOSE) && (sc->sc_composed_char > 0)) 644163890Smarius return (TRUE); 645163890Smarius 646163890Smarius return (sunkbd_check(kbd)); 647122470Sjake} 648122470Sjake 649122470Sjakestatic int 650122470Sjakesunkbd_ioctl(keyboard_t *kbd, u_long cmd, caddr_t data) 651122470Sjake{ 652122470Sjake struct sunkbd_softc *sc; 653163890Smarius int c, error; 654162711Sru#if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5) 655162711Sru int ival; 656162711Sru#endif 657122470Sjake 658122470Sjake sc = (struct sunkbd_softc *)kbd; 659122470Sjake error = 0; 660122470Sjake switch (cmd) { 661122470Sjake case KDGKBMODE: 662122470Sjake *(int *)data = sc->sc_mode; 663122470Sjake break; 664162711Sru#if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5) 665162711Sru case _IO('K', 7): 666162711Sru ival = IOCPARM_IVAL(data); 667162711Sru data = (caddr_t)&ival; 668162711Sru /* FALLTHROUGH */ 669162711Sru#endif 670122470Sjake case KDSKBMODE: 671122470Sjake switch (*(int *)data) { 672122470Sjake case K_XLATE: 673122470Sjake if (sc->sc_mode != K_XLATE) { 674122470Sjake /* make lock key state and LED state match */ 675122470Sjake sc->sc_state &= ~LOCK_MASK; 676122470Sjake sc->sc_state |= KBD_LED_VAL(kbd); 677122470Sjake } 678122470Sjake /* FALLTHROUGH */ 679122470Sjake case K_RAW: 680122470Sjake case K_CODE: 681122470Sjake if (sc->sc_mode != *(int *)data) { 682122470Sjake sunkbd_clear_state(kbd); 683122470Sjake sc->sc_mode = *(int *)data; 684122470Sjake } 685122470Sjake break; 686122470Sjake default: 687122470Sjake error = EINVAL; 688122470Sjake break; 689122470Sjake } 690122470Sjake break; 691122470Sjake case KDGETLED: 692122470Sjake *(int *)data = KBD_LED_VAL(kbd); 693122470Sjake break; 694162711Sru#if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5) 695162711Sru case _IO('K', 66): 696162711Sru ival = IOCPARM_IVAL(data); 697162711Sru data = (caddr_t)&ival; 698162711Sru /* FALLTHROUGH */ 699162711Sru#endif 700122470Sjake case KDSETLED: 701122470Sjake if (*(int *)data & ~LOCK_MASK) { 702122470Sjake error = EINVAL; 703122470Sjake break; 704122470Sjake } 705163890Smarius if (sc->sc_sysdev == NULL) 706122470Sjake break; 707163890Smarius c = 0; 708122470Sjake if (*(int *)data & CLKED) 709163890Smarius c |= SKBD_LED_CAPSLOCK; 710122470Sjake if (*(int *)data & NLKED) 711163890Smarius c |= SKBD_LED_NUMLOCK; 712122470Sjake if (*(int *)data & SLKED) 713163890Smarius c |= SKBD_LED_SCROLLLOCK; 714163890Smarius uart_lock(sc->sc_sysdev->hwmtx); 715168281Smarcel sc->sc_sysdev->ops->putc(&sc->sc_sysdev->bas, SKBD_CMD_SETLED); 716168281Smarcel sc->sc_sysdev->ops->putc(&sc->sc_sysdev->bas, c); 717163890Smarius uart_unlock(sc->sc_sysdev->hwmtx); 718122470Sjake KBD_LED_VAL(kbd) = *(int *)data; 719122470Sjake break; 720122470Sjake case KDGKBSTATE: 721122470Sjake *(int *)data = sc->sc_state & LOCK_MASK; 722122470Sjake break; 723162711Sru#if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5) 724162711Sru case _IO('K', 20): 725162711Sru ival = IOCPARM_IVAL(data); 726162711Sru data = (caddr_t)&ival; 727162711Sru /* FALLTHROUGH */ 728162711Sru#endif 729122470Sjake case KDSKBSTATE: 730122470Sjake if (*(int *)data & ~LOCK_MASK) { 731122470Sjake error = EINVAL; 732122470Sjake break; 733122470Sjake } 734122470Sjake sc->sc_state &= ~LOCK_MASK; 735122470Sjake sc->sc_state |= *(int *)data; 736162711Sru /* set LEDs and quit */ 737162711Sru return (sunkbd_ioctl(kbd, KDSETLED, data)); 738122470Sjake case KDSETREPEAT: 739122470Sjake case KDSETRAD: 740122470Sjake break; 741122470Sjake case PIO_KEYMAP: 742224126Sed case OPIO_KEYMAP: 743122470Sjake case PIO_KEYMAPENT: 744122470Sjake case PIO_DEADKEYMAP: 745122470Sjake default: 746122470Sjake return (genkbd_commonioctl(kbd, cmd, data)); 747122470Sjake } 748122470Sjake return (error); 749122470Sjake} 750122470Sjake 751122470Sjakestatic int 752122470Sjakesunkbd_lock(keyboard_t *kbd, int lock) 753122470Sjake{ 754163890Smarius 755122470Sjake TODO; 756122470Sjake return (0); 757122470Sjake} 758122470Sjake 759122470Sjakestatic void 760122470Sjakesunkbd_clear_state(keyboard_t *kbd) 761122470Sjake{ 762163890Smarius struct sunkbd_softc *sc; 763163890Smarius 764163890Smarius sc = (struct sunkbd_softc *)kbd; 765163890Smarius sc->sc_repeat_key = -1; 766163890Smarius sc->sc_accents = 0; 767163890Smarius sc->sc_composed_char = 0; 768163890Smarius sc->sc_flags = 0; 769163890Smarius sc->sc_polling = 0; 770163890Smarius sc->sc_repeating = 0; 771163890Smarius sc->sc_state &= LOCK_MASK; /* Preserve locking key state. */ 772163890Smarius 773163890Smarius#if defined(SUNKBD_EMULATE_ATKBD) 774163890Smarius sc->sc_buffered_char[0] = 0; 775163890Smarius sc->sc_buffered_char[1] = 0; 776163890Smarius#endif 777122470Sjake} 778122470Sjake 779122470Sjakestatic int 780122470Sjakesunkbd_get_state(keyboard_t *kbd, void *buf, size_t len) 781122470Sjake{ 782163890Smarius 783122470Sjake TODO; 784122470Sjake return (0); 785122470Sjake} 786122470Sjake 787122470Sjakestatic int 788122470Sjakesunkbd_set_state(keyboard_t *kbd, void *buf, size_t len) 789122470Sjake{ 790163890Smarius 791122470Sjake TODO; 792122470Sjake return (0); 793122470Sjake} 794122470Sjake 795122470Sjakestatic int 796122470Sjakesunkbd_poll_mode(keyboard_t *kbd, int on) 797122470Sjake{ 798122470Sjake struct sunkbd_softc *sc; 799122470Sjake 800122470Sjake sc = (struct sunkbd_softc *)kbd; 801122470Sjake if (on) 802122470Sjake sc->sc_polling++; 803122470Sjake else 804122470Sjake sc->sc_polling--; 805122470Sjake return (0); 806122470Sjake} 807122470Sjake 808122470Sjakestatic void 809122470Sjakesunkbd_diag(keyboard_t *kbd, int level) 810122470Sjake{ 811163890Smarius 812122470Sjake TODO; 813122470Sjake} 814122470Sjake 815122470Sjakestatic void 816122470Sjakesunkbd_repeat(void *v) 817122470Sjake{ 818122470Sjake struct sunkbd_softc *sc = v; 819122470Sjake 820162424Semax if (KBD_IS_ACTIVE(&sc->sc_kbd) && KBD_IS_BUSY(&sc->sc_kbd)) { 821162424Semax if (sc->sc_repeat_key != -1) { 822162424Semax sc->sc_repeating = 1; 823162424Semax sc->sc_kbd.kb_callback.kc_func(&sc->sc_kbd, 824162424Semax KBDIO_KEYINPUT, sc->sc_kbd.kb_callback.kc_arg); 825162424Semax } 826122470Sjake } 827122470Sjake} 828163890Smarius 829163890Smarius#if defined(SUNKBD_EMULATE_ATKBD) 830163890Smariusstatic int 831163890Smariuskeycode2scancode(int keycode, int shift, int up) 832163890Smarius{ 833163890Smarius static const int scan[] = { 834163890Smarius /* KP enter, right ctrl, KP divide */ 835163890Smarius 0x1c , 0x1d , 0x35 , 836163890Smarius /* print screen */ 837163890Smarius 0x37 | SCAN_PREFIX_SHIFT, 838163890Smarius /* right alt, home, up, page up, left, right, end */ 839163890Smarius 0x38, 0x47, 0x48, 0x49, 0x4b, 0x4d, 0x4f, 840163890Smarius /* down, page down, insert, delete */ 841163890Smarius 0x50, 0x51, 0x52, 0x53, 842163890Smarius /* pause/break (see also below) */ 843163890Smarius 0x46, 844163890Smarius /* 845163890Smarius * MS: left window, right window, menu 846163890Smarius * also Sun: left meta, right meta, compose 847163890Smarius */ 848163890Smarius 0x5b, 0x5c, 0x5d, 849163890Smarius /* Sun type 6 USB */ 850163890Smarius /* help, stop, again, props, undo, front, copy */ 851163890Smarius 0x68, 0x5e, 0x5f, 0x60, 0x61, 0x62, 0x63, 852163890Smarius /* open, paste, find, cut, audiomute, audiolower, audioraise */ 853163890Smarius 0x64, 0x65, 0x66, 0x67, 0x25, 0x1f, 0x1e, 854163890Smarius /* power */ 855163890Smarius 0x20 856163890Smarius }; 857163890Smarius int scancode; 858163890Smarius 859163890Smarius scancode = keycode; 860163890Smarius if ((keycode >= 89) && (keycode < 89 + sizeof(scan) / sizeof(scan[0]))) 861163890Smarius scancode = scan[keycode - 89] | SCAN_PREFIX_E0; 862163890Smarius /* pause/break */ 863163890Smarius if ((keycode == 104) && !(shift & CTLS)) 864163890Smarius scancode = 0x45 | SCAN_PREFIX_E1 | SCAN_PREFIX_CTL; 865163890Smarius if (shift & SHIFTS) 866163890Smarius scancode &= ~SCAN_PREFIX_SHIFT; 867163890Smarius return (scancode | (up ? SCAN_RELEASE : SCAN_PRESS)); 868163890Smarius} 869163890Smarius#endif 870