• 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/drivers/serial/
1/*
2 * Based on the same principle as kgdboe using the NETPOLL api, this
3 * driver uses a console polling api to implement a gdb serial inteface
4 * which is multiplexed on a console port.
5 *
6 * Maintainer: Jason Wessel <jason.wessel@windriver.com>
7 *
8 * 2007-2008 (c) Jason Wessel - Wind River Systems, Inc.
9 *
10 * This file is licensed under the terms of the GNU General Public
11 * License version 2. This program is licensed "as is" without any
12 * warranty of any kind, whether express or implied.
13 */
14#include <linux/kernel.h>
15#include <linux/ctype.h>
16#include <linux/kgdb.h>
17#include <linux/kdb.h>
18#include <linux/tty.h>
19#include <linux/console.h>
20#include <linux/vt_kern.h>
21
22#define MAX_CONFIG_LEN		40
23
24static struct kgdb_io		kgdboc_io_ops;
25
26/* -1 = init not run yet, 0 = unconfigured, 1 = configured. */
27static int configured		= -1;
28
29static char config[MAX_CONFIG_LEN];
30static struct kparam_string kps = {
31	.string			= config,
32	.maxlen			= MAX_CONFIG_LEN,
33};
34
35static int kgdboc_use_kms;  /* 1 if we use kernel mode switching */
36static struct tty_driver	*kgdb_tty_driver;
37static int			kgdb_tty_line;
38
39#ifdef CONFIG_KDB_KEYBOARD
40static int kgdboc_register_kbd(char **cptr)
41{
42	if (strncmp(*cptr, "kbd", 3) == 0) {
43		if (kdb_poll_idx < KDB_POLL_FUNC_MAX) {
44			kdb_poll_funcs[kdb_poll_idx] = kdb_get_kbd_char;
45			kdb_poll_idx++;
46			if (cptr[0][3] == ',')
47				*cptr += 4;
48			else
49				return 1;
50		}
51	}
52	return 0;
53}
54
55static void kgdboc_unregister_kbd(void)
56{
57	int i;
58
59	for (i = 0; i < kdb_poll_idx; i++) {
60		if (kdb_poll_funcs[i] == kdb_get_kbd_char) {
61			kdb_poll_idx--;
62			kdb_poll_funcs[i] = kdb_poll_funcs[kdb_poll_idx];
63			kdb_poll_funcs[kdb_poll_idx] = NULL;
64			i--;
65		}
66	}
67}
68#else /* ! CONFIG_KDB_KEYBOARD */
69#define kgdboc_register_kbd(x) 0
70#define kgdboc_unregister_kbd()
71#endif /* ! CONFIG_KDB_KEYBOARD */
72
73static int kgdboc_option_setup(char *opt)
74{
75	if (strlen(opt) > MAX_CONFIG_LEN) {
76		printk(KERN_ERR "kgdboc: config string too long\n");
77		return -ENOSPC;
78	}
79	strcpy(config, opt);
80
81	return 0;
82}
83
84__setup("kgdboc=", kgdboc_option_setup);
85
86static void cleanup_kgdboc(void)
87{
88	kgdboc_unregister_kbd();
89	if (configured == 1)
90		kgdb_unregister_io_module(&kgdboc_io_ops);
91}
92
93static int configure_kgdboc(void)
94{
95	struct tty_driver *p;
96	int tty_line = 0;
97	int err;
98	char *cptr = config;
99	struct console *cons;
100
101	err = kgdboc_option_setup(config);
102	if (err || !strlen(config) || isspace(config[0]))
103		goto noconfig;
104
105	err = -ENODEV;
106	kgdboc_io_ops.is_console = 0;
107	kgdb_tty_driver = NULL;
108
109	kgdboc_use_kms = 0;
110	if (strncmp(cptr, "kms,", 4) == 0) {
111		cptr += 4;
112		kgdboc_use_kms = 1;
113	}
114
115	if (kgdboc_register_kbd(&cptr))
116		goto do_register;
117
118	p = tty_find_polling_driver(cptr, &tty_line);
119	if (!p)
120		goto noconfig;
121
122	cons = console_drivers;
123	while (cons) {
124		int idx;
125		if (cons->device && cons->device(cons, &idx) == p &&
126		    idx == tty_line) {
127			kgdboc_io_ops.is_console = 1;
128			break;
129		}
130		cons = cons->next;
131	}
132
133	kgdb_tty_driver = p;
134	kgdb_tty_line = tty_line;
135
136do_register:
137	err = kgdb_register_io_module(&kgdboc_io_ops);
138	if (err)
139		goto noconfig;
140
141	configured = 1;
142
143	return 0;
144
145noconfig:
146	config[0] = 0;
147	configured = 0;
148	cleanup_kgdboc();
149
150	return err;
151}
152
153static int __init init_kgdboc(void)
154{
155	/* Already configured? */
156	if (configured == 1)
157		return 0;
158
159	return configure_kgdboc();
160}
161
162static int kgdboc_get_char(void)
163{
164	if (!kgdb_tty_driver)
165		return -1;
166	return kgdb_tty_driver->ops->poll_get_char(kgdb_tty_driver,
167						kgdb_tty_line);
168}
169
170static void kgdboc_put_char(u8 chr)
171{
172	if (!kgdb_tty_driver)
173		return;
174	kgdb_tty_driver->ops->poll_put_char(kgdb_tty_driver,
175					kgdb_tty_line, chr);
176}
177
178static int param_set_kgdboc_var(const char *kmessage, struct kernel_param *kp)
179{
180	int len = strlen(kmessage);
181
182	if (len >= MAX_CONFIG_LEN) {
183		printk(KERN_ERR "kgdboc: config string too long\n");
184		return -ENOSPC;
185	}
186
187	/* Only copy in the string if the init function has not run yet */
188	if (configured < 0) {
189		strcpy(config, kmessage);
190		return 0;
191	}
192
193	if (kgdb_connected) {
194		printk(KERN_ERR
195		       "kgdboc: Cannot reconfigure while KGDB is connected.\n");
196
197		return -EBUSY;
198	}
199
200	strcpy(config, kmessage);
201	/* Chop out \n char as a result of echo */
202	if (config[len - 1] == '\n')
203		config[len - 1] = '\0';
204
205	if (configured == 1)
206		cleanup_kgdboc();
207
208	/* Go and configure with the new params. */
209	return configure_kgdboc();
210}
211
212static int dbg_restore_graphics;
213
214static void kgdboc_pre_exp_handler(void)
215{
216	if (!dbg_restore_graphics && kgdboc_use_kms) {
217		dbg_restore_graphics = 1;
218		con_debug_enter(vc_cons[fg_console].d);
219	}
220	/* Increment the module count when the debugger is active */
221	if (!kgdb_connected)
222		try_module_get(THIS_MODULE);
223}
224
225static void kgdboc_post_exp_handler(void)
226{
227	/* decrement the module count when the debugger detaches */
228	if (!kgdb_connected)
229		module_put(THIS_MODULE);
230	if (kgdboc_use_kms && dbg_restore_graphics) {
231		dbg_restore_graphics = 0;
232		con_debug_leave();
233	}
234}
235
236static struct kgdb_io kgdboc_io_ops = {
237	.name			= "kgdboc",
238	.read_char		= kgdboc_get_char,
239	.write_char		= kgdboc_put_char,
240	.pre_exception		= kgdboc_pre_exp_handler,
241	.post_exception		= kgdboc_post_exp_handler,
242};
243
244#ifdef CONFIG_KGDB_SERIAL_CONSOLE
245/* This is only available if kgdboc is a built in for early debugging */
246int __init kgdboc_early_init(char *opt)
247{
248	/* save the first character of the config string because the
249	 * init routine can destroy it.
250	 */
251	char save_ch;
252
253	kgdboc_option_setup(opt);
254	save_ch = config[0];
255	init_kgdboc();
256	config[0] = save_ch;
257	return 0;
258}
259
260early_param("ekgdboc", kgdboc_early_init);
261#endif /* CONFIG_KGDB_SERIAL_CONSOLE */
262
263module_init(init_kgdboc);
264module_exit(cleanup_kgdboc);
265module_param_call(kgdboc, param_set_kgdboc_var, param_get_string, &kps, 0644);
266MODULE_PARM_DESC(kgdboc, "<serial_device>[,baud]");
267MODULE_DESCRIPTION("KGDB Console TTY Driver");
268MODULE_LICENSE("GPL");
269