xref: /titanic_44/usr/src/uts/i86pc/boot/boot_keyboard.c (revision 843e19887f64dde75055cf8842fc4db2171eff45)
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 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 /*
29  * Miniature keyboard driver for bootstrap.  This allows keyboard
30  * support to continue after we take over interrupts and disable
31  * BIOS keyboard support.
32  */
33 
34 #include <sys/types.h>
35 #include <sys/archsystm.h>
36 #include <sys/boot_console.h>
37 #include "boot_keyboard_table.h"
38 
39 #if defined(_BOOT)
40 #include "dboot/dboot_asm.h"
41 #include "dboot/dboot_xboot.h"
42 #endif /* _BOOT */
43 
44 /*
45  * Definitions for BIOS keyboard state.  We use BIOS's variable to store
46  * state, ensuring that we stay in sync with it.
47  */
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
58 
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
66 
67 #if defined(__xpv) && defined(_BOOT)
68 
69 /*
70  * Device memory addresses
71  *
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.
77  */
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])
81 
82 #else /* __xpv && _BOOT */
83 
84 /* Device memory addresses */
85 #define	kb_flag		((unsigned char *)BIOS_KB_FLAG)
86 #define	kb_flag_1	((unsigned char *)BIOS_KB_FLAG_1)
87 
88 #endif /* __xpv && _BOOT */
89 
90 /*
91  * Keyboard controller registers
92  */
93 #define	I8042_DATA		0x60
94 #define	I8042_STAT		0x64
95 #define	I8042_CMD		0x64
96 
97 /*
98  * Keyboard controller status register bits
99  */
100 #define	I8042_STAT_OUTBF	0x01
101 #define	I8042_STAT_INBF		0x02
102 #define	I8042_STAT_AUXBF	0x20
103 
104 /*
105  * Keyboard controller commands
106  */
107 #define	I8042_RCB		0x20
108 #define	I8042_WCB		0x60
109 
110 /*
111  * Keyboard commands
112  */
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
117 
118 #ifndef ASSERT
119 #define	ASSERT(x)
120 #endif
121 
122 #define	peek8(p)	(*(p))
123 #define	poke8(p, val)	(*(p) = (val))
124 
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;
130 	/*
131 	 * Possible values:
132 	 *
133 	 * -1		Nothing pending
134 	 * 0x000-0x0ff	Pending byte
135 	 * 0x100-0x1ff	Needs leading zero, then low byte next.
136 	 *
137 	 * Others undefined.
138 	 */
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 */
145 };
146 
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);
151 
152 int
kb_getchar(void)153 kb_getchar(void)
154 {
155 	int ret;
156 
157 	while (!kb_ischar())
158 		/* LOOP */;
159 
160 	/*
161 	 * kb_ischar() doesn't succeed without leaving kb.pending
162 	 * set.
163 	 */
164 	ASSERT(kb.pending >= 0);
165 
166 	if (kb.pending & 0x100) {
167 		ret = 0;
168 		kb.pending &= 0xff;
169 	} else {
170 		ret = kb.pending;
171 		kb.pending = -1;
172 	}
173 
174 	return (ret);
175 }
176 
177 int
kb_ischar(void)178 kb_ischar(void)
179 {
180 	unsigned char buffer_stat;
181 	unsigned char code;
182 	unsigned char leds;
183 
184 	if (!kb.initialized) {
185 		kb_init();
186 		kb.initialized = B_TRUE;
187 	}
188 
189 	if (kb.pending >= 0)
190 		return (1);
191 
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);
197 
198 		switch (buffer_stat) {
199 		case 0:
200 		case I8042_STAT_AUXBF:
201 			return (0);
202 		case (I8042_STAT_OUTBF | I8042_STAT_AUXBF):
203 			/*
204 			 * Discard unwanted mouse data.
205 			 */
206 			(void) inb(I8042_DATA);
207 			continue;
208 		}
209 
210 		code = inb(I8042_DATA);
211 
212 		switch (code) {
213 		/*
214 		 * case 0xAA:
215 		 *
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.
226 		 */
227 		case 0xFA:
228 
229 			switch (kb.led_state) {
230 			case KB_LED_IDLE:
231 				/*
232 				 * Spurious.  Oh well, ignore it.
233 				 */
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;
243 				/*
244 				 * Check for changes made while we were
245 				 * working on the last change.
246 				 */
247 				kb_update_leds();
248 				break;
249 			}
250 			continue;
251 
252 		case 0xE0:
253 		case 0xE1:
254 			/*
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.
259 			 */
260 			continue;
261 
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:
296 					/*
297 					 * Ignore all other releases.
298 					 */
299 					break;
300 				}
301 			} else {
302 				/* Press */
303 
304 				kb.pending = kb_translate(code);
305 				if (kb.pending >= 0) {
306 					return (1);
307 				}
308 			}
309 		}
310 	}
311 }
312 
313 int
kb_translate(unsigned char code)314 kb_translate(unsigned char code)
315 {
316 	struct keyboard_translate *k;
317 	unsigned short action;
318 	boolean_t shifted;
319 
320 	k = keyboard_translate + code;
321 
322 	shifted = (peek8(kb_flag) & BIOS_EITHER_SHIFT) != 0;
323 
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;
333 	}
334 
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;
343 
344 	switch (action & 0xFF00) {
345 	case KBTYPE_NORMAL:
346 	case KBTYPE_ALPHA:
347 		return (action & 0xFF);
348 
349 	case KBTYPE_NUMPAD:
350 	case KBTYPE_FUNC:
351 		return ((action & 0xFF) | 0x100);
352 
353 	case KBTYPE_SPEC:
354 		break;
355 
356 	default:
357 		/*
358 		 * Bad entry.
359 		 */
360 		ASSERT(0);
361 		return (-1);
362 	}
363 
364 	/*
365 	 * Handle special keys, mostly shifts.
366 	 */
367 	switch (action) {
368 	case KBTYPE_SPEC_NOP:
369 	case KBTYPE_SPEC_UNDEF:
370 		break;
371 
372 	case KBTYPE_SPEC_LSHIFT:
373 		poke8(kb_flag, peek8(kb_flag) | BIOS_LEFT_SHIFT);
374 		break;
375 
376 	case KBTYPE_SPEC_RSHIFT:
377 		poke8(kb_flag, peek8(kb_flag) | BIOS_RIGHT_SHIFT);
378 		break;
379 
380 	case KBTYPE_SPEC_CTRL:
381 		poke8(kb_flag, peek8(kb_flag) | BIOS_CTL_SHIFT);
382 		break;
383 
384 	case KBTYPE_SPEC_ALT:
385 		poke8(kb_flag, peek8(kb_flag) | BIOS_ALT_SHIFT);
386 		break;
387 
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);
392 		}
393 		break;
394 
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);
399 		}
400 		break;
401 
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);
406 		}
407 		break;
408 
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 */
415 		}
416 #endif
417 		break;
418 
419 	default:
420 		/*
421 		 * Bad entry
422 		 */
423 		ASSERT(0);
424 		break;
425 	}
426 
427 	/*
428 	 * Consider updating the LEDs.  This does nothing if nothing
429 	 * needs to be done.
430 	 */
431 	kb_update_leds();
432 
433 	return (-1);
434 }
435 
436 void
kb_send(unsigned char cmd)437 kb_send(unsigned char cmd)
438 {
439 	int retries;
440 
441 	for (retries = 0;
442 	    (inb(I8042_STAT) & I8042_STAT_INBF) != 0 && retries < 100000;
443 	    retries++)
444 		/* LOOP */;
445 	outb(I8042_DATA, cmd);
446 }
447 
448 void
kb_update_leds(void)449 kb_update_leds(void)
450 {
451 	if (kb.led_state != KB_LED_IDLE) {
452 		/*
453 		 * The state machine will take care of any additional
454 		 * changes that are necessary.
455 		 */
456 		return;
457 	}
458 
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;
464 	}
465 }
466 
467 #define	MIMR_PORT	0x21	/* Mask register for master PIC */
468 #define	MIMR_KB		2	/* Keyboard mask bit in master PIC */
469 
470 void
kb_init(void)471 kb_init(void)
472 {
473 	/*
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.
484 	 */
485 	kb_update_leds();
486 }
487 
488 unsigned char
kb_calculate_leds(void)489 kb_calculate_leds(void)
490 {
491 	int res;
492 
493 	res = 0;
494 
495 	if (peek8(kb_flag) & BIOS_CAPS_STATE)
496 		res |= KB_LED_CAPS_LOCK;
497 
498 	if (peek8(kb_flag) & BIOS_NUM_STATE)
499 		res |= KB_LED_NUM_LOCK;
500 
501 	if (peek8(kb_flag) & BIOS_SCROLL_STATE)
502 		res |= KB_LED_SCROLL_LOCK;
503 
504 	return ((char)res);
505 }
506