2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
4 * Copyright (c) 2003 Jake Burkholder.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 #include <sys/cdefs.h>
30 __FBSDID("$FreeBSD$");
32 #include "opt_compat.h"
34 #include "opt_sunkbd.h"
36 #if (defined(SUNKBD_EMULATE_ATKBD) && defined(SUNKBD_DFLT_KEYMAP)) || \
37 !defined(SUNKBD_EMULATE_ATKBD)
38 #define KBD_DFLT_KEYMAP
41 #include <sys/param.h>
42 #include <sys/systm.h>
44 #include <sys/interrupt.h>
46 #include <sys/kernel.h>
47 #include <sys/limits.h>
49 #include <machine/bus.h>
51 #include <dev/kbd/kbdreg.h>
52 #include <dev/kbd/kbdtables.h>
54 #include <dev/uart/uart.h>
55 #include <dev/uart/uart_bus.h>
56 #include <dev/uart/uart_cpu.h>
58 #include <dev/uart/uart_kbd_sun.h>
59 #if !defined(SUNKBD_EMULATE_ATKBD)
60 #include <dev/uart/uart_kbd_sun_tables.h>
63 #if defined(SUNKBD_EMULATE_ATKBD) && defined(SUNKBD_DFLT_KEYMAP)
64 #include "sunkbdmap.h"
68 #define SUNKBD_DRIVER_NAME "sunkbd"
70 #define TODO printf("%s: unimplemented", __func__)
74 struct uart_softc *sc_uart;
75 struct uart_devinfo *sc_sysdev;
77 struct callout sc_repeat_callout;
83 #define KPCOMPOSE (1 << 0)
89 #if defined(SUNKBD_EMULATE_ATKBD)
90 int sc_buffered_char[2];
94 static int sunkbd_configure(int flags);
95 static int sunkbd_probe_keyboard(struct uart_devinfo *di);
97 static int sunkbd_probe(int unit, void *arg, int flags);
98 static int sunkbd_init(int unit, keyboard_t **kbdp, void *arg, int flags);
99 static int sunkbd_term(keyboard_t *kbd);
100 static int sunkbd_intr(keyboard_t *kbd, void *arg);
101 static int sunkbd_test_if(keyboard_t *kbd);
102 static int sunkbd_enable(keyboard_t *kbd);
103 static int sunkbd_disable(keyboard_t *kbd);
104 static int sunkbd_read(keyboard_t *kbd, int wait);
105 static int sunkbd_check(keyboard_t *kbd);
106 static u_int sunkbd_read_char(keyboard_t *kbd, int wait);
107 static int sunkbd_check_char(keyboard_t *kbd);
108 static int sunkbd_ioctl(keyboard_t *kbd, u_long cmd, caddr_t data);
109 static int sunkbd_lock(keyboard_t *kbd, int lock);
110 static void sunkbd_clear_state(keyboard_t *kbd);
111 static int sunkbd_get_state(keyboard_t *kbd, void *buf, size_t len);
112 static int sunkbd_set_state(keyboard_t *kbd, void *buf, size_t len);
113 static int sunkbd_poll_mode(keyboard_t *kbd, int on);
114 static void sunkbd_diag(keyboard_t *kbd, int level);
116 static void sunkbd_repeat(void *v);
117 #if defined(SUNKBD_EMULATE_ATKBD)
118 static int keycode2scancode(int keycode, int shift, int up);
121 static keyboard_switch_t sunkbdsw = {
143 KEYBOARD_DRIVER(sunkbd, sunkbdsw, sunkbd_configure);
145 static struct sunkbd_softc sunkbd_softc;
146 static struct uart_devinfo uart_keyboard;
148 #if defined(SUNKBD_EMULATE_ATKBD)
150 #define SCAN_PRESS 0x000
151 #define SCAN_RELEASE 0x080
152 #define SCAN_PREFIX_E0 0x100
153 #define SCAN_PREFIX_E1 0x200
154 #define SCAN_PREFIX_CTL 0x400
155 #define SCAN_PREFIX_SHIFT 0x800
156 #define SCAN_PREFIX (SCAN_PREFIX_E0 | SCAN_PREFIX_E1 | \
157 SCAN_PREFIX_CTL | SCAN_PREFIX_SHIFT)
159 #define NOTR 0x0 /* no translation */
161 static const uint8_t sunkbd_trtab[] = {
162 NOTR, 0x6d, 0x78, 0x6e, 0x79, 0x3b, 0x3c, 0x44, /* 0x00 - 0x07 */
163 0x3d, 0x57, 0x3e, 0x58, 0x3f, 0x5d, 0x40, NOTR, /* 0x08 - 0x0f */
164 0x41, 0x42, 0x43, 0x38, 0x5f, 0x68, 0x5c, 0x46, /* 0x10 - 0x17 */
165 0x61, 0x6f, 0x70, 0x64, 0x62, 0x01, 0x02, 0x03, /* 0x18 - 0x1f */
166 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, /* 0x20 - 0x27 */
167 0x0c, 0x0d, 0x29, 0x0e, 0x66, 0x77, 0x5b, 0x37, /* 0x28 - 0x2f */
168 0x7a, 0x71, 0x53, 0x74, 0x5e, 0x0f, 0x10, 0x11, /* 0x30 - 0x37 */
169 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, /* 0x38 - 0x3f */
170 0x1a, 0x1b, 0x67, 0x6b, 0x47, 0x48, 0x49, 0x4a, /* 0x40 - 0x47 */
171 0x73, 0x72, 0x63, NOTR, 0x1d, 0x1e, 0x1f, 0x20, /* 0x48 - 0x4f */
172 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, /* 0x50 - 0x57 */
173 0x2b, 0x1c, 0x59, 0x4b, 0x4c, 0x4d, 0x52, 0x75, /* 0x58 - 0x5f */
174 0x60, 0x76, 0x45, 0x2a, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x60 - 0x67 */
175 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, NOTR, /* 0x68 - 0x6f */
176 0x4f, 0x50, 0x51, NOTR, NOTR, NOTR, 0x6c, 0x3a, /* 0x70 - 0x77 */
177 0x69, 0x39, 0x6a, 0x65, 0x56, 0x4e, NOTR, NOTR /* 0x78 - 0x7f */
183 sunkbd_probe_keyboard(struct uart_devinfo *di)
185 int c, id, ltries, tries;
187 for (tries = 5; tries != 0; tries--) {
188 uart_putc(di, SKBD_CMD_RESET);
189 for (ltries = 1000; ltries != 0; ltries--) {
190 if (uart_poll(di) == SKBD_RSP_RESET)
197 for (ltries = 1000; ltries != 0; ltries--) {
198 switch (c = uart_poll(di)) {
212 static int sunkbd_attach(struct uart_softc *sc);
213 static void sunkbd_uart_intr(void *arg);
216 sunkbd_configure(int flags)
218 struct sunkbd_softc *sc;
221 * We are only prepared to be used for the high-level console
222 * when the keyboard is both configured and attached.
224 if (!(flags & KB_CONF_PROBE_ONLY)) {
225 if (KBD_IS_INITIALIZED(&sunkbd_softc.sc_kbd))
231 if (uart_cpu_getdev(UART_DEV_KEYBOARD, &uart_keyboard))
233 if (uart_probe(&uart_keyboard))
235 uart_init(&uart_keyboard);
237 uart_keyboard.type = UART_DEV_KEYBOARD;
238 uart_keyboard.attach = sunkbd_attach;
239 uart_add_sysdev(&uart_keyboard);
241 if (sunkbd_probe_keyboard(&uart_keyboard) != KB_SUN4)
245 callout_init(&sc->sc_repeat_callout, 0);
246 sunkbd_clear_state(&sc->sc_kbd);
248 #if defined(SUNKBD_EMULATE_ATKBD)
249 kbd_init_struct(&sc->sc_kbd, SUNKBD_DRIVER_NAME, KB_101, 0, 0, 0, 0);
250 kbd_set_maps(&sc->sc_kbd, &key_map, &accent_map, fkey_tab,
251 sizeof(fkey_tab) / sizeof(fkey_tab[0]));
253 kbd_init_struct(&sc->sc_kbd, SUNKBD_DRIVER_NAME, KB_OTHER, 0, 0, 0, 0);
254 kbd_set_maps(&sc->sc_kbd, &keymap_sun_us_unix_kbd,
255 &accentmap_sun_us_unix_kbd, fkey_tab,
256 sizeof(fkey_tab) / sizeof(fkey_tab[0]));
258 sc->sc_mode = K_XLATE;
259 kbd_register(&sc->sc_kbd);
261 sc->sc_sysdev = &uart_keyboard;
264 /* Return number of found keyboards. */
269 sunkbd_attach(struct uart_softc *sc)
273 * Don't attach if we didn't probe the keyboard. Note that
274 * the UART is still marked as a system device in that case.
276 if (sunkbd_softc.sc_sysdev == NULL) {
277 device_printf(sc->sc_dev, "keyboard not present\n");
281 if (sc->sc_sysdev != NULL) {
282 sunkbd_softc.sc_uart = sc;
284 #ifdef KBD_INSTALL_CDEV
285 kbd_attach(&sunkbd_softc.sc_kbd);
287 sunkbd_enable(&sunkbd_softc.sc_kbd);
289 swi_add(&tty_intr_event, uart_driver_name, sunkbd_uart_intr,
290 &sunkbd_softc, SWI_TTY, INTR_TYPE_TTY, &sc->sc_softih);
293 KBD_INIT_DONE(&sunkbd_softc.sc_kbd);
300 sunkbd_uart_intr(void *arg)
302 struct sunkbd_softc *sc = arg;
305 if (sc->sc_uart->sc_leaving)
308 pend = atomic_readandclear_32(&sc->sc_uart->sc_ttypend);
309 if (!(pend & SER_INT_MASK))
312 if (pend & SER_INT_RXREADY) {
313 if (KBD_IS_ACTIVE(&sc->sc_kbd) && KBD_IS_BUSY(&sc->sc_kbd)) {
314 sc->sc_kbd.kb_callback.kc_func(&sc->sc_kbd,
315 KBDIO_KEYINPUT, sc->sc_kbd.kb_callback.kc_arg);
321 sunkbd_probe(int unit, void *arg, int flags)
329 sunkbd_init(int unit, keyboard_t **kbdp, void *arg, int flags)
337 sunkbd_term(keyboard_t *kbd)
345 sunkbd_intr(keyboard_t *kbd, void *arg)
353 sunkbd_test_if(keyboard_t *kbd)
361 sunkbd_enable(keyboard_t *kbd)
369 sunkbd_disable(keyboard_t *kbd)
377 sunkbd_read(keyboard_t *kbd, int wait)
385 sunkbd_check(keyboard_t *kbd)
387 struct sunkbd_softc *sc;
389 if (!KBD_IS_ACTIVE(kbd))
392 sc = (struct sunkbd_softc *)kbd;
394 #if defined(SUNKBD_EMULATE_ATKBD)
395 if (sc->sc_buffered_char[0])
399 if (sc->sc_repeating)
402 if (sc->sc_uart != NULL && !uart_rx_empty(sc->sc_uart))
405 if (sc->sc_polling != 0 && sc->sc_sysdev != NULL &&
406 uart_rxready(sc->sc_sysdev))
413 sunkbd_read_char(keyboard_t *kbd, int wait)
415 struct sunkbd_softc *sc;
416 int key, release, repeated, suncode;
418 sc = (struct sunkbd_softc *)kbd;
420 #if defined(SUNKBD_EMULATE_ATKBD)
421 if (sc->sc_mode == K_RAW && sc->sc_buffered_char[0]) {
422 key = sc->sc_buffered_char[0];
423 if (key & SCAN_PREFIX) {
424 sc->sc_buffered_char[0] = key & ~SCAN_PREFIX;
425 return ((key & SCAN_PREFIX_E0) ? 0xe0 : 0xe1);
427 sc->sc_buffered_char[0] = sc->sc_buffered_char[1];
428 sc->sc_buffered_char[1] = 0;
435 if (sc->sc_repeating) {
437 sc->sc_repeating = 0;
438 callout_reset(&sc->sc_repeat_callout, hz / 10,
440 suncode = sc->sc_repeat_key;
446 if (!(sc->sc_flags & KPCOMPOSE) && (sc->sc_composed_char > 0)) {
447 key = sc->sc_composed_char;
448 sc->sc_composed_char = 0;
454 if (sc->sc_uart != NULL && !uart_rx_empty(sc->sc_uart)) {
455 suncode = uart_rx_get(sc->sc_uart);
456 } else if (sc->sc_polling != 0 && sc->sc_sysdev != NULL) {
458 suncode = uart_getc(sc->sc_sysdev);
459 else if ((suncode = uart_poll(sc->sc_sysdev)) == -1)
471 key = SKBD_KEY_CHAR(suncode);
472 release = suncode & SKBD_KEY_RELEASE;
475 callout_reset(&sc->sc_repeat_callout,
476 hz / 2, sunkbd_repeat, sc);
477 sc->sc_repeat_key = suncode;
478 } else if (sc->sc_repeat_key == key) {
479 callout_stop(&sc->sc_repeat_callout);
480 sc->sc_repeat_key = -1;
484 #if defined(SUNKBD_EMULATE_ATKBD)
485 key = sunkbd_trtab[key];
491 case 0x1d: /* ctrl */
493 sc->sc_flags &= ~CTLS;
495 sc->sc_flags |= CTLS;
497 case 0x2a: /* left shift */
498 case 0x36: /* right shift */
500 sc->sc_flags &= ~SHIFTS;
502 sc->sc_flags |= SHIFTS;
505 case 0x5d: /* altgr */
507 sc->sc_flags &= ~ALTS;
509 sc->sc_flags |= ALTS;
513 if (sc->sc_mode == K_RAW) {
514 key = keycode2scancode(key, sc->sc_flags,
516 if (key & SCAN_PREFIX) {
517 if (key & SCAN_PREFIX_CTL) {
518 sc->sc_buffered_char[0] =
519 0x1d | (key & SCAN_RELEASE);
520 sc->sc_buffered_char[1] =
522 } else if (key & SCAN_PREFIX_SHIFT) {
523 sc->sc_buffered_char[0] =
524 0x2a | (key & SCAN_RELEASE);
525 sc->sc_buffered_char[1] =
526 key & ~SCAN_PREFIX_SHIFT;
528 sc->sc_buffered_char[0] =
530 sc->sc_buffered_char[1] = 0;
532 return ((key & SCAN_PREFIX_E0) ?
538 case 0x5c: /* print screen */
539 if (sc->sc_flags & ALTS)
540 key = 0x54; /* sysrq */
542 case 0x68: /* pause/break */
543 if (sc->sc_flags & CTLS)
544 key = 0x6c; /* break */
548 if (sc->sc_mode == K_CODE)
549 return (key | release);
551 if (sc->sc_mode == K_RAW || sc->sc_mode == K_CODE)
555 #if defined(SUNKBD_EMULATE_ATKBD)
556 if (key == 0x38) { /* left alt (KP compose key) */
558 if (key == 0x13) { /* left alt (KP compose key) */
561 if (sc->sc_flags & KPCOMPOSE) {
562 sc->sc_flags &= ~KPCOMPOSE;
563 if (sc->sc_composed_char >
565 sc->sc_composed_char =
569 if (!(sc->sc_flags & KPCOMPOSE)) {
570 sc->sc_flags |= KPCOMPOSE;
571 sc->sc_composed_char = 0;
575 if (sc->sc_flags & KPCOMPOSE) {
577 case 0x44: /* KP 7 */
578 case 0x45: /* KP 8 */
579 case 0x46: /* KP 9 */
580 sc->sc_composed_char *= 10;
581 sc->sc_composed_char += suncode - 0x3d;
582 if (sc->sc_composed_char > UCHAR_MAX)
585 case 0x5b: /* KP 4 */
586 case 0x5c: /* KP 5 */
587 case 0x5d: /* KP 6 */
588 sc->sc_composed_char *= 10;
589 sc->sc_composed_char += suncode - 0x58;
590 if (sc->sc_composed_char > UCHAR_MAX)
593 case 0x70: /* KP 1 */
594 case 0x71: /* KP 2 */
595 case 0x72: /* KP 3 */
596 sc->sc_composed_char *= 10;
597 sc->sc_composed_char += suncode - 0x6f;
598 if (sc->sc_composed_char > UCHAR_MAX)
601 case 0x5e: /* KP 0 */
602 sc->sc_composed_char *= 10;
603 if (sc->sc_composed_char > UCHAR_MAX)
607 case 0x44 | SKBD_KEY_RELEASE: /* KP 7 */
608 case 0x45 | SKBD_KEY_RELEASE: /* KP 8 */
609 case 0x46 | SKBD_KEY_RELEASE: /* KP 9 */
610 case 0x5b | SKBD_KEY_RELEASE: /* KP 4 */
611 case 0x5c | SKBD_KEY_RELEASE: /* KP 5 */
612 case 0x5d | SKBD_KEY_RELEASE: /* KP 6 */
613 case 0x70 | SKBD_KEY_RELEASE: /* KP 1 */
614 case 0x71 | SKBD_KEY_RELEASE: /* KP 2 */
615 case 0x72 | SKBD_KEY_RELEASE: /* KP 3 */
616 case 0x5e | SKBD_KEY_RELEASE: /* KP 0 */
619 if (sc->sc_composed_char > 0) {
620 sc->sc_flags &= ~KPCOMPOSE;
621 sc->sc_composed_char = 0;
627 key = genkbd_keyaction(kbd, key, release,
628 &sc->sc_state, &sc->sc_accents);
629 if (key != NOKEY || repeated)
637 sunkbd_check_char(keyboard_t *kbd)
639 struct sunkbd_softc *sc;
641 if (!KBD_IS_ACTIVE(kbd))
644 sc = (struct sunkbd_softc *)kbd;
645 if (!(sc->sc_flags & KPCOMPOSE) && (sc->sc_composed_char > 0))
648 return (sunkbd_check(kbd));
652 sunkbd_ioctl(keyboard_t *kbd, u_long cmd, caddr_t data)
654 struct sunkbd_softc *sc;
656 #if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5)
660 sc = (struct sunkbd_softc *)kbd;
664 *(int *)data = sc->sc_mode;
666 #if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5)
668 ival = IOCPARM_IVAL(data);
669 data = (caddr_t)&ival;
673 switch (*(int *)data) {
675 if (sc->sc_mode != K_XLATE) {
676 /* make lock key state and LED state match */
677 sc->sc_state &= ~LOCK_MASK;
678 sc->sc_state |= KBD_LED_VAL(kbd);
683 if (sc->sc_mode != *(int *)data) {
684 sunkbd_clear_state(kbd);
685 sc->sc_mode = *(int *)data;
694 *(int *)data = KBD_LED_VAL(kbd);
696 #if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5)
698 ival = IOCPARM_IVAL(data);
699 data = (caddr_t)&ival;
703 if (*(int *)data & ~LOCK_MASK) {
707 if (sc->sc_sysdev == NULL)
710 if (*(int *)data & CLKED)
711 c |= SKBD_LED_CAPSLOCK;
712 if (*(int *)data & NLKED)
713 c |= SKBD_LED_NUMLOCK;
714 if (*(int *)data & SLKED)
715 c |= SKBD_LED_SCROLLLOCK;
716 uart_lock(sc->sc_sysdev->hwmtx);
717 sc->sc_sysdev->ops->putc(&sc->sc_sysdev->bas, SKBD_CMD_SETLED);
718 sc->sc_sysdev->ops->putc(&sc->sc_sysdev->bas, c);
719 uart_unlock(sc->sc_sysdev->hwmtx);
720 KBD_LED_VAL(kbd) = *(int *)data;
723 *(int *)data = sc->sc_state & LOCK_MASK;
725 #if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5)
727 ival = IOCPARM_IVAL(data);
728 data = (caddr_t)&ival;
732 if (*(int *)data & ~LOCK_MASK) {
736 sc->sc_state &= ~LOCK_MASK;
737 sc->sc_state |= *(int *)data;
738 /* set LEDs and quit */
739 return (sunkbd_ioctl(kbd, KDSETLED, data));
748 return (genkbd_commonioctl(kbd, cmd, data));
754 sunkbd_lock(keyboard_t *kbd, int lock)
762 sunkbd_clear_state(keyboard_t *kbd)
764 struct sunkbd_softc *sc;
766 sc = (struct sunkbd_softc *)kbd;
767 sc->sc_repeat_key = -1;
769 sc->sc_composed_char = 0;
772 sc->sc_repeating = 0;
773 sc->sc_state &= LOCK_MASK; /* Preserve locking key state. */
775 #if defined(SUNKBD_EMULATE_ATKBD)
776 sc->sc_buffered_char[0] = 0;
777 sc->sc_buffered_char[1] = 0;
782 sunkbd_get_state(keyboard_t *kbd, void *buf, size_t len)
790 sunkbd_set_state(keyboard_t *kbd, void *buf, size_t len)
798 sunkbd_poll_mode(keyboard_t *kbd, int on)
800 struct sunkbd_softc *sc;
802 sc = (struct sunkbd_softc *)kbd;
811 sunkbd_diag(keyboard_t *kbd, int level)
818 sunkbd_repeat(void *v)
820 struct sunkbd_softc *sc = v;
822 if (KBD_IS_ACTIVE(&sc->sc_kbd) && KBD_IS_BUSY(&sc->sc_kbd)) {
823 if (sc->sc_repeat_key != -1) {
824 sc->sc_repeating = 1;
825 sc->sc_kbd.kb_callback.kc_func(&sc->sc_kbd,
826 KBDIO_KEYINPUT, sc->sc_kbd.kb_callback.kc_arg);
831 #if defined(SUNKBD_EMULATE_ATKBD)
833 keycode2scancode(int keycode, int shift, int up)
835 static const int scan[] = {
836 /* KP enter, right ctrl, KP divide */
839 0x37 | SCAN_PREFIX_SHIFT,
840 /* right alt, home, up, page up, left, right, end */
841 0x38, 0x47, 0x48, 0x49, 0x4b, 0x4d, 0x4f,
842 /* down, page down, insert, delete */
843 0x50, 0x51, 0x52, 0x53,
844 /* pause/break (see also below) */
847 * MS: left window, right window, menu
848 * also Sun: left meta, right meta, compose
852 /* help, stop, again, props, undo, front, copy */
853 0x68, 0x5e, 0x5f, 0x60, 0x61, 0x62, 0x63,
854 /* open, paste, find, cut, audiomute, audiolower, audioraise */
855 0x64, 0x65, 0x66, 0x67, 0x25, 0x1f, 0x1e,
862 if ((keycode >= 89) && (keycode < 89 + nitems(scan)))
863 scancode = scan[keycode - 89] | SCAN_PREFIX_E0;
865 if ((keycode == 104) && !(shift & CTLS))
866 scancode = 0x45 | SCAN_PREFIX_E1 | SCAN_PREFIX_CTL;
868 scancode &= ~SCAN_PREFIX_SHIFT;
869 return (scancode | (up ? SCAN_RELEASE : SCAN_PRESS));