xref: /illumos-gate/usr/src/uts/i86pc/boot/boot_keyboard.c (revision 66582b606a8194f7f3ba5b3a3a6dca5b0d346361)
1 /*
2  * CDDL HEADER START
3  *
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.
7  *
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.
12  *
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]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 /*
27  * Miniature keyboard driver for bootstrap.  This allows keyboard
28  * support to continue after we take over interrupts and disable
29  * BIOS keyboard support.
30  */
31 
32 #include <sys/types.h>
33 #include <sys/archsystm.h>
34 #include <sys/boot_console.h>
35 #include "boot_keyboard_table.h"
36 
37 #if defined(_BOOT)
38 #include "dboot/dboot_asm.h"
39 #include "dboot/dboot_xboot.h"
40 #endif /* _BOOT */
41 
42 /*
43  * Definitions for BIOS keyboard state.  We use BIOS's variable to store
44  * state, ensuring that we stay in sync with it.
45  */
46 #define	BIOS_KB_FLAG		0x417
47 #define	BIOS_RIGHT_SHIFT	0x01
48 #define	BIOS_LEFT_SHIFT		0x02
49 #define	BIOS_EITHER_SHIFT	(BIOS_LEFT_SHIFT | BIOS_RIGHT_SHIFT)
50 #define	BIOS_CTL_SHIFT		0x04
51 #define	BIOS_ALT_SHIFT		0x08
52 #define	BIOS_SCROLL_STATE	0x10
53 #define	BIOS_NUM_STATE		0x20
54 #define	BIOS_CAPS_STATE		0x40
55 #define	BIOS_INS_STATE		0x80
56 
57 #define	BIOS_KB_FLAG_1		0x418
58 #define	BIOS_SYS_SHIFT		0x04
59 #define	BIOS_HOLD_STATE		0x08
60 #define	BIOS_SCROLL_SHIFT	0x10
61 #define	BIOS_NUM_SHIFT		0x20
62 #define	BIOS_CAPS_SHIFT		0x40
63 #define	BIOS_INS_SHIFT		0x80
64 
65 #if defined(__xpv) && defined(_BOOT)
66 
67 /*
68  * Device memory addresses
69  *
70  * In dboot under the hypervisor we don't have any memory mappings
71  * for the first meg of low memory so we can't access devices there.
72  * Intead we've mapped the device memory that we need to access into
73  * a local variable within dboot so we can access the device memory
74  * there.
75  */
76 extern unsigned short *kb_status;
77 #define	kb_flag		((unsigned char *)&kb_status[BIOS_KB_FLAG])
78 #define	kb_flag_1	((unsigned char *)&kb_status[BIOS_KB_FLAG_1])
79 
80 #else /* __xpv && _BOOT */
81 
82 /* Device memory addresses */
83 #define	kb_flag		((unsigned char *)BIOS_KB_FLAG)
84 #define	kb_flag_1	((unsigned char *)BIOS_KB_FLAG_1)
85 
86 #endif /* __xpv && _BOOT */
87 
88 /*
89  * Keyboard controller registers
90  */
91 #define	I8042_DATA		0x60
92 #define	I8042_STAT		0x64
93 #define	I8042_CMD		0x64
94 
95 /*
96  * Keyboard controller status register bits
97  */
98 #define	I8042_STAT_OUTBF	0x01
99 #define	I8042_STAT_INBF		0x02
100 #define	I8042_STAT_AUXBF	0x20
101 
102 /*
103  * Keyboard controller commands
104  */
105 #define	I8042_RCB		0x20
106 #define	I8042_WCB		0x60
107 
108 /*
109  * Keyboard commands
110  */
111 #define	KB_SET_LED		0xED	/* LED byte follows... */
112 #define	KB_LED_SCROLL_LOCK	0x01	/* Bits for LED byte */
113 #define	KB_LED_NUM_LOCK		0x02
114 #define	KB_LED_CAPS_LOCK	0x04
115 
116 #ifndef ASSERT
117 #define	ASSERT(x)
118 #endif
119 
120 #define	peek8(p)	(*(p))
121 #define	poke8(p, val)	(*(p) = (val))
122 
123 static struct {
124 	boolean_t	initialized;
125 	enum { KB_LED_IDLE, KB_LED_COMMAND_SENT, KB_LED_VALUE_SENT }
126 			led_state;
127 	int		led_commanded;
128 	/*
129 	 * Possible values:
130 	 *
131 	 * -1		Nothing pending
132 	 * 0x000-0x0ff	Pending byte
133 	 * 0x100-0x1ff	Needs leading zero, then low byte next.
134 	 *
135 	 * Others undefined.
136 	 */
137 	int		pending;
138 } kb = {
139 	B_FALSE,	/* initialized? */
140 	KB_LED_IDLE,	/* LED command state */
141 	-1,		/* commanded LEDs - force refresh */
142 	-1,		/* pending */
143 };
144 
145 #define	KTAB_STRLEN 3
146 static char keystringtab[KTAB_STRLEN] = {'\033', '[', ' '};
147 static int keystring = -1;
148 
149 static int kb_translate(unsigned char code);
150 static void kb_send(unsigned char cmd);
151 static void kb_update_leds(void);
152 static uchar_t kb_calculate_leds(void);
153 
154 int
155 kb_getchar(void)
156 {
157 	int ret;
158 
159 	while (!kb_ischar())
160 		/* LOOP */;
161 
162 	if (keystring >= 0) {
163 		ret = keystringtab[keystring++];
164 		if (keystring == KTAB_STRLEN) {
165 			keystring = -1;
166 			kb.pending = -1;
167 		}
168 		return (ret);
169 	}
170 
171 	/*
172 	 * kb_ischar() doesn't succeed without leaving kb.pending
173 	 * set.
174 	 */
175 	ASSERT(kb.pending >= 0);
176 
177 	if (kb.pending & 0x100) {
178 		kb.pending &= 0xff;
179 		switch (kb.pending) {
180 		case 'H':		/* Up */
181 			keystringtab[2] = 'A';
182 			keystring = 0;
183 			return (kb_getchar());
184 		case 'P':		/* Down */
185 			keystringtab[2] = 'B';
186 			keystring = 0;
187 			return (kb_getchar());
188 		case 'M':		/* Right */
189 			keystringtab[2] = 'C';
190 			keystring = 0;
191 			return (kb_getchar());
192 		case 'K':		/* Left */
193 			keystringtab[2] = 'D';
194 			keystring = 0;
195 			return (kb_getchar());
196 		default:
197 			ret = 0;
198 		}
199 	} else {
200 		ret = kb.pending;
201 		kb.pending = -1;
202 	}
203 
204 	return (ret);
205 }
206 
207 int
208 kb_ischar(void)
209 {
210 	unsigned char buffer_stat;
211 	unsigned char code;
212 	unsigned char leds;
213 
214 	if (!kb.initialized) {
215 		kb_init();
216 		kb.initialized = B_TRUE;
217 	}
218 
219 	if (kb.pending >= 0)
220 		return (1);
221 
222 	for (;;) {
223 		buffer_stat = inb(I8042_STAT);
224 		if (buffer_stat == 0xff)
225 			return (0);
226 		buffer_stat &= (I8042_STAT_OUTBF | I8042_STAT_AUXBF);
227 
228 		switch (buffer_stat) {
229 		case 0:
230 		case I8042_STAT_AUXBF:
231 			return (0);
232 		case (I8042_STAT_OUTBF | I8042_STAT_AUXBF):
233 			/*
234 			 * Discard unwanted mouse data.
235 			 */
236 			(void) inb(I8042_DATA);
237 			continue;
238 		}
239 
240 		code = inb(I8042_DATA);
241 
242 		switch (code) {
243 		/*
244 		 * case 0xAA:
245 		 *
246 		 * You might think that we should ignore 0xAA on the
247 		 * grounds that it is the BAT Complete response and will
248 		 * occur on keyboard detach/reattach.  Unfortunately,
249 		 * it is ambiguous - this is also the code for a break
250 		 * of the left shift key.  Since it will be harmless for
251 		 * us to "spuriously" process a break of Left Shift,
252 		 * we just let the normal code handle it.  Perhaps we
253 		 * should take a hint and refresh the LEDs, but I
254 		 * refuse to get very worried about hot-plug issues
255 		 * in this mini-driver.
256 		 */
257 		case 0xFA:
258 
259 			switch (kb.led_state) {
260 			case KB_LED_IDLE:
261 				/*
262 				 * Spurious.  Oh well, ignore it.
263 				 */
264 				break;
265 			case KB_LED_COMMAND_SENT:
266 				leds = kb_calculate_leds();
267 				kb_send(leds);
268 				kb.led_commanded = leds;
269 				kb.led_state = KB_LED_VALUE_SENT;
270 				break;
271 			case KB_LED_VALUE_SENT:
272 				kb.led_state = KB_LED_IDLE;
273 				/*
274 				 * Check for changes made while we were
275 				 * working on the last change.
276 				 */
277 				kb_update_leds();
278 				break;
279 			}
280 			continue;
281 
282 		case 0xE0:
283 		case 0xE1:
284 			/*
285 			 * These are used to distinguish the keys added on
286 			 * the AT-101 keyboard from the original 84 keys.
287 			 * We don't care, and the codes are carefully arranged
288 			 * so that we don't have to.
289 			 */
290 			continue;
291 
292 		default:
293 			if (code & 0x80) {
294 				/* Release */
295 				code &= 0x7f;
296 				switch (keyboard_translate[code].normal) {
297 				case KBTYPE_SPEC_LSHIFT:
298 					poke8(kb_flag, peek8(kb_flag) &
299 					    ~BIOS_LEFT_SHIFT);
300 					break;
301 				case KBTYPE_SPEC_RSHIFT:
302 					poke8(kb_flag, peek8(kb_flag) &
303 					    ~BIOS_RIGHT_SHIFT);
304 					break;
305 				case KBTYPE_SPEC_CTRL:
306 					poke8(kb_flag, peek8(kb_flag) &
307 					    ~BIOS_CTL_SHIFT);
308 					break;
309 				case KBTYPE_SPEC_ALT:
310 					poke8(kb_flag, peek8(kb_flag) &
311 					    ~BIOS_ALT_SHIFT);
312 					break;
313 				case KBTYPE_SPEC_CAPS_LOCK:
314 					poke8(kb_flag_1, peek8(kb_flag_1) &
315 					    ~BIOS_CAPS_SHIFT);
316 					break;
317 				case KBTYPE_SPEC_NUM_LOCK:
318 					poke8(kb_flag_1, peek8(kb_flag_1) &
319 					    ~BIOS_NUM_SHIFT);
320 					break;
321 				case KBTYPE_SPEC_SCROLL_LOCK:
322 					poke8(kb_flag_1, peek8(kb_flag_1) &
323 					    ~BIOS_SCROLL_SHIFT);
324 					break;
325 				default:
326 					/*
327 					 * Ignore all other releases.
328 					 */
329 					break;
330 				}
331 			} else {
332 				/* Press */
333 
334 				kb.pending = kb_translate(code);
335 				if (kb.pending >= 0) {
336 					return (1);
337 				}
338 			}
339 		}
340 	}
341 }
342 
343 int
344 kb_translate(unsigned char code)
345 {
346 	struct keyboard_translate *k;
347 	unsigned short action;
348 	boolean_t shifted;
349 
350 	k = keyboard_translate + code;
351 
352 	shifted = (peek8(kb_flag) & BIOS_EITHER_SHIFT) != 0;
353 
354 	switch (k->normal & 0xFF00) {
355 	case KBTYPE_NUMPAD:
356 		if (peek8(kb_flag) & BIOS_NUM_STATE)
357 			shifted = !shifted;
358 		break;
359 	case KBTYPE_ALPHA:
360 		if (peek8(kb_flag) & BIOS_CAPS_STATE)
361 			shifted = !shifted;
362 		break;
363 	}
364 
365 	if (peek8(kb_flag) & BIOS_ALT_SHIFT)
366 		action = k->alted;
367 	else if (peek8(kb_flag) & BIOS_CTL_SHIFT)
368 		action = k->ctrled;
369 	else if (shifted)
370 		action = k->shifted;
371 	else
372 		action = k->normal;
373 
374 	switch (action & 0xFF00) {
375 	case KBTYPE_NORMAL:
376 	case KBTYPE_ALPHA:
377 		return (action & 0xFF);
378 
379 	case KBTYPE_NUMPAD:
380 	case KBTYPE_FUNC:
381 		return ((action & 0xFF) | 0x100);
382 
383 	case KBTYPE_SPEC:
384 		break;
385 
386 	default:
387 		/*
388 		 * Bad entry.
389 		 */
390 		ASSERT(0);
391 		return (-1);
392 	}
393 
394 	/*
395 	 * Handle special keys, mostly shifts.
396 	 */
397 	switch (action) {
398 	case KBTYPE_SPEC_NOP:
399 	case KBTYPE_SPEC_UNDEF:
400 		break;
401 
402 	case KBTYPE_SPEC_LSHIFT:
403 		poke8(kb_flag, peek8(kb_flag) | BIOS_LEFT_SHIFT);
404 		break;
405 
406 	case KBTYPE_SPEC_RSHIFT:
407 		poke8(kb_flag, peek8(kb_flag) | BIOS_RIGHT_SHIFT);
408 		break;
409 
410 	case KBTYPE_SPEC_CTRL:
411 		poke8(kb_flag, peek8(kb_flag) | BIOS_CTL_SHIFT);
412 		break;
413 
414 	case KBTYPE_SPEC_ALT:
415 		poke8(kb_flag, peek8(kb_flag) | BIOS_ALT_SHIFT);
416 		break;
417 
418 	case KBTYPE_SPEC_CAPS_LOCK:
419 		if (!(peek8(kb_flag_1) & BIOS_CAPS_SHIFT)) {
420 			poke8(kb_flag_1, peek8(kb_flag_1) | BIOS_CAPS_SHIFT);
421 			poke8(kb_flag, peek8(kb_flag) ^ BIOS_CAPS_STATE);
422 		}
423 		break;
424 
425 	case KBTYPE_SPEC_NUM_LOCK:
426 		if (!(peek8(kb_flag_1) & BIOS_NUM_SHIFT)) {
427 			poke8(kb_flag_1, peek8(kb_flag_1) | BIOS_NUM_SHIFT);
428 			poke8(kb_flag, peek8(kb_flag) ^ BIOS_NUM_STATE);
429 		}
430 		break;
431 
432 	case KBTYPE_SPEC_SCROLL_LOCK:
433 		if (!(peek8(kb_flag_1) & BIOS_SCROLL_SHIFT)) {
434 			poke8(kb_flag_1, peek8(kb_flag_1) | BIOS_SCROLL_SHIFT);
435 			poke8(kb_flag, peek8(kb_flag) ^ BIOS_SCROLL_STATE);
436 		}
437 		break;
438 
439 	case KBTYPE_SPEC_MAYBE_REBOOT:
440 #if 0	/* Solaris doesn't reboot via ctrl-alt-del */
441 		if ((peek8(kb_flag) & (BIOS_CTL_SHIFT|BIOS_ALT_SHIFT)) ==
442 		    (BIOS_CTL_SHIFT|BIOS_ALT_SHIFT)) {
443 			reset();
444 			/* NOTREACHED */
445 		}
446 #endif
447 		break;
448 
449 	default:
450 		/*
451 		 * Bad entry
452 		 */
453 		ASSERT(0);
454 		break;
455 	}
456 
457 	/*
458 	 * Consider updating the LEDs.  This does nothing if nothing
459 	 * needs to be done.
460 	 */
461 	kb_update_leds();
462 
463 	return (-1);
464 }
465 
466 void
467 kb_send(unsigned char cmd)
468 {
469 	int retries;
470 
471 	for (retries = 0;
472 	    (inb(I8042_STAT) & I8042_STAT_INBF) != 0 && retries < 100000;
473 	    retries++)
474 		/* LOOP */;
475 	outb(I8042_DATA, cmd);
476 }
477 
478 void
479 kb_update_leds(void)
480 {
481 	if (kb.led_state != KB_LED_IDLE) {
482 		/*
483 		 * The state machine will take care of any additional
484 		 * changes that are necessary.
485 		 */
486 		return;
487 	}
488 
489 	if (kb_calculate_leds() == kb.led_commanded) {
490 		kb.led_state = KB_LED_IDLE;
491 	} else {
492 		kb_send(KB_SET_LED);
493 		kb.led_state = KB_LED_COMMAND_SENT;
494 	}
495 }
496 
497 #define	MIMR_PORT	0x21	/* Mask register for master PIC */
498 #define	MIMR_KB		2	/* Keyboard mask bit in master PIC */
499 
500 void
501 kb_init(void)
502 {
503 	/*
504 	 * Resist the urge to muck with the keyboard/mouse.  Just assume
505 	 * that the bios, grub, and any optional hypervisor have left
506 	 * the keyboard in a sane and usable state.  Messing with it now
507 	 * could result it making it unusuable, which would break early
508 	 * kmdb debugging support.  Note that we don't actually need to
509 	 * disable interrupts for the keyboard/mouse since we're already
510 	 * in protected mode and we're not compeating with the bios for
511 	 * keyboard access.  Also, we don't need to disable the mouse
512 	 * port since our polled input routine will just drop any mouse
513 	 * data that it recieves.
514 	 */
515 	kb_update_leds();
516 }
517 
518 unsigned char
519 kb_calculate_leds(void)
520 {
521 	int res;
522 
523 	res = 0;
524 
525 	if (peek8(kb_flag) & BIOS_CAPS_STATE)
526 		res |= KB_LED_CAPS_LOCK;
527 
528 	if (peek8(kb_flag) & BIOS_NUM_STATE)
529 		res |= KB_LED_NUM_LOCK;
530 
531 	if (peek8(kb_flag) & BIOS_SCROLL_STATE)
532 		res |= KB_LED_SCROLL_LOCK;
533 
534 	return ((char)res);
535 }
536