2 * This file is part of the libpayload project.
4 * Copyright (C) 2008 Advanced Micro Devices, Inc.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 #include <libpayload.h>
33 #define I8042_CMD_READ_MODE 0x20
34 #define I8042_CMD_WRITE_MODE 0x60
36 #define I8042_MODE_XLATE 0x40
38 unsigned short map[4][0x57] = {
40 0x00, 0x1B, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36,
41 0x37, 0x38, 0x39, 0x30, 0x2D, 0x3D, 0x08, 0x09,
42 0x71, 0x77, 0x65, 0x72, 0x74, 0x79, 0x75, 0x69,
43 0x6F, 0x70, 0x5B, 0x5D, 0x0A, 0x00, 0x61, 0x73,
44 0x64, 0x66, 0x67, 0x68, 0x6A, 0x6B, 0x6C, 0x3B,
45 0x27, 0x60, 0x00, 0x5C, 0x7A, 0x78, 0x63, 0x76,
46 0x62, 0x6E, 0x6D, 0x2C, 0x2E, 0x2F, 0x00, 0x2A,
47 0x00, 0x20, 0x00, KEY_F(1), KEY_F(2), KEY_F(3), KEY_F(4), KEY_F(5),
48 KEY_F(6), KEY_F(7), KEY_F(8), KEY_F(9), KEY_F(10), 0x00, 0x00, KEY_HOME,
49 KEY_UP, KEY_NPAGE, 0x00, KEY_LEFT, 0x00, KEY_RIGHT, 0x00, KEY_END,
50 KEY_DOWN, KEY_PPAGE, 0x00, KEY_DC, 0x00, 0x00, 0x00
53 0x00, 0x1B, 0x21, 0x40, 0x23, 0x24, 0x25, 0x5E,
54 0x26, 0x2A, 0x28, 0x29, 0x5F, 0x2B, 0x08, 0x00,
55 0x51, 0x57, 0x45, 0x52, 0x54, 0x59, 0x55, 0x49,
56 0x4F, 0x50, 0x7B, 0x7D, 0x0A, 0x00, 0x41, 0x53,
57 0x44, 0x46, 0x47, 0x48, 0x4A, 0x4B, 0x4C, 0x3A,
58 0x22, 0x7E, 0x00, 0x7C, 0x5A, 0x58, 0x43, 0x56,
59 0x42, 0x4E, 0x4D, 0x3C, 0x3E, 0x3F, 0x00, 0x2A,
60 0x00, 0x20, 0x00, KEY_F(1), KEY_F(2), KEY_F(3), KEY_F(4), KEY_F(5),
61 KEY_F(6), KEY_F(7), KEY_F(8), KEY_F(9), KEY_F(10), 0x00, 0x00, KEY_HOME,
62 KEY_UP, KEY_NPAGE, 0x00, KEY_LEFT, 0x00, KEY_RIGHT, 0x00, KEY_END,
63 KEY_DOWN, KEY_PPAGE, 0x00, KEY_DC, 0x00, 0x00, 0x00
66 0x00, 0x1B, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36,
67 0x37, 0x38, 0x39, 0x30, 0x2D, 0x3D, 0x08, 0x09,
68 0x71, 0x77, 0x65, 0x72, 0x74, 0x79, 0x75, 0x69,
69 0x6F, 0x70, 0x5B, 0x5D, 0x0A, 0x00, 0x61, 0x73,
70 0x64, 0x66, 0x67, 0x68, 0x6A, 0x6B, 0x6C, 0x3B,
71 0x27, 0x60, 0x00, 0x5C, 0x7A, 0x78, 0x63, 0x76,
72 0x62, 0x6E, 0x6D, 0x2C, 0x2E, 0x2F, 0x00, 0x2A,
73 0x00, 0x20, 0x00, KEY_F(1), KEY_F(2), KEY_F(3), KEY_F(4), KEY_F(5),
74 KEY_F(6), KEY_F(7), KEY_F(8), KEY_F(9), KEY_F(10), 0x00, 0x00, KEY_HOME,
75 KEY_UP, KEY_NPAGE, 0x00, KEY_LEFT, 0x00, KEY_RIGHT, 0x00, KEY_END,
76 KEY_DOWN, KEY_PPAGE, 0x00, KEY_DC, 0x00, 0x00, 0x00
79 0x00, 0x1B, 0x21, 0x40, 0x23, 0x24, 0x25, 0x5E,
80 0x26, 0x2A, 0x28, 0x29, 0x5F, 0x2B, 0x08, 0x00,
81 0x51, 0x57, 0x45, 0x52, 0x54, 0x59, 0x55, 0x49,
82 0x4F, 0x50, 0x7B, 0x7D, 0x0A, 0x00, 0x41, 0x53,
83 0x44, 0x46, 0x47, 0x48, 0x4A, 0x4B, 0x4C, 0x3A,
84 0x22, 0x7E, 0x00, 0x7C, 0x5A, 0x58, 0x43, 0x56,
85 0x42, 0x4E, 0x4D, 0x3C, 0x3E, 0x3F, 0x00, 0x2A,
86 0x00, 0x20, 0x00, KEY_F(1), KEY_F(2), KEY_F(3), KEY_F(4), KEY_F(5),
87 KEY_F(6), KEY_F(7), KEY_F(8), KEY_F(9), KEY_F(10), 0x00, 0x00, KEY_HOME,
88 KEY_UP, KEY_NPAGE, 0x00, KEY_LEFT, 0x00, KEY_RIGHT, 0x00, KEY_END,
89 KEY_DOWN, KEY_PPAGE, 0x00, KEY_DC, 0x00, 0x00, 0x00
93 #define MOD_SHIFT (1 << 0)
94 #define MOD_CTRL (1 << 1)
95 #define MOD_CAPSLOCK (1 << 2)
96 #define MOD_ALT (1 << 3)
98 int keyboard_havechar(void)
100 unsigned char c = inb(0x64);
104 unsigned char keyboard_get_scancode(void)
106 unsigned char ch = 0;
108 if (keyboard_havechar())
114 int keyboard_getchar(void)
116 static int modifier = 0;
121 while (!keyboard_havechar()) ;
123 ch = keyboard_get_scancode();
128 modifier |= MOD_SHIFT;
132 modifier &= ~MOD_SHIFT;
138 modifier &= ~MOD_ALT;
141 modifier |= MOD_CTRL;
144 modifier &= ~MOD_CTRL;
147 if (modifier & MOD_CAPSLOCK)
148 modifier &= ~MOD_CAPSLOCK;
150 modifier |= MOD_CAPSLOCK;
154 if (!(ch & 0x80) && ch < 0x57) {
156 (modifier & MOD_SHIFT) ^ (modifier & MOD_CAPSLOCK) ? 1 : 0;
158 if (modifier & MOD_ALT)
161 ret = map[shift][ch];
163 if (modifier & MOD_CTRL)
164 ret = (ret >= 'a' && ret <= 'z') ? ret & 0x1f : 0;
172 static int keyboard_wait_read(void)
176 while(timeout-- && !(inb(0x64) & 0x01))
179 return (timeout <= 0) ? -1 : 0;
182 static int keyboard_wait_write(void)
186 while(timeout-- && (inb(0x64) & 0x02))
189 return (timeout <= 0) ? -1 : 0;
192 static unsigned char keyboard_get_mode(void)
194 outb(I8042_CMD_READ_MODE, 0x64);
195 keyboard_wait_read();
199 static void keyboard_set_mode(unsigned char mode)
201 outb(I8042_CMD_WRITE_MODE, 0x64);
202 keyboard_wait_write();
206 void keyboard_init(void)
210 /* Empty keyboard buffer */
211 while (keyboard_havechar()) keyboard_getchar();
213 /* Read the current mode */
214 mode = keyboard_get_mode();
216 /* Turn on scancode translate mode so that we can
217 use the scancode set 1 tables */
219 mode |= I8042_MODE_XLATE;
221 /* Write the new mode */
222 keyboard_set_mode(mode);