1f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel/* 2f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel * Based on the same principle as kgdboe using the NETPOLL api, this 3f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel * driver uses a console polling api to implement a gdb serial inteface 4f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel * which is multiplexed on a console port. 5f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel * 6f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel * Maintainer: Jason Wessel <jason.wessel@windriver.com> 7f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel * 8f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel * 2007-2008 (c) Jason Wessel - Wind River Systems, Inc. 9f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel * 10f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel * This file is licensed under the terms of the GNU General Public 11f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel * License version 2. This program is licensed "as is" without any 12f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel * warranty of any kind, whether express or implied. 13f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel */ 14f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel#include <linux/kernel.h> 15f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel#include <linux/ctype.h> 16f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel#include <linux/kgdb.h> 17ada64e4c98eb5f04a9ca223c5ff9e7ac22ce6404Jason Wessel#include <linux/kdb.h> 18f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel#include <linux/tty.h> 19efe2f29e324fd20e0449bcd6dc6dbe4734c2ba94Jason Wessel#include <linux/console.h> 20408a4be1f8cbee511895ee07da2a007a5a24303fJason Wessel#include <linux/vt_kern.h> 21111c182340cd22e238ab1cc6564df336c6ebd7cbDmitry Torokhov#include <linux/input.h> 22578b9ce0095ff3dd2c3b94508407c3be8fcce68dPaul Gortmaker#include <linux/module.h> 23f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel 24f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel#define MAX_CONFIG_LEN 40 25f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel 26f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wesselstatic struct kgdb_io kgdboc_io_ops; 27f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel 28f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel/* -1 = init not run yet, 0 = unconfigured, 1 = configured. */ 29f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wesselstatic int configured = -1; 30f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel 31f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wesselstatic char config[MAX_CONFIG_LEN]; 32f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wesselstatic struct kparam_string kps = { 33f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel .string = config, 34f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel .maxlen = MAX_CONFIG_LEN, 35f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel}; 36f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel 37408a4be1f8cbee511895ee07da2a007a5a24303fJason Wesselstatic int kgdboc_use_kms; /* 1 if we use kernel mode switching */ 38f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wesselstatic struct tty_driver *kgdb_tty_driver; 39f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wesselstatic int kgdb_tty_line; 40f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel 41ada64e4c98eb5f04a9ca223c5ff9e7ac22ce6404Jason Wessel#ifdef CONFIG_KDB_KEYBOARD 42111c182340cd22e238ab1cc6564df336c6ebd7cbDmitry Torokhovstatic int kgdboc_reset_connect(struct input_handler *handler, 43111c182340cd22e238ab1cc6564df336c6ebd7cbDmitry Torokhov struct input_dev *dev, 44111c182340cd22e238ab1cc6564df336c6ebd7cbDmitry Torokhov const struct input_device_id *id) 45111c182340cd22e238ab1cc6564df336c6ebd7cbDmitry Torokhov{ 46111c182340cd22e238ab1cc6564df336c6ebd7cbDmitry Torokhov input_reset_device(dev); 47111c182340cd22e238ab1cc6564df336c6ebd7cbDmitry Torokhov 48111c182340cd22e238ab1cc6564df336c6ebd7cbDmitry Torokhov /* Retrun an error - we do not want to bind, just to reset */ 49111c182340cd22e238ab1cc6564df336c6ebd7cbDmitry Torokhov return -ENODEV; 50111c182340cd22e238ab1cc6564df336c6ebd7cbDmitry Torokhov} 51111c182340cd22e238ab1cc6564df336c6ebd7cbDmitry Torokhov 52111c182340cd22e238ab1cc6564df336c6ebd7cbDmitry Torokhovstatic void kgdboc_reset_disconnect(struct input_handle *handle) 53111c182340cd22e238ab1cc6564df336c6ebd7cbDmitry Torokhov{ 54111c182340cd22e238ab1cc6564df336c6ebd7cbDmitry Torokhov /* We do not expect anyone to actually bind to us */ 55111c182340cd22e238ab1cc6564df336c6ebd7cbDmitry Torokhov BUG(); 56111c182340cd22e238ab1cc6564df336c6ebd7cbDmitry Torokhov} 57111c182340cd22e238ab1cc6564df336c6ebd7cbDmitry Torokhov 58111c182340cd22e238ab1cc6564df336c6ebd7cbDmitry Torokhovstatic const struct input_device_id kgdboc_reset_ids[] = { 59111c182340cd22e238ab1cc6564df336c6ebd7cbDmitry Torokhov { 60111c182340cd22e238ab1cc6564df336c6ebd7cbDmitry Torokhov .flags = INPUT_DEVICE_ID_MATCH_EVBIT, 61111c182340cd22e238ab1cc6564df336c6ebd7cbDmitry Torokhov .evbit = { BIT_MASK(EV_KEY) }, 62111c182340cd22e238ab1cc6564df336c6ebd7cbDmitry Torokhov }, 63111c182340cd22e238ab1cc6564df336c6ebd7cbDmitry Torokhov { } 64111c182340cd22e238ab1cc6564df336c6ebd7cbDmitry Torokhov}; 65111c182340cd22e238ab1cc6564df336c6ebd7cbDmitry Torokhov 66111c182340cd22e238ab1cc6564df336c6ebd7cbDmitry Torokhovstatic struct input_handler kgdboc_reset_handler = { 67111c182340cd22e238ab1cc6564df336c6ebd7cbDmitry Torokhov .connect = kgdboc_reset_connect, 68111c182340cd22e238ab1cc6564df336c6ebd7cbDmitry Torokhov .disconnect = kgdboc_reset_disconnect, 69111c182340cd22e238ab1cc6564df336c6ebd7cbDmitry Torokhov .name = "kgdboc_reset", 70111c182340cd22e238ab1cc6564df336c6ebd7cbDmitry Torokhov .id_table = kgdboc_reset_ids, 71111c182340cd22e238ab1cc6564df336c6ebd7cbDmitry Torokhov}; 72111c182340cd22e238ab1cc6564df336c6ebd7cbDmitry Torokhov 73111c182340cd22e238ab1cc6564df336c6ebd7cbDmitry Torokhovstatic DEFINE_MUTEX(kgdboc_reset_mutex); 74111c182340cd22e238ab1cc6564df336c6ebd7cbDmitry Torokhov 75111c182340cd22e238ab1cc6564df336c6ebd7cbDmitry Torokhovstatic void kgdboc_restore_input_helper(struct work_struct *dummy) 76111c182340cd22e238ab1cc6564df336c6ebd7cbDmitry Torokhov{ 77111c182340cd22e238ab1cc6564df336c6ebd7cbDmitry Torokhov /* 78111c182340cd22e238ab1cc6564df336c6ebd7cbDmitry Torokhov * We need to take a mutex to prevent several instances of 79111c182340cd22e238ab1cc6564df336c6ebd7cbDmitry Torokhov * this work running on different CPUs so they don't try 80111c182340cd22e238ab1cc6564df336c6ebd7cbDmitry Torokhov * to register again already registered handler. 81111c182340cd22e238ab1cc6564df336c6ebd7cbDmitry Torokhov */ 82111c182340cd22e238ab1cc6564df336c6ebd7cbDmitry Torokhov mutex_lock(&kgdboc_reset_mutex); 83111c182340cd22e238ab1cc6564df336c6ebd7cbDmitry Torokhov 84111c182340cd22e238ab1cc6564df336c6ebd7cbDmitry Torokhov if (input_register_handler(&kgdboc_reset_handler) == 0) 85111c182340cd22e238ab1cc6564df336c6ebd7cbDmitry Torokhov input_unregister_handler(&kgdboc_reset_handler); 86111c182340cd22e238ab1cc6564df336c6ebd7cbDmitry Torokhov 87111c182340cd22e238ab1cc6564df336c6ebd7cbDmitry Torokhov mutex_unlock(&kgdboc_reset_mutex); 88111c182340cd22e238ab1cc6564df336c6ebd7cbDmitry Torokhov} 89111c182340cd22e238ab1cc6564df336c6ebd7cbDmitry Torokhov 90111c182340cd22e238ab1cc6564df336c6ebd7cbDmitry Torokhovstatic DECLARE_WORK(kgdboc_restore_input_work, kgdboc_restore_input_helper); 91111c182340cd22e238ab1cc6564df336c6ebd7cbDmitry Torokhov 92111c182340cd22e238ab1cc6564df336c6ebd7cbDmitry Torokhovstatic void kgdboc_restore_input(void) 93111c182340cd22e238ab1cc6564df336c6ebd7cbDmitry Torokhov{ 948863ada9c47503bb93eba5e3a9ba88e6311db31fJason Wessel if (likely(system_state == SYSTEM_RUNNING)) 958863ada9c47503bb93eba5e3a9ba88e6311db31fJason Wessel schedule_work(&kgdboc_restore_input_work); 96111c182340cd22e238ab1cc6564df336c6ebd7cbDmitry Torokhov} 97111c182340cd22e238ab1cc6564df336c6ebd7cbDmitry Torokhov 98ada64e4c98eb5f04a9ca223c5ff9e7ac22ce6404Jason Wesselstatic int kgdboc_register_kbd(char **cptr) 99ada64e4c98eb5f04a9ca223c5ff9e7ac22ce6404Jason Wessel{ 100ada64e4c98eb5f04a9ca223c5ff9e7ac22ce6404Jason Wessel if (strncmp(*cptr, "kbd", 3) == 0) { 101ada64e4c98eb5f04a9ca223c5ff9e7ac22ce6404Jason Wessel if (kdb_poll_idx < KDB_POLL_FUNC_MAX) { 102ada64e4c98eb5f04a9ca223c5ff9e7ac22ce6404Jason Wessel kdb_poll_funcs[kdb_poll_idx] = kdb_get_kbd_char; 103ada64e4c98eb5f04a9ca223c5ff9e7ac22ce6404Jason Wessel kdb_poll_idx++; 104ada64e4c98eb5f04a9ca223c5ff9e7ac22ce6404Jason Wessel if (cptr[0][3] == ',') 105ada64e4c98eb5f04a9ca223c5ff9e7ac22ce6404Jason Wessel *cptr += 4; 106ada64e4c98eb5f04a9ca223c5ff9e7ac22ce6404Jason Wessel else 107ada64e4c98eb5f04a9ca223c5ff9e7ac22ce6404Jason Wessel return 1; 108ada64e4c98eb5f04a9ca223c5ff9e7ac22ce6404Jason Wessel } 109ada64e4c98eb5f04a9ca223c5ff9e7ac22ce6404Jason Wessel } 110ada64e4c98eb5f04a9ca223c5ff9e7ac22ce6404Jason Wessel return 0; 111ada64e4c98eb5f04a9ca223c5ff9e7ac22ce6404Jason Wessel} 112ada64e4c98eb5f04a9ca223c5ff9e7ac22ce6404Jason Wessel 113ada64e4c98eb5f04a9ca223c5ff9e7ac22ce6404Jason Wesselstatic void kgdboc_unregister_kbd(void) 114ada64e4c98eb5f04a9ca223c5ff9e7ac22ce6404Jason Wessel{ 115ada64e4c98eb5f04a9ca223c5ff9e7ac22ce6404Jason Wessel int i; 116ada64e4c98eb5f04a9ca223c5ff9e7ac22ce6404Jason Wessel 117ada64e4c98eb5f04a9ca223c5ff9e7ac22ce6404Jason Wessel for (i = 0; i < kdb_poll_idx; i++) { 118ada64e4c98eb5f04a9ca223c5ff9e7ac22ce6404Jason Wessel if (kdb_poll_funcs[i] == kdb_get_kbd_char) { 119ada64e4c98eb5f04a9ca223c5ff9e7ac22ce6404Jason Wessel kdb_poll_idx--; 120ada64e4c98eb5f04a9ca223c5ff9e7ac22ce6404Jason Wessel kdb_poll_funcs[i] = kdb_poll_funcs[kdb_poll_idx]; 121ada64e4c98eb5f04a9ca223c5ff9e7ac22ce6404Jason Wessel kdb_poll_funcs[kdb_poll_idx] = NULL; 122ada64e4c98eb5f04a9ca223c5ff9e7ac22ce6404Jason Wessel i--; 123ada64e4c98eb5f04a9ca223c5ff9e7ac22ce6404Jason Wessel } 124ada64e4c98eb5f04a9ca223c5ff9e7ac22ce6404Jason Wessel } 125111c182340cd22e238ab1cc6564df336c6ebd7cbDmitry Torokhov flush_work_sync(&kgdboc_restore_input_work); 126ada64e4c98eb5f04a9ca223c5ff9e7ac22ce6404Jason Wessel} 127ada64e4c98eb5f04a9ca223c5ff9e7ac22ce6404Jason Wessel#else /* ! CONFIG_KDB_KEYBOARD */ 128ada64e4c98eb5f04a9ca223c5ff9e7ac22ce6404Jason Wessel#define kgdboc_register_kbd(x) 0 129ada64e4c98eb5f04a9ca223c5ff9e7ac22ce6404Jason Wessel#define kgdboc_unregister_kbd() 130111c182340cd22e238ab1cc6564df336c6ebd7cbDmitry Torokhov#define kgdboc_restore_input() 131ada64e4c98eb5f04a9ca223c5ff9e7ac22ce6404Jason Wessel#endif /* ! CONFIG_KDB_KEYBOARD */ 132ada64e4c98eb5f04a9ca223c5ff9e7ac22ce6404Jason Wessel 133f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wesselstatic int kgdboc_option_setup(char *opt) 134f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel{ 135adb4b83c12f9d966ea3478aa14c60511467c9916Dan Carpenter if (strlen(opt) >= MAX_CONFIG_LEN) { 136f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel printk(KERN_ERR "kgdboc: config string too long\n"); 137f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel return -ENOSPC; 138f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel } 139f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel strcpy(config, opt); 140f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel 141f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel return 0; 142f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel} 143f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel 144f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel__setup("kgdboc=", kgdboc_option_setup); 145f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel 146ada64e4c98eb5f04a9ca223c5ff9e7ac22ce6404Jason Wesselstatic void cleanup_kgdboc(void) 147ada64e4c98eb5f04a9ca223c5ff9e7ac22ce6404Jason Wessel{ 148ada64e4c98eb5f04a9ca223c5ff9e7ac22ce6404Jason Wessel kgdboc_unregister_kbd(); 149ada64e4c98eb5f04a9ca223c5ff9e7ac22ce6404Jason Wessel if (configured == 1) 150ada64e4c98eb5f04a9ca223c5ff9e7ac22ce6404Jason Wessel kgdb_unregister_io_module(&kgdboc_io_ops); 151ada64e4c98eb5f04a9ca223c5ff9e7ac22ce6404Jason Wessel} 152ada64e4c98eb5f04a9ca223c5ff9e7ac22ce6404Jason Wessel 153f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wesselstatic int configure_kgdboc(void) 154f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel{ 155f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel struct tty_driver *p; 156f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel int tty_line = 0; 157f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel int err; 158ada64e4c98eb5f04a9ca223c5ff9e7ac22ce6404Jason Wessel char *cptr = config; 159efe2f29e324fd20e0449bcd6dc6dbe4734c2ba94Jason Wessel struct console *cons; 160f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel 161f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel err = kgdboc_option_setup(config); 162f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel if (err || !strlen(config) || isspace(config[0])) 163f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel goto noconfig; 164f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel 165f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel err = -ENODEV; 166efe2f29e324fd20e0449bcd6dc6dbe4734c2ba94Jason Wessel kgdboc_io_ops.is_console = 0; 167ada64e4c98eb5f04a9ca223c5ff9e7ac22ce6404Jason Wessel kgdb_tty_driver = NULL; 168ada64e4c98eb5f04a9ca223c5ff9e7ac22ce6404Jason Wessel 169408a4be1f8cbee511895ee07da2a007a5a24303fJason Wessel kgdboc_use_kms = 0; 170408a4be1f8cbee511895ee07da2a007a5a24303fJason Wessel if (strncmp(cptr, "kms,", 4) == 0) { 171408a4be1f8cbee511895ee07da2a007a5a24303fJason Wessel cptr += 4; 172408a4be1f8cbee511895ee07da2a007a5a24303fJason Wessel kgdboc_use_kms = 1; 173408a4be1f8cbee511895ee07da2a007a5a24303fJason Wessel } 174408a4be1f8cbee511895ee07da2a007a5a24303fJason Wessel 175ada64e4c98eb5f04a9ca223c5ff9e7ac22ce6404Jason Wessel if (kgdboc_register_kbd(&cptr)) 176ada64e4c98eb5f04a9ca223c5ff9e7ac22ce6404Jason Wessel goto do_register; 177f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel 178ada64e4c98eb5f04a9ca223c5ff9e7ac22ce6404Jason Wessel p = tty_find_polling_driver(cptr, &tty_line); 179f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel if (!p) 180f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel goto noconfig; 181f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel 182efe2f29e324fd20e0449bcd6dc6dbe4734c2ba94Jason Wessel cons = console_drivers; 183efe2f29e324fd20e0449bcd6dc6dbe4734c2ba94Jason Wessel while (cons) { 184efe2f29e324fd20e0449bcd6dc6dbe4734c2ba94Jason Wessel int idx; 185efe2f29e324fd20e0449bcd6dc6dbe4734c2ba94Jason Wessel if (cons->device && cons->device(cons, &idx) == p && 186efe2f29e324fd20e0449bcd6dc6dbe4734c2ba94Jason Wessel idx == tty_line) { 187efe2f29e324fd20e0449bcd6dc6dbe4734c2ba94Jason Wessel kgdboc_io_ops.is_console = 1; 188efe2f29e324fd20e0449bcd6dc6dbe4734c2ba94Jason Wessel break; 189efe2f29e324fd20e0449bcd6dc6dbe4734c2ba94Jason Wessel } 190efe2f29e324fd20e0449bcd6dc6dbe4734c2ba94Jason Wessel cons = cons->next; 191efe2f29e324fd20e0449bcd6dc6dbe4734c2ba94Jason Wessel } 192efe2f29e324fd20e0449bcd6dc6dbe4734c2ba94Jason Wessel 193f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel kgdb_tty_driver = p; 194f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel kgdb_tty_line = tty_line; 195f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel 196ada64e4c98eb5f04a9ca223c5ff9e7ac22ce6404Jason Wesseldo_register: 197f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel err = kgdb_register_io_module(&kgdboc_io_ops); 198f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel if (err) 199f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel goto noconfig; 200f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel 201f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel configured = 1; 202f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel 203f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel return 0; 204f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel 205f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wesselnoconfig: 206f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel config[0] = 0; 207f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel configured = 0; 208ada64e4c98eb5f04a9ca223c5ff9e7ac22ce6404Jason Wessel cleanup_kgdboc(); 209f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel 210f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel return err; 211f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel} 212f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel 213f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wesselstatic int __init init_kgdboc(void) 214f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel{ 215f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel /* Already configured? */ 216f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel if (configured == 1) 217f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel return 0; 218f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel 219f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel return configure_kgdboc(); 220f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel} 221f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel 222f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wesselstatic int kgdboc_get_char(void) 223f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel{ 224ada64e4c98eb5f04a9ca223c5ff9e7ac22ce6404Jason Wessel if (!kgdb_tty_driver) 225ada64e4c98eb5f04a9ca223c5ff9e7ac22ce6404Jason Wessel return -1; 226f34d7a5b7010b82fe97da95496b9971435530062Alan Cox return kgdb_tty_driver->ops->poll_get_char(kgdb_tty_driver, 227f34d7a5b7010b82fe97da95496b9971435530062Alan Cox kgdb_tty_line); 228f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel} 229f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel 230f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wesselstatic void kgdboc_put_char(u8 chr) 231f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel{ 232ada64e4c98eb5f04a9ca223c5ff9e7ac22ce6404Jason Wessel if (!kgdb_tty_driver) 233ada64e4c98eb5f04a9ca223c5ff9e7ac22ce6404Jason Wessel return; 234f34d7a5b7010b82fe97da95496b9971435530062Alan Cox kgdb_tty_driver->ops->poll_put_char(kgdb_tty_driver, 235f34d7a5b7010b82fe97da95496b9971435530062Alan Cox kgdb_tty_line, chr); 236f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel} 237f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel 238f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wesselstatic int param_set_kgdboc_var(const char *kmessage, struct kernel_param *kp) 239f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel{ 240c191e5ad6b3fd8cc84b2b6d62c02fcd6837c8a8fJason Wessel int len = strlen(kmessage); 241c191e5ad6b3fd8cc84b2b6d62c02fcd6837c8a8fJason Wessel 242c191e5ad6b3fd8cc84b2b6d62c02fcd6837c8a8fJason Wessel if (len >= MAX_CONFIG_LEN) { 243f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel printk(KERN_ERR "kgdboc: config string too long\n"); 244f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel return -ENOSPC; 245f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel } 246f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel 247f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel /* Only copy in the string if the init function has not run yet */ 248f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel if (configured < 0) { 249f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel strcpy(config, kmessage); 250f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel return 0; 251f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel } 252f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel 253f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel if (kgdb_connected) { 254f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel printk(KERN_ERR 255f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel "kgdboc: Cannot reconfigure while KGDB is connected.\n"); 256f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel 257f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel return -EBUSY; 258f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel } 259f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel 260f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel strcpy(config, kmessage); 261c191e5ad6b3fd8cc84b2b6d62c02fcd6837c8a8fJason Wessel /* Chop out \n char as a result of echo */ 262c191e5ad6b3fd8cc84b2b6d62c02fcd6837c8a8fJason Wessel if (config[len - 1] == '\n') 263c191e5ad6b3fd8cc84b2b6d62c02fcd6837c8a8fJason Wessel config[len - 1] = '\0'; 264f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel 265f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel if (configured == 1) 266f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel cleanup_kgdboc(); 267f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel 268f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel /* Go and configure with the new params. */ 269f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel return configure_kgdboc(); 270f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel} 271f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel 272408a4be1f8cbee511895ee07da2a007a5a24303fJason Wesselstatic int dbg_restore_graphics; 273408a4be1f8cbee511895ee07da2a007a5a24303fJason Wessel 274f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wesselstatic void kgdboc_pre_exp_handler(void) 275f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel{ 276408a4be1f8cbee511895ee07da2a007a5a24303fJason Wessel if (!dbg_restore_graphics && kgdboc_use_kms) { 277408a4be1f8cbee511895ee07da2a007a5a24303fJason Wessel dbg_restore_graphics = 1; 278408a4be1f8cbee511895ee07da2a007a5a24303fJason Wessel con_debug_enter(vc_cons[fg_console].d); 279408a4be1f8cbee511895ee07da2a007a5a24303fJason Wessel } 280f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel /* Increment the module count when the debugger is active */ 281f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel if (!kgdb_connected) 282f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel try_module_get(THIS_MODULE); 283f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel} 284f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel 285f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wesselstatic void kgdboc_post_exp_handler(void) 286f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel{ 287f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel /* decrement the module count when the debugger detaches */ 288f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel if (!kgdb_connected) 289f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel module_put(THIS_MODULE); 290408a4be1f8cbee511895ee07da2a007a5a24303fJason Wessel if (kgdboc_use_kms && dbg_restore_graphics) { 291408a4be1f8cbee511895ee07da2a007a5a24303fJason Wessel dbg_restore_graphics = 0; 292408a4be1f8cbee511895ee07da2a007a5a24303fJason Wessel con_debug_leave(); 293408a4be1f8cbee511895ee07da2a007a5a24303fJason Wessel } 294111c182340cd22e238ab1cc6564df336c6ebd7cbDmitry Torokhov kgdboc_restore_input(); 295f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel} 296f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel 297f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wesselstatic struct kgdb_io kgdboc_io_ops = { 298f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel .name = "kgdboc", 299f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel .read_char = kgdboc_get_char, 300f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel .write_char = kgdboc_put_char, 301f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel .pre_exception = kgdboc_pre_exp_handler, 302f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel .post_exception = kgdboc_post_exp_handler, 303f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel}; 304f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wessel 3059731191f75a54c4fa17e9b9b88f3144cf4b47836Jason Wessel#ifdef CONFIG_KGDB_SERIAL_CONSOLE 3069731191f75a54c4fa17e9b9b88f3144cf4b47836Jason Wessel/* This is only available if kgdboc is a built in for early debugging */ 30791b152aa85bbcf076e269565394c31964f940371Jason Wesselstatic int __init kgdboc_early_init(char *opt) 3089731191f75a54c4fa17e9b9b88f3144cf4b47836Jason Wessel{ 3099731191f75a54c4fa17e9b9b88f3144cf4b47836Jason Wessel /* save the first character of the config string because the 3109731191f75a54c4fa17e9b9b88f3144cf4b47836Jason Wessel * init routine can destroy it. 3119731191f75a54c4fa17e9b9b88f3144cf4b47836Jason Wessel */ 3129731191f75a54c4fa17e9b9b88f3144cf4b47836Jason Wessel char save_ch; 3139731191f75a54c4fa17e9b9b88f3144cf4b47836Jason Wessel 3149731191f75a54c4fa17e9b9b88f3144cf4b47836Jason Wessel kgdboc_option_setup(opt); 3159731191f75a54c4fa17e9b9b88f3144cf4b47836Jason Wessel save_ch = config[0]; 3169731191f75a54c4fa17e9b9b88f3144cf4b47836Jason Wessel init_kgdboc(); 3179731191f75a54c4fa17e9b9b88f3144cf4b47836Jason Wessel config[0] = save_ch; 3189731191f75a54c4fa17e9b9b88f3144cf4b47836Jason Wessel return 0; 3199731191f75a54c4fa17e9b9b88f3144cf4b47836Jason Wessel} 3209731191f75a54c4fa17e9b9b88f3144cf4b47836Jason Wessel 3219731191f75a54c4fa17e9b9b88f3144cf4b47836Jason Wesselearly_param("ekgdboc", kgdboc_early_init); 3229731191f75a54c4fa17e9b9b88f3144cf4b47836Jason Wessel#endif /* CONFIG_KGDB_SERIAL_CONSOLE */ 3239731191f75a54c4fa17e9b9b88f3144cf4b47836Jason Wessel 324f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wesselmodule_init(init_kgdboc); 325f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wesselmodule_exit(cleanup_kgdboc); 326f2d937f3bf00665ccf048b3b6616ef95859b0945Jason Wesselmodule_param_call(kgdboc, param_set_kgdboc_var, param_get_string, &kps, 0644); 327f2d937f3bf00665ccf048b3b6616ef95859b0945Jason WesselMODULE_PARM_DESC(kgdboc, "<serial_device>[,baud]"); 328f2d937f3bf00665ccf048b3b6616ef95859b0945Jason WesselMODULE_DESCRIPTION("KGDB Console TTY Driver"); 329f2d937f3bf00665ccf048b3b6616ef95859b0945Jason WesselMODULE_LICENSE("GPL"); 330