3 * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 * PROJECT: ReactOS kernel
21 * FILE: ntoskrnl/dbg/kdb_keyboard.c
22 * PURPOSE: Keyboard driver
23 * PROGRAMMER: Victor Kirhenshtein (sauros@iname.com)
24 * Jason Filby (jasonfilby@yahoo.com)
27 /* INCLUDES ****************************************************************/
29 #include <ddk/ntddk.h>
31 #include <ntos/keyboard.h>
32 #include <ntos/minmax.h>
39 #define KBD_STATUS_REG 0x64
40 #define KBD_CNTL_REG 0x64
41 #define KBD_DATA_REG 0x60
43 #define KBD_STAT_OBF 0x01 /* Keyboard output buffer full */
45 #define kbd_read_input() READ_PORT_UCHAR((PUCHAR)KBD_DATA_REG)
46 #define kbd_read_status() READ_PORT_UCHAR((PUCHAR)KBD_STATUS_REG)
48 static unsigned char keyb_layout
[2][128] =
50 "\000\0331234567890-=\177\t" /* 0x00 - 0x0f */
51 "qwertyuiop[]\r\000as" /* 0x10 - 0x1f */
52 "dfghjkl;'`\000\\zxcv" /* 0x20 - 0x2f */
53 "bnm,./\000*\000 \000\201\202\203\204\205" /* 0x30 - 0x3f */
54 "\206\207\210\211\212\000\000789-456+1" /* 0x40 - 0x4f */
55 "230\177\000\000\213\214\000\000\000\000\000\000\000\000\000\000" /* 0x50 - 0x5f */
56 "\r\000/" /* 0x60 - 0x6f */
58 "\000\033!@#$%^&*()_+\177\t" /* 0x00 - 0x0f */
59 "QWERTYUIOP{}\r\000AS" /* 0x10 - 0x1f */
60 "DFGHJKL:\"`\000\\ZXCV" /* 0x20 - 0x2f */
61 "BNM<>?\000*\000 \000\201\202\203\204\205" /* 0x30 - 0x3f */
62 "\206\207\210\211\212\000\000789-456+1" /* 0x40 - 0x4f */
63 "230\177\000\000\213\214\000\000\000\000\000\000\000\000\000\000" /* 0x50 - 0x5f */
64 "\r\000/" /* 0x60 - 0x6f */
70 KdbTryGetCharKeyboard()
72 static byte_t last_key
= 0;
73 static byte_t shift
= 0;
76 unsigned char status
= kbd_read_status();
77 while (status
& KBD_STAT_OBF
) {
79 scancode
= kbd_read_input();
80 /* check for SHIFT-keys */
81 if (((scancode
& 0x7F) == 42) || ((scancode
& 0x7F) == 54))
83 shift
= !(scancode
& 0x80);
86 /* ignore all other RELEASED-codes */
89 else if (last_key
!= scancode
)
91 //printf("kbd: %d, %d, %c\n", scancode, last_key, keyb_layout[shift][scancode]);
93 c
= keyb_layout
[shift
][scancode
];
104 /* GLOBALS *******************************************************************/
107 * Keyboard I/O ports.
109 #define K_RDWR 0x60 /* keyboard data & cmds (read/write) */
110 #define K_STATUS 0x64 /* keybd status (read-only) */
111 #define K_CMD 0x64 /* keybd ctlr command (write-only) */
114 * Bit definitions for K_STATUS port.
116 #define K_OBUF_FUL 0x01 /* output (from keybd) buffer full */
117 #define K_IBUF_FUL 0x02 /* input (to keybd) buffer full */
118 #define K_SYSFLAG 0x04 /* "System Flag" */
119 #define K_CMD_DATA 0x08 /* 1 = input buf has cmd, 0 = data */
120 #define K_KBD_INHIBIT 0x10 /* 0 if keyboard inhibited */
121 #define K_AUX_OBUF_FUL 0x20 /* 1 = obuf holds aux device data */
122 #define K_TIMEOUT 0x40 /* timout error flag */
123 #define K_PARITY_ERROR 0x80 /* parity error flag */
126 * Keyboard controller commands (sent to K_CMD port).
128 #define KC_CMD_READ 0x20 /* read controller command byte */
129 #define KC_CMD_WRITE 0x60 /* write controller command byte */
130 #define KC_CMD_DIS_AUX 0xa7 /* disable auxiliary device */
131 #define KC_CMD_ENB_AUX 0xa8 /* enable auxiliary device */
132 #define KC_CMD_TEST_AUX 0xa9 /* test auxiliary device interface */
133 #define KC_CMD_SELFTEST 0xaa /* keyboard controller self-test */
134 #define KC_CMD_TEST 0xab /* test keyboard interface */
135 #define KC_CMD_DUMP 0xac /* diagnostic dump */
136 #define KC_CMD_DISABLE 0xad /* disable keyboard */
137 #define KC_CMD_ENABLE 0xae /* enable keyboard */
138 #define KC_CMD_RDKBD 0xc4 /* read keyboard ID */
139 #define KC_CMD_WIN 0xd0 /* read output port */
140 #define KC_CMD_WOUT 0xd1 /* write output port */
141 #define KC_CMD_ECHO 0xee /* used for diagnostic testing */
142 #define KC_CMD_PULSE 0xff /* pulse bits 3-0 based on low nybble */
145 * Keyboard commands (send to K_RDWR).
147 #define K_CMD_LEDS 0xed /* set status LEDs (caps lock, etc.) */
148 #define K_CMD_TYPEMATIC 0xf3 /* set key repeat and delay */
151 * Bit definitions for controller command byte (sent following
152 * KC_CMD_WRITE command).
154 * Bits 0x02 and 0x80 unused, always set to 0.
156 #define K_CB_ENBLIRQ 0x01 /* enable data-ready intrpt */
157 #define K_CB_SETSYSF 0x04 /* Set System Flag */
158 #define K_CB_INHBOVR 0x08 /* Inhibit Override */
159 #define K_CB_DISBLE 0x10 /* disable keyboard */
160 #define K_CB_IGNPARITY 0x20 /* ignore parity from keyboard */
161 #define K_CB_SCAN 0x40 /* standard scan conversion */
164 * Bit definitions for "Indicator Status Byte" (sent after a
165 * K_CMD_LEDS command). If the bit is on, the LED is on. Undefined
166 * bit positions must be 0.
168 #define K_LED_SCRLLK 0x1 /* scroll lock */
169 #define K_LED_NUMLK 0x2 /* num lock */
170 #define K_LED_CAPSLK 0x4 /* caps lock */
173 * Bit definitions for "Miscellaneous port B" (K_PORTB).
176 #define K_ENABLETMR2 0x01 /* enable output from timer 2 */
177 #define K_SPKRDATA 0x02 /* direct input to speaker */
178 #define K_ENABLEPRTB 0x04 /* "enable" port B */
179 #define K_EIOPRTB 0x08 /* enable NMI on parity error */
181 #define K_REFRESHB 0x10 /* refresh flag from INLTCONT PAL */
182 #define K_OUT2B 0x20 /* timer 2 output */
183 #define K_ICKB 0x40 /* I/O channel check (parity error) */
186 * Bit definitions for the keyboard controller's output port.
188 #define KO_SYSRESET 0x01 /* processor reset */
189 #define KO_GATE20 0x02 /* A20 address line enable */
190 #define KO_AUX_DATA_OUT 0x04 /* output data to auxiliary device */
191 #define KO_AUX_CLOCK 0x08 /* auxiliary device clock */
192 #define KO_OBUF_FUL 0x10 /* keyboard output buffer full */
193 #define KO_AUX_OBUF_FUL 0x20 /* aux device output buffer full */
194 #define KO_CLOCK 0x40 /* keyboard clock */
195 #define KO_DATA_OUT 0x80 /* output data to keyboard */
198 * Keyboard return codes.
200 #define K_RET_RESET_DONE 0xaa /* BAT complete */
201 #define K_RET_ECHO 0xee /* echo after echo command */
202 #define K_RET_ACK 0xfa /* ack */
203 #define K_RET_RESET_FAIL 0xfc /* BAT error */
204 #define K_RET_RESEND 0xfe /* resend request */
210 static char keymap
[128][2] = {
212 {27, 27}, /* 1 - ESC */
225 {8, 8}, /* 14 - Backspace */
226 {'\t', '\t'}, /* 15 */
239 {'\r', '\r'}, /* 28 - Enter */
240 {CTRL
, CTRL
}, /* 29 - Ctrl */
251 {'\'', '"'}, /* 40 */
253 {SHIFT
, SHIFT
}, /* 42 - Left Shift */
254 {'\\', '|'}, /* 43 */
265 {SHIFT
, SHIFT
}, /* 54 - Right Shift */
266 {0, 0}, /* 55 - Print Screen */
267 {META
, META
}, /* 56 - Alt */
268 {' ', ' '}, /* 57 - Space bar */
269 {0, 0}, /* 58 - Caps Lock */
270 {0, 0}, /* 59 - F1 */
271 {0, 0}, /* 60 - F2 */
272 {0, 0}, /* 61 - F3 */
273 {0, 0}, /* 62 - F4 */
274 {0, 0}, /* 63 - F5 */
275 {0, 0}, /* 64 - F6 */
276 {0, 0}, /* 65 - F7 */
277 {0, 0}, /* 66 - F8 */
278 {0, 0}, /* 67 - F9 */
279 {0, 0}, /* 68 - F10 */
280 {0, 0}, /* 69 - Num Lock */
281 {0, 0}, /* 70 - Scroll Lock */
282 {'7', '7'}, /* 71 - Numeric keypad 7 */
283 {'8', '8'}, /* 72 - Numeric keypad 8 */
284 {'9', '9'}, /* 73 - Numeric keypad 9 */
285 {'-', '-'}, /* 74 - Numeric keypad '-' */
286 {'4', '4'}, /* 75 - Numeric keypad 4 */
287 {'5', '5'}, /* 76 - Numeric keypad 5 */
288 {'6', '6'}, /* 77 - Numeric keypad 6 */
289 {'+', '+'}, /* 78 - Numeric keypad '+' */
290 {'1', '1'}, /* 79 - Numeric keypad 1 */
291 {'2', '2'}, /* 80 - Numeric keypad 2 */
292 {'3', '3'}, /* 81 - Numeric keypad 3 */
293 {'0', '0'}, /* 82 - Numeric keypad 0 */
294 {'.', '.'}, /* 83 - Numeric keypad '.' */
297 /* FUNCTIONS *****************************************************************/
300 * Quick poll for a pending input character.
301 * Returns a character if available, -1 otherwise. This routine can return
302 * false negatives in the following cases:
304 * - a valid character is in transit from the keyboard when called
305 * - a key release is received (from a previous key press)
306 * - a SHIFT key press is received (shift state is recorded however)
307 * - a key press for a multi-character sequence is received
309 * Yes, this is horrible.
312 KdbTryGetCharKeyboard(VOID
)
314 static unsigned shift_state
, ctrl_state
, meta_state
;
315 unsigned scan_code
, ch
;
317 /* See if a scan code is ready, returning if none. */
318 if ((READ_PORT_UCHAR((PUCHAR
)K_STATUS
) & K_OBUF_FUL
) == 0) {
321 scan_code
= READ_PORT_UCHAR((PUCHAR
)K_RDWR
);
323 /* Handle key releases - only release of SHIFT is important. */
324 if (scan_code
& 0x80) {
326 if (keymap
[scan_code
][0] == SHIFT
)
328 else if (keymap
[scan_code
][0] == CTRL
)
330 else if (keymap
[scan_code
][0] == META
)
334 /* Translate the character through the keymap. */
335 ch
= keymap
[scan_code
][shift_state
] | meta_state
;
339 } else if (ch
== CTRL
) {
342 } else if (ch
== META
) {
348 ch
= (keymap
[scan_code
][1] - '@') | meta_state
;