1
0
mirror of https://xff.cz/git/u-boot/ synced 2025-09-01 08:42:12 +02:00
Files
u-boot-megous/drivers/input/i8042.c
Gabe Black ef94f7fa64 input: Use finer grain udelays while waitng for the i8042 keyboard buffer to empty
On x86, the i8042 keyboard controller driver frequently waits for the keyboard
input buffer to be empty to make sure the controller has had a chance to
process the data it was given. The way the delay loop was structured, if the
controller hadn't cleared the corresponding status bit immediately, it would
wait 1ms before checking again. If the keyboard responded quickly but not
instantly, the driver would still wait a full 1ms when perhaps 1us would have
been sufficient. Because udelay is a busy wait anyway, this change decreases
the delay between checks to 1us.

Also, this change gets rid of a hardcoded 250ms delay.

On Stumpy, this saves 100-150ms during boot.

Signed-off-by: Gabe Black <gabeblack@chromium.org>
Signed-off-by: Simon Glass <sjg@chromium.org>
Signed-off-by: Tom Rini <trini@ti.com>
2012-10-19 15:25:43 -07:00

652 lines
22 KiB
C

/*
* (C) Copyright 2002 ELTEC Elektronik AG
* Frank Gottschling <fgottschling@eltec.de>
*
* See file CREDITS for list of people who contributed to this
* project.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
/* i8042.c - Intel 8042 keyboard driver routines */
/* includes */
#include <common.h>
#ifdef CONFIG_USE_CPCIDVI
extern u8 gt_cpcidvi_in8(u32 offset);
extern void gt_cpcidvi_out8(u32 offset, u8 data);
#define in8(a) gt_cpcidvi_in8(a)
#define out8(a, b) gt_cpcidvi_out8(a, b)
#endif
#include <i8042.h>
/* defines */
#ifdef CONFIG_CONSOLE_CURSOR
extern void console_cursor(int state);
static int blinkCount = CONFIG_SYS_CONSOLE_BLINK_COUNT;
static int cursor_state;
#endif
/* locals */
static int kbd_input = -1; /* no input yet */
static int kbd_mapping = KBD_US; /* default US keyboard */
static int kbd_flags = NORMAL; /* after reset */
static int kbd_state; /* unshift code */
static void kbd_conv_char(unsigned char scan_code);
static void kbd_led_set(void);
static void kbd_normal(unsigned char scan_code);
static void kbd_shift(unsigned char scan_code);
static void kbd_ctrl(unsigned char scan_code);
static void kbd_num(unsigned char scan_code);
static void kbd_caps(unsigned char scan_code);
static void kbd_scroll(unsigned char scan_code);
static void kbd_alt(unsigned char scan_code);
static int kbd_input_empty(void);
static int kbd_reset(void);
static unsigned char kbd_fct_map[144] = {
/* kbd_fct_map table for scan code */
0, AS, AS, AS, AS, AS, AS, AS, /* scan 0- 7 */
AS, AS, AS, AS, AS, AS, AS, AS, /* scan 8- F */
AS, AS, AS, AS, AS, AS, AS, AS, /* scan 10-17 */
AS, AS, AS, AS, AS, CN, AS, AS, /* scan 18-1F */
AS, AS, AS, AS, AS, AS, AS, AS, /* scan 20-27 */
AS, AS, SH, AS, AS, AS, AS, AS, /* scan 28-2F */
AS, AS, AS, AS, AS, AS, SH, AS, /* scan 30-37 */
AS, AS, CP, 0, 0, 0, 0, 0, /* scan 38-3F */
0, 0, 0, 0, 0, NM, ST, ES, /* scan 40-47 */
ES, ES, ES, ES, ES, ES, ES, ES, /* scan 48-4F */
ES, ES, ES, ES, 0, 0, AS, 0, /* scan 50-57 */
0, 0, 0, 0, 0, 0, 0, 0, /* scan 58-5F */
0, 0, 0, 0, 0, 0, 0, 0, /* scan 60-67 */
0, 0, 0, 0, 0, 0, 0, 0, /* scan 68-6F */
AS, 0, 0, AS, 0, 0, AS, 0, /* scan 70-77 */
0, AS, 0, 0, 0, AS, 0, 0, /* scan 78-7F */
AS, CN, AS, AS, AK, ST, EX, EX, /* enhanced */
AS, EX, EX, AS, EX, AS, EX, EX /* enhanced */
};
static unsigned char kbd_key_map[2][5][144] = {
{ /* US keyboard */
{ /* unshift code */
0, 0x1b, '1', '2', '3', '4', '5', '6', /* scan 0- 7 */
'7', '8', '9', '0', '-', '=', 0x08, '\t', /* scan 8- F */
'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', /* scan 10-17 */
'o', 'p', '[', ']', '\r', CN, 'a', 's', /* scan 18-1F */
'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', /* scan 20-27 */
'\'', '`', SH, '\\', 'z', 'x', 'c', 'v', /* scan 28-2F */
'b', 'n', 'm', ',', '.', '/', SH, '*', /* scan 30-37 */
' ', ' ', CP, 0, 0, 0, 0, 0, /* scan 38-3F */
0, 0, 0, 0, 0, NM, ST, '7', /* scan 40-47 */
'8', '9', '-', '4', '5', '6', '+', '1', /* scan 48-4F */
'2', '3', '0', '.', 0, 0, 0, 0, /* scan 50-57 */
0, 0, 0, 0, 0, 0, 0, 0, /* scan 58-5F */
0, 0, 0, 0, 0, 0, 0, 0, /* scan 60-67 */
0, 0, 0, 0, 0, 0, 0, 0, /* scan 68-6F */
0, 0, 0, 0, 0, 0, 0, 0, /* scan 70-77 */
0, 0, 0, 0, 0, 0, 0, 0, /* scan 78-7F */
'\r', CN, '/', '*', ' ', ST, 'F', 'A', /* extended */
0, 'D', 'C', 0, 'B', 0, '@', 'P' /* extended */
},
{ /* shift code */
0, 0x1b, '!', '@', '#', '$', '%', '^', /* scan 0- 7 */
'&', '*', '(', ')', '_', '+', 0x08, '\t', /* scan 8- F */
'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', /* scan 10-17 */
'O', 'P', '{', '}', '\r', CN, 'A', 'S', /* scan 18-1F */
'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', /* scan 20-27 */
'"', '~', SH, '|', 'Z', 'X', 'C', 'V', /* scan 28-2F */
'B', 'N', 'M', '<', '>', '?', SH, '*', /* scan 30-37 */
' ', ' ', CP, 0, 0, 0, 0, 0, /* scan 38-3F */
0, 0, 0, 0, 0, NM, ST, '7', /* scan 40-47 */
'8', '9', '-', '4', '5', '6', '+', '1', /* scan 48-4F */
'2', '3', '0', '.', 0, 0, 0, 0, /* scan 50-57 */
0, 0, 0, 0, 0, 0, 0, 0, /* scan 58-5F */
0, 0, 0, 0, 0, 0, 0, 0, /* scan 60-67 */
0, 0, 0, 0, 0, 0, 0, 0, /* scan 68-6F */
0, 0, 0, 0, 0, 0, 0, 0, /* scan 70-77 */
0, 0, 0, 0, 0, 0, 0, 0, /* scan 78-7F */
'\r', CN, '/', '*', ' ', ST, 'F', 'A', /* extended */
0, 'D', 'C', 0, 'B', 0, '@', 'P' /* extended */
},
{ /* control code */
0xff, 0x1b, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, /* scan 0- 7 */
0x1e, 0xff, 0xff, 0xff, 0x1f, 0xff, 0xff, '\t', /* scan 8- F */
0x11, 0x17, 0x05, 0x12, 0x14, 0x19, 0x15, 0x09, /* scan 10-17 */
0x0f, 0x10, 0x1b, 0x1d, '\r', CN, 0x01, 0x13, /* scan 18-1F */
0x04, 0x06, 0x07, 0x08, 0x0a, 0x0b, 0x0c, 0xff, /* scan 20-27 */
0xff, 0x1c, SH, 0xff, 0x1a, 0x18, 0x03, 0x16, /* scan 28-2F */
0x02, 0x0e, 0x0d, 0xff, 0xff, 0xff, SH, 0xff, /* scan 30-37 */
0xff, 0xff, CP, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 38-3F */
0xff, 0xff, 0xff, 0xff, 0xff, NM, ST, 0xff, /* scan 40-47 */
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 48-4F */
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 50-57 */
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 58-5F */
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 60-67 */
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 68-6F */
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 70-77 */
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 78-7F */
'\r', CN, '/', '*', ' ', ST, 0xff, 0xff, /* extended */
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff /* extended */
},
{ /* non numeric code */
0, 0x1b, '1', '2', '3', '4', '5', '6', /* scan 0- 7 */
'7', '8', '9', '0', '-', '=', 0x08, '\t', /* scan 8- F */
'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', /* scan 10-17 */
'o', 'p', '[', ']', '\r', CN, 'a', 's', /* scan 18-1F */
'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', /* scan 20-27 */
'\'', '`', SH, '\\', 'z', 'x', 'c', 'v', /* scan 28-2F */
'b', 'n', 'm', ',', '.', '/', SH, '*', /* scan 30-37 */
' ', ' ', CP, 0, 0, 0, 0, 0, /* scan 38-3F */
0, 0, 0, 0, 0, NM, ST, 'w', /* scan 40-47 */
'x', 'y', 'l', 't', 'u', 'v', 'm', 'q', /* scan 48-4F */
'r', 's', 'p', 'n', 0, 0, 0, 0, /* scan 50-57 */
0, 0, 0, 0, 0, 0, 0, 0, /* scan 58-5F */
0, 0, 0, 0, 0, 0, 0, 0, /* scan 60-67 */
0, 0, 0, 0, 0, 0, 0, 0, /* scan 68-6F */
0, 0, 0, 0, 0, 0, 0, 0, /* scan 70-77 */
0, 0, 0, 0, 0, 0, 0, 0, /* scan 78-7F */
'\r', CN, '/', '*', ' ', ST, 'F', 'A', /* extended */
0, 'D', 'C', 0, 'B', 0, '@', 'P' /* extended */
},
{ /* right alt mode - not used in US keyboard */
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 0 - 7 */
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 8 - F */
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 10 -17 */
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 18 -1F */
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 20 -27 */
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 28 -2F */
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 30 -37 */
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 38 -3F */
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 40 -47 */
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 48 -4F */
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 50 -57 */
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 58 -5F */
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 60 -67 */
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 68 -6F */
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 70 -77 */
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 78 -7F */
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* extended */
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff /* extended */
}
},
{ /* german keyboard */
{ /* unshift code */
0, 0x1b, '1', '2', '3', '4', '5', '6', /* scan 0- 7 */
'7', '8', '9', '0', 0xe1, '\'', 0x08, '\t', /* scan 8- F */
'q', 'w', 'e', 'r', 't', 'z', 'u', 'i', /* scan 10-17 */
'o', 'p', 0x81, '+', '\r', CN, 'a', 's', /* scan 18-1F */
'd', 'f', 'g', 'h', 'j', 'k', 'l', 0x94, /* scan 20-27 */
0x84, '^', SH, '#', 'y', 'x', 'c', 'v', /* scan 28-2F */
'b', 'n', 'm', ',', '.', '-', SH, '*', /* scan 30-37 */
' ', ' ', CP, 0, 0, 0, 0, 0, /* scan 38-3F */
0, 0, 0, 0, 0, NM, ST, '7', /* scan 40-47 */
'8', '9', '-', '4', '5', '6', '+', '1', /* scan 48-4F */
'2', '3', '0', ',', 0, 0, '<', 0, /* scan 50-57 */
0, 0, 0, 0, 0, 0, 0, 0, /* scan 58-5F */
0, 0, 0, 0, 0, 0, 0, 0, /* scan 60-67 */
0, 0, 0, 0, 0, 0, 0, 0, /* scan 68-6F */
0, 0, 0, 0, 0, 0, 0, 0, /* scan 70-77 */
0, 0, 0, 0, 0, 0, 0, 0, /* scan 78-7F */
'\r', CN, '/', '*', ' ', ST, 'F', 'A', /* extended */
0, 'D', 'C', 0, 'B', 0, '@', 'P' /* extended */
},
{ /* shift code */
0, 0x1b, '!', '"', 0x15, '$', '%', '&', /* scan 0- 7 */
'/', '(', ')', '=', '?', '`', 0x08, '\t', /* scan 8- F */
'Q', 'W', 'E', 'R', 'T', 'Z', 'U', 'I', /* scan 10-17 */
'O', 'P', 0x9a, '*', '\r', CN, 'A', 'S', /* scan 18-1F */
'D', 'F', 'G', 'H', 'J', 'K', 'L', 0x99, /* scan 20-27 */
0x8e, 0xf8, SH, '\'', 'Y', 'X', 'C', 'V', /* scan 28-2F */
'B', 'N', 'M', ';', ':', '_', SH, '*', /* scan 30-37 */
' ', ' ', CP, 0, 0, 0, 0, 0, /* scan 38-3F */
0, 0, 0, 0, 0, NM, ST, '7', /* scan 40-47 */
'8', '9', '-', '4', '5', '6', '+', '1', /* scan 48-4F */
'2', '3', '0', ',', 0, 0, '>', 0, /* scan 50-57 */
0, 0, 0, 0, 0, 0, 0, 0, /* scan 58-5F */
0, 0, 0, 0, 0, 0, 0, 0, /* scan 60-67 */
0, 0, 0, 0, 0, 0, 0, 0, /* scan 68-6F */
0, 0, 0, 0, 0, 0, 0, 0, /* scan 70-77 */
0, 0, 0, 0, 0, 0, 0, 0, /* scan 78-7F */
'\r', CN, '/', '*', ' ', ST, 'F', 'A', /* extended */
0, 'D', 'C', 0, 'B', 0, '@', 'P' /* extended */
},
{ /* control code */
0xff, 0x1b, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, /* scan 0- 7 */
0x1e, 0xff, 0xff, 0xff, 0x1f, 0xff, 0xff, '\t', /* scan 8- F */
0x11, 0x17, 0x05, 0x12, 0x14, 0x19, 0x15, 0x09, /* scan 10-17 */
0x0f, 0x10, 0x1b, 0x1d, '\r', CN, 0x01, 0x13, /* scan 18-1F */
0x04, 0x06, 0x07, 0x08, 0x0a, 0x0b, 0x0c, 0xff, /* scan 20-27 */
0xff, 0x1c, SH, 0xff, 0x1a, 0x18, 0x03, 0x16, /* scan 28-2F */
0x02, 0x0e, 0x0d, 0xff, 0xff, 0xff, SH, 0xff, /* scan 30-37 */
0xff, 0xff, CP, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 38-3F */
0xff, 0xff, 0xff, 0xff, 0xff, NM, ST, 0xff, /* scan 40-47 */
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 48-4F */
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 50-57 */
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 58-5F */
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 60-67 */
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 68-6F */
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 70-77 */
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 78-7F */
'\r', CN, '/', '*', ' ', ST, 0xff, 0xff, /* extended */
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff /* extended */
},
{ /* non numeric code */
0, 0x1b, '1', '2', '3', '4', '5', '6', /* scan 0- 7 */
'7', '8', '9', '0', 0xe1, '\'', 0x08, '\t', /* scan 8- F */
'q', 'w', 'e', 'r', 't', 'z', 'u', 'i', /* scan 10-17 */
'o', 'p', 0x81, '+', '\r', CN, 'a', 's', /* scan 18-1F */
'd', 'f', 'g', 'h', 'j', 'k', 'l', 0x94, /* scan 20-27 */
0x84, '^', SH, 0, 'y', 'x', 'c', 'v', /* scan 28-2F */
'b', 'n', 'm', ',', '.', '-', SH, '*', /* scan 30-37 */
' ', ' ', CP, 0, 0, 0, 0, 0, /* scan 38-3F */
0, 0, 0, 0, 0, NM, ST, 'w', /* scan 40-47 */
'x', 'y', 'l', 't', 'u', 'v', 'm', 'q', /* scan 48-4F */
'r', 's', 'p', 'n', 0, 0, '<', 0, /* scan 50-57 */
0, 0, 0, 0, 0, 0, 0, 0, /* scan 58-5F */
0, 0, 0, 0, 0, 0, 0, 0, /* scan 60-67 */
0, 0, 0, 0, 0, 0, 0, 0, /* scan 68-6F */
0, 0, 0, 0, 0, 0, 0, 0, /* scan 70-77 */
0, 0, 0, 0, 0, 0, 0, 0, /* scan 78-7F */
'\r', CN, '/', '*', ' ', ST, 'F', 'A', /* extended */
0, 'D', 'C', 0, 'B', 0, '@', 'P' /* extended */
},
{ /* Right alt mode - is used in German keyboard */
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 0 - 7 */
'{', '[', ']', '}', '\\', 0xff, 0xff, 0xff, /* scan 8 - F */
'@', 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 10 -17 */
0xff, 0xff, 0xff, '~', 0xff, 0xff, 0xff, 0xff, /* scan 18 -1F */
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 20 -27 */
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 28 -2F */
0xff, 0xff, 0xe6, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 30 -37 */
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 38 -3F */
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 40 -47 */
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 48 -4F */
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, '|', 0xff, /* scan 50 -57 */
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 58 -5F */
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 60 -67 */
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 68 -6F */
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 70 -77 */
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 78 -7F */
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* extended */
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff /* extended */
}
}
};
static unsigned char ext_key_map[] = {
0x1c, /* keypad enter */
0x1d, /* right control */
0x35, /* keypad slash */
0x37, /* print screen */
0x38, /* right alt */
0x46, /* break */
0x47, /* editpad home */
0x48, /* editpad up */
0x49, /* editpad pgup */
0x4b, /* editpad left */
0x4d, /* editpad right */
0x4f, /* editpad end */
0x50, /* editpad dn */
0x51, /* editpad pgdn */
0x52, /* editpad ins */
0x53, /* editpad del */
0x00 /* map end */
};
/******************************************************************************/
static int kbd_controller_present(void)
{
return in8(I8042_STATUS_REG) != 0xff;
}
/*******************************************************************************
*
* i8042_kbd_init - reset keyboard and init state flags
*/
int i8042_kbd_init(void)
{
int keymap, try;
char *penv;
if (!kbd_controller_present())
return -1;
#ifdef CONFIG_USE_CPCIDVI
penv = getenv("console");
if (penv != NULL) {
if (strncmp(penv, "serial", 7) == 0)
return -1;
}
#endif
/* Init keyboard device (default US layout) */
keymap = KBD_US;
penv = getenv("keymap");
if (penv != NULL) {
if (strncmp(penv, "de", 3) == 0)
keymap = KBD_GER;
}
for (try = 0; try < KBD_RESET_TRIES; try++) {
if (kbd_reset() == 0) {
kbd_mapping = keymap;
kbd_flags = NORMAL;
kbd_state = 0;
kbd_led_set();
return 0;
}
}
return -1;
}
/*******************************************************************************
*
* i8042_tstc - test if keyboard input is available
* option: cursor blinking if called in a loop
*/
int i8042_tstc(void)
{
unsigned char scan_code = 0;
#ifdef CONFIG_CONSOLE_CURSOR
if (--blinkCount == 0) {
cursor_state ^= 1;
console_cursor(cursor_state);
blinkCount = CONFIG_SYS_CONSOLE_BLINK_COUNT;
udelay(10);
}
#endif
if ((in8(I8042_STATUS_REG) & 0x01) == 0) {
return 0;
} else {
scan_code = in8(I8042_DATA_REG);
if (scan_code == 0xfa)
return 0;
kbd_conv_char(scan_code);
if (kbd_input != -1)
return 1;
}
return 0;
}
/*******************************************************************************
*
* i8042_getc - wait till keyboard input is available
* option: turn on/off cursor while waiting
*/
int i8042_getc(void)
{
int ret_chr;
unsigned char scan_code;
while (kbd_input == -1) {
while ((in8(I8042_STATUS_REG) & 0x01) == 0) {
#ifdef CONFIG_CONSOLE_CURSOR
if (--blinkCount == 0) {
cursor_state ^= 1;
console_cursor(cursor_state);
blinkCount = CONFIG_SYS_CONSOLE_BLINK_COUNT;
}
udelay(10);
#endif
}
scan_code = in8(I8042_DATA_REG);
if (scan_code != 0xfa)
kbd_conv_char (scan_code);
}
ret_chr = kbd_input;
kbd_input = -1;
return ret_chr;
}
/******************************************************************************/
static void kbd_conv_char(unsigned char scan_code)
{
if (scan_code == 0xe0) {
kbd_flags |= EXT;
return;
}
/* if high bit of scan_code, set break flag */
if (scan_code & 0x80)
kbd_flags |= BRK;
else
kbd_flags &= ~BRK;
if ((scan_code == 0xe1) || (kbd_flags & E1)) {
if (scan_code == 0xe1) {
kbd_flags ^= BRK; /* reset the break flag */
kbd_flags ^= E1; /* bitwise EXOR with E1 flag */
}
return;
}
scan_code &= 0x7f;
if (kbd_flags & EXT) {
int i;
kbd_flags ^= EXT;
for (i = 0; ext_key_map[i]; i++) {
if (ext_key_map[i] == scan_code) {
scan_code = 0x80 + i;
break;
}
}
/* not found ? */
if (!ext_key_map[i])
return;
}
switch (kbd_fct_map[scan_code]) {
case AS:
kbd_normal(scan_code);
break;
case SH:
kbd_shift(scan_code);
break;
case CN:
kbd_ctrl(scan_code);
break;
case NM:
kbd_num(scan_code);
break;
case CP:
kbd_caps(scan_code);
break;
case ST:
kbd_scroll(scan_code);
break;
case AK:
kbd_alt(scan_code);
break;
}
return;
}
/******************************************************************************/
static void kbd_normal(unsigned char scan_code)
{
unsigned char chr;
if ((kbd_flags & BRK) == NORMAL) {
chr = kbd_key_map[kbd_mapping][kbd_state][scan_code];
if ((chr == 0xff) || (chr == 0x00))
return;
/* if caps lock convert upper to lower */
if (((kbd_flags & CAPS) == CAPS) &&
(chr >= 'a' && chr <= 'z')) {
chr -= 'a' - 'A';
}
kbd_input = chr;
}
}
/******************************************************************************/
static void kbd_shift(unsigned char scan_code)
{
if ((kbd_flags & BRK) == BRK) {
kbd_state = AS;
kbd_flags &= (~SHIFT);
} else {
kbd_state = SH;
kbd_flags |= SHIFT;
}
}
/******************************************************************************/
static void kbd_ctrl(unsigned char scan_code)
{
if ((kbd_flags & BRK) == BRK) {
kbd_state = AS;
kbd_flags &= (~CTRL);
} else {
kbd_state = CN;
kbd_flags |= CTRL;
}
}
/******************************************************************************/
static void kbd_caps(unsigned char scan_code)
{
if ((kbd_flags & BRK) == NORMAL) {
kbd_flags ^= CAPS;
kbd_led_set(); /* update keyboard LED */
}
}
/******************************************************************************/
static void kbd_num(unsigned char scan_code)
{
if ((kbd_flags & BRK) == NORMAL) {
kbd_flags ^= NUM;
kbd_state = (kbd_flags & NUM) ? AS : NM;
kbd_led_set(); /* update keyboard LED */
}
}
/******************************************************************************/
static void kbd_scroll(unsigned char scan_code)
{
if ((kbd_flags & BRK) == NORMAL) {
kbd_flags ^= STP;
kbd_led_set(); /* update keyboard LED */
if (kbd_flags & STP)
kbd_input = 0x13;
else
kbd_input = 0x11;
}
}
/******************************************************************************/
static void kbd_alt(unsigned char scan_code)
{
if ((kbd_flags & BRK) == BRK) {
kbd_state = AS;
kbd_flags &= (~ALT);
} else {
kbd_state = AK;
kbd_flags &= ALT;
}
}
/******************************************************************************/
static void kbd_led_set(void)
{
kbd_input_empty();
out8(I8042_DATA_REG, 0xed); /* SET LED command */
kbd_input_empty();
out8(I8042_DATA_REG, (kbd_flags & 0x7)); /* LED bits only */
}
/******************************************************************************/
static int kbd_input_empty(void)
{
int kbdTimeout = KBD_TIMEOUT * 1000;
while ((in8(I8042_STATUS_REG) & I8042_STATUS_IN_DATA) && kbdTimeout--)
udelay(1);
return kbdTimeout != -1;
}
/******************************************************************************/
static int kbd_reset(void)
{
if (kbd_input_empty() == 0)
return -1;
out8(I8042_DATA_REG, 0xff);
if (kbd_input_empty() == 0)
return -1;
#ifdef CONFIG_USE_CPCIDVI
out8(I8042_COMMAND_REG, 0x60);
#else
out8(I8042_DATA_REG, 0x60);
#endif
if (kbd_input_empty() == 0)
return -1;
out8(I8042_DATA_REG, 0x45);
if (kbd_input_empty() == 0)
return -1;
out8(I8042_COMMAND_REG, 0xae);
if (kbd_input_empty() == 0)
return -1;
return 0;
}