1 /* 2 * Kernel Debugger Architecture Dependent Console I/O handler 3 * 4 * This file is subject to the terms and conditions of the GNU General Public 5 * License. 6 * 7 * Copyright (c) 1999-2006 Silicon Graphics, Inc. All Rights Reserved. 8 * Copyright (c) 2009 Wind River Systems, Inc. All Rights Reserved. 9 */ 10 11 #include <linux/kdb.h> 12 #include <linux/keyboard.h> 13 #include <linux/ctype.h> 14 #include <linux/module.h> 15 #include <linux/io.h> 16 17 /* Keyboard Controller Registers on normal PCs. */ 18 19 #define KBD_STATUS_REG 0x64 /* Status register (R) */ 20 #define KBD_DATA_REG 0x60 /* Keyboard data register (R/W) */ 21 22 /* Status Register Bits */ 23 24 #define KBD_STAT_OBF 0x01 /* Keyboard output buffer full */ 25 #define KBD_STAT_MOUSE_OBF 0x20 /* Mouse output buffer full */ 26 27 static int kbd_exists; 28 29 /* 30 * Check if the keyboard controller has a keypress for us. 31 * Some parts (Enter Release, LED change) are still blocking polled here, 32 * but hopefully they are all short. 33 */ 34 int kdb_get_kbd_char(void) 35 { 36 int scancode, scanstatus; 37 static int shift_lock; /* CAPS LOCK state (0-off, 1-on) */ 38 static int shift_key; /* Shift next keypress */ 39 static int ctrl_key; 40 u_short keychar; 41 42 if (KDB_FLAG(NO_I8042) || KDB_FLAG(NO_VT_CONSOLE) || 43 (inb(KBD_STATUS_REG) == 0xff && inb(KBD_DATA_REG) == 0xff)) { 44 kbd_exists = 0; 45 return -1; 46 } 47 kbd_exists = 1; 48 49 if ((inb(KBD_STATUS_REG) & KBD_STAT_OBF) == 0) 50 return -1; 51 52 /* 53 * Fetch the scancode 54 */ 55 scancode = inb(KBD_DATA_REG); 56 scanstatus = inb(KBD_STATUS_REG); 57 58 /* 59 * Ignore mouse events. 60 */ 61 if (scanstatus & KBD_STAT_MOUSE_OBF) 62 return -1; 63 64 /* 65 * Ignore release, trigger on make 66 * (except for shift keys, where we want to 67 * keep the shift state so long as the key is 68 * held down). 69 */ 70 71 if (((scancode&0x7f) == 0x2a) || ((scancode&0x7f) == 0x36)) { 72 /* 73 * Next key may use shift table 74 */ 75 if ((scancode & 0x80) == 0) 76 shift_key = 1; 77 else 78 shift_key = 0; 79 return -1; 80 } 81 82 if ((scancode&0x7f) == 0x1d) { 83 /* 84 * Left ctrl key 85 */ 86 if ((scancode & 0x80) == 0) 87 ctrl_key = 1; 88 else 89 ctrl_key = 0; 90 return -1; 91 } 92 93 if ((scancode & 0x80) != 0) 94 return -1; 95 96 scancode &= 0x7f; 97 98 /* 99 * Translate scancode 100 */ 101 102 if (scancode == 0x3a) { 103 /* 104 * Toggle caps lock 105 */ 106 shift_lock ^= 1; 107 108 #ifdef KDB_BLINK_LED 109 kdb_toggleled(0x4); 110 #endif 111 return -1; 112 } 113 114 if (scancode == 0x0e) { 115 /* 116 * Backspace 117 */ 118 return 8; 119 } 120 121 /* Special Key */ 122 switch (scancode) { 123 case 0xF: /* Tab */ 124 return 9; 125 case 0x53: /* Del */ 126 return 4; 127 case 0x47: /* Home */ 128 return 1; 129 case 0x4F: /* End */ 130 return 5; 131 case 0x4B: /* Left */ 132 return 2; 133 case 0x48: /* Up */ 134 return 16; 135 case 0x50: /* Down */ 136 return 14; 137 case 0x4D: /* Right */ 138 return 6; 139 } 140 141 if (scancode == 0xe0) 142 return -1; 143 144 /* 145 * For Japanese 86/106 keyboards 146 * See comment in drivers/char/pc_keyb.c. 147 * - Masahiro Adegawa 148 */ 149 if (scancode == 0x73) 150 scancode = 0x59; 151 else if (scancode == 0x7d) 152 scancode = 0x7c; 153 154 if (!shift_lock && !shift_key && !ctrl_key) { 155 keychar = plain_map[scancode]; 156 } else if ((shift_lock || shift_key) && key_maps[1]) { 157 keychar = key_maps[1][scancode]; 158 } else if (ctrl_key && key_maps[4]) { 159 keychar = key_maps[4][scancode]; 160 } else { 161 keychar = 0x0020; 162 kdb_printf("Unknown state/scancode (%d)\n", scancode); 163 } 164 keychar &= 0x0fff; 165 if (keychar == '\t') 166 keychar = ' '; 167 switch (KTYP(keychar)) { 168 case KT_LETTER: 169 case KT_LATIN: 170 if (isprint(keychar)) 171 break; /* printable characters */ 172 /* drop through */ 173 case KT_SPEC: 174 if (keychar == K_ENTER) 175 break; 176 /* drop through */ 177 default: 178 return -1; /* ignore unprintables */ 179 } 180 181 if ((scancode & 0x7f) == 0x1c) { 182 /* 183 * enter key. All done. Absorb the release scancode. 184 */ 185 while ((inb(KBD_STATUS_REG) & KBD_STAT_OBF) == 0) 186 ; 187 188 /* 189 * Fetch the scancode 190 */ 191 scancode = inb(KBD_DATA_REG); 192 scanstatus = inb(KBD_STATUS_REG); 193 194 while (scanstatus & KBD_STAT_MOUSE_OBF) { 195 scancode = inb(KBD_DATA_REG); 196 scanstatus = inb(KBD_STATUS_REG); 197 } 198 199 if (scancode != 0x9c) { 200 /* 201 * Wasn't an enter-release, why not? 202 */ 203 kdb_printf("kdb: expected enter got 0x%x status 0x%x\n", 204 scancode, scanstatus); 205 } 206 207 return 13; 208 } 209 210 return keychar & 0xff; 211 } 212 EXPORT_SYMBOL_GPL(kdb_get_kbd_char); 213