1ada64e4cSJason Wessel /*
2ada64e4cSJason Wessel * Kernel Debugger Architecture Dependent Console I/O handler
3ada64e4cSJason Wessel *
4ada64e4cSJason Wessel * This file is subject to the terms and conditions of the GNU General Public
5ada64e4cSJason Wessel * License.
6ada64e4cSJason Wessel *
7ada64e4cSJason Wessel * Copyright (c) 1999-2006 Silicon Graphics, Inc. All Rights Reserved.
8ada64e4cSJason Wessel * Copyright (c) 2009 Wind River Systems, Inc. All Rights Reserved.
9ada64e4cSJason Wessel */
10ada64e4cSJason Wessel
11ada64e4cSJason Wessel #include <linux/kdb.h>
12ada64e4cSJason Wessel #include <linux/keyboard.h>
13ada64e4cSJason Wessel #include <linux/ctype.h>
14ada64e4cSJason Wessel #include <linux/io.h>
15ada64e4cSJason Wessel
16*0914e4d3SArnd Bergmann #include "kdb_private.h"
17*0914e4d3SArnd Bergmann
18ada64e4cSJason Wessel /* Keyboard Controller Registers on normal PCs. */
19ada64e4cSJason Wessel
20ada64e4cSJason Wessel #define KBD_STATUS_REG 0x64 /* Status register (R) */
21ada64e4cSJason Wessel #define KBD_DATA_REG 0x60 /* Keyboard data register (R/W) */
22ada64e4cSJason Wessel
23ada64e4cSJason Wessel /* Status Register Bits */
24ada64e4cSJason Wessel
25ada64e4cSJason Wessel #define KBD_STAT_OBF 0x01 /* Keyboard output buffer full */
26ada64e4cSJason Wessel #define KBD_STAT_MOUSE_OBF 0x20 /* Mouse output buffer full */
27ada64e4cSJason Wessel
28ada64e4cSJason Wessel static int kbd_exists;
298f30d411SAndrei Warkentin static int kbd_last_ret;
30ada64e4cSJason Wessel
31ada64e4cSJason Wessel /*
32ada64e4cSJason Wessel * Check if the keyboard controller has a keypress for us.
33ada64e4cSJason Wessel * Some parts (Enter Release, LED change) are still blocking polled here,
34ada64e4cSJason Wessel * but hopefully they are all short.
35ada64e4cSJason Wessel */
kdb_get_kbd_char(void)36ada64e4cSJason Wessel int kdb_get_kbd_char(void)
37ada64e4cSJason Wessel {
38ada64e4cSJason Wessel int scancode, scanstatus;
39ada64e4cSJason Wessel static int shift_lock; /* CAPS LOCK state (0-off, 1-on) */
40ada64e4cSJason Wessel static int shift_key; /* Shift next keypress */
41ada64e4cSJason Wessel static int ctrl_key;
42ada64e4cSJason Wessel u_short keychar;
43ada64e4cSJason Wessel
44ada64e4cSJason Wessel if (KDB_FLAG(NO_I8042) || KDB_FLAG(NO_VT_CONSOLE) ||
45ada64e4cSJason Wessel (inb(KBD_STATUS_REG) == 0xff && inb(KBD_DATA_REG) == 0xff)) {
46ada64e4cSJason Wessel kbd_exists = 0;
47ada64e4cSJason Wessel return -1;
48ada64e4cSJason Wessel }
49ada64e4cSJason Wessel kbd_exists = 1;
50ada64e4cSJason Wessel
51ada64e4cSJason Wessel if ((inb(KBD_STATUS_REG) & KBD_STAT_OBF) == 0)
52ada64e4cSJason Wessel return -1;
53ada64e4cSJason Wessel
54ada64e4cSJason Wessel /*
55ada64e4cSJason Wessel * Fetch the scancode
56ada64e4cSJason Wessel */
57ada64e4cSJason Wessel scancode = inb(KBD_DATA_REG);
58ada64e4cSJason Wessel scanstatus = inb(KBD_STATUS_REG);
59ada64e4cSJason Wessel
60ada64e4cSJason Wessel /*
61ada64e4cSJason Wessel * Ignore mouse events.
62ada64e4cSJason Wessel */
63ada64e4cSJason Wessel if (scanstatus & KBD_STAT_MOUSE_OBF)
64ada64e4cSJason Wessel return -1;
65ada64e4cSJason Wessel
66ada64e4cSJason Wessel /*
67ada64e4cSJason Wessel * Ignore release, trigger on make
68ada64e4cSJason Wessel * (except for shift keys, where we want to
69ada64e4cSJason Wessel * keep the shift state so long as the key is
70ada64e4cSJason Wessel * held down).
71ada64e4cSJason Wessel */
72ada64e4cSJason Wessel
73ada64e4cSJason Wessel if (((scancode&0x7f) == 0x2a) || ((scancode&0x7f) == 0x36)) {
74ada64e4cSJason Wessel /*
75ada64e4cSJason Wessel * Next key may use shift table
76ada64e4cSJason Wessel */
77ada64e4cSJason Wessel if ((scancode & 0x80) == 0)
78ada64e4cSJason Wessel shift_key = 1;
79ada64e4cSJason Wessel else
80ada64e4cSJason Wessel shift_key = 0;
81ada64e4cSJason Wessel return -1;
82ada64e4cSJason Wessel }
83ada64e4cSJason Wessel
84ada64e4cSJason Wessel if ((scancode&0x7f) == 0x1d) {
85ada64e4cSJason Wessel /*
86ada64e4cSJason Wessel * Left ctrl key
87ada64e4cSJason Wessel */
88ada64e4cSJason Wessel if ((scancode & 0x80) == 0)
89ada64e4cSJason Wessel ctrl_key = 1;
90ada64e4cSJason Wessel else
91ada64e4cSJason Wessel ctrl_key = 0;
92ada64e4cSJason Wessel return -1;
93ada64e4cSJason Wessel }
94ada64e4cSJason Wessel
958f30d411SAndrei Warkentin if ((scancode & 0x80) != 0) {
968f30d411SAndrei Warkentin if (scancode == 0x9c)
978f30d411SAndrei Warkentin kbd_last_ret = 0;
98ada64e4cSJason Wessel return -1;
998f30d411SAndrei Warkentin }
100ada64e4cSJason Wessel
101ada64e4cSJason Wessel scancode &= 0x7f;
102ada64e4cSJason Wessel
103ada64e4cSJason Wessel /*
104ada64e4cSJason Wessel * Translate scancode
105ada64e4cSJason Wessel */
106ada64e4cSJason Wessel
107ada64e4cSJason Wessel if (scancode == 0x3a) {
108ada64e4cSJason Wessel /*
109ada64e4cSJason Wessel * Toggle caps lock
110ada64e4cSJason Wessel */
111ada64e4cSJason Wessel shift_lock ^= 1;
112ada64e4cSJason Wessel
113ada64e4cSJason Wessel #ifdef KDB_BLINK_LED
114ada64e4cSJason Wessel kdb_toggleled(0x4);
115ada64e4cSJason Wessel #endif
116ada64e4cSJason Wessel return -1;
117ada64e4cSJason Wessel }
118ada64e4cSJason Wessel
119ada64e4cSJason Wessel if (scancode == 0x0e) {
120ada64e4cSJason Wessel /*
121ada64e4cSJason Wessel * Backspace
122ada64e4cSJason Wessel */
123ada64e4cSJason Wessel return 8;
124ada64e4cSJason Wessel }
125ada64e4cSJason Wessel
126ada64e4cSJason Wessel /* Special Key */
127ada64e4cSJason Wessel switch (scancode) {
128ada64e4cSJason Wessel case 0xF: /* Tab */
129ada64e4cSJason Wessel return 9;
130ada64e4cSJason Wessel case 0x53: /* Del */
131ada64e4cSJason Wessel return 4;
132ada64e4cSJason Wessel case 0x47: /* Home */
133ada64e4cSJason Wessel return 1;
134ada64e4cSJason Wessel case 0x4F: /* End */
135ada64e4cSJason Wessel return 5;
136ada64e4cSJason Wessel case 0x4B: /* Left */
137ada64e4cSJason Wessel return 2;
138ada64e4cSJason Wessel case 0x48: /* Up */
139ada64e4cSJason Wessel return 16;
140ada64e4cSJason Wessel case 0x50: /* Down */
141ada64e4cSJason Wessel return 14;
142ada64e4cSJason Wessel case 0x4D: /* Right */
143ada64e4cSJason Wessel return 6;
144ada64e4cSJason Wessel }
145ada64e4cSJason Wessel
146ada64e4cSJason Wessel if (scancode == 0xe0)
147ada64e4cSJason Wessel return -1;
148ada64e4cSJason Wessel
149ada64e4cSJason Wessel /*
150ada64e4cSJason Wessel * For Japanese 86/106 keyboards
151ada64e4cSJason Wessel * See comment in drivers/char/pc_keyb.c.
152ada64e4cSJason Wessel * - Masahiro Adegawa
153ada64e4cSJason Wessel */
154ada64e4cSJason Wessel if (scancode == 0x73)
155ada64e4cSJason Wessel scancode = 0x59;
156ada64e4cSJason Wessel else if (scancode == 0x7d)
157ada64e4cSJason Wessel scancode = 0x7c;
158ada64e4cSJason Wessel
159ada64e4cSJason Wessel if (!shift_lock && !shift_key && !ctrl_key) {
160ada64e4cSJason Wessel keychar = plain_map[scancode];
161ada64e4cSJason Wessel } else if ((shift_lock || shift_key) && key_maps[1]) {
162ada64e4cSJason Wessel keychar = key_maps[1][scancode];
163ada64e4cSJason Wessel } else if (ctrl_key && key_maps[4]) {
164ada64e4cSJason Wessel keychar = key_maps[4][scancode];
165ada64e4cSJason Wessel } else {
166ada64e4cSJason Wessel keychar = 0x0020;
167ada64e4cSJason Wessel kdb_printf("Unknown state/scancode (%d)\n", scancode);
168ada64e4cSJason Wessel }
169ada64e4cSJason Wessel keychar &= 0x0fff;
170ada64e4cSJason Wessel if (keychar == '\t')
171ada64e4cSJason Wessel keychar = ' ';
172ada64e4cSJason Wessel switch (KTYP(keychar)) {
173ada64e4cSJason Wessel case KT_LETTER:
174ada64e4cSJason Wessel case KT_LATIN:
175ada64e4cSJason Wessel if (isprint(keychar))
176ada64e4cSJason Wessel break; /* printable characters */
177df561f66SGustavo A. R. Silva fallthrough;
178ada64e4cSJason Wessel case KT_SPEC:
179ada64e4cSJason Wessel if (keychar == K_ENTER)
180ada64e4cSJason Wessel break;
181df561f66SGustavo A. R. Silva fallthrough;
182ada64e4cSJason Wessel default:
183ada64e4cSJason Wessel return -1; /* ignore unprintables */
184ada64e4cSJason Wessel }
185ada64e4cSJason Wessel
1868f30d411SAndrei Warkentin if (scancode == 0x1c) {
1878f30d411SAndrei Warkentin kbd_last_ret = 1;
188ada64e4cSJason Wessel return 13;
189ada64e4cSJason Wessel }
190ada64e4cSJason Wessel
191ada64e4cSJason Wessel return keychar & 0xff;
192ada64e4cSJason Wessel }
193ada64e4cSJason Wessel EXPORT_SYMBOL_GPL(kdb_get_kbd_char);
1948f30d411SAndrei Warkentin
1958f30d411SAndrei Warkentin /*
1968f30d411SAndrei Warkentin * Best effort cleanup of ENTER break codes on leaving KDB. Called on
1978f30d411SAndrei Warkentin * exiting KDB, when we know we processed an ENTER or KP ENTER scan
1988f30d411SAndrei Warkentin * code.
1998f30d411SAndrei Warkentin */
kdb_kbd_cleanup_state(void)2008f30d411SAndrei Warkentin void kdb_kbd_cleanup_state(void)
2018f30d411SAndrei Warkentin {
2028f30d411SAndrei Warkentin int scancode, scanstatus;
2038f30d411SAndrei Warkentin
2048f30d411SAndrei Warkentin /*
2058f30d411SAndrei Warkentin * Nothing to clean up, since either
2068f30d411SAndrei Warkentin * ENTER was never pressed, or has already
2078f30d411SAndrei Warkentin * gotten cleaned up.
2088f30d411SAndrei Warkentin */
2098f30d411SAndrei Warkentin if (!kbd_last_ret)
2108f30d411SAndrei Warkentin return;
2118f30d411SAndrei Warkentin
2128f30d411SAndrei Warkentin kbd_last_ret = 0;
2138f30d411SAndrei Warkentin /*
2148f30d411SAndrei Warkentin * Enter key. Need to absorb the break code here, lest it gets
2158f30d411SAndrei Warkentin * leaked out if we exit KDB as the result of processing 'g'.
2168f30d411SAndrei Warkentin *
2178f30d411SAndrei Warkentin * This has several interesting implications:
2188f30d411SAndrei Warkentin * + Need to handle KP ENTER, which has break code 0xe0 0x9c.
2198f30d411SAndrei Warkentin * + Need to handle repeat ENTER and repeat KP ENTER. Repeats
2208f30d411SAndrei Warkentin * only get a break code at the end of the repeated
2218f30d411SAndrei Warkentin * sequence. This means we can't propagate the repeated key
2228f30d411SAndrei Warkentin * press, and must swallow it away.
2238f30d411SAndrei Warkentin * + Need to handle possible PS/2 mouse input.
2248f30d411SAndrei Warkentin * + Need to handle mashed keys.
2258f30d411SAndrei Warkentin */
2268f30d411SAndrei Warkentin
2278f30d411SAndrei Warkentin while (1) {
2288f30d411SAndrei Warkentin while ((inb(KBD_STATUS_REG) & KBD_STAT_OBF) == 0)
2298f30d411SAndrei Warkentin cpu_relax();
2308f30d411SAndrei Warkentin
2318f30d411SAndrei Warkentin /*
2328f30d411SAndrei Warkentin * Fetch the scancode.
2338f30d411SAndrei Warkentin */
2348f30d411SAndrei Warkentin scancode = inb(KBD_DATA_REG);
2358f30d411SAndrei Warkentin scanstatus = inb(KBD_STATUS_REG);
2368f30d411SAndrei Warkentin
2378f30d411SAndrei Warkentin /*
2388f30d411SAndrei Warkentin * Skip mouse input.
2398f30d411SAndrei Warkentin */
2408f30d411SAndrei Warkentin if (scanstatus & KBD_STAT_MOUSE_OBF)
2418f30d411SAndrei Warkentin continue;
2428f30d411SAndrei Warkentin
2438f30d411SAndrei Warkentin /*
2448f30d411SAndrei Warkentin * If we see 0xe0, this is either a break code for KP
2458f30d411SAndrei Warkentin * ENTER, or a repeat make for KP ENTER. Either way,
2468f30d411SAndrei Warkentin * since the second byte is equivalent to an ENTER,
2478f30d411SAndrei Warkentin * skip the 0xe0 and try again.
2488f30d411SAndrei Warkentin *
2498f30d411SAndrei Warkentin * If we see 0x1c, this must be a repeat ENTER or KP
2508f30d411SAndrei Warkentin * ENTER (and we swallowed 0xe0 before). Try again.
2518f30d411SAndrei Warkentin *
2528f30d411SAndrei Warkentin * We can also see make and break codes for other keys
2538f30d411SAndrei Warkentin * mashed before or after pressing ENTER. Thus, if we
2548f30d411SAndrei Warkentin * see anything other than 0x9c, we have to try again.
2558f30d411SAndrei Warkentin *
2568f30d411SAndrei Warkentin * Note, if you held some key as ENTER was depressed,
2578f30d411SAndrei Warkentin * that break code would get leaked out.
2588f30d411SAndrei Warkentin */
2598f30d411SAndrei Warkentin if (scancode != 0x9c)
2608f30d411SAndrei Warkentin continue;
2618f30d411SAndrei Warkentin
2628f30d411SAndrei Warkentin return;
2638f30d411SAndrei Warkentin }
2648f30d411SAndrei Warkentin }
265