1 /* 2 * (C) Copyright 2002 ELTEC Elektronik AG 3 * Frank Gottschling <fgottschling@eltec.de> 4 * 5 * See file CREDITS for list of people who contributed to this 6 * project. 7 * 8 * This program is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU General Public License as 10 * published by the Free Software Foundation; either version 2 of 11 * the License, or (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to the Free Software 20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 21 * MA 02111-1307 USA 22 */ 23 24 /* i8042.c - Intel 8042 keyboard driver routines */ 25 26 /* includes */ 27 28 #include <common.h> 29 30 #ifdef CONFIG_USE_CPCIDVI 31 extern u8 gt_cpcidvi_in8(u32 offset); 32 extern void gt_cpcidvi_out8(u32 offset, u8 data); 33 34 #define in8(a) gt_cpcidvi_in8(a) 35 #define out8(a, b) gt_cpcidvi_out8(a, b) 36 #endif 37 38 #include <i8042.h> 39 40 /* defines */ 41 42 #ifdef CONFIG_CONSOLE_CURSOR 43 extern void console_cursor(int state); 44 static int blinkCount = CONFIG_SYS_CONSOLE_BLINK_COUNT; 45 static int cursor_state; 46 #endif 47 48 /* locals */ 49 50 static int kbd_input = -1; /* no input yet */ 51 static int kbd_mapping = KBD_US; /* default US keyboard */ 52 static int kbd_flags = NORMAL; /* after reset */ 53 static int kbd_state; /* unshift code */ 54 55 static void kbd_conv_char(unsigned char scan_code); 56 static void kbd_led_set(void); 57 static void kbd_normal(unsigned char scan_code); 58 static void kbd_shift(unsigned char scan_code); 59 static void kbd_ctrl(unsigned char scan_code); 60 static void kbd_num(unsigned char scan_code); 61 static void kbd_caps(unsigned char scan_code); 62 static void kbd_scroll(unsigned char scan_code); 63 static void kbd_alt(unsigned char scan_code); 64 static int kbd_input_empty(void); 65 static int kbd_reset(void); 66 67 static unsigned char kbd_fct_map[144] = { 68 /* kbd_fct_map table for scan code */ 69 0, AS, AS, AS, AS, AS, AS, AS, /* scan 0- 7 */ 70 AS, AS, AS, AS, AS, AS, AS, AS, /* scan 8- F */ 71 AS, AS, AS, AS, AS, AS, AS, AS, /* scan 10-17 */ 72 AS, AS, AS, AS, AS, CN, AS, AS, /* scan 18-1F */ 73 AS, AS, AS, AS, AS, AS, AS, AS, /* scan 20-27 */ 74 AS, AS, SH, AS, AS, AS, AS, AS, /* scan 28-2F */ 75 AS, AS, AS, AS, AS, AS, SH, AS, /* scan 30-37 */ 76 AS, AS, CP, 0, 0, 0, 0, 0, /* scan 38-3F */ 77 0, 0, 0, 0, 0, NM, ST, ES, /* scan 40-47 */ 78 ES, ES, ES, ES, ES, ES, ES, ES, /* scan 48-4F */ 79 ES, ES, ES, ES, 0, 0, AS, 0, /* scan 50-57 */ 80 0, 0, 0, 0, 0, 0, 0, 0, /* scan 58-5F */ 81 0, 0, 0, 0, 0, 0, 0, 0, /* scan 60-67 */ 82 0, 0, 0, 0, 0, 0, 0, 0, /* scan 68-6F */ 83 AS, 0, 0, AS, 0, 0, AS, 0, /* scan 70-77 */ 84 0, AS, 0, 0, 0, AS, 0, 0, /* scan 78-7F */ 85 AS, CN, AS, AS, AK, ST, EX, EX, /* enhanced */ 86 AS, EX, EX, AS, EX, AS, EX, EX /* enhanced */ 87 }; 88 89 static unsigned char kbd_key_map[2][5][144] = { 90 { /* US keyboard */ 91 { /* unshift code */ 92 0, 0x1b, '1', '2', '3', '4', '5', '6', /* scan 0- 7 */ 93 '7', '8', '9', '0', '-', '=', 0x08, '\t', /* scan 8- F */ 94 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', /* scan 10-17 */ 95 'o', 'p', '[', ']', '\r', CN, 'a', 's', /* scan 18-1F */ 96 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', /* scan 20-27 */ 97 '\'', '`', SH, '\\', 'z', 'x', 'c', 'v', /* scan 28-2F */ 98 'b', 'n', 'm', ',', '.', '/', SH, '*', /* scan 30-37 */ 99 ' ', ' ', CP, 0, 0, 0, 0, 0, /* scan 38-3F */ 100 0, 0, 0, 0, 0, NM, ST, '7', /* scan 40-47 */ 101 '8', '9', '-', '4', '5', '6', '+', '1', /* scan 48-4F */ 102 '2', '3', '0', '.', 0, 0, 0, 0, /* scan 50-57 */ 103 0, 0, 0, 0, 0, 0, 0, 0, /* scan 58-5F */ 104 0, 0, 0, 0, 0, 0, 0, 0, /* scan 60-67 */ 105 0, 0, 0, 0, 0, 0, 0, 0, /* scan 68-6F */ 106 0, 0, 0, 0, 0, 0, 0, 0, /* scan 70-77 */ 107 0, 0, 0, 0, 0, 0, 0, 0, /* scan 78-7F */ 108 '\r', CN, '/', '*', ' ', ST, 'F', 'A', /* extended */ 109 0, 'D', 'C', 0, 'B', 0, '@', 'P' /* extended */ 110 }, 111 { /* shift code */ 112 0, 0x1b, '!', '@', '#', '$', '%', '^', /* scan 0- 7 */ 113 '&', '*', '(', ')', '_', '+', 0x08, '\t', /* scan 8- F */ 114 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', /* scan 10-17 */ 115 'O', 'P', '{', '}', '\r', CN, 'A', 'S', /* scan 18-1F */ 116 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', /* scan 20-27 */ 117 '"', '~', SH, '|', 'Z', 'X', 'C', 'V', /* scan 28-2F */ 118 'B', 'N', 'M', '<', '>', '?', SH, '*', /* scan 30-37 */ 119 ' ', ' ', CP, 0, 0, 0, 0, 0, /* scan 38-3F */ 120 0, 0, 0, 0, 0, NM, ST, '7', /* scan 40-47 */ 121 '8', '9', '-', '4', '5', '6', '+', '1', /* scan 48-4F */ 122 '2', '3', '0', '.', 0, 0, 0, 0, /* scan 50-57 */ 123 0, 0, 0, 0, 0, 0, 0, 0, /* scan 58-5F */ 124 0, 0, 0, 0, 0, 0, 0, 0, /* scan 60-67 */ 125 0, 0, 0, 0, 0, 0, 0, 0, /* scan 68-6F */ 126 0, 0, 0, 0, 0, 0, 0, 0, /* scan 70-77 */ 127 0, 0, 0, 0, 0, 0, 0, 0, /* scan 78-7F */ 128 '\r', CN, '/', '*', ' ', ST, 'F', 'A', /* extended */ 129 0, 'D', 'C', 0, 'B', 0, '@', 'P' /* extended */ 130 }, 131 { /* control code */ 132 0xff, 0x1b, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, /* scan 0- 7 */ 133 0x1e, 0xff, 0xff, 0xff, 0x1f, 0xff, 0xff, '\t', /* scan 8- F */ 134 0x11, 0x17, 0x05, 0x12, 0x14, 0x19, 0x15, 0x09, /* scan 10-17 */ 135 0x0f, 0x10, 0x1b, 0x1d, '\r', CN, 0x01, 0x13, /* scan 18-1F */ 136 0x04, 0x06, 0x07, 0x08, 0x0a, 0x0b, 0x0c, 0xff, /* scan 20-27 */ 137 0xff, 0x1c, SH, 0xff, 0x1a, 0x18, 0x03, 0x16, /* scan 28-2F */ 138 0x02, 0x0e, 0x0d, 0xff, 0xff, 0xff, SH, 0xff, /* scan 30-37 */ 139 0xff, 0xff, CP, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 38-3F */ 140 0xff, 0xff, 0xff, 0xff, 0xff, NM, ST, 0xff, /* scan 40-47 */ 141 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 48-4F */ 142 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 50-57 */ 143 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 58-5F */ 144 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 60-67 */ 145 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 68-6F */ 146 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 70-77 */ 147 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 78-7F */ 148 '\r', CN, '/', '*', ' ', ST, 0xff, 0xff, /* extended */ 149 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff /* extended */ 150 }, 151 { /* non numeric code */ 152 0, 0x1b, '1', '2', '3', '4', '5', '6', /* scan 0- 7 */ 153 '7', '8', '9', '0', '-', '=', 0x08, '\t', /* scan 8- F */ 154 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', /* scan 10-17 */ 155 'o', 'p', '[', ']', '\r', CN, 'a', 's', /* scan 18-1F */ 156 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', /* scan 20-27 */ 157 '\'', '`', SH, '\\', 'z', 'x', 'c', 'v', /* scan 28-2F */ 158 'b', 'n', 'm', ',', '.', '/', SH, '*', /* scan 30-37 */ 159 ' ', ' ', CP, 0, 0, 0, 0, 0, /* scan 38-3F */ 160 0, 0, 0, 0, 0, NM, ST, 'w', /* scan 40-47 */ 161 'x', 'y', 'l', 't', 'u', 'v', 'm', 'q', /* scan 48-4F */ 162 'r', 's', 'p', 'n', 0, 0, 0, 0, /* scan 50-57 */ 163 0, 0, 0, 0, 0, 0, 0, 0, /* scan 58-5F */ 164 0, 0, 0, 0, 0, 0, 0, 0, /* scan 60-67 */ 165 0, 0, 0, 0, 0, 0, 0, 0, /* scan 68-6F */ 166 0, 0, 0, 0, 0, 0, 0, 0, /* scan 70-77 */ 167 0, 0, 0, 0, 0, 0, 0, 0, /* scan 78-7F */ 168 '\r', CN, '/', '*', ' ', ST, 'F', 'A', /* extended */ 169 0, 'D', 'C', 0, 'B', 0, '@', 'P' /* extended */ 170 }, 171 { /* right alt mode - not used in US keyboard */ 172 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 0 - 7 */ 173 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 8 - F */ 174 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 10 -17 */ 175 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 18 -1F */ 176 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 20 -27 */ 177 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 28 -2F */ 178 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 30 -37 */ 179 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 38 -3F */ 180 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 40 -47 */ 181 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 48 -4F */ 182 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 50 -57 */ 183 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 58 -5F */ 184 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 60 -67 */ 185 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 68 -6F */ 186 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 70 -77 */ 187 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 78 -7F */ 188 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* extended */ 189 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff /* extended */ 190 } 191 }, 192 { /* german keyboard */ 193 { /* unshift code */ 194 0, 0x1b, '1', '2', '3', '4', '5', '6', /* scan 0- 7 */ 195 '7', '8', '9', '0', 0xe1, '\'', 0x08, '\t', /* scan 8- F */ 196 'q', 'w', 'e', 'r', 't', 'z', 'u', 'i', /* scan 10-17 */ 197 'o', 'p', 0x81, '+', '\r', CN, 'a', 's', /* scan 18-1F */ 198 'd', 'f', 'g', 'h', 'j', 'k', 'l', 0x94, /* scan 20-27 */ 199 0x84, '^', SH, '#', 'y', 'x', 'c', 'v', /* scan 28-2F */ 200 'b', 'n', 'm', ',', '.', '-', SH, '*', /* scan 30-37 */ 201 ' ', ' ', CP, 0, 0, 0, 0, 0, /* scan 38-3F */ 202 0, 0, 0, 0, 0, NM, ST, '7', /* scan 40-47 */ 203 '8', '9', '-', '4', '5', '6', '+', '1', /* scan 48-4F */ 204 '2', '3', '0', ',', 0, 0, '<', 0, /* scan 50-57 */ 205 0, 0, 0, 0, 0, 0, 0, 0, /* scan 58-5F */ 206 0, 0, 0, 0, 0, 0, 0, 0, /* scan 60-67 */ 207 0, 0, 0, 0, 0, 0, 0, 0, /* scan 68-6F */ 208 0, 0, 0, 0, 0, 0, 0, 0, /* scan 70-77 */ 209 0, 0, 0, 0, 0, 0, 0, 0, /* scan 78-7F */ 210 '\r', CN, '/', '*', ' ', ST, 'F', 'A', /* extended */ 211 0, 'D', 'C', 0, 'B', 0, '@', 'P' /* extended */ 212 }, 213 { /* shift code */ 214 0, 0x1b, '!', '"', 0x15, '$', '%', '&', /* scan 0- 7 */ 215 '/', '(', ')', '=', '?', '`', 0x08, '\t', /* scan 8- F */ 216 'Q', 'W', 'E', 'R', 'T', 'Z', 'U', 'I', /* scan 10-17 */ 217 'O', 'P', 0x9a, '*', '\r', CN, 'A', 'S', /* scan 18-1F */ 218 'D', 'F', 'G', 'H', 'J', 'K', 'L', 0x99, /* scan 20-27 */ 219 0x8e, 0xf8, SH, '\'', 'Y', 'X', 'C', 'V', /* scan 28-2F */ 220 'B', 'N', 'M', ';', ':', '_', SH, '*', /* scan 30-37 */ 221 ' ', ' ', CP, 0, 0, 0, 0, 0, /* scan 38-3F */ 222 0, 0, 0, 0, 0, NM, ST, '7', /* scan 40-47 */ 223 '8', '9', '-', '4', '5', '6', '+', '1', /* scan 48-4F */ 224 '2', '3', '0', ',', 0, 0, '>', 0, /* scan 50-57 */ 225 0, 0, 0, 0, 0, 0, 0, 0, /* scan 58-5F */ 226 0, 0, 0, 0, 0, 0, 0, 0, /* scan 60-67 */ 227 0, 0, 0, 0, 0, 0, 0, 0, /* scan 68-6F */ 228 0, 0, 0, 0, 0, 0, 0, 0, /* scan 70-77 */ 229 0, 0, 0, 0, 0, 0, 0, 0, /* scan 78-7F */ 230 '\r', CN, '/', '*', ' ', ST, 'F', 'A', /* extended */ 231 0, 'D', 'C', 0, 'B', 0, '@', 'P' /* extended */ 232 }, 233 { /* control code */ 234 0xff, 0x1b, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, /* scan 0- 7 */ 235 0x1e, 0xff, 0xff, 0xff, 0x1f, 0xff, 0xff, '\t', /* scan 8- F */ 236 0x11, 0x17, 0x05, 0x12, 0x14, 0x19, 0x15, 0x09, /* scan 10-17 */ 237 0x0f, 0x10, 0x1b, 0x1d, '\r', CN, 0x01, 0x13, /* scan 18-1F */ 238 0x04, 0x06, 0x07, 0x08, 0x0a, 0x0b, 0x0c, 0xff, /* scan 20-27 */ 239 0xff, 0x1c, SH, 0xff, 0x1a, 0x18, 0x03, 0x16, /* scan 28-2F */ 240 0x02, 0x0e, 0x0d, 0xff, 0xff, 0xff, SH, 0xff, /* scan 30-37 */ 241 0xff, 0xff, CP, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 38-3F */ 242 0xff, 0xff, 0xff, 0xff, 0xff, NM, ST, 0xff, /* scan 40-47 */ 243 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 48-4F */ 244 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 50-57 */ 245 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 58-5F */ 246 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 60-67 */ 247 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 68-6F */ 248 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 70-77 */ 249 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 78-7F */ 250 '\r', CN, '/', '*', ' ', ST, 0xff, 0xff, /* extended */ 251 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff /* extended */ 252 }, 253 { /* non numeric code */ 254 0, 0x1b, '1', '2', '3', '4', '5', '6', /* scan 0- 7 */ 255 '7', '8', '9', '0', 0xe1, '\'', 0x08, '\t', /* scan 8- F */ 256 'q', 'w', 'e', 'r', 't', 'z', 'u', 'i', /* scan 10-17 */ 257 'o', 'p', 0x81, '+', '\r', CN, 'a', 's', /* scan 18-1F */ 258 'd', 'f', 'g', 'h', 'j', 'k', 'l', 0x94, /* scan 20-27 */ 259 0x84, '^', SH, 0, 'y', 'x', 'c', 'v', /* scan 28-2F */ 260 'b', 'n', 'm', ',', '.', '-', SH, '*', /* scan 30-37 */ 261 ' ', ' ', CP, 0, 0, 0, 0, 0, /* scan 38-3F */ 262 0, 0, 0, 0, 0, NM, ST, 'w', /* scan 40-47 */ 263 'x', 'y', 'l', 't', 'u', 'v', 'm', 'q', /* scan 48-4F */ 264 'r', 's', 'p', 'n', 0, 0, '<', 0, /* scan 50-57 */ 265 0, 0, 0, 0, 0, 0, 0, 0, /* scan 58-5F */ 266 0, 0, 0, 0, 0, 0, 0, 0, /* scan 60-67 */ 267 0, 0, 0, 0, 0, 0, 0, 0, /* scan 68-6F */ 268 0, 0, 0, 0, 0, 0, 0, 0, /* scan 70-77 */ 269 0, 0, 0, 0, 0, 0, 0, 0, /* scan 78-7F */ 270 '\r', CN, '/', '*', ' ', ST, 'F', 'A', /* extended */ 271 0, 'D', 'C', 0, 'B', 0, '@', 'P' /* extended */ 272 }, 273 { /* Right alt mode - is used in German keyboard */ 274 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 0 - 7 */ 275 '{', '[', ']', '}', '\\', 0xff, 0xff, 0xff, /* scan 8 - F */ 276 '@', 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 10 -17 */ 277 0xff, 0xff, 0xff, '~', 0xff, 0xff, 0xff, 0xff, /* scan 18 -1F */ 278 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 20 -27 */ 279 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 28 -2F */ 280 0xff, 0xff, 0xe6, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 30 -37 */ 281 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 38 -3F */ 282 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 40 -47 */ 283 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 48 -4F */ 284 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, '|', 0xff, /* scan 50 -57 */ 285 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 58 -5F */ 286 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 60 -67 */ 287 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 68 -6F */ 288 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 70 -77 */ 289 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 78 -7F */ 290 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* extended */ 291 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff /* extended */ 292 } 293 } 294 }; 295 296 static unsigned char ext_key_map[] = { 297 0x1c, /* keypad enter */ 298 0x1d, /* right control */ 299 0x35, /* keypad slash */ 300 0x37, /* print screen */ 301 0x38, /* right alt */ 302 0x46, /* break */ 303 0x47, /* editpad home */ 304 0x48, /* editpad up */ 305 0x49, /* editpad pgup */ 306 0x4b, /* editpad left */ 307 0x4d, /* editpad right */ 308 0x4f, /* editpad end */ 309 0x50, /* editpad dn */ 310 0x51, /* editpad pgdn */ 311 0x52, /* editpad ins */ 312 0x53, /* editpad del */ 313 0x00 /* map end */ 314 }; 315 316 /******************************************************************************* 317 * 318 * i8042_kbd_init - reset keyboard and init state flags 319 */ 320 int i8042_kbd_init(void) 321 { 322 int keymap, try; 323 char *penv; 324 325 #ifdef CONFIG_USE_CPCIDVI 326 penv = getenv("console"); 327 if (penv != NULL) { 328 if (strncmp(penv, "serial", 7) == 0) 329 return -1; 330 } 331 #endif 332 /* Init keyboard device (default US layout) */ 333 keymap = KBD_US; 334 penv = getenv("keymap"); 335 if (penv != NULL) { 336 if (strncmp(penv, "de", 3) == 0) 337 keymap = KBD_GER; 338 } 339 340 for (try = 0; try < KBD_RESET_TRIES; try++) { 341 if (kbd_reset() == 0) { 342 kbd_mapping = keymap; 343 kbd_flags = NORMAL; 344 kbd_state = 0; 345 kbd_led_set(); 346 return 0; 347 } 348 } 349 return -1; 350 } 351 352 353 /******************************************************************************* 354 * 355 * i8042_tstc - test if keyboard input is available 356 * option: cursor blinking if called in a loop 357 */ 358 int i8042_tstc(void) 359 { 360 unsigned char scan_code = 0; 361 362 #ifdef CONFIG_CONSOLE_CURSOR 363 if (--blinkCount == 0) { 364 cursor_state ^= 1; 365 console_cursor(cursor_state); 366 blinkCount = CONFIG_SYS_CONSOLE_BLINK_COUNT; 367 udelay(10); 368 } 369 #endif 370 371 if ((in8(I8042_STATUS_REG) & 0x01) == 0) { 372 return 0; 373 } else { 374 scan_code = in8(I8042_DATA_REG); 375 if (scan_code == 0xfa) 376 return 0; 377 378 kbd_conv_char(scan_code); 379 380 if (kbd_input != -1) 381 return 1; 382 } 383 return 0; 384 } 385 386 387 /******************************************************************************* 388 * 389 * i8042_getc - wait till keyboard input is available 390 * option: turn on/off cursor while waiting 391 */ 392 int i8042_getc(void) 393 { 394 int ret_chr; 395 unsigned char scan_code; 396 397 while (kbd_input == -1) { 398 while ((in8(I8042_STATUS_REG) & 0x01) == 0) { 399 #ifdef CONFIG_CONSOLE_CURSOR 400 if (--blinkCount == 0) { 401 cursor_state ^= 1; 402 console_cursor(cursor_state); 403 blinkCount = CONFIG_SYS_CONSOLE_BLINK_COUNT; 404 } 405 udelay(10); 406 #endif 407 } 408 scan_code = in8(I8042_DATA_REG); 409 if (scan_code != 0xfa) 410 kbd_conv_char (scan_code); 411 } 412 ret_chr = kbd_input; 413 kbd_input = -1; 414 return ret_chr; 415 } 416 417 418 /******************************************************************************/ 419 420 static void kbd_conv_char(unsigned char scan_code) 421 { 422 if (scan_code == 0xe0) { 423 kbd_flags |= EXT; 424 return; 425 } 426 427 /* if high bit of scan_code, set break flag */ 428 if (scan_code & 0x80) 429 kbd_flags |= BRK; 430 else 431 kbd_flags &= ~BRK; 432 433 if ((scan_code == 0xe1) || (kbd_flags & E1)) { 434 if (scan_code == 0xe1) { 435 kbd_flags ^= BRK; /* reset the break flag */ 436 kbd_flags ^= E1; /* bitwise EXOR with E1 flag */ 437 } 438 return; 439 } 440 441 scan_code &= 0x7f; 442 443 if (kbd_flags & EXT) { 444 int i; 445 446 kbd_flags ^= EXT; 447 for (i = 0; ext_key_map[i]; i++) { 448 if (ext_key_map[i] == scan_code) { 449 scan_code = 0x80 + i; 450 break; 451 } 452 } 453 /* not found ? */ 454 if (!ext_key_map[i]) 455 return; 456 } 457 458 switch (kbd_fct_map[scan_code]) { 459 case AS: 460 kbd_normal(scan_code); 461 break; 462 case SH: 463 kbd_shift(scan_code); 464 break; 465 case CN: 466 kbd_ctrl(scan_code); 467 break; 468 case NM: 469 kbd_num(scan_code); 470 break; 471 case CP: 472 kbd_caps(scan_code); 473 break; 474 case ST: 475 kbd_scroll(scan_code); 476 break; 477 case AK: 478 kbd_alt(scan_code); 479 break; 480 } 481 return; 482 } 483 484 485 /******************************************************************************/ 486 487 static void kbd_normal(unsigned char scan_code) 488 { 489 unsigned char chr; 490 491 if ((kbd_flags & BRK) == NORMAL) { 492 chr = kbd_key_map[kbd_mapping][kbd_state][scan_code]; 493 if ((chr == 0xff) || (chr == 0x00)) 494 return; 495 496 /* if caps lock convert upper to lower */ 497 if (((kbd_flags & CAPS) == CAPS) && 498 (chr >= 'a' && chr <= 'z')) { 499 chr -= 'a' - 'A'; 500 } 501 kbd_input = chr; 502 } 503 } 504 505 506 /******************************************************************************/ 507 508 static void kbd_shift(unsigned char scan_code) 509 { 510 if ((kbd_flags & BRK) == BRK) { 511 kbd_state = AS; 512 kbd_flags &= (~SHIFT); 513 } else { 514 kbd_state = SH; 515 kbd_flags |= SHIFT; 516 } 517 } 518 519 520 /******************************************************************************/ 521 522 static void kbd_ctrl(unsigned char scan_code) 523 { 524 if ((kbd_flags & BRK) == BRK) { 525 kbd_state = AS; 526 kbd_flags &= (~CTRL); 527 } else { 528 kbd_state = CN; 529 kbd_flags |= CTRL; 530 } 531 } 532 533 534 /******************************************************************************/ 535 536 static void kbd_caps(unsigned char scan_code) 537 { 538 if ((kbd_flags & BRK) == NORMAL) { 539 kbd_flags ^= CAPS; 540 kbd_led_set(); /* update keyboard LED */ 541 } 542 } 543 544 545 /******************************************************************************/ 546 547 static void kbd_num(unsigned char scan_code) 548 { 549 if ((kbd_flags & BRK) == NORMAL) { 550 kbd_flags ^= NUM; 551 kbd_state = (kbd_flags & NUM) ? AS : NM; 552 kbd_led_set(); /* update keyboard LED */ 553 } 554 } 555 556 557 /******************************************************************************/ 558 559 static void kbd_scroll(unsigned char scan_code) 560 { 561 if ((kbd_flags & BRK) == NORMAL) { 562 kbd_flags ^= STP; 563 kbd_led_set(); /* update keyboard LED */ 564 if (kbd_flags & STP) 565 kbd_input = 0x13; 566 else 567 kbd_input = 0x11; 568 } 569 } 570 571 /******************************************************************************/ 572 573 static void kbd_alt(unsigned char scan_code) 574 { 575 if ((kbd_flags & BRK) == BRK) { 576 kbd_state = AS; 577 kbd_flags &= (~ALT); 578 } else { 579 kbd_state = AK; 580 kbd_flags &= ALT; 581 } 582 } 583 584 585 /******************************************************************************/ 586 587 static void kbd_led_set(void) 588 { 589 kbd_input_empty(); 590 out8(I8042_DATA_REG, 0xed); /* SET LED command */ 591 kbd_input_empty(); 592 out8(I8042_DATA_REG, (kbd_flags & 0x7)); /* LED bits only */ 593 } 594 595 596 /******************************************************************************/ 597 598 static int kbd_input_empty(void) 599 { 600 int kbdTimeout = KBD_TIMEOUT; 601 602 /* wait for input buf empty */ 603 while ((in8(I8042_STATUS_REG) & 0x02) && kbdTimeout--) 604 udelay(1000); 605 606 return kbdTimeout; 607 } 608 609 /******************************************************************************/ 610 611 static int kbd_reset(void) 612 { 613 if (kbd_input_empty() == 0) 614 return -1; 615 616 out8(I8042_DATA_REG, 0xff); 617 618 udelay(250000); 619 620 if (kbd_input_empty() == 0) 621 return -1; 622 623 #ifdef CONFIG_USE_CPCIDVI 624 out8(I8042_COMMAND_REG, 0x60); 625 #else 626 out8(I8042_DATA_REG, 0x60); 627 #endif 628 629 if (kbd_input_empty() == 0) 630 return -1; 631 632 out8(I8042_DATA_REG, 0x45); 633 634 635 if (kbd_input_empty() == 0) 636 return -1; 637 638 out8(I8042_COMMAND_REG, 0xae); 639 640 if (kbd_input_empty() == 0) 641 return -1; 642 643 return 0; 644 } 645