• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6.36/kernel/debug/kdb/
1/*
2 * Kernel Debugger Architecture Dependent Console I/O handler
3 *
4 * This file is subject to the terms and conditions of the GNU General Public
5 * License.
6 *
7 * Copyright (c) 1999-2006 Silicon Graphics, Inc.  All Rights Reserved.
8 * Copyright (c) 2009 Wind River Systems, Inc.  All Rights Reserved.
9 */
10
11#include <linux/kdb.h>
12#include <linux/keyboard.h>
13#include <linux/ctype.h>
14#include <linux/module.h>
15#include <linux/io.h>
16
17/* Keyboard Controller Registers on normal PCs. */
18
19#define KBD_STATUS_REG		0x64	/* Status register (R) */
20#define KBD_DATA_REG		0x60	/* Keyboard data register (R/W) */
21
22/* Status Register Bits */
23
24#define KBD_STAT_OBF 		0x01	/* Keyboard output buffer full */
25#define KBD_STAT_MOUSE_OBF	0x20	/* Mouse output buffer full */
26
27static int kbd_exists;
28
29/*
30 * Check if the keyboard controller has a keypress for us.
31 * Some parts (Enter Release, LED change) are still blocking polled here,
32 * but hopefully they are all short.
33 */
34int kdb_get_kbd_char(void)
35{
36	int scancode, scanstatus;
37	static int shift_lock;	/* CAPS LOCK state (0-off, 1-on) */
38	static int shift_key;	/* Shift next keypress */
39	static int ctrl_key;
40	u_short keychar;
41
42	if (KDB_FLAG(NO_I8042) || KDB_FLAG(NO_VT_CONSOLE) ||
43	    (inb(KBD_STATUS_REG) == 0xff && inb(KBD_DATA_REG) == 0xff)) {
44		kbd_exists = 0;
45		return -1;
46	}
47	kbd_exists = 1;
48
49	if ((inb(KBD_STATUS_REG) & KBD_STAT_OBF) == 0)
50		return -1;
51
52	/*
53	 * Fetch the scancode
54	 */
55	scancode = inb(KBD_DATA_REG);
56	scanstatus = inb(KBD_STATUS_REG);
57
58	/*
59	 * Ignore mouse events.
60	 */
61	if (scanstatus & KBD_STAT_MOUSE_OBF)
62		return -1;
63
64	/*
65	 * Ignore release, trigger on make
66	 * (except for shift keys, where we want to
67	 *  keep the shift state so long as the key is
68	 *  held down).
69	 */
70
71	if (((scancode&0x7f) == 0x2a) || ((scancode&0x7f) == 0x36)) {
72		/*
73		 * Next key may use shift table
74		 */
75		if ((scancode & 0x80) == 0)
76			shift_key = 1;
77		else
78			shift_key = 0;
79		return -1;
80	}
81
82	if ((scancode&0x7f) == 0x1d) {
83		/*
84		 * Left ctrl key
85		 */
86		if ((scancode & 0x80) == 0)
87			ctrl_key = 1;
88		else
89			ctrl_key = 0;
90		return -1;
91	}
92
93	if ((scancode & 0x80) != 0)
94		return -1;
95
96	scancode &= 0x7f;
97
98	/*
99	 * Translate scancode
100	 */
101
102	if (scancode == 0x3a) {
103		/*
104		 * Toggle caps lock
105		 */
106		shift_lock ^= 1;
107
108#ifdef	KDB_BLINK_LED
109		kdb_toggleled(0x4);
110#endif
111		return -1;
112	}
113
114	if (scancode == 0x0e) {
115		/*
116		 * Backspace
117		 */
118		return 8;
119	}
120
121	/* Special Key */
122	switch (scancode) {
123	case 0xF: /* Tab */
124		return 9;
125	case 0x53: /* Del */
126		return 4;
127	case 0x47: /* Home */
128		return 1;
129	case 0x4F: /* End */
130		return 5;
131	case 0x4B: /* Left */
132		return 2;
133	case 0x48: /* Up */
134		return 16;
135	case 0x50: /* Down */
136		return 14;
137	case 0x4D: /* Right */
138		return 6;
139	}
140
141	if (scancode == 0xe0)
142		return -1;
143
144	/*
145	 * For Japanese 86/106 keyboards
146	 * 	See comment in drivers/char/pc_keyb.c.
147	 * 	- Masahiro Adegawa
148	 */
149	if (scancode == 0x73)
150		scancode = 0x59;
151	else if (scancode == 0x7d)
152		scancode = 0x7c;
153
154	if (!shift_lock && !shift_key && !ctrl_key) {
155		keychar = plain_map[scancode];
156	} else if ((shift_lock || shift_key) && key_maps[1]) {
157		keychar = key_maps[1][scancode];
158	} else if (ctrl_key && key_maps[4]) {
159		keychar = key_maps[4][scancode];
160	} else {
161		keychar = 0x0020;
162		kdb_printf("Unknown state/scancode (%d)\n", scancode);
163	}
164	keychar &= 0x0fff;
165	if (keychar == '\t')
166		keychar = ' ';
167	switch (KTYP(keychar)) {
168	case KT_LETTER:
169	case KT_LATIN:
170		if (isprint(keychar))
171			break;		/* printable characters */
172		/* drop through */
173	case KT_SPEC:
174		if (keychar == K_ENTER)
175			break;
176		/* drop through */
177	default:
178		return -1;	/* ignore unprintables */
179	}
180
181	if ((scancode & 0x7f) == 0x1c) {
182		/*
183		 * enter key.  All done.  Absorb the release scancode.
184		 */
185		while ((inb(KBD_STATUS_REG) & KBD_STAT_OBF) == 0)
186			;
187
188		/*
189		 * Fetch the scancode
190		 */
191		scancode = inb(KBD_DATA_REG);
192		scanstatus = inb(KBD_STATUS_REG);
193
194		while (scanstatus & KBD_STAT_MOUSE_OBF) {
195			scancode = inb(KBD_DATA_REG);
196			scanstatus = inb(KBD_STATUS_REG);
197		}
198
199		if (scancode != 0x9c) {
200			/*
201			 * Wasn't an enter-release,  why not?
202			 */
203			kdb_printf("kdb: expected enter got 0x%x status 0x%x\n",
204			       scancode, scanstatus);
205		}
206
207		return 13;
208	}
209
210	return keychar & 0xff;
211}
212EXPORT_SYMBOL_GPL(kdb_get_kbd_char);
213