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