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