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