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 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 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 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 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 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 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 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