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