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