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 static int kbd_controller_present(void) 319 { 320 return in8(I8042_STATUS_REG) != 0xff; 321 } 322 323 /******************************************************************************* 324 * 325 * i8042_kbd_init - reset keyboard and init state flags 326 */ 327 int i8042_kbd_init(void) 328 { 329 int keymap, try; 330 char *penv; 331 332 if (!kbd_controller_present()) 333 return -1; 334 335 #ifdef CONFIG_USE_CPCIDVI 336 penv = getenv("console"); 337 if (penv != NULL) { 338 if (strncmp(penv, "serial", 7) == 0) 339 return -1; 340 } 341 #endif 342 /* Init keyboard device (default US layout) */ 343 keymap = KBD_US; 344 penv = getenv("keymap"); 345 if (penv != NULL) { 346 if (strncmp(penv, "de", 3) == 0) 347 keymap = KBD_GER; 348 } 349 350 for (try = 0; try < KBD_RESET_TRIES; try++) { 351 if (kbd_reset() == 0) { 352 kbd_mapping = keymap; 353 kbd_flags = NORMAL; 354 kbd_state = 0; 355 kbd_led_set(); 356 return 0; 357 } 358 } 359 return -1; 360 } 361 362 363 /******************************************************************************* 364 * 365 * i8042_tstc - test if keyboard input is available 366 * option: cursor blinking if called in a loop 367 */ 368 int i8042_tstc(void) 369 { 370 unsigned char scan_code = 0; 371 372 #ifdef CONFIG_CONSOLE_CURSOR 373 if (--blinkCount == 0) { 374 cursor_state ^= 1; 375 console_cursor(cursor_state); 376 blinkCount = CONFIG_SYS_CONSOLE_BLINK_COUNT; 377 udelay(10); 378 } 379 #endif 380 381 if ((in8(I8042_STATUS_REG) & 0x01) == 0) { 382 return 0; 383 } else { 384 scan_code = in8(I8042_DATA_REG); 385 if (scan_code == 0xfa) 386 return 0; 387 388 kbd_conv_char(scan_code); 389 390 if (kbd_input != -1) 391 return 1; 392 } 393 return 0; 394 } 395 396 397 /******************************************************************************* 398 * 399 * i8042_getc - wait till keyboard input is available 400 * option: turn on/off cursor while waiting 401 */ 402 int i8042_getc(void) 403 { 404 int ret_chr; 405 unsigned char scan_code; 406 407 while (kbd_input == -1) { 408 while ((in8(I8042_STATUS_REG) & 0x01) == 0) { 409 #ifdef CONFIG_CONSOLE_CURSOR 410 if (--blinkCount == 0) { 411 cursor_state ^= 1; 412 console_cursor(cursor_state); 413 blinkCount = CONFIG_SYS_CONSOLE_BLINK_COUNT; 414 } 415 udelay(10); 416 #endif 417 } 418 scan_code = in8(I8042_DATA_REG); 419 if (scan_code != 0xfa) 420 kbd_conv_char (scan_code); 421 } 422 ret_chr = kbd_input; 423 kbd_input = -1; 424 return ret_chr; 425 } 426 427 428 /******************************************************************************/ 429 430 static void kbd_conv_char(unsigned char scan_code) 431 { 432 if (scan_code == 0xe0) { 433 kbd_flags |= EXT; 434 return; 435 } 436 437 /* if high bit of scan_code, set break flag */ 438 if (scan_code & 0x80) 439 kbd_flags |= BRK; 440 else 441 kbd_flags &= ~BRK; 442 443 if ((scan_code == 0xe1) || (kbd_flags & E1)) { 444 if (scan_code == 0xe1) { 445 kbd_flags ^= BRK; /* reset the break flag */ 446 kbd_flags ^= E1; /* bitwise EXOR with E1 flag */ 447 } 448 return; 449 } 450 451 scan_code &= 0x7f; 452 453 if (kbd_flags & EXT) { 454 int i; 455 456 kbd_flags ^= EXT; 457 for (i = 0; ext_key_map[i]; i++) { 458 if (ext_key_map[i] == scan_code) { 459 scan_code = 0x80 + i; 460 break; 461 } 462 } 463 /* not found ? */ 464 if (!ext_key_map[i]) 465 return; 466 } 467 468 switch (kbd_fct_map[scan_code]) { 469 case AS: 470 kbd_normal(scan_code); 471 break; 472 case SH: 473 kbd_shift(scan_code); 474 break; 475 case CN: 476 kbd_ctrl(scan_code); 477 break; 478 case NM: 479 kbd_num(scan_code); 480 break; 481 case CP: 482 kbd_caps(scan_code); 483 break; 484 case ST: 485 kbd_scroll(scan_code); 486 break; 487 case AK: 488 kbd_alt(scan_code); 489 break; 490 } 491 return; 492 } 493 494 495 /******************************************************************************/ 496 497 static void kbd_normal(unsigned char scan_code) 498 { 499 unsigned char chr; 500 501 if ((kbd_flags & BRK) == NORMAL) { 502 chr = kbd_key_map[kbd_mapping][kbd_state][scan_code]; 503 if ((chr == 0xff) || (chr == 0x00)) 504 return; 505 506 /* if caps lock convert upper to lower */ 507 if (((kbd_flags & CAPS) == CAPS) && 508 (chr >= 'a' && chr <= 'z')) { 509 chr -= 'a' - 'A'; 510 } 511 kbd_input = chr; 512 } 513 } 514 515 516 /******************************************************************************/ 517 518 static void kbd_shift(unsigned char scan_code) 519 { 520 if ((kbd_flags & BRK) == BRK) { 521 kbd_state = AS; 522 kbd_flags &= (~SHIFT); 523 } else { 524 kbd_state = SH; 525 kbd_flags |= SHIFT; 526 } 527 } 528 529 530 /******************************************************************************/ 531 532 static void kbd_ctrl(unsigned char scan_code) 533 { 534 if ((kbd_flags & BRK) == BRK) { 535 kbd_state = AS; 536 kbd_flags &= (~CTRL); 537 } else { 538 kbd_state = CN; 539 kbd_flags |= CTRL; 540 } 541 } 542 543 544 /******************************************************************************/ 545 546 static void kbd_caps(unsigned char scan_code) 547 { 548 if ((kbd_flags & BRK) == NORMAL) { 549 kbd_flags ^= CAPS; 550 kbd_led_set(); /* update keyboard LED */ 551 } 552 } 553 554 555 /******************************************************************************/ 556 557 static void kbd_num(unsigned char scan_code) 558 { 559 if ((kbd_flags & BRK) == NORMAL) { 560 kbd_flags ^= NUM; 561 kbd_state = (kbd_flags & NUM) ? AS : NM; 562 kbd_led_set(); /* update keyboard LED */ 563 } 564 } 565 566 567 /******************************************************************************/ 568 569 static void kbd_scroll(unsigned char scan_code) 570 { 571 if ((kbd_flags & BRK) == NORMAL) { 572 kbd_flags ^= STP; 573 kbd_led_set(); /* update keyboard LED */ 574 if (kbd_flags & STP) 575 kbd_input = 0x13; 576 else 577 kbd_input = 0x11; 578 } 579 } 580 581 /******************************************************************************/ 582 583 static void kbd_alt(unsigned char scan_code) 584 { 585 if ((kbd_flags & BRK) == BRK) { 586 kbd_state = AS; 587 kbd_flags &= (~ALT); 588 } else { 589 kbd_state = AK; 590 kbd_flags &= ALT; 591 } 592 } 593 594 595 /******************************************************************************/ 596 597 static void kbd_led_set(void) 598 { 599 kbd_input_empty(); 600 out8(I8042_DATA_REG, 0xed); /* SET LED command */ 601 kbd_input_empty(); 602 out8(I8042_DATA_REG, (kbd_flags & 0x7)); /* LED bits only */ 603 } 604 605 606 /******************************************************************************/ 607 608 static int kbd_input_empty(void) 609 { 610 int kbdTimeout = KBD_TIMEOUT; 611 612 /* wait for input buf empty */ 613 while ((in8(I8042_STATUS_REG) & 0x02) && kbdTimeout--) 614 udelay(1000); 615 616 return kbdTimeout != -1; 617 } 618 619 /******************************************************************************/ 620 621 static int kbd_reset(void) 622 { 623 if (kbd_input_empty() == 0) 624 return -1; 625 626 out8(I8042_DATA_REG, 0xff); 627 628 udelay(250000); 629 630 if (kbd_input_empty() == 0) 631 return -1; 632 633 #ifdef CONFIG_USE_CPCIDVI 634 out8(I8042_COMMAND_REG, 0x60); 635 #else 636 out8(I8042_DATA_REG, 0x60); 637 #endif 638 639 if (kbd_input_empty() == 0) 640 return -1; 641 642 out8(I8042_DATA_REG, 0x45); 643 644 645 if (kbd_input_empty() == 0) 646 return -1; 647 648 out8(I8042_COMMAND_REG, 0xae); 649 650 if (kbd_input_empty() == 0) 651 return -1; 652 653 return 0; 654 } 655