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