Merge commit '74ecdb5171c9f3673b9393b1a3dc6f3a65e93895'
[unleashed.git] / arch / x86 / kernel / platform / i86pc / boot / boot_keyboard.c
blobf1d7ffafb5f92b069f2cfb51efd266257ba24a0b
1 /*
2 * CDDL HEADER START
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]
19 * CDDL HEADER END
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"
39 #if defined(_BOOT)
40 #include <dboot_asm.h>
41 #include <dboot_xboot.h>
42 #endif /* _BOOT */
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
76 * there.
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
111 * Keyboard commands
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
118 #ifndef ASSERT
119 #define ASSERT(x)
120 #endif
122 #define peek8(p) (*(p))
123 #define poke8(p, val) (*(p) = (val))
125 static struct {
126 boolean_t initialized;
127 enum { KB_LED_IDLE, KB_LED_COMMAND_SENT, KB_LED_VALUE_SENT }
128 led_state;
129 int led_commanded;
131 * Possible values:
133 * -1 Nothing pending
134 * 0x000-0x0ff Pending byte
135 * 0x100-0x1ff Needs leading zero, then low byte next.
137 * Others undefined.
139 int pending;
140 } kb = {
141 B_FALSE, /* initialized? */
142 KB_LED_IDLE, /* LED command state */
143 -1, /* commanded LEDs - force refresh */
144 -1, /* pending */
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);
153 kb_getchar(void)
155 int ret;
157 while (!kb_ischar())
158 /* LOOP */;
161 * kb_ischar() doesn't succeed without leaving kb.pending
162 * set.
164 ASSERT(kb.pending >= 0);
166 if (kb.pending & 0x100) {
167 ret = 0;
168 kb.pending &= 0xff;
169 } else {
170 ret = kb.pending;
171 kb.pending = -1;
174 return (ret);
178 kb_ischar(void)
180 unsigned char buffer_stat;
181 unsigned char code;
182 unsigned char leds;
184 if (!kb.initialized) {
185 kb_init();
186 kb.initialized = B_TRUE;
189 if (kb.pending >= 0)
190 return (1);
192 for (;;) {
193 buffer_stat = inb(I8042_STAT);
194 if (buffer_stat == 0xff)
195 return (0);
196 buffer_stat &= (I8042_STAT_OUTBF | I8042_STAT_AUXBF);
198 switch (buffer_stat) {
199 case 0:
200 case I8042_STAT_AUXBF:
201 return (0);
202 case (I8042_STAT_OUTBF | I8042_STAT_AUXBF):
204 * Discard unwanted mouse data.
206 (void) inb(I8042_DATA);
207 continue;
210 code = inb(I8042_DATA);
212 switch (code) {
214 * case 0xAA:
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.
227 case 0xFA:
229 switch (kb.led_state) {
230 case KB_LED_IDLE:
232 * Spurious. Oh well, ignore it.
234 break;
235 case KB_LED_COMMAND_SENT:
236 leds = kb_calculate_leds();
237 kb_send(leds);
238 kb.led_commanded = leds;
239 kb.led_state = KB_LED_VALUE_SENT;
240 break;
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.
247 kb_update_leds();
248 break;
250 continue;
252 case 0xE0:
253 case 0xE1:
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.
260 continue;
262 default:
263 if (code & 0x80) {
264 /* Release */
265 code &= 0x7f;
266 switch (keyboard_translate[code].normal) {
267 case KBTYPE_SPEC_LSHIFT:
268 poke8(kb_flag, peek8(kb_flag) &
269 ~BIOS_LEFT_SHIFT);
270 break;
271 case KBTYPE_SPEC_RSHIFT:
272 poke8(kb_flag, peek8(kb_flag) &
273 ~BIOS_RIGHT_SHIFT);
274 break;
275 case KBTYPE_SPEC_CTRL:
276 poke8(kb_flag, peek8(kb_flag) &
277 ~BIOS_CTL_SHIFT);
278 break;
279 case KBTYPE_SPEC_ALT:
280 poke8(kb_flag, peek8(kb_flag) &
281 ~BIOS_ALT_SHIFT);
282 break;
283 case KBTYPE_SPEC_CAPS_LOCK:
284 poke8(kb_flag_1, peek8(kb_flag_1) &
285 ~BIOS_CAPS_SHIFT);
286 break;
287 case KBTYPE_SPEC_NUM_LOCK:
288 poke8(kb_flag_1, peek8(kb_flag_1) &
289 ~BIOS_NUM_SHIFT);
290 break;
291 case KBTYPE_SPEC_SCROLL_LOCK:
292 poke8(kb_flag_1, peek8(kb_flag_1) &
293 ~BIOS_SCROLL_SHIFT);
294 break;
295 default:
297 * Ignore all other releases.
299 break;
301 } else {
302 /* Press */
304 kb.pending = kb_translate(code);
305 if (kb.pending >= 0) {
306 return (1);
314 kb_translate(unsigned char code)
316 struct keyboard_translate *k;
317 unsigned short action;
318 boolean_t shifted;
320 k = keyboard_translate + code;
322 shifted = (peek8(kb_flag) & BIOS_EITHER_SHIFT) != 0;
324 switch (k->normal & 0xFF00) {
325 case KBTYPE_NUMPAD:
326 if (peek8(kb_flag) & BIOS_NUM_STATE)
327 shifted = !shifted;
328 break;
329 case KBTYPE_ALPHA:
330 if (peek8(kb_flag) & BIOS_CAPS_STATE)
331 shifted = !shifted;
332 break;
335 if (peek8(kb_flag) & BIOS_ALT_SHIFT)
336 action = k->alted;
337 else if (peek8(kb_flag) & BIOS_CTL_SHIFT)
338 action = k->ctrled;
339 else if (shifted)
340 action = k->shifted;
341 else
342 action = k->normal;
344 switch (action & 0xFF00) {
345 case KBTYPE_NORMAL:
346 case KBTYPE_ALPHA:
347 return (action & 0xFF);
349 case KBTYPE_NUMPAD:
350 case KBTYPE_FUNC:
351 return ((action & 0xFF) | 0x100);
353 case KBTYPE_SPEC:
354 break;
356 default:
358 * Bad entry.
360 ASSERT(0);
361 return (-1);
365 * Handle special keys, mostly shifts.
367 switch (action) {
368 case KBTYPE_SPEC_NOP:
369 case KBTYPE_SPEC_UNDEF:
370 break;
372 case KBTYPE_SPEC_LSHIFT:
373 poke8(kb_flag, peek8(kb_flag) | BIOS_LEFT_SHIFT);
374 break;
376 case KBTYPE_SPEC_RSHIFT:
377 poke8(kb_flag, peek8(kb_flag) | BIOS_RIGHT_SHIFT);
378 break;
380 case KBTYPE_SPEC_CTRL:
381 poke8(kb_flag, peek8(kb_flag) | BIOS_CTL_SHIFT);
382 break;
384 case KBTYPE_SPEC_ALT:
385 poke8(kb_flag, peek8(kb_flag) | BIOS_ALT_SHIFT);
386 break;
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);
393 break;
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);
400 break;
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);
407 break;
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)) {
413 reset();
414 /* NOTREACHED */
416 #endif
417 break;
419 default:
421 * Bad entry
423 ASSERT(0);
424 break;
428 * Consider updating the LEDs. This does nothing if nothing
429 * needs to be done.
431 kb_update_leds();
433 return (-1);
436 void
437 kb_send(unsigned char cmd)
439 int retries;
441 for (retries = 0;
442 (inb(I8042_STAT) & I8042_STAT_INBF) != 0 && retries < 100000;
443 retries++)
444 /* LOOP */;
445 outb(I8042_DATA, cmd);
448 void
449 kb_update_leds(void)
451 if (kb.led_state != KB_LED_IDLE) {
453 * The state machine will take care of any additional
454 * changes that are necessary.
456 return;
459 if (kb_calculate_leds() == kb.led_commanded) {
460 kb.led_state = KB_LED_IDLE;
461 } else {
462 kb_send(KB_SET_LED);
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 */
470 void
471 kb_init(void)
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.
485 kb_update_leds();
488 unsigned char
489 kb_calculate_leds(void)
491 int res;
493 res = 0;
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;
504 return ((char)res);