1ae115bc7Smrj /* 2ae115bc7Smrj * CDDL HEADER START 3ae115bc7Smrj * 4ae115bc7Smrj * The contents of this file are subject to the terms of the 5ae115bc7Smrj * Common Development and Distribution License (the "License"). 6ae115bc7Smrj * You may not use this file except in compliance with the License. 7ae115bc7Smrj * 8ae115bc7Smrj * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9ae115bc7Smrj * or http://www.opensolaris.org/os/licensing. 10ae115bc7Smrj * See the License for the specific language governing permissions 11ae115bc7Smrj * and limitations under the License. 12ae115bc7Smrj * 13ae115bc7Smrj * When distributing Covered Code, include this CDDL HEADER in each 14ae115bc7Smrj * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15ae115bc7Smrj * If applicable, add the following below this CDDL HEADER, with the 16ae115bc7Smrj * fields enclosed by brackets "[]" replaced with your own identifying 17ae115bc7Smrj * information: Portions Copyright [yyyy] [name of copyright owner] 18ae115bc7Smrj * 19ae115bc7Smrj * CDDL HEADER END 20ae115bc7Smrj */ 21ae115bc7Smrj /* 22ae115bc7Smrj * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 23ae115bc7Smrj * Use is subject to license terms. 24ae115bc7Smrj */ 25ae115bc7Smrj 26ae115bc7Smrj #pragma ident "%Z%%M% %I% %E% SMI" 27ae115bc7Smrj 28ae115bc7Smrj /* 29ae115bc7Smrj * Miniature keyboard driver for bootstrap. This allows keyboard 30ae115bc7Smrj * support to continue after we take over interrupts and disable 31ae115bc7Smrj * BIOS keyboard support. 32ae115bc7Smrj */ 33ae115bc7Smrj 34ae115bc7Smrj #include <sys/types.h> 35ae115bc7Smrj #include <sys/archsystm.h> 36ae115bc7Smrj #include <sys/boot_console.h> 37ae115bc7Smrj #include "boot_keyboard_table.h" 38ae115bc7Smrj 39ae115bc7Smrj #if defined(_BOOT) 40*843e1988Sjohnlev #include "dboot/dboot_asm.h" 41ae115bc7Smrj #include "dboot/dboot_xboot.h" 42*843e1988Sjohnlev #endif /* _BOOT */ 43ae115bc7Smrj 44ae115bc7Smrj /* 45ae115bc7Smrj * Definitions for BIOS keyboard state. We use BIOS's variable to store 46ae115bc7Smrj * state, ensuring that we stay in sync with it. 47ae115bc7Smrj */ 48ae115bc7Smrj #define BIOS_KB_FLAG 0x417 49ae115bc7Smrj #define BIOS_RIGHT_SHIFT 0x01 50ae115bc7Smrj #define BIOS_LEFT_SHIFT 0x02 51ae115bc7Smrj #define BIOS_EITHER_SHIFT (BIOS_LEFT_SHIFT | BIOS_RIGHT_SHIFT) 52ae115bc7Smrj #define BIOS_CTL_SHIFT 0x04 53ae115bc7Smrj #define BIOS_ALT_SHIFT 0x08 54ae115bc7Smrj #define BIOS_SCROLL_STATE 0x10 55ae115bc7Smrj #define BIOS_NUM_STATE 0x20 56ae115bc7Smrj #define BIOS_CAPS_STATE 0x40 57ae115bc7Smrj #define BIOS_INS_STATE 0x80 58ae115bc7Smrj 59ae115bc7Smrj #define BIOS_KB_FLAG_1 0x418 60ae115bc7Smrj #define BIOS_SYS_SHIFT 0x04 61ae115bc7Smrj #define BIOS_HOLD_STATE 0x08 62ae115bc7Smrj #define BIOS_SCROLL_SHIFT 0x10 63ae115bc7Smrj #define BIOS_NUM_SHIFT 0x20 64ae115bc7Smrj #define BIOS_CAPS_SHIFT 0x40 65ae115bc7Smrj #define BIOS_INS_SHIFT 0x80 66ae115bc7Smrj 67*843e1988Sjohnlev #if defined(__xpv) && defined(_BOOT) 68*843e1988Sjohnlev 69*843e1988Sjohnlev /* 70*843e1988Sjohnlev * Device memory addresses 71*843e1988Sjohnlev * 72*843e1988Sjohnlev * In dboot under the hypervisor we don't have any memory mappings 73*843e1988Sjohnlev * for the first meg of low memory so we can't access devices there. 74*843e1988Sjohnlev * Intead we've mapped the device memory that we need to access into 75*843e1988Sjohnlev * a local variable within dboot so we can access the device memory 76*843e1988Sjohnlev * there. 77*843e1988Sjohnlev */ 78*843e1988Sjohnlev extern unsigned short *kb_status; 79*843e1988Sjohnlev #define kb_flag ((unsigned char *)&kb_status[BIOS_KB_FLAG]) 80*843e1988Sjohnlev #define kb_flag_1 ((unsigned char *)&kb_status[BIOS_KB_FLAG_1]) 81*843e1988Sjohnlev 82*843e1988Sjohnlev #else /* __xpv && _BOOT */ 83*843e1988Sjohnlev 84*843e1988Sjohnlev /* Device memory addresses */ 85ae115bc7Smrj #define kb_flag ((unsigned char *)BIOS_KB_FLAG) 86ae115bc7Smrj #define kb_flag_1 ((unsigned char *)BIOS_KB_FLAG_1) 87ae115bc7Smrj 88*843e1988Sjohnlev #endif /* __xpv && _BOOT */ 89*843e1988Sjohnlev 90ae115bc7Smrj /* 91ae115bc7Smrj * Keyboard controller registers 92ae115bc7Smrj */ 93ae115bc7Smrj #define I8042_DATA 0x60 94ae115bc7Smrj #define I8042_STAT 0x64 95ae115bc7Smrj #define I8042_CMD 0x64 96ae115bc7Smrj 97ae115bc7Smrj /* 98ae115bc7Smrj * Keyboard controller status register bits 99ae115bc7Smrj */ 100ae115bc7Smrj #define I8042_STAT_OUTBF 0x01 101ae115bc7Smrj #define I8042_STAT_INBF 0x02 102ae115bc7Smrj #define I8042_STAT_AUXBF 0x20 103ae115bc7Smrj 104ae115bc7Smrj /* 105ae115bc7Smrj * Keyboard controller commands 106ae115bc7Smrj */ 107ae115bc7Smrj #define I8042_RCB 0x20 108ae115bc7Smrj #define I8042_WCB 0x60 109ae115bc7Smrj 110ae115bc7Smrj /* 111ae115bc7Smrj * Keyboard commands 112ae115bc7Smrj */ 113ae115bc7Smrj #define KB_SET_LED 0xED /* LED byte follows... */ 114ae115bc7Smrj #define KB_LED_SCROLL_LOCK 0x01 /* Bits for LED byte */ 115ae115bc7Smrj #define KB_LED_NUM_LOCK 0x02 116ae115bc7Smrj #define KB_LED_CAPS_LOCK 0x04 117ae115bc7Smrj 118ae115bc7Smrj #ifndef ASSERT 119ae115bc7Smrj #define ASSERT(x) 120ae115bc7Smrj #endif 121ae115bc7Smrj 122ae115bc7Smrj #define peek8(p) (*(p)) 123ae115bc7Smrj #define poke8(p, val) (*(p) = (val)) 124ae115bc7Smrj 125ae115bc7Smrj static struct { 126ae115bc7Smrj boolean_t initialized; 127ae115bc7Smrj enum { KB_LED_IDLE, KB_LED_COMMAND_SENT, KB_LED_VALUE_SENT } 128ae115bc7Smrj led_state; 129ae115bc7Smrj int led_commanded; 130ae115bc7Smrj /* 131ae115bc7Smrj * Possible values: 132ae115bc7Smrj * 133ae115bc7Smrj * -1 Nothing pending 134ae115bc7Smrj * 0x000-0x0ff Pending byte 135ae115bc7Smrj * 0x100-0x1ff Needs leading zero, then low byte next. 136ae115bc7Smrj * 137ae115bc7Smrj * Others undefined. 138ae115bc7Smrj */ 139ae115bc7Smrj int pending; 140ae115bc7Smrj } kb = { 141ae115bc7Smrj B_FALSE, /* initialized? */ 142ae115bc7Smrj KB_LED_IDLE, /* LED command state */ 143ae115bc7Smrj -1, /* commanded LEDs - force refresh */ 144ae115bc7Smrj -1, /* pending */ 145ae115bc7Smrj }; 146ae115bc7Smrj 147ae115bc7Smrj static int kb_translate(unsigned char code); 148ae115bc7Smrj static void kb_send(unsigned char cmd); 149ae115bc7Smrj static void kb_update_leds(void); 150ae115bc7Smrj static uchar_t kb_calculate_leds(void); 151ae115bc7Smrj 152ae115bc7Smrj int 153ae115bc7Smrj kb_getchar(void) 154ae115bc7Smrj { 155ae115bc7Smrj int ret; 156ae115bc7Smrj 157ae115bc7Smrj while (!kb_ischar()) 158ae115bc7Smrj /* LOOP */; 159ae115bc7Smrj 160ae115bc7Smrj /* 161ae115bc7Smrj * kb_ischar() doesn't succeed without leaving kb.pending 162ae115bc7Smrj * set. 163ae115bc7Smrj */ 164ae115bc7Smrj ASSERT(kb.pending >= 0); 165ae115bc7Smrj 166ae115bc7Smrj if (kb.pending & 0x100) { 167ae115bc7Smrj ret = 0; 168ae115bc7Smrj kb.pending &= 0xff; 169ae115bc7Smrj } else { 170ae115bc7Smrj ret = kb.pending; 171ae115bc7Smrj kb.pending = -1; 172ae115bc7Smrj } 173ae115bc7Smrj 174ae115bc7Smrj return (ret); 175ae115bc7Smrj } 176ae115bc7Smrj 177ae115bc7Smrj int 178ae115bc7Smrj kb_ischar(void) 179ae115bc7Smrj { 180ae115bc7Smrj unsigned char buffer_stat; 181ae115bc7Smrj unsigned char code; 182ae115bc7Smrj unsigned char leds; 183ae115bc7Smrj 184ae115bc7Smrj if (!kb.initialized) { 185ae115bc7Smrj kb_init(); 186ae115bc7Smrj kb.initialized = B_TRUE; 187ae115bc7Smrj } 188ae115bc7Smrj 189ae115bc7Smrj if (kb.pending >= 0) 190ae115bc7Smrj return (1); 191ae115bc7Smrj 192ae115bc7Smrj for (;;) { 193ae115bc7Smrj buffer_stat = inb(I8042_STAT); 194ae115bc7Smrj if (buffer_stat == 0xff) 195ae115bc7Smrj return (0); 196ae115bc7Smrj buffer_stat &= (I8042_STAT_OUTBF | I8042_STAT_AUXBF); 197ae115bc7Smrj 198ae115bc7Smrj switch (buffer_stat) { 199ae115bc7Smrj case 0: 200ae115bc7Smrj case I8042_STAT_AUXBF: 201ae115bc7Smrj return (0); 202ae115bc7Smrj case (I8042_STAT_OUTBF | I8042_STAT_AUXBF): 203ae115bc7Smrj /* 204ae115bc7Smrj * Discard unwanted mouse data. 205ae115bc7Smrj */ 206ae115bc7Smrj (void) inb(I8042_DATA); 207ae115bc7Smrj continue; 208ae115bc7Smrj } 209ae115bc7Smrj 210ae115bc7Smrj code = inb(I8042_DATA); 211ae115bc7Smrj 212ae115bc7Smrj switch (code) { 213ae115bc7Smrj /* 214ae115bc7Smrj * case 0xAA: 215ae115bc7Smrj * 216ae115bc7Smrj * You might think that we should ignore 0xAA on the 217ae115bc7Smrj * grounds that it is the BAT Complete response and will 218ae115bc7Smrj * occur on keyboard detach/reattach. Unfortunately, 219ae115bc7Smrj * it is ambiguous - this is also the code for a break 220ae115bc7Smrj * of the left shift key. Since it will be harmless for 221ae115bc7Smrj * us to "spuriously" process a break of Left Shift, 222ae115bc7Smrj * we just let the normal code handle it. Perhaps we 223ae115bc7Smrj * should take a hint and refresh the LEDs, but I 224ae115bc7Smrj * refuse to get very worried about hot-plug issues 225ae115bc7Smrj * in this mini-driver. 226ae115bc7Smrj */ 227ae115bc7Smrj case 0xFA: 228ae115bc7Smrj 229ae115bc7Smrj switch (kb.led_state) { 230ae115bc7Smrj case KB_LED_IDLE: 231ae115bc7Smrj /* 232ae115bc7Smrj * Spurious. Oh well, ignore it. 233ae115bc7Smrj */ 234ae115bc7Smrj break; 235ae115bc7Smrj case KB_LED_COMMAND_SENT: 236ae115bc7Smrj leds = kb_calculate_leds(); 237ae115bc7Smrj kb_send(leds); 238ae115bc7Smrj kb.led_commanded = leds; 239ae115bc7Smrj kb.led_state = KB_LED_VALUE_SENT; 240ae115bc7Smrj break; 241ae115bc7Smrj case KB_LED_VALUE_SENT: 242ae115bc7Smrj kb.led_state = KB_LED_IDLE; 243ae115bc7Smrj /* 244ae115bc7Smrj * Check for changes made while we were 245ae115bc7Smrj * working on the last change. 246ae115bc7Smrj */ 247ae115bc7Smrj kb_update_leds(); 248ae115bc7Smrj break; 249ae115bc7Smrj } 250ae115bc7Smrj continue; 251ae115bc7Smrj 252ae115bc7Smrj case 0xE0: 253ae115bc7Smrj case 0xE1: 254ae115bc7Smrj /* 255ae115bc7Smrj * These are used to distinguish the keys added on 256ae115bc7Smrj * the AT-101 keyboard from the original 84 keys. 257ae115bc7Smrj * We don't care, and the codes are carefully arranged 258ae115bc7Smrj * so that we don't have to. 259ae115bc7Smrj */ 260ae115bc7Smrj continue; 261ae115bc7Smrj 262ae115bc7Smrj default: 263ae115bc7Smrj if (code & 0x80) { 264ae115bc7Smrj /* Release */ 265ae115bc7Smrj code &= 0x7f; 266ae115bc7Smrj switch (keyboard_translate[code].normal) { 267ae115bc7Smrj case KBTYPE_SPEC_LSHIFT: 268ae115bc7Smrj poke8(kb_flag, peek8(kb_flag) & 269ae115bc7Smrj ~BIOS_LEFT_SHIFT); 270ae115bc7Smrj break; 271ae115bc7Smrj case KBTYPE_SPEC_RSHIFT: 272ae115bc7Smrj poke8(kb_flag, peek8(kb_flag) & 273ae115bc7Smrj ~BIOS_RIGHT_SHIFT); 274ae115bc7Smrj break; 275ae115bc7Smrj case KBTYPE_SPEC_CTRL: 276ae115bc7Smrj poke8(kb_flag, peek8(kb_flag) & 277ae115bc7Smrj ~BIOS_CTL_SHIFT); 278ae115bc7Smrj break; 279ae115bc7Smrj case KBTYPE_SPEC_ALT: 280ae115bc7Smrj poke8(kb_flag, peek8(kb_flag) & 281ae115bc7Smrj ~BIOS_ALT_SHIFT); 282ae115bc7Smrj break; 283ae115bc7Smrj case KBTYPE_SPEC_CAPS_LOCK: 284ae115bc7Smrj poke8(kb_flag_1, peek8(kb_flag_1) & 285ae115bc7Smrj ~BIOS_CAPS_SHIFT); 286ae115bc7Smrj break; 287ae115bc7Smrj case KBTYPE_SPEC_NUM_LOCK: 288ae115bc7Smrj poke8(kb_flag_1, peek8(kb_flag_1) & 289ae115bc7Smrj ~BIOS_NUM_SHIFT); 290ae115bc7Smrj break; 291ae115bc7Smrj case KBTYPE_SPEC_SCROLL_LOCK: 292ae115bc7Smrj poke8(kb_flag_1, peek8(kb_flag_1) & 293ae115bc7Smrj ~BIOS_SCROLL_SHIFT); 294ae115bc7Smrj break; 295ae115bc7Smrj default: 296ae115bc7Smrj /* 297ae115bc7Smrj * Ignore all other releases. 298ae115bc7Smrj */ 299ae115bc7Smrj break; 300ae115bc7Smrj } 301ae115bc7Smrj } else { 302ae115bc7Smrj /* Press */ 303ae115bc7Smrj 304ae115bc7Smrj kb.pending = kb_translate(code); 305ae115bc7Smrj if (kb.pending >= 0) { 306ae115bc7Smrj return (1); 307ae115bc7Smrj } 308ae115bc7Smrj } 309ae115bc7Smrj } 310ae115bc7Smrj } 311ae115bc7Smrj } 312ae115bc7Smrj 313ae115bc7Smrj int 314ae115bc7Smrj kb_translate(unsigned char code) 315ae115bc7Smrj { 316ae115bc7Smrj struct keyboard_translate *k; 317ae115bc7Smrj unsigned short action; 318ae115bc7Smrj boolean_t shifted; 319ae115bc7Smrj 320ae115bc7Smrj k = keyboard_translate + code; 321ae115bc7Smrj 322ae115bc7Smrj shifted = (peek8(kb_flag) & BIOS_EITHER_SHIFT) != 0; 323ae115bc7Smrj 324ae115bc7Smrj switch (k->normal & 0xFF00) { 325ae115bc7Smrj case KBTYPE_NUMPAD: 326ae115bc7Smrj if (peek8(kb_flag) & BIOS_NUM_STATE) 327ae115bc7Smrj shifted = !shifted; 328ae115bc7Smrj break; 329ae115bc7Smrj case KBTYPE_ALPHA: 330ae115bc7Smrj if (peek8(kb_flag) & BIOS_CAPS_STATE) 331ae115bc7Smrj shifted = !shifted; 332ae115bc7Smrj break; 333ae115bc7Smrj } 334ae115bc7Smrj 335ae115bc7Smrj if (peek8(kb_flag) & BIOS_ALT_SHIFT) 336ae115bc7Smrj action = k->alted; 337ae115bc7Smrj else if (peek8(kb_flag) & BIOS_CTL_SHIFT) 338ae115bc7Smrj action = k->ctrled; 339ae115bc7Smrj else if (shifted) 340ae115bc7Smrj action = k->shifted; 341ae115bc7Smrj else 342ae115bc7Smrj action = k->normal; 343ae115bc7Smrj 344ae115bc7Smrj switch (action & 0xFF00) { 345ae115bc7Smrj case KBTYPE_NORMAL: 346ae115bc7Smrj case KBTYPE_ALPHA: 347ae115bc7Smrj return (action & 0xFF); 348ae115bc7Smrj 349ae115bc7Smrj case KBTYPE_NUMPAD: 350ae115bc7Smrj case KBTYPE_FUNC: 351ae115bc7Smrj return ((action & 0xFF) | 0x100); 352ae115bc7Smrj 353ae115bc7Smrj case KBTYPE_SPEC: 354ae115bc7Smrj break; 355ae115bc7Smrj 356ae115bc7Smrj default: 357ae115bc7Smrj /* 358ae115bc7Smrj * Bad entry. 359ae115bc7Smrj */ 360ae115bc7Smrj ASSERT(0); 361ae115bc7Smrj return (-1); 362ae115bc7Smrj } 363ae115bc7Smrj 364ae115bc7Smrj /* 365ae115bc7Smrj * Handle special keys, mostly shifts. 366ae115bc7Smrj */ 367ae115bc7Smrj switch (action) { 368ae115bc7Smrj case KBTYPE_SPEC_NOP: 369ae115bc7Smrj case KBTYPE_SPEC_UNDEF: 370ae115bc7Smrj break; 371ae115bc7Smrj 372ae115bc7Smrj case KBTYPE_SPEC_LSHIFT: 373ae115bc7Smrj poke8(kb_flag, peek8(kb_flag) | BIOS_LEFT_SHIFT); 374ae115bc7Smrj break; 375ae115bc7Smrj 376ae115bc7Smrj case KBTYPE_SPEC_RSHIFT: 377ae115bc7Smrj poke8(kb_flag, peek8(kb_flag) | BIOS_RIGHT_SHIFT); 378ae115bc7Smrj break; 379ae115bc7Smrj 380ae115bc7Smrj case KBTYPE_SPEC_CTRL: 381ae115bc7Smrj poke8(kb_flag, peek8(kb_flag) | BIOS_CTL_SHIFT); 382ae115bc7Smrj break; 383ae115bc7Smrj 384ae115bc7Smrj case KBTYPE_SPEC_ALT: 385ae115bc7Smrj poke8(kb_flag, peek8(kb_flag) | BIOS_ALT_SHIFT); 386ae115bc7Smrj break; 387ae115bc7Smrj 388ae115bc7Smrj case KBTYPE_SPEC_CAPS_LOCK: 389ae115bc7Smrj if (!(peek8(kb_flag_1) & BIOS_CAPS_SHIFT)) { 390ae115bc7Smrj poke8(kb_flag_1, peek8(kb_flag_1) | BIOS_CAPS_SHIFT); 391ae115bc7Smrj poke8(kb_flag, peek8(kb_flag) ^ BIOS_CAPS_STATE); 392ae115bc7Smrj } 393ae115bc7Smrj break; 394ae115bc7Smrj 395ae115bc7Smrj case KBTYPE_SPEC_NUM_LOCK: 396ae115bc7Smrj if (!(peek8(kb_flag_1) & BIOS_NUM_SHIFT)) { 397ae115bc7Smrj poke8(kb_flag_1, peek8(kb_flag_1) | BIOS_NUM_SHIFT); 398ae115bc7Smrj poke8(kb_flag, peek8(kb_flag) ^ BIOS_NUM_STATE); 399ae115bc7Smrj } 400ae115bc7Smrj break; 401ae115bc7Smrj 402ae115bc7Smrj case KBTYPE_SPEC_SCROLL_LOCK: 403ae115bc7Smrj if (!(peek8(kb_flag_1) & BIOS_SCROLL_SHIFT)) { 404ae115bc7Smrj poke8(kb_flag_1, peek8(kb_flag_1) | BIOS_SCROLL_SHIFT); 405ae115bc7Smrj poke8(kb_flag, peek8(kb_flag) ^ BIOS_SCROLL_STATE); 406ae115bc7Smrj } 407ae115bc7Smrj break; 408ae115bc7Smrj 409ae115bc7Smrj case KBTYPE_SPEC_MAYBE_REBOOT: 410ae115bc7Smrj #if 0 /* Solaris doesn't reboot via ctrl-alt-del */ 411ae115bc7Smrj if ((peek8(kb_flag) & (BIOS_CTL_SHIFT|BIOS_ALT_SHIFT)) == 412ae115bc7Smrj (BIOS_CTL_SHIFT|BIOS_ALT_SHIFT)) { 413ae115bc7Smrj reset(); 414ae115bc7Smrj /* NOTREACHED */ 415ae115bc7Smrj } 416ae115bc7Smrj #endif 417ae115bc7Smrj break; 418ae115bc7Smrj 419ae115bc7Smrj default: 420ae115bc7Smrj /* 421ae115bc7Smrj * Bad entry 422ae115bc7Smrj */ 423ae115bc7Smrj ASSERT(0); 424ae115bc7Smrj break; 425ae115bc7Smrj } 426ae115bc7Smrj 427ae115bc7Smrj /* 428ae115bc7Smrj * Consider updating the LEDs. This does nothing if nothing 429ae115bc7Smrj * needs to be done. 430ae115bc7Smrj */ 431ae115bc7Smrj kb_update_leds(); 432ae115bc7Smrj 433ae115bc7Smrj return (-1); 434ae115bc7Smrj } 435ae115bc7Smrj 436ae115bc7Smrj void 437ae115bc7Smrj kb_send(unsigned char cmd) 438ae115bc7Smrj { 439ae115bc7Smrj int retries; 440ae115bc7Smrj 441ae115bc7Smrj for (retries = 0; 442ae115bc7Smrj (inb(I8042_STAT) & I8042_STAT_INBF) != 0 && retries < 100000; 443ae115bc7Smrj retries++) 444ae115bc7Smrj /* LOOP */; 445ae115bc7Smrj outb(I8042_DATA, cmd); 446ae115bc7Smrj } 447ae115bc7Smrj 448ae115bc7Smrj void 449ae115bc7Smrj kb_update_leds(void) 450ae115bc7Smrj { 451ae115bc7Smrj if (kb.led_state != KB_LED_IDLE) { 452ae115bc7Smrj /* 453ae115bc7Smrj * The state machine will take care of any additional 454ae115bc7Smrj * changes that are necessary. 455ae115bc7Smrj */ 456ae115bc7Smrj return; 457ae115bc7Smrj } 458ae115bc7Smrj 459ae115bc7Smrj if (kb_calculate_leds() == kb.led_commanded) { 460ae115bc7Smrj kb.led_state = KB_LED_IDLE; 461ae115bc7Smrj } else { 462ae115bc7Smrj kb_send(KB_SET_LED); 463ae115bc7Smrj kb.led_state = KB_LED_COMMAND_SENT; 464ae115bc7Smrj } 465ae115bc7Smrj } 466ae115bc7Smrj 467ae115bc7Smrj #define MIMR_PORT 0x21 /* Mask register for master PIC */ 468ae115bc7Smrj #define MIMR_KB 2 /* Keyboard mask bit in master PIC */ 469ae115bc7Smrj 470ae115bc7Smrj void 471ae115bc7Smrj kb_init(void) 472ae115bc7Smrj { 473ae115bc7Smrj /* 474*843e1988Sjohnlev * Resist the urge to muck with the keyboard/mouse. Just assume 475*843e1988Sjohnlev * that the bios, grub, and any optional hypervisor have left 476*843e1988Sjohnlev * the keyboard in a sane and usable state. Messing with it now 477*843e1988Sjohnlev * could result it making it unusuable, which would break early 478*843e1988Sjohnlev * kmdb debugging support. Note that we don't actually need to 479*843e1988Sjohnlev * disable interrupts for the keyboard/mouse since we're already 480*843e1988Sjohnlev * in protected mode and we're not compeating with the bios for 481*843e1988Sjohnlev * keyboard access. Also, we don't need to disable the mouse 482*843e1988Sjohnlev * port since our polled input routine will just drop any mouse 483*843e1988Sjohnlev * data that it recieves. 484ae115bc7Smrj */ 485ae115bc7Smrj kb_update_leds(); 486ae115bc7Smrj } 487ae115bc7Smrj 488ae115bc7Smrj unsigned char 489ae115bc7Smrj kb_calculate_leds(void) 490ae115bc7Smrj { 491ae115bc7Smrj int res; 492ae115bc7Smrj 493ae115bc7Smrj res = 0; 494ae115bc7Smrj 495ae115bc7Smrj if (peek8(kb_flag) & BIOS_CAPS_STATE) 496ae115bc7Smrj res |= KB_LED_CAPS_LOCK; 497ae115bc7Smrj 498ae115bc7Smrj if (peek8(kb_flag) & BIOS_NUM_STATE) 499ae115bc7Smrj res |= KB_LED_NUM_LOCK; 500ae115bc7Smrj 501ae115bc7Smrj if (peek8(kb_flag) & BIOS_SCROLL_STATE) 502ae115bc7Smrj res |= KB_LED_SCROLL_LOCK; 503ae115bc7Smrj 504ae115bc7Smrj return ((char)res); 505ae115bc7Smrj } 506