4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #pragma ident "%Z%%M% %I% %E% SMI"
29 * Miniature keyboard driver for bootstrap. This allows keyboard
30 * support to continue after we take over interrupts and disable
31 * BIOS keyboard support.
34 #include <sys/types.h>
35 #include <sys/archsystm.h>
36 #include <sys/boot_console.h>
37 #include "boot_keyboard_table.h"
40 #include <dboot_asm.h>
41 #include <dboot_xboot.h>
45 * Definitions for BIOS keyboard state. We use BIOS's variable to store
46 * state, ensuring that we stay in sync with it.
48 #define BIOS_KB_FLAG 0x417
49 #define BIOS_RIGHT_SHIFT 0x01
50 #define BIOS_LEFT_SHIFT 0x02
51 #define BIOS_EITHER_SHIFT (BIOS_LEFT_SHIFT | BIOS_RIGHT_SHIFT)
52 #define BIOS_CTL_SHIFT 0x04
53 #define BIOS_ALT_SHIFT 0x08
54 #define BIOS_SCROLL_STATE 0x10
55 #define BIOS_NUM_STATE 0x20
56 #define BIOS_CAPS_STATE 0x40
57 #define BIOS_INS_STATE 0x80
59 #define BIOS_KB_FLAG_1 0x418
60 #define BIOS_SYS_SHIFT 0x04
61 #define BIOS_HOLD_STATE 0x08
62 #define BIOS_SCROLL_SHIFT 0x10
63 #define BIOS_NUM_SHIFT 0x20
64 #define BIOS_CAPS_SHIFT 0x40
65 #define BIOS_INS_SHIFT 0x80
67 #if defined(__xpv) && defined(_BOOT)
70 * Device memory addresses
72 * In dboot under the hypervisor we don't have any memory mappings
73 * for the first meg of low memory so we can't access devices there.
74 * Intead we've mapped the device memory that we need to access into
75 * a local variable within dboot so we can access the device memory
78 extern unsigned short *kb_status
;
79 #define kb_flag ((unsigned char *)&kb_status[BIOS_KB_FLAG])
80 #define kb_flag_1 ((unsigned char *)&kb_status[BIOS_KB_FLAG_1])
82 #else /* __xpv && _BOOT */
84 /* Device memory addresses */
85 #define kb_flag ((unsigned char *)BIOS_KB_FLAG)
86 #define kb_flag_1 ((unsigned char *)BIOS_KB_FLAG_1)
88 #endif /* __xpv && _BOOT */
91 * Keyboard controller registers
93 #define I8042_DATA 0x60
94 #define I8042_STAT 0x64
95 #define I8042_CMD 0x64
98 * Keyboard controller status register bits
100 #define I8042_STAT_OUTBF 0x01
101 #define I8042_STAT_INBF 0x02
102 #define I8042_STAT_AUXBF 0x20
105 * Keyboard controller commands
107 #define I8042_RCB 0x20
108 #define I8042_WCB 0x60
113 #define KB_SET_LED 0xED /* LED byte follows... */
114 #define KB_LED_SCROLL_LOCK 0x01 /* Bits for LED byte */
115 #define KB_LED_NUM_LOCK 0x02
116 #define KB_LED_CAPS_LOCK 0x04
122 #define peek8(p) (*(p))
123 #define poke8(p, val) (*(p) = (val))
126 boolean_t initialized
;
127 enum { KB_LED_IDLE
, KB_LED_COMMAND_SENT
, KB_LED_VALUE_SENT
}
134 * 0x000-0x0ff Pending byte
135 * 0x100-0x1ff Needs leading zero, then low byte next.
141 B_FALSE
, /* initialized? */
142 KB_LED_IDLE
, /* LED command state */
143 -1, /* commanded LEDs - force refresh */
147 static int kb_translate(unsigned char code
);
148 static void kb_send(unsigned char cmd
);
149 static void kb_update_leds(void);
150 static uchar_t
kb_calculate_leds(void);
161 * kb_ischar() doesn't succeed without leaving kb.pending
164 ASSERT(kb
.pending
>= 0);
166 if (kb
.pending
& 0x100) {
180 unsigned char buffer_stat
;
184 if (!kb
.initialized
) {
186 kb
.initialized
= B_TRUE
;
193 buffer_stat
= inb(I8042_STAT
);
194 if (buffer_stat
== 0xff)
196 buffer_stat
&= (I8042_STAT_OUTBF
| I8042_STAT_AUXBF
);
198 switch (buffer_stat
) {
200 case I8042_STAT_AUXBF
:
202 case (I8042_STAT_OUTBF
| I8042_STAT_AUXBF
):
204 * Discard unwanted mouse data.
206 (void) inb(I8042_DATA
);
210 code
= inb(I8042_DATA
);
216 * You might think that we should ignore 0xAA on the
217 * grounds that it is the BAT Complete response and will
218 * occur on keyboard detach/reattach. Unfortunately,
219 * it is ambiguous - this is also the code for a break
220 * of the left shift key. Since it will be harmless for
221 * us to "spuriously" process a break of Left Shift,
222 * we just let the normal code handle it. Perhaps we
223 * should take a hint and refresh the LEDs, but I
224 * refuse to get very worried about hot-plug issues
225 * in this mini-driver.
229 switch (kb
.led_state
) {
232 * Spurious. Oh well, ignore it.
235 case KB_LED_COMMAND_SENT
:
236 leds
= kb_calculate_leds();
238 kb
.led_commanded
= leds
;
239 kb
.led_state
= KB_LED_VALUE_SENT
;
241 case KB_LED_VALUE_SENT
:
242 kb
.led_state
= KB_LED_IDLE
;
244 * Check for changes made while we were
245 * working on the last change.
255 * These are used to distinguish the keys added on
256 * the AT-101 keyboard from the original 84 keys.
257 * We don't care, and the codes are carefully arranged
258 * so that we don't have to.
266 switch (keyboard_translate
[code
].normal
) {
267 case KBTYPE_SPEC_LSHIFT
:
268 poke8(kb_flag
, peek8(kb_flag
) &
271 case KBTYPE_SPEC_RSHIFT
:
272 poke8(kb_flag
, peek8(kb_flag
) &
275 case KBTYPE_SPEC_CTRL
:
276 poke8(kb_flag
, peek8(kb_flag
) &
279 case KBTYPE_SPEC_ALT
:
280 poke8(kb_flag
, peek8(kb_flag
) &
283 case KBTYPE_SPEC_CAPS_LOCK
:
284 poke8(kb_flag_1
, peek8(kb_flag_1
) &
287 case KBTYPE_SPEC_NUM_LOCK
:
288 poke8(kb_flag_1
, peek8(kb_flag_1
) &
291 case KBTYPE_SPEC_SCROLL_LOCK
:
292 poke8(kb_flag_1
, peek8(kb_flag_1
) &
297 * Ignore all other releases.
304 kb
.pending
= kb_translate(code
);
305 if (kb
.pending
>= 0) {
314 kb_translate(unsigned char code
)
316 struct keyboard_translate
*k
;
317 unsigned short action
;
320 k
= keyboard_translate
+ code
;
322 shifted
= (peek8(kb_flag
) & BIOS_EITHER_SHIFT
) != 0;
324 switch (k
->normal
& 0xFF00) {
326 if (peek8(kb_flag
) & BIOS_NUM_STATE
)
330 if (peek8(kb_flag
) & BIOS_CAPS_STATE
)
335 if (peek8(kb_flag
) & BIOS_ALT_SHIFT
)
337 else if (peek8(kb_flag
) & BIOS_CTL_SHIFT
)
344 switch (action
& 0xFF00) {
347 return (action
& 0xFF);
351 return ((action
& 0xFF) | 0x100);
365 * Handle special keys, mostly shifts.
368 case KBTYPE_SPEC_NOP
:
369 case KBTYPE_SPEC_UNDEF
:
372 case KBTYPE_SPEC_LSHIFT
:
373 poke8(kb_flag
, peek8(kb_flag
) | BIOS_LEFT_SHIFT
);
376 case KBTYPE_SPEC_RSHIFT
:
377 poke8(kb_flag
, peek8(kb_flag
) | BIOS_RIGHT_SHIFT
);
380 case KBTYPE_SPEC_CTRL
:
381 poke8(kb_flag
, peek8(kb_flag
) | BIOS_CTL_SHIFT
);
384 case KBTYPE_SPEC_ALT
:
385 poke8(kb_flag
, peek8(kb_flag
) | BIOS_ALT_SHIFT
);
388 case KBTYPE_SPEC_CAPS_LOCK
:
389 if (!(peek8(kb_flag_1
) & BIOS_CAPS_SHIFT
)) {
390 poke8(kb_flag_1
, peek8(kb_flag_1
) | BIOS_CAPS_SHIFT
);
391 poke8(kb_flag
, peek8(kb_flag
) ^ BIOS_CAPS_STATE
);
395 case KBTYPE_SPEC_NUM_LOCK
:
396 if (!(peek8(kb_flag_1
) & BIOS_NUM_SHIFT
)) {
397 poke8(kb_flag_1
, peek8(kb_flag_1
) | BIOS_NUM_SHIFT
);
398 poke8(kb_flag
, peek8(kb_flag
) ^ BIOS_NUM_STATE
);
402 case KBTYPE_SPEC_SCROLL_LOCK
:
403 if (!(peek8(kb_flag_1
) & BIOS_SCROLL_SHIFT
)) {
404 poke8(kb_flag_1
, peek8(kb_flag_1
) | BIOS_SCROLL_SHIFT
);
405 poke8(kb_flag
, peek8(kb_flag
) ^ BIOS_SCROLL_STATE
);
409 case KBTYPE_SPEC_MAYBE_REBOOT
:
410 #if 0 /* Solaris doesn't reboot via ctrl-alt-del */
411 if ((peek8(kb_flag
) & (BIOS_CTL_SHIFT
|BIOS_ALT_SHIFT
)) ==
412 (BIOS_CTL_SHIFT
|BIOS_ALT_SHIFT
)) {
428 * Consider updating the LEDs. This does nothing if nothing
437 kb_send(unsigned char cmd
)
442 (inb(I8042_STAT
) & I8042_STAT_INBF
) != 0 && retries
< 100000;
445 outb(I8042_DATA
, cmd
);
451 if (kb
.led_state
!= KB_LED_IDLE
) {
453 * The state machine will take care of any additional
454 * changes that are necessary.
459 if (kb_calculate_leds() == kb
.led_commanded
) {
460 kb
.led_state
= KB_LED_IDLE
;
463 kb
.led_state
= KB_LED_COMMAND_SENT
;
467 #define MIMR_PORT 0x21 /* Mask register for master PIC */
468 #define MIMR_KB 2 /* Keyboard mask bit in master PIC */
474 * Resist the urge to muck with the keyboard/mouse. Just assume
475 * that the bios, grub, and any optional hypervisor have left
476 * the keyboard in a sane and usable state. Messing with it now
477 * could result it making it unusuable, which would break early
478 * kmdb debugging support. Note that we don't actually need to
479 * disable interrupts for the keyboard/mouse since we're already
480 * in protected mode and we're not compeating with the bios for
481 * keyboard access. Also, we don't need to disable the mouse
482 * port since our polled input routine will just drop any mouse
483 * data that it recieves.
489 kb_calculate_leds(void)
495 if (peek8(kb_flag
) & BIOS_CAPS_STATE
)
496 res
|= KB_LED_CAPS_LOCK
;
498 if (peek8(kb_flag
) & BIOS_NUM_STATE
)
499 res
|= KB_LED_NUM_LOCK
;
501 if (peek8(kb_flag
) & BIOS_SCROLL_STATE
)
502 res
|= KB_LED_SCROLL_LOCK
;