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