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