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#include <linux/input.h>
22#include <linux/module.h>
23
24#define MAX_CONFIG_LEN		40
25
26static struct kgdb_io		kgdboc_io_ops;
27
28/* -1 = init not run yet, 0 = unconfigured, 1 = configured. */
29static int configured		= -1;
30
31static char config[MAX_CONFIG_LEN];
32static struct kparam_string kps = {
33	.string			= config,
34	.maxlen			= MAX_CONFIG_LEN,
35};
36
37static int kgdboc_use_kms;  /* 1 if we use kernel mode switching */
38static struct tty_driver	*kgdb_tty_driver;
39static int			kgdb_tty_line;
40
41#ifdef CONFIG_KDB_KEYBOARD
42static int kgdboc_reset_connect(struct input_handler *handler,
43				struct input_dev *dev,
44				const struct input_device_id *id)
45{
46	input_reset_device(dev);
47
48	/* Retrun an error - we do not want to bind, just to reset */
49	return -ENODEV;
50}
51
52static void kgdboc_reset_disconnect(struct input_handle *handle)
53{
54	/* We do not expect anyone to actually bind to us */
55	BUG();
56}
57
58static const struct input_device_id kgdboc_reset_ids[] = {
59	{
60		.flags = INPUT_DEVICE_ID_MATCH_EVBIT,
61		.evbit = { BIT_MASK(EV_KEY) },
62	},
63	{ }
64};
65
66static struct input_handler kgdboc_reset_handler = {
67	.connect	= kgdboc_reset_connect,
68	.disconnect	= kgdboc_reset_disconnect,
69	.name		= "kgdboc_reset",
70	.id_table	= kgdboc_reset_ids,
71};
72
73static DEFINE_MUTEX(kgdboc_reset_mutex);
74
75static void kgdboc_restore_input_helper(struct work_struct *dummy)
76{
77	/*
78	 * We need to take a mutex to prevent several instances of
79	 * this work running on different CPUs so they don't try
80	 * to register again already registered handler.
81	 */
82	mutex_lock(&kgdboc_reset_mutex);
83
84	if (input_register_handler(&kgdboc_reset_handler) == 0)
85		input_unregister_handler(&kgdboc_reset_handler);
86
87	mutex_unlock(&kgdboc_reset_mutex);
88}
89
90static DECLARE_WORK(kgdboc_restore_input_work, kgdboc_restore_input_helper);
91
92static void kgdboc_restore_input(void)
93{
94	if (likely(system_state == SYSTEM_RUNNING))
95		schedule_work(&kgdboc_restore_input_work);
96}
97
98static int kgdboc_register_kbd(char **cptr)
99{
100	if (strncmp(*cptr, "kbd", 3) == 0) {
101		if (kdb_poll_idx < KDB_POLL_FUNC_MAX) {
102			kdb_poll_funcs[kdb_poll_idx] = kdb_get_kbd_char;
103			kdb_poll_idx++;
104			if (cptr[0][3] == ',')
105				*cptr += 4;
106			else
107				return 1;
108		}
109	}
110	return 0;
111}
112
113static void kgdboc_unregister_kbd(void)
114{
115	int i;
116
117	for (i = 0; i < kdb_poll_idx; i++) {
118		if (kdb_poll_funcs[i] == kdb_get_kbd_char) {
119			kdb_poll_idx--;
120			kdb_poll_funcs[i] = kdb_poll_funcs[kdb_poll_idx];
121			kdb_poll_funcs[kdb_poll_idx] = NULL;
122			i--;
123		}
124	}
125	flush_work_sync(&kgdboc_restore_input_work);
126}
127#else /* ! CONFIG_KDB_KEYBOARD */
128#define kgdboc_register_kbd(x) 0
129#define kgdboc_unregister_kbd()
130#define kgdboc_restore_input()
131#endif /* ! CONFIG_KDB_KEYBOARD */
132
133static int kgdboc_option_setup(char *opt)
134{
135	if (strlen(opt) >= MAX_CONFIG_LEN) {
136		printk(KERN_ERR "kgdboc: config string too long\n");
137		return -ENOSPC;
138	}
139	strcpy(config, opt);
140
141	return 0;
142}
143
144__setup("kgdboc=", kgdboc_option_setup);
145
146static void cleanup_kgdboc(void)
147{
148	kgdboc_unregister_kbd();
149	if (configured == 1)
150		kgdb_unregister_io_module(&kgdboc_io_ops);
151}
152
153static int configure_kgdboc(void)
154{
155	struct tty_driver *p;
156	int tty_line = 0;
157	int err;
158	char *cptr = config;
159	struct console *cons;
160
161	err = kgdboc_option_setup(config);
162	if (err || !strlen(config) || isspace(config[0]))
163		goto noconfig;
164
165	err = -ENODEV;
166	kgdboc_io_ops.is_console = 0;
167	kgdb_tty_driver = NULL;
168
169	kgdboc_use_kms = 0;
170	if (strncmp(cptr, "kms,", 4) == 0) {
171		cptr += 4;
172		kgdboc_use_kms = 1;
173	}
174
175	if (kgdboc_register_kbd(&cptr))
176		goto do_register;
177
178	p = tty_find_polling_driver(cptr, &tty_line);
179	if (!p)
180		goto noconfig;
181
182	cons = console_drivers;
183	while (cons) {
184		int idx;
185		if (cons->device && cons->device(cons, &idx) == p &&
186		    idx == tty_line) {
187			kgdboc_io_ops.is_console = 1;
188			break;
189		}
190		cons = cons->next;
191	}
192
193	kgdb_tty_driver = p;
194	kgdb_tty_line = tty_line;
195
196do_register:
197	err = kgdb_register_io_module(&kgdboc_io_ops);
198	if (err)
199		goto noconfig;
200
201	configured = 1;
202
203	return 0;
204
205noconfig:
206	config[0] = 0;
207	configured = 0;
208	cleanup_kgdboc();
209
210	return err;
211}
212
213static int __init init_kgdboc(void)
214{
215	/* Already configured? */
216	if (configured == 1)
217		return 0;
218
219	return configure_kgdboc();
220}
221
222static int kgdboc_get_char(void)
223{
224	if (!kgdb_tty_driver)
225		return -1;
226	return kgdb_tty_driver->ops->poll_get_char(kgdb_tty_driver,
227						kgdb_tty_line);
228}
229
230static void kgdboc_put_char(u8 chr)
231{
232	if (!kgdb_tty_driver)
233		return;
234	kgdb_tty_driver->ops->poll_put_char(kgdb_tty_driver,
235					kgdb_tty_line, chr);
236}
237
238static int param_set_kgdboc_var(const char *kmessage, struct kernel_param *kp)
239{
240	int len = strlen(kmessage);
241
242	if (len >= MAX_CONFIG_LEN) {
243		printk(KERN_ERR "kgdboc: config string too long\n");
244		return -ENOSPC;
245	}
246
247	/* Only copy in the string if the init function has not run yet */
248	if (configured < 0) {
249		strcpy(config, kmessage);
250		return 0;
251	}
252
253	if (kgdb_connected) {
254		printk(KERN_ERR
255		       "kgdboc: Cannot reconfigure while KGDB is connected.\n");
256
257		return -EBUSY;
258	}
259
260	strcpy(config, kmessage);
261	/* Chop out \n char as a result of echo */
262	if (config[len - 1] == '\n')
263		config[len - 1] = '\0';
264
265	if (configured == 1)
266		cleanup_kgdboc();
267
268	/* Go and configure with the new params. */
269	return configure_kgdboc();
270}
271
272static int dbg_restore_graphics;
273
274static void kgdboc_pre_exp_handler(void)
275{
276	if (!dbg_restore_graphics && kgdboc_use_kms) {
277		dbg_restore_graphics = 1;
278		con_debug_enter(vc_cons[fg_console].d);
279	}
280	/* Increment the module count when the debugger is active */
281	if (!kgdb_connected)
282		try_module_get(THIS_MODULE);
283}
284
285static void kgdboc_post_exp_handler(void)
286{
287	/* decrement the module count when the debugger detaches */
288	if (!kgdb_connected)
289		module_put(THIS_MODULE);
290	if (kgdboc_use_kms && dbg_restore_graphics) {
291		dbg_restore_graphics = 0;
292		con_debug_leave();
293	}
294	kgdboc_restore_input();
295}
296
297static struct kgdb_io kgdboc_io_ops = {
298	.name			= "kgdboc",
299	.read_char		= kgdboc_get_char,
300	.write_char		= kgdboc_put_char,
301	.pre_exception		= kgdboc_pre_exp_handler,
302	.post_exception		= kgdboc_post_exp_handler,
303};
304
305#ifdef CONFIG_KGDB_SERIAL_CONSOLE
306/* This is only available if kgdboc is a built in for early debugging */
307static int __init kgdboc_early_init(char *opt)
308{
309	/* save the first character of the config string because the
310	 * init routine can destroy it.
311	 */
312	char save_ch;
313
314	kgdboc_option_setup(opt);
315	save_ch = config[0];
316	init_kgdboc();
317	config[0] = save_ch;
318	return 0;
319}
320
321early_param("ekgdboc", kgdboc_early_init);
322#endif /* CONFIG_KGDB_SERIAL_CONSOLE */
323
324module_init(init_kgdboc);
325module_exit(cleanup_kgdboc);
326module_param_call(kgdboc, param_set_kgdboc_var, param_get_string, &kps, 0644);
327MODULE_PARM_DESC(kgdboc, "<serial_device>[,baud]");
328MODULE_DESCRIPTION("KGDB Console TTY Driver");
329MODULE_LICENSE("GPL");
330