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