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
kb_getchar(void)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
kb_ischar(void)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
kb_translate(unsigned char code)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
kb_send(unsigned char cmd)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
kb_update_leds(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
kb_init(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
kb_calculate_leds(void)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