17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
56ee4b8d7Ssetje * Common Development and Distribution License (the "License").
66ee4b8d7Ssetje * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate * and limitations under the License.
127c478bd9Sstevel@tonic-gate *
137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * CDDL HEADER END
207c478bd9Sstevel@tonic-gate */
217c478bd9Sstevel@tonic-gate /*
22ae115bc7Smrj * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
237c478bd9Sstevel@tonic-gate * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate */
257c478bd9Sstevel@tonic-gate
267c478bd9Sstevel@tonic-gate /*
277c478bd9Sstevel@tonic-gate * Miniature keyboard driver for bootstrap. This allows keyboard
287c478bd9Sstevel@tonic-gate * support to continue after we take over interrupts and disable
297c478bd9Sstevel@tonic-gate * BIOS keyboard support.
307c478bd9Sstevel@tonic-gate */
317c478bd9Sstevel@tonic-gate
327c478bd9Sstevel@tonic-gate #include <sys/types.h>
33ae115bc7Smrj #include <sys/archsystm.h>
34ae115bc7Smrj #include <sys/boot_console.h>
35ae115bc7Smrj #include "boot_keyboard_table.h"
36ae115bc7Smrj
37ae115bc7Smrj #if defined(_BOOT)
38843e1988Sjohnlev #include "dboot/dboot_asm.h"
39ae115bc7Smrj #include "dboot/dboot_xboot.h"
40843e1988Sjohnlev #endif /* _BOOT */
417c478bd9Sstevel@tonic-gate
427c478bd9Sstevel@tonic-gate /*
437c478bd9Sstevel@tonic-gate * Definitions for BIOS keyboard state. We use BIOS's variable to store
447c478bd9Sstevel@tonic-gate * state, ensuring that we stay in sync with it.
457c478bd9Sstevel@tonic-gate */
467c478bd9Sstevel@tonic-gate #define BIOS_KB_FLAG 0x417
477c478bd9Sstevel@tonic-gate #define BIOS_RIGHT_SHIFT 0x01
487c478bd9Sstevel@tonic-gate #define BIOS_LEFT_SHIFT 0x02
497c478bd9Sstevel@tonic-gate #define BIOS_EITHER_SHIFT (BIOS_LEFT_SHIFT | BIOS_RIGHT_SHIFT)
507c478bd9Sstevel@tonic-gate #define BIOS_CTL_SHIFT 0x04
517c478bd9Sstevel@tonic-gate #define BIOS_ALT_SHIFT 0x08
527c478bd9Sstevel@tonic-gate #define BIOS_SCROLL_STATE 0x10
537c478bd9Sstevel@tonic-gate #define BIOS_NUM_STATE 0x20
547c478bd9Sstevel@tonic-gate #define BIOS_CAPS_STATE 0x40
557c478bd9Sstevel@tonic-gate #define BIOS_INS_STATE 0x80
567c478bd9Sstevel@tonic-gate
577c478bd9Sstevel@tonic-gate #define BIOS_KB_FLAG_1 0x418
587c478bd9Sstevel@tonic-gate #define BIOS_SYS_SHIFT 0x04
597c478bd9Sstevel@tonic-gate #define BIOS_HOLD_STATE 0x08
607c478bd9Sstevel@tonic-gate #define BIOS_SCROLL_SHIFT 0x10
617c478bd9Sstevel@tonic-gate #define BIOS_NUM_SHIFT 0x20
627c478bd9Sstevel@tonic-gate #define BIOS_CAPS_SHIFT 0x40
637c478bd9Sstevel@tonic-gate #define BIOS_INS_SHIFT 0x80
647c478bd9Sstevel@tonic-gate
65843e1988Sjohnlev #if defined(__xpv) && defined(_BOOT)
66843e1988Sjohnlev
67843e1988Sjohnlev /*
68843e1988Sjohnlev * Device memory addresses
69843e1988Sjohnlev *
70843e1988Sjohnlev * In dboot under the hypervisor we don't have any memory mappings
71843e1988Sjohnlev * for the first meg of low memory so we can't access devices there.
72843e1988Sjohnlev * Intead we've mapped the device memory that we need to access into
73843e1988Sjohnlev * a local variable within dboot so we can access the device memory
74843e1988Sjohnlev * there.
75843e1988Sjohnlev */
76843e1988Sjohnlev extern unsigned short *kb_status;
77843e1988Sjohnlev #define kb_flag ((unsigned char *)&kb_status[BIOS_KB_FLAG])
78843e1988Sjohnlev #define kb_flag_1 ((unsigned char *)&kb_status[BIOS_KB_FLAG_1])
79843e1988Sjohnlev
80843e1988Sjohnlev #else /* __xpv && _BOOT */
81843e1988Sjohnlev
82843e1988Sjohnlev /* Device memory addresses */
83*a34c59afSToomas Soome static unsigned char *kb_status = ((unsigned char *)BIOS_KB_FLAG);
84*a34c59afSToomas Soome #define kb_flag (&kb_status[0])
85*a34c59afSToomas Soome #define kb_flag_1 (&kb_status[1])
867c478bd9Sstevel@tonic-gate
87843e1988Sjohnlev #endif /* __xpv && _BOOT */
88843e1988Sjohnlev
897c478bd9Sstevel@tonic-gate /*
907c478bd9Sstevel@tonic-gate * Keyboard controller registers
917c478bd9Sstevel@tonic-gate */
927c478bd9Sstevel@tonic-gate #define I8042_DATA 0x60
937c478bd9Sstevel@tonic-gate #define I8042_STAT 0x64
947c478bd9Sstevel@tonic-gate #define I8042_CMD 0x64
957c478bd9Sstevel@tonic-gate
967c478bd9Sstevel@tonic-gate /*
977c478bd9Sstevel@tonic-gate * Keyboard controller status register bits
987c478bd9Sstevel@tonic-gate */
997c478bd9Sstevel@tonic-gate #define I8042_STAT_OUTBF 0x01
1007c478bd9Sstevel@tonic-gate #define I8042_STAT_INBF 0x02
1017c478bd9Sstevel@tonic-gate #define I8042_STAT_AUXBF 0x20
1027c478bd9Sstevel@tonic-gate
1037c478bd9Sstevel@tonic-gate /*
1047c478bd9Sstevel@tonic-gate * Keyboard controller commands
1057c478bd9Sstevel@tonic-gate */
1067c478bd9Sstevel@tonic-gate #define I8042_RCB 0x20
1077c478bd9Sstevel@tonic-gate #define I8042_WCB 0x60
1087c478bd9Sstevel@tonic-gate
1097c478bd9Sstevel@tonic-gate /*
1107c478bd9Sstevel@tonic-gate * Keyboard commands
1117c478bd9Sstevel@tonic-gate */
1127c478bd9Sstevel@tonic-gate #define KB_SET_LED 0xED /* LED byte follows... */
1137c478bd9Sstevel@tonic-gate #define KB_LED_SCROLL_LOCK 0x01 /* Bits for LED byte */
1147c478bd9Sstevel@tonic-gate #define KB_LED_NUM_LOCK 0x02
1157c478bd9Sstevel@tonic-gate #define KB_LED_CAPS_LOCK 0x04
1167c478bd9Sstevel@tonic-gate
1177c478bd9Sstevel@tonic-gate #ifndef ASSERT
1187c478bd9Sstevel@tonic-gate #define ASSERT(x)
1197c478bd9Sstevel@tonic-gate #endif
1207c478bd9Sstevel@tonic-gate
1217c478bd9Sstevel@tonic-gate #define peek8(p) (*(p))
1227c478bd9Sstevel@tonic-gate #define poke8(p, val) (*(p) = (val))
1237c478bd9Sstevel@tonic-gate
1247c478bd9Sstevel@tonic-gate static struct {
1257c478bd9Sstevel@tonic-gate boolean_t initialized;
1267c478bd9Sstevel@tonic-gate enum { KB_LED_IDLE, KB_LED_COMMAND_SENT, KB_LED_VALUE_SENT }
1277c478bd9Sstevel@tonic-gate led_state;
1287c478bd9Sstevel@tonic-gate int led_commanded;
1297c478bd9Sstevel@tonic-gate /*
1307c478bd9Sstevel@tonic-gate * Possible values:
1317c478bd9Sstevel@tonic-gate *
1327c478bd9Sstevel@tonic-gate * -1 Nothing pending
1337c478bd9Sstevel@tonic-gate * 0x000-0x0ff Pending byte
1347c478bd9Sstevel@tonic-gate * 0x100-0x1ff Needs leading zero, then low byte next.
1357c478bd9Sstevel@tonic-gate *
1367c478bd9Sstevel@tonic-gate * Others undefined.
1377c478bd9Sstevel@tonic-gate */
1387c478bd9Sstevel@tonic-gate int pending;
1397c478bd9Sstevel@tonic-gate } kb = {
1407c478bd9Sstevel@tonic-gate B_FALSE, /* initialized? */
1417c478bd9Sstevel@tonic-gate KB_LED_IDLE, /* LED command state */
1427c478bd9Sstevel@tonic-gate -1, /* commanded LEDs - force refresh */
1437c478bd9Sstevel@tonic-gate -1, /* pending */
1447c478bd9Sstevel@tonic-gate };
1457c478bd9Sstevel@tonic-gate
146ead1aeb9SToomas Soome #define KTAB_STRLEN 3
147ead1aeb9SToomas Soome static char keystringtab[KTAB_STRLEN] = {'\033', '[', ' '};
148ead1aeb9SToomas Soome static int keystring = -1;
149ead1aeb9SToomas Soome
1507c478bd9Sstevel@tonic-gate static int kb_translate(unsigned char code);
1517c478bd9Sstevel@tonic-gate static void kb_send(unsigned char cmd);
1527c478bd9Sstevel@tonic-gate static void kb_update_leds(void);
1537c478bd9Sstevel@tonic-gate static uchar_t kb_calculate_leds(void);
1547c478bd9Sstevel@tonic-gate
1557c478bd9Sstevel@tonic-gate int
kb_getchar(void)1567c478bd9Sstevel@tonic-gate kb_getchar(void)
1577c478bd9Sstevel@tonic-gate {
1587c478bd9Sstevel@tonic-gate int ret;
1597c478bd9Sstevel@tonic-gate
1607c478bd9Sstevel@tonic-gate while (!kb_ischar())
1617c478bd9Sstevel@tonic-gate /* LOOP */;
1627c478bd9Sstevel@tonic-gate
163ead1aeb9SToomas Soome if (keystring >= 0) {
164ead1aeb9SToomas Soome ret = keystringtab[keystring++];
165ead1aeb9SToomas Soome if (keystring == KTAB_STRLEN) {
166ead1aeb9SToomas Soome keystring = -1;
167ead1aeb9SToomas Soome kb.pending = -1;
168ead1aeb9SToomas Soome }
169ead1aeb9SToomas Soome return (ret);
170ead1aeb9SToomas Soome }
171ead1aeb9SToomas Soome
1727c478bd9Sstevel@tonic-gate /*
1737c478bd9Sstevel@tonic-gate * kb_ischar() doesn't succeed without leaving kb.pending
1747c478bd9Sstevel@tonic-gate * set.
1757c478bd9Sstevel@tonic-gate */
1767c478bd9Sstevel@tonic-gate ASSERT(kb.pending >= 0);
1777c478bd9Sstevel@tonic-gate
1787c478bd9Sstevel@tonic-gate if (kb.pending & 0x100) {
1797c478bd9Sstevel@tonic-gate kb.pending &= 0xff;
180ead1aeb9SToomas Soome switch (kb.pending) {
181ead1aeb9SToomas Soome case 'H': /* Up */
182ead1aeb9SToomas Soome keystringtab[2] = 'A';
183ead1aeb9SToomas Soome keystring = 0;
184ead1aeb9SToomas Soome return (kb_getchar());
185ead1aeb9SToomas Soome case 'P': /* Down */
186ead1aeb9SToomas Soome keystringtab[2] = 'B';
187ead1aeb9SToomas Soome keystring = 0;
188ead1aeb9SToomas Soome return (kb_getchar());
189ead1aeb9SToomas Soome case 'M': /* Right */
190ead1aeb9SToomas Soome keystringtab[2] = 'C';
191ead1aeb9SToomas Soome keystring = 0;
192ead1aeb9SToomas Soome return (kb_getchar());
193ead1aeb9SToomas Soome case 'K': /* Left */
194ead1aeb9SToomas Soome keystringtab[2] = 'D';
195ead1aeb9SToomas Soome keystring = 0;
196ead1aeb9SToomas Soome return (kb_getchar());
197ead1aeb9SToomas Soome default:
198ead1aeb9SToomas Soome ret = 0;
199ead1aeb9SToomas Soome }
2007c478bd9Sstevel@tonic-gate } else {
2017c478bd9Sstevel@tonic-gate ret = kb.pending;
2027c478bd9Sstevel@tonic-gate kb.pending = -1;
2037c478bd9Sstevel@tonic-gate }
2047c478bd9Sstevel@tonic-gate
2057c478bd9Sstevel@tonic-gate return (ret);
2067c478bd9Sstevel@tonic-gate }
2077c478bd9Sstevel@tonic-gate
2087c478bd9Sstevel@tonic-gate int
kb_ischar(void)2097c478bd9Sstevel@tonic-gate kb_ischar(void)
2107c478bd9Sstevel@tonic-gate {
2117c478bd9Sstevel@tonic-gate unsigned char buffer_stat;
2127c478bd9Sstevel@tonic-gate unsigned char code;
2137c478bd9Sstevel@tonic-gate unsigned char leds;
2147c478bd9Sstevel@tonic-gate
2157c478bd9Sstevel@tonic-gate if (!kb.initialized) {
2167c478bd9Sstevel@tonic-gate kb_init();
2177c478bd9Sstevel@tonic-gate kb.initialized = B_TRUE;
2187c478bd9Sstevel@tonic-gate }
2197c478bd9Sstevel@tonic-gate
2207c478bd9Sstevel@tonic-gate if (kb.pending >= 0)
2217c478bd9Sstevel@tonic-gate return (1);
2227c478bd9Sstevel@tonic-gate
2237c478bd9Sstevel@tonic-gate for (;;) {
2246ee4b8d7Ssetje buffer_stat = inb(I8042_STAT);
2256ee4b8d7Ssetje if (buffer_stat == 0xff)
2266ee4b8d7Ssetje return (0);
2276ee4b8d7Ssetje buffer_stat &= (I8042_STAT_OUTBF | I8042_STAT_AUXBF);
2287c478bd9Sstevel@tonic-gate
2297c478bd9Sstevel@tonic-gate switch (buffer_stat) {
2307c478bd9Sstevel@tonic-gate case 0:
2317c478bd9Sstevel@tonic-gate case I8042_STAT_AUXBF:
2327c478bd9Sstevel@tonic-gate return (0);
2337c478bd9Sstevel@tonic-gate case (I8042_STAT_OUTBF | I8042_STAT_AUXBF):
2347c478bd9Sstevel@tonic-gate /*
2357c478bd9Sstevel@tonic-gate * Discard unwanted mouse data.
2367c478bd9Sstevel@tonic-gate */
2377c478bd9Sstevel@tonic-gate (void) inb(I8042_DATA);
2387c478bd9Sstevel@tonic-gate continue;
2397c478bd9Sstevel@tonic-gate }
2407c478bd9Sstevel@tonic-gate
2417c478bd9Sstevel@tonic-gate code = inb(I8042_DATA);
2427c478bd9Sstevel@tonic-gate
2437c478bd9Sstevel@tonic-gate switch (code) {
2447c478bd9Sstevel@tonic-gate /*
2457c478bd9Sstevel@tonic-gate * case 0xAA:
2467c478bd9Sstevel@tonic-gate *
2477c478bd9Sstevel@tonic-gate * You might think that we should ignore 0xAA on the
2487c478bd9Sstevel@tonic-gate * grounds that it is the BAT Complete response and will
2497c478bd9Sstevel@tonic-gate * occur on keyboard detach/reattach. Unfortunately,
2507c478bd9Sstevel@tonic-gate * it is ambiguous - this is also the code for a break
2517c478bd9Sstevel@tonic-gate * of the left shift key. Since it will be harmless for
2527c478bd9Sstevel@tonic-gate * us to "spuriously" process a break of Left Shift,
2537c478bd9Sstevel@tonic-gate * we just let the normal code handle it. Perhaps we
2547c478bd9Sstevel@tonic-gate * should take a hint and refresh the LEDs, but I
2557c478bd9Sstevel@tonic-gate * refuse to get very worried about hot-plug issues
2567c478bd9Sstevel@tonic-gate * in this mini-driver.
2577c478bd9Sstevel@tonic-gate */
2587c478bd9Sstevel@tonic-gate case 0xFA:
2597c478bd9Sstevel@tonic-gate
2607c478bd9Sstevel@tonic-gate switch (kb.led_state) {
2617c478bd9Sstevel@tonic-gate case KB_LED_IDLE:
2627c478bd9Sstevel@tonic-gate /*
2637c478bd9Sstevel@tonic-gate * Spurious. Oh well, ignore it.
2647c478bd9Sstevel@tonic-gate */
2657c478bd9Sstevel@tonic-gate break;
2667c478bd9Sstevel@tonic-gate case KB_LED_COMMAND_SENT:
2677c478bd9Sstevel@tonic-gate leds = kb_calculate_leds();
2687c478bd9Sstevel@tonic-gate kb_send(leds);
2697c478bd9Sstevel@tonic-gate kb.led_commanded = leds;
2707c478bd9Sstevel@tonic-gate kb.led_state = KB_LED_VALUE_SENT;
2717c478bd9Sstevel@tonic-gate break;
2727c478bd9Sstevel@tonic-gate case KB_LED_VALUE_SENT:
2737c478bd9Sstevel@tonic-gate kb.led_state = KB_LED_IDLE;
2747c478bd9Sstevel@tonic-gate /*
2757c478bd9Sstevel@tonic-gate * Check for changes made while we were
2767c478bd9Sstevel@tonic-gate * working on the last change.
2777c478bd9Sstevel@tonic-gate */
2787c478bd9Sstevel@tonic-gate kb_update_leds();
2797c478bd9Sstevel@tonic-gate break;
2807c478bd9Sstevel@tonic-gate }
2817c478bd9Sstevel@tonic-gate continue;
2827c478bd9Sstevel@tonic-gate
2837c478bd9Sstevel@tonic-gate case 0xE0:
2847c478bd9Sstevel@tonic-gate case 0xE1:
2857c478bd9Sstevel@tonic-gate /*
2867c478bd9Sstevel@tonic-gate * These are used to distinguish the keys added on
2877c478bd9Sstevel@tonic-gate * the AT-101 keyboard from the original 84 keys.
2887c478bd9Sstevel@tonic-gate * We don't care, and the codes are carefully arranged
2897c478bd9Sstevel@tonic-gate * so that we don't have to.
2907c478bd9Sstevel@tonic-gate */
2917c478bd9Sstevel@tonic-gate continue;
2927c478bd9Sstevel@tonic-gate
2937c478bd9Sstevel@tonic-gate default:
2947c478bd9Sstevel@tonic-gate if (code & 0x80) {
2957c478bd9Sstevel@tonic-gate /* Release */
2967c478bd9Sstevel@tonic-gate code &= 0x7f;
2977c478bd9Sstevel@tonic-gate switch (keyboard_translate[code].normal) {
2987c478bd9Sstevel@tonic-gate case KBTYPE_SPEC_LSHIFT:
2997c478bd9Sstevel@tonic-gate poke8(kb_flag, peek8(kb_flag) &
3007c478bd9Sstevel@tonic-gate ~BIOS_LEFT_SHIFT);
3017c478bd9Sstevel@tonic-gate break;
3027c478bd9Sstevel@tonic-gate case KBTYPE_SPEC_RSHIFT:
3037c478bd9Sstevel@tonic-gate poke8(kb_flag, peek8(kb_flag) &
3047c478bd9Sstevel@tonic-gate ~BIOS_RIGHT_SHIFT);
3057c478bd9Sstevel@tonic-gate break;
3067c478bd9Sstevel@tonic-gate case KBTYPE_SPEC_CTRL:
3077c478bd9Sstevel@tonic-gate poke8(kb_flag, peek8(kb_flag) &
3087c478bd9Sstevel@tonic-gate ~BIOS_CTL_SHIFT);
3097c478bd9Sstevel@tonic-gate break;
3107c478bd9Sstevel@tonic-gate case KBTYPE_SPEC_ALT:
3117c478bd9Sstevel@tonic-gate poke8(kb_flag, peek8(kb_flag) &
3127c478bd9Sstevel@tonic-gate ~BIOS_ALT_SHIFT);
3137c478bd9Sstevel@tonic-gate break;
3147c478bd9Sstevel@tonic-gate case KBTYPE_SPEC_CAPS_LOCK:
3157c478bd9Sstevel@tonic-gate poke8(kb_flag_1, peek8(kb_flag_1) &
3167c478bd9Sstevel@tonic-gate ~BIOS_CAPS_SHIFT);
3177c478bd9Sstevel@tonic-gate break;
3187c478bd9Sstevel@tonic-gate case KBTYPE_SPEC_NUM_LOCK:
3197c478bd9Sstevel@tonic-gate poke8(kb_flag_1, peek8(kb_flag_1) &
3207c478bd9Sstevel@tonic-gate ~BIOS_NUM_SHIFT);
3217c478bd9Sstevel@tonic-gate break;
3227c478bd9Sstevel@tonic-gate case KBTYPE_SPEC_SCROLL_LOCK:
3237c478bd9Sstevel@tonic-gate poke8(kb_flag_1, peek8(kb_flag_1) &
3247c478bd9Sstevel@tonic-gate ~BIOS_SCROLL_SHIFT);
3257c478bd9Sstevel@tonic-gate break;
3267c478bd9Sstevel@tonic-gate default:
3277c478bd9Sstevel@tonic-gate /*
3287c478bd9Sstevel@tonic-gate * Ignore all other releases.
3297c478bd9Sstevel@tonic-gate */
3307c478bd9Sstevel@tonic-gate break;
3317c478bd9Sstevel@tonic-gate }
3327c478bd9Sstevel@tonic-gate } else {
3337c478bd9Sstevel@tonic-gate /* Press */
3347c478bd9Sstevel@tonic-gate
3357c478bd9Sstevel@tonic-gate kb.pending = kb_translate(code);
3367c478bd9Sstevel@tonic-gate if (kb.pending >= 0) {
3377c478bd9Sstevel@tonic-gate return (1);
3387c478bd9Sstevel@tonic-gate }
3397c478bd9Sstevel@tonic-gate }
3407c478bd9Sstevel@tonic-gate }
3417c478bd9Sstevel@tonic-gate }
3427c478bd9Sstevel@tonic-gate }
3437c478bd9Sstevel@tonic-gate
3447c478bd9Sstevel@tonic-gate int
kb_translate(unsigned char code)3457c478bd9Sstevel@tonic-gate kb_translate(unsigned char code)
3467c478bd9Sstevel@tonic-gate {
3477c478bd9Sstevel@tonic-gate struct keyboard_translate *k;
3487c478bd9Sstevel@tonic-gate unsigned short action;
3497c478bd9Sstevel@tonic-gate boolean_t shifted;
3507c478bd9Sstevel@tonic-gate
3517c478bd9Sstevel@tonic-gate k = keyboard_translate + code;
3527c478bd9Sstevel@tonic-gate
3537c478bd9Sstevel@tonic-gate shifted = (peek8(kb_flag) & BIOS_EITHER_SHIFT) != 0;
3547c478bd9Sstevel@tonic-gate
3557c478bd9Sstevel@tonic-gate switch (k->normal & 0xFF00) {
3567c478bd9Sstevel@tonic-gate case KBTYPE_NUMPAD:
3577c478bd9Sstevel@tonic-gate if (peek8(kb_flag) & BIOS_NUM_STATE)
3587c478bd9Sstevel@tonic-gate shifted = !shifted;
3597c478bd9Sstevel@tonic-gate break;
3607c478bd9Sstevel@tonic-gate case KBTYPE_ALPHA:
3617c478bd9Sstevel@tonic-gate if (peek8(kb_flag) & BIOS_CAPS_STATE)
3627c478bd9Sstevel@tonic-gate shifted = !shifted;
3637c478bd9Sstevel@tonic-gate break;
3647c478bd9Sstevel@tonic-gate }
3657c478bd9Sstevel@tonic-gate
3667c478bd9Sstevel@tonic-gate if (peek8(kb_flag) & BIOS_ALT_SHIFT)
3677c478bd9Sstevel@tonic-gate action = k->alted;
3687c478bd9Sstevel@tonic-gate else if (peek8(kb_flag) & BIOS_CTL_SHIFT)
3697c478bd9Sstevel@tonic-gate action = k->ctrled;
3707c478bd9Sstevel@tonic-gate else if (shifted)
3717c478bd9Sstevel@tonic-gate action = k->shifted;
3727c478bd9Sstevel@tonic-gate else
3737c478bd9Sstevel@tonic-gate action = k->normal;
3747c478bd9Sstevel@tonic-gate
3757c478bd9Sstevel@tonic-gate switch (action & 0xFF00) {
3767c478bd9Sstevel@tonic-gate case KBTYPE_NORMAL:
3777c478bd9Sstevel@tonic-gate case KBTYPE_ALPHA:
3787c478bd9Sstevel@tonic-gate return (action & 0xFF);
3797c478bd9Sstevel@tonic-gate
3807c478bd9Sstevel@tonic-gate case KBTYPE_NUMPAD:
3817c478bd9Sstevel@tonic-gate case KBTYPE_FUNC:
3827c478bd9Sstevel@tonic-gate return ((action & 0xFF) | 0x100);
3837c478bd9Sstevel@tonic-gate
3847c478bd9Sstevel@tonic-gate case KBTYPE_SPEC:
3857c478bd9Sstevel@tonic-gate break;
3867c478bd9Sstevel@tonic-gate
3877c478bd9Sstevel@tonic-gate default:
3887c478bd9Sstevel@tonic-gate /*
3897c478bd9Sstevel@tonic-gate * Bad entry.
3907c478bd9Sstevel@tonic-gate */
3917c478bd9Sstevel@tonic-gate ASSERT(0);
3927c478bd9Sstevel@tonic-gate return (-1);
3937c478bd9Sstevel@tonic-gate }
3947c478bd9Sstevel@tonic-gate
3957c478bd9Sstevel@tonic-gate /*
3967c478bd9Sstevel@tonic-gate * Handle special keys, mostly shifts.
3977c478bd9Sstevel@tonic-gate */
3987c478bd9Sstevel@tonic-gate switch (action) {
3997c478bd9Sstevel@tonic-gate case KBTYPE_SPEC_NOP:
4007c478bd9Sstevel@tonic-gate case KBTYPE_SPEC_UNDEF:
4017c478bd9Sstevel@tonic-gate break;
4027c478bd9Sstevel@tonic-gate
4037c478bd9Sstevel@tonic-gate case KBTYPE_SPEC_LSHIFT:
4047c478bd9Sstevel@tonic-gate poke8(kb_flag, peek8(kb_flag) | BIOS_LEFT_SHIFT);
4057c478bd9Sstevel@tonic-gate break;
4067c478bd9Sstevel@tonic-gate
4077c478bd9Sstevel@tonic-gate case KBTYPE_SPEC_RSHIFT:
4087c478bd9Sstevel@tonic-gate poke8(kb_flag, peek8(kb_flag) | BIOS_RIGHT_SHIFT);
4097c478bd9Sstevel@tonic-gate break;
4107c478bd9Sstevel@tonic-gate
4117c478bd9Sstevel@tonic-gate case KBTYPE_SPEC_CTRL:
4127c478bd9Sstevel@tonic-gate poke8(kb_flag, peek8(kb_flag) | BIOS_CTL_SHIFT);
4137c478bd9Sstevel@tonic-gate break;
4147c478bd9Sstevel@tonic-gate
4157c478bd9Sstevel@tonic-gate case KBTYPE_SPEC_ALT:
4167c478bd9Sstevel@tonic-gate poke8(kb_flag, peek8(kb_flag) | BIOS_ALT_SHIFT);
4177c478bd9Sstevel@tonic-gate break;
4187c478bd9Sstevel@tonic-gate
4197c478bd9Sstevel@tonic-gate case KBTYPE_SPEC_CAPS_LOCK:
4207c478bd9Sstevel@tonic-gate if (!(peek8(kb_flag_1) & BIOS_CAPS_SHIFT)) {
4217c478bd9Sstevel@tonic-gate poke8(kb_flag_1, peek8(kb_flag_1) | BIOS_CAPS_SHIFT);
4227c478bd9Sstevel@tonic-gate poke8(kb_flag, peek8(kb_flag) ^ BIOS_CAPS_STATE);
4237c478bd9Sstevel@tonic-gate }
4247c478bd9Sstevel@tonic-gate break;
4257c478bd9Sstevel@tonic-gate
4267c478bd9Sstevel@tonic-gate case KBTYPE_SPEC_NUM_LOCK:
4277c478bd9Sstevel@tonic-gate if (!(peek8(kb_flag_1) & BIOS_NUM_SHIFT)) {
4287c478bd9Sstevel@tonic-gate poke8(kb_flag_1, peek8(kb_flag_1) | BIOS_NUM_SHIFT);
4297c478bd9Sstevel@tonic-gate poke8(kb_flag, peek8(kb_flag) ^ BIOS_NUM_STATE);
4307c478bd9Sstevel@tonic-gate }
4317c478bd9Sstevel@tonic-gate break;
4327c478bd9Sstevel@tonic-gate
4337c478bd9Sstevel@tonic-gate case KBTYPE_SPEC_SCROLL_LOCK:
4347c478bd9Sstevel@tonic-gate if (!(peek8(kb_flag_1) & BIOS_SCROLL_SHIFT)) {
4357c478bd9Sstevel@tonic-gate poke8(kb_flag_1, peek8(kb_flag_1) | BIOS_SCROLL_SHIFT);
4367c478bd9Sstevel@tonic-gate poke8(kb_flag, peek8(kb_flag) ^ BIOS_SCROLL_STATE);
4377c478bd9Sstevel@tonic-gate }
4387c478bd9Sstevel@tonic-gate break;
4397c478bd9Sstevel@tonic-gate
4407c478bd9Sstevel@tonic-gate case KBTYPE_SPEC_MAYBE_REBOOT:
441ae115bc7Smrj #if 0 /* Solaris doesn't reboot via ctrl-alt-del */
4427c478bd9Sstevel@tonic-gate if ((peek8(kb_flag) & (BIOS_CTL_SHIFT|BIOS_ALT_SHIFT)) ==
4437c478bd9Sstevel@tonic-gate (BIOS_CTL_SHIFT|BIOS_ALT_SHIFT)) {
4447c478bd9Sstevel@tonic-gate reset();
4457c478bd9Sstevel@tonic-gate /* NOTREACHED */
4467c478bd9Sstevel@tonic-gate }
447ae115bc7Smrj #endif
4487c478bd9Sstevel@tonic-gate break;
4497c478bd9Sstevel@tonic-gate
4507c478bd9Sstevel@tonic-gate default:
4517c478bd9Sstevel@tonic-gate /*
4527c478bd9Sstevel@tonic-gate * Bad entry
4537c478bd9Sstevel@tonic-gate */
4547c478bd9Sstevel@tonic-gate ASSERT(0);
4557c478bd9Sstevel@tonic-gate break;
4567c478bd9Sstevel@tonic-gate }
4577c478bd9Sstevel@tonic-gate
4587c478bd9Sstevel@tonic-gate /*
4597c478bd9Sstevel@tonic-gate * Consider updating the LEDs. This does nothing if nothing
4607c478bd9Sstevel@tonic-gate * needs to be done.
4617c478bd9Sstevel@tonic-gate */
4627c478bd9Sstevel@tonic-gate kb_update_leds();
4637c478bd9Sstevel@tonic-gate
4647c478bd9Sstevel@tonic-gate return (-1);
4657c478bd9Sstevel@tonic-gate }
4667c478bd9Sstevel@tonic-gate
4677c478bd9Sstevel@tonic-gate void
kb_send(unsigned char cmd)4687c478bd9Sstevel@tonic-gate kb_send(unsigned char cmd)
4697c478bd9Sstevel@tonic-gate {
4706ee4b8d7Ssetje int retries;
4716ee4b8d7Ssetje
4726ee4b8d7Ssetje for (retries = 0;
4736ee4b8d7Ssetje (inb(I8042_STAT) & I8042_STAT_INBF) != 0 && retries < 100000;
4746ee4b8d7Ssetje retries++)
4757c478bd9Sstevel@tonic-gate /* LOOP */;
4767c478bd9Sstevel@tonic-gate outb(I8042_DATA, cmd);
4777c478bd9Sstevel@tonic-gate }
4787c478bd9Sstevel@tonic-gate
4797c478bd9Sstevel@tonic-gate void
kb_update_leds(void)4807c478bd9Sstevel@tonic-gate kb_update_leds(void)
4817c478bd9Sstevel@tonic-gate {
4827c478bd9Sstevel@tonic-gate if (kb.led_state != KB_LED_IDLE) {
4837c478bd9Sstevel@tonic-gate /*
4847c478bd9Sstevel@tonic-gate * The state machine will take care of any additional
4857c478bd9Sstevel@tonic-gate * changes that are necessary.
4867c478bd9Sstevel@tonic-gate */
4877c478bd9Sstevel@tonic-gate return;
4887c478bd9Sstevel@tonic-gate }
4897c478bd9Sstevel@tonic-gate
4907c478bd9Sstevel@tonic-gate if (kb_calculate_leds() == kb.led_commanded) {
4917c478bd9Sstevel@tonic-gate kb.led_state = KB_LED_IDLE;
4927c478bd9Sstevel@tonic-gate } else {
4937c478bd9Sstevel@tonic-gate kb_send(KB_SET_LED);
4947c478bd9Sstevel@tonic-gate kb.led_state = KB_LED_COMMAND_SENT;
4957c478bd9Sstevel@tonic-gate }
4967c478bd9Sstevel@tonic-gate }
4977c478bd9Sstevel@tonic-gate
4987c478bd9Sstevel@tonic-gate #define MIMR_PORT 0x21 /* Mask register for master PIC */
4997c478bd9Sstevel@tonic-gate #define MIMR_KB 2 /* Keyboard mask bit in master PIC */
5007c478bd9Sstevel@tonic-gate
5017c478bd9Sstevel@tonic-gate void
kb_init(void)5027c478bd9Sstevel@tonic-gate kb_init(void)
5037c478bd9Sstevel@tonic-gate {
5047c478bd9Sstevel@tonic-gate /*
505843e1988Sjohnlev * Resist the urge to muck with the keyboard/mouse. Just assume
506843e1988Sjohnlev * that the bios, grub, and any optional hypervisor have left
507843e1988Sjohnlev * the keyboard in a sane and usable state. Messing with it now
508843e1988Sjohnlev * could result it making it unusuable, which would break early
509843e1988Sjohnlev * kmdb debugging support. Note that we don't actually need to
510843e1988Sjohnlev * disable interrupts for the keyboard/mouse since we're already
511843e1988Sjohnlev * in protected mode and we're not compeating with the bios for
512843e1988Sjohnlev * keyboard access. Also, we don't need to disable the mouse
513843e1988Sjohnlev * port since our polled input routine will just drop any mouse
514843e1988Sjohnlev * data that it recieves.
5157c478bd9Sstevel@tonic-gate */
5167c478bd9Sstevel@tonic-gate kb_update_leds();
5177c478bd9Sstevel@tonic-gate }
5187c478bd9Sstevel@tonic-gate
5197c478bd9Sstevel@tonic-gate unsigned char
kb_calculate_leds(void)5207c478bd9Sstevel@tonic-gate kb_calculate_leds(void)
5217c478bd9Sstevel@tonic-gate {
5227c478bd9Sstevel@tonic-gate int res;
5237c478bd9Sstevel@tonic-gate
5247c478bd9Sstevel@tonic-gate res = 0;
5257c478bd9Sstevel@tonic-gate
5267c478bd9Sstevel@tonic-gate if (peek8(kb_flag) & BIOS_CAPS_STATE)
5277c478bd9Sstevel@tonic-gate res |= KB_LED_CAPS_LOCK;
5287c478bd9Sstevel@tonic-gate
5297c478bd9Sstevel@tonic-gate if (peek8(kb_flag) & BIOS_NUM_STATE)
5307c478bd9Sstevel@tonic-gate res |= KB_LED_NUM_LOCK;
5317c478bd9Sstevel@tonic-gate
5327c478bd9Sstevel@tonic-gate if (peek8(kb_flag) & BIOS_SCROLL_STATE)
5337c478bd9Sstevel@tonic-gate res |= KB_LED_SCROLL_LOCK;
5347c478bd9Sstevel@tonic-gate
535ae115bc7Smrj return ((char)res);
5367c478bd9Sstevel@tonic-gate }
537