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
160914e4d3SArnd Bergmann #include "kdb_private.h"
170914e4d3SArnd 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
28*24b2455fSNir Lichtman #define CTRL(c) ((c) - 64)
29*24b2455fSNir Lichtman
30ada64e4cSJason Wessel static int kbd_exists;
318f30d411SAndrei Warkentin static int kbd_last_ret;
32ada64e4cSJason Wessel
33ada64e4cSJason Wessel /*
34ada64e4cSJason Wessel * Check if the keyboard controller has a keypress for us.
35ada64e4cSJason Wessel * Some parts (Enter Release, LED change) are still blocking polled here,
36ada64e4cSJason Wessel * but hopefully they are all short.
37ada64e4cSJason Wessel */
kdb_get_kbd_char(void)38ada64e4cSJason Wessel int kdb_get_kbd_char(void)
39ada64e4cSJason Wessel {
40ada64e4cSJason Wessel int scancode, scanstatus;
41ada64e4cSJason Wessel static int shift_lock; /* CAPS LOCK state (0-off, 1-on) */
42ada64e4cSJason Wessel static int shift_key; /* Shift next keypress */
43ada64e4cSJason Wessel static int ctrl_key;
44ada64e4cSJason Wessel u_short keychar;
45ada64e4cSJason Wessel
46ada64e4cSJason Wessel if (KDB_FLAG(NO_I8042) || KDB_FLAG(NO_VT_CONSOLE) ||
47ada64e4cSJason Wessel (inb(KBD_STATUS_REG) == 0xff && inb(KBD_DATA_REG) == 0xff)) {
48ada64e4cSJason Wessel kbd_exists = 0;
49ada64e4cSJason Wessel return -1;
50ada64e4cSJason Wessel }
51ada64e4cSJason Wessel kbd_exists = 1;
52ada64e4cSJason Wessel
53ada64e4cSJason Wessel if ((inb(KBD_STATUS_REG) & KBD_STAT_OBF) == 0)
54ada64e4cSJason Wessel return -1;
55ada64e4cSJason Wessel
56ada64e4cSJason Wessel /*
57ada64e4cSJason Wessel * Fetch the scancode
58ada64e4cSJason Wessel */
59ada64e4cSJason Wessel scancode = inb(KBD_DATA_REG);
60ada64e4cSJason Wessel scanstatus = inb(KBD_STATUS_REG);
61ada64e4cSJason Wessel
62ada64e4cSJason Wessel /*
63ada64e4cSJason Wessel * Ignore mouse events.
64ada64e4cSJason Wessel */
65ada64e4cSJason Wessel if (scanstatus & KBD_STAT_MOUSE_OBF)
66ada64e4cSJason Wessel return -1;
67ada64e4cSJason Wessel
68ada64e4cSJason Wessel /*
69ada64e4cSJason Wessel * Ignore release, trigger on make
70ada64e4cSJason Wessel * (except for shift keys, where we want to
71ada64e4cSJason Wessel * keep the shift state so long as the key is
72ada64e4cSJason Wessel * held down).
73ada64e4cSJason Wessel */
74ada64e4cSJason Wessel
75ada64e4cSJason Wessel if (((scancode&0x7f) == 0x2a) || ((scancode&0x7f) == 0x36)) {
76ada64e4cSJason Wessel /*
77ada64e4cSJason Wessel * Next key may use shift table
78ada64e4cSJason Wessel */
79ada64e4cSJason Wessel if ((scancode & 0x80) == 0)
80ada64e4cSJason Wessel shift_key = 1;
81ada64e4cSJason Wessel else
82ada64e4cSJason Wessel shift_key = 0;
83ada64e4cSJason Wessel return -1;
84ada64e4cSJason Wessel }
85ada64e4cSJason Wessel
86ada64e4cSJason Wessel if ((scancode&0x7f) == 0x1d) {
87ada64e4cSJason Wessel /*
88ada64e4cSJason Wessel * Left ctrl key
89ada64e4cSJason Wessel */
90ada64e4cSJason Wessel if ((scancode & 0x80) == 0)
91ada64e4cSJason Wessel ctrl_key = 1;
92ada64e4cSJason Wessel else
93ada64e4cSJason Wessel ctrl_key = 0;
94ada64e4cSJason Wessel return -1;
95ada64e4cSJason Wessel }
96ada64e4cSJason Wessel
978f30d411SAndrei Warkentin if ((scancode & 0x80) != 0) {
988f30d411SAndrei Warkentin if (scancode == 0x9c)
998f30d411SAndrei Warkentin kbd_last_ret = 0;
100ada64e4cSJason Wessel return -1;
1018f30d411SAndrei Warkentin }
102ada64e4cSJason Wessel
103ada64e4cSJason Wessel scancode &= 0x7f;
104ada64e4cSJason Wessel
105ada64e4cSJason Wessel /*
106ada64e4cSJason Wessel * Translate scancode
107ada64e4cSJason Wessel */
108ada64e4cSJason Wessel
109ada64e4cSJason Wessel if (scancode == 0x3a) {
110ada64e4cSJason Wessel /*
111ada64e4cSJason Wessel * Toggle caps lock
112ada64e4cSJason Wessel */
113ada64e4cSJason Wessel shift_lock ^= 1;
114ada64e4cSJason Wessel
115ada64e4cSJason Wessel #ifdef KDB_BLINK_LED
116ada64e4cSJason Wessel kdb_toggleled(0x4);
117ada64e4cSJason Wessel #endif
118ada64e4cSJason Wessel return -1;
119ada64e4cSJason Wessel }
120ada64e4cSJason Wessel
121ada64e4cSJason Wessel if (scancode == 0x0e) {
122ada64e4cSJason Wessel /*
123ada64e4cSJason Wessel * Backspace
124ada64e4cSJason Wessel */
125ada64e4cSJason Wessel return 8;
126ada64e4cSJason Wessel }
127ada64e4cSJason Wessel
128*24b2455fSNir Lichtman /* Translate special keys to equivalent CTRL control characters */
129ada64e4cSJason Wessel switch (scancode) {
130ada64e4cSJason Wessel case 0xF: /* Tab */
131*24b2455fSNir Lichtman return CTRL('I');
132ada64e4cSJason Wessel case 0x53: /* Del */
133*24b2455fSNir Lichtman return CTRL('D');
134ada64e4cSJason Wessel case 0x47: /* Home */
135*24b2455fSNir Lichtman return CTRL('A');
136ada64e4cSJason Wessel case 0x4F: /* End */
137*24b2455fSNir Lichtman return CTRL('E');
138ada64e4cSJason Wessel case 0x4B: /* Left */
139*24b2455fSNir Lichtman return CTRL('B');
140ada64e4cSJason Wessel case 0x48: /* Up */
141*24b2455fSNir Lichtman return CTRL('P');
142ada64e4cSJason Wessel case 0x50: /* Down */
143*24b2455fSNir Lichtman return CTRL('N');
144ada64e4cSJason Wessel case 0x4D: /* Right */
145*24b2455fSNir Lichtman return CTRL('F');
146ada64e4cSJason Wessel }
147ada64e4cSJason Wessel
148ada64e4cSJason Wessel if (scancode == 0xe0)
149ada64e4cSJason Wessel return -1;
150ada64e4cSJason Wessel
151ada64e4cSJason Wessel /*
152ada64e4cSJason Wessel * For Japanese 86/106 keyboards
153ada64e4cSJason Wessel * See comment in drivers/char/pc_keyb.c.
154ada64e4cSJason Wessel * - Masahiro Adegawa
155ada64e4cSJason Wessel */
156ada64e4cSJason Wessel if (scancode == 0x73)
157ada64e4cSJason Wessel scancode = 0x59;
158ada64e4cSJason Wessel else if (scancode == 0x7d)
159ada64e4cSJason Wessel scancode = 0x7c;
160ada64e4cSJason Wessel
161ada64e4cSJason Wessel if (!shift_lock && !shift_key && !ctrl_key) {
162ada64e4cSJason Wessel keychar = plain_map[scancode];
163ada64e4cSJason Wessel } else if ((shift_lock || shift_key) && key_maps[1]) {
164ada64e4cSJason Wessel keychar = key_maps[1][scancode];
165ada64e4cSJason Wessel } else if (ctrl_key && key_maps[4]) {
166ada64e4cSJason Wessel keychar = key_maps[4][scancode];
167ada64e4cSJason Wessel } else {
168ada64e4cSJason Wessel keychar = 0x0020;
169ada64e4cSJason Wessel kdb_printf("Unknown state/scancode (%d)\n", scancode);
170ada64e4cSJason Wessel }
171ada64e4cSJason Wessel keychar &= 0x0fff;
172ada64e4cSJason Wessel if (keychar == '\t')
173ada64e4cSJason Wessel keychar = ' ';
174ada64e4cSJason Wessel switch (KTYP(keychar)) {
175ada64e4cSJason Wessel case KT_LETTER:
176ada64e4cSJason Wessel case KT_LATIN:
177*24b2455fSNir Lichtman switch (keychar) {
178*24b2455fSNir Lichtman /* non-printable supported control characters */
179*24b2455fSNir Lichtman case CTRL('A'): /* Home */
180*24b2455fSNir Lichtman case CTRL('B'): /* Left */
181*24b2455fSNir Lichtman case CTRL('D'): /* Del */
182*24b2455fSNir Lichtman case CTRL('E'): /* End */
183*24b2455fSNir Lichtman case CTRL('F'): /* Right */
184*24b2455fSNir Lichtman case CTRL('I'): /* Tab */
185*24b2455fSNir Lichtman case CTRL('N'): /* Down */
186*24b2455fSNir Lichtman case CTRL('P'): /* Up */
187*24b2455fSNir Lichtman return keychar;
188*24b2455fSNir Lichtman }
189*24b2455fSNir Lichtman
190ada64e4cSJason Wessel if (isprint(keychar))
191ada64e4cSJason Wessel break; /* printable characters */
192df561f66SGustavo A. R. Silva fallthrough;
193ada64e4cSJason Wessel case KT_SPEC:
194ada64e4cSJason Wessel if (keychar == K_ENTER)
195ada64e4cSJason Wessel break;
196df561f66SGustavo A. R. Silva fallthrough;
197ada64e4cSJason Wessel default:
198ada64e4cSJason Wessel return -1; /* ignore unprintables */
199ada64e4cSJason Wessel }
200ada64e4cSJason Wessel
2018f30d411SAndrei Warkentin if (scancode == 0x1c) {
2028f30d411SAndrei Warkentin kbd_last_ret = 1;
203ada64e4cSJason Wessel return 13;
204ada64e4cSJason Wessel }
205ada64e4cSJason Wessel
206ada64e4cSJason Wessel return keychar & 0xff;
207ada64e4cSJason Wessel }
208ada64e4cSJason Wessel EXPORT_SYMBOL_GPL(kdb_get_kbd_char);
2098f30d411SAndrei Warkentin
2108f30d411SAndrei Warkentin /*
2118f30d411SAndrei Warkentin * Best effort cleanup of ENTER break codes on leaving KDB. Called on
2128f30d411SAndrei Warkentin * exiting KDB, when we know we processed an ENTER or KP ENTER scan
2138f30d411SAndrei Warkentin * code.
2148f30d411SAndrei Warkentin */
kdb_kbd_cleanup_state(void)2158f30d411SAndrei Warkentin void kdb_kbd_cleanup_state(void)
2168f30d411SAndrei Warkentin {
2178f30d411SAndrei Warkentin int scancode, scanstatus;
2188f30d411SAndrei Warkentin
2198f30d411SAndrei Warkentin /*
2208f30d411SAndrei Warkentin * Nothing to clean up, since either
2218f30d411SAndrei Warkentin * ENTER was never pressed, or has already
2228f30d411SAndrei Warkentin * gotten cleaned up.
2238f30d411SAndrei Warkentin */
2248f30d411SAndrei Warkentin if (!kbd_last_ret)
2258f30d411SAndrei Warkentin return;
2268f30d411SAndrei Warkentin
2278f30d411SAndrei Warkentin kbd_last_ret = 0;
2288f30d411SAndrei Warkentin /*
2298f30d411SAndrei Warkentin * Enter key. Need to absorb the break code here, lest it gets
2308f30d411SAndrei Warkentin * leaked out if we exit KDB as the result of processing 'g'.
2318f30d411SAndrei Warkentin *
2328f30d411SAndrei Warkentin * This has several interesting implications:
2338f30d411SAndrei Warkentin * + Need to handle KP ENTER, which has break code 0xe0 0x9c.
2348f30d411SAndrei Warkentin * + Need to handle repeat ENTER and repeat KP ENTER. Repeats
2358f30d411SAndrei Warkentin * only get a break code at the end of the repeated
2368f30d411SAndrei Warkentin * sequence. This means we can't propagate the repeated key
2378f30d411SAndrei Warkentin * press, and must swallow it away.
2388f30d411SAndrei Warkentin * + Need to handle possible PS/2 mouse input.
2398f30d411SAndrei Warkentin * + Need to handle mashed keys.
2408f30d411SAndrei Warkentin */
2418f30d411SAndrei Warkentin
2428f30d411SAndrei Warkentin while (1) {
2438f30d411SAndrei Warkentin while ((inb(KBD_STATUS_REG) & KBD_STAT_OBF) == 0)
2448f30d411SAndrei Warkentin cpu_relax();
2458f30d411SAndrei Warkentin
2468f30d411SAndrei Warkentin /*
2478f30d411SAndrei Warkentin * Fetch the scancode.
2488f30d411SAndrei Warkentin */
2498f30d411SAndrei Warkentin scancode = inb(KBD_DATA_REG);
2508f30d411SAndrei Warkentin scanstatus = inb(KBD_STATUS_REG);
2518f30d411SAndrei Warkentin
2528f30d411SAndrei Warkentin /*
2538f30d411SAndrei Warkentin * Skip mouse input.
2548f30d411SAndrei Warkentin */
2558f30d411SAndrei Warkentin if (scanstatus & KBD_STAT_MOUSE_OBF)
2568f30d411SAndrei Warkentin continue;
2578f30d411SAndrei Warkentin
2588f30d411SAndrei Warkentin /*
2598f30d411SAndrei Warkentin * If we see 0xe0, this is either a break code for KP
2608f30d411SAndrei Warkentin * ENTER, or a repeat make for KP ENTER. Either way,
2618f30d411SAndrei Warkentin * since the second byte is equivalent to an ENTER,
2628f30d411SAndrei Warkentin * skip the 0xe0 and try again.
2638f30d411SAndrei Warkentin *
2648f30d411SAndrei Warkentin * If we see 0x1c, this must be a repeat ENTER or KP
2658f30d411SAndrei Warkentin * ENTER (and we swallowed 0xe0 before). Try again.
2668f30d411SAndrei Warkentin *
2678f30d411SAndrei Warkentin * We can also see make and break codes for other keys
2688f30d411SAndrei Warkentin * mashed before or after pressing ENTER. Thus, if we
2698f30d411SAndrei Warkentin * see anything other than 0x9c, we have to try again.
2708f30d411SAndrei Warkentin *
2718f30d411SAndrei Warkentin * Note, if you held some key as ENTER was depressed,
2728f30d411SAndrei Warkentin * that break code would get leaked out.
2738f30d411SAndrei Warkentin */
2748f30d411SAndrei Warkentin if (scancode != 0x9c)
2758f30d411SAndrei Warkentin continue;
2768f30d411SAndrei Warkentin
2778f30d411SAndrei Warkentin return;
2788f30d411SAndrei Warkentin }
2798f30d411SAndrei Warkentin }
280