linux/drivers/serial/kgdboc.c
<<
>>
Prefs
   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/tty.h>
  18
  19#define MAX_CONFIG_LEN          40
  20
  21static struct kgdb_io           kgdboc_io_ops;
  22
  23/* -1 = init not run yet, 0 = unconfigured, 1 = configured. */
  24static int configured           = -1;
  25
  26static char config[MAX_CONFIG_LEN];
  27static struct kparam_string kps = {
  28        .string                 = config,
  29        .maxlen                 = MAX_CONFIG_LEN,
  30};
  31
  32static struct tty_driver        *kgdb_tty_driver;
  33static int                      kgdb_tty_line;
  34
  35static int kgdboc_option_setup(char *opt)
  36{
  37        if (strlen(opt) > MAX_CONFIG_LEN) {
  38                printk(KERN_ERR "kgdboc: config string too long\n");
  39                return -ENOSPC;
  40        }
  41        strcpy(config, opt);
  42
  43        return 0;
  44}
  45
  46__setup("kgdboc=", kgdboc_option_setup);
  47
  48static int configure_kgdboc(void)
  49{
  50        struct tty_driver *p;
  51        int tty_line = 0;
  52        int err;
  53
  54        err = kgdboc_option_setup(config);
  55        if (err || !strlen(config) || isspace(config[0]))
  56                goto noconfig;
  57
  58        err = -ENODEV;
  59
  60        p = tty_find_polling_driver(config, &tty_line);
  61        if (!p)
  62                goto noconfig;
  63
  64        kgdb_tty_driver = p;
  65        kgdb_tty_line = tty_line;
  66
  67        err = kgdb_register_io_module(&kgdboc_io_ops);
  68        if (err)
  69                goto noconfig;
  70
  71        configured = 1;
  72
  73        return 0;
  74
  75noconfig:
  76        config[0] = 0;
  77        configured = 0;
  78
  79        return err;
  80}
  81
  82static int __init init_kgdboc(void)
  83{
  84        /* Already configured? */
  85        if (configured == 1)
  86                return 0;
  87
  88        return configure_kgdboc();
  89}
  90
  91static void cleanup_kgdboc(void)
  92{
  93        if (configured == 1)
  94                kgdb_unregister_io_module(&kgdboc_io_ops);
  95}
  96
  97static int kgdboc_get_char(void)
  98{
  99        return kgdb_tty_driver->ops->poll_get_char(kgdb_tty_driver,
 100                                                kgdb_tty_line);
 101}
 102
 103static void kgdboc_put_char(u8 chr)
 104{
 105        kgdb_tty_driver->ops->poll_put_char(kgdb_tty_driver,
 106                                        kgdb_tty_line, chr);
 107}
 108
 109static int param_set_kgdboc_var(const char *kmessage, struct kernel_param *kp)
 110{
 111        int len = strlen(kmessage);
 112
 113        if (len >= MAX_CONFIG_LEN) {
 114                printk(KERN_ERR "kgdboc: config string too long\n");
 115                return -ENOSPC;
 116        }
 117
 118        /* Only copy in the string if the init function has not run yet */
 119        if (configured < 0) {
 120                strcpy(config, kmessage);
 121                return 0;
 122        }
 123
 124        if (kgdb_connected) {
 125                printk(KERN_ERR
 126                       "kgdboc: Cannot reconfigure while KGDB is connected.\n");
 127
 128                return -EBUSY;
 129        }
 130
 131        strcpy(config, kmessage);
 132        /* Chop out \n char as a result of echo */
 133        if (config[len - 1] == '\n')
 134                config[len - 1] = '\0';
 135
 136        if (configured == 1)
 137                cleanup_kgdboc();
 138
 139        /* Go and configure with the new params. */
 140        return configure_kgdboc();
 141}
 142
 143static void kgdboc_pre_exp_handler(void)
 144{
 145        /* Increment the module count when the debugger is active */
 146        if (!kgdb_connected)
 147                try_module_get(THIS_MODULE);
 148}
 149
 150static void kgdboc_post_exp_handler(void)
 151{
 152        /* decrement the module count when the debugger detaches */
 153        if (!kgdb_connected)
 154                module_put(THIS_MODULE);
 155}
 156
 157static struct kgdb_io kgdboc_io_ops = {
 158        .name                   = "kgdboc",
 159        .read_char              = kgdboc_get_char,
 160        .write_char             = kgdboc_put_char,
 161        .pre_exception          = kgdboc_pre_exp_handler,
 162        .post_exception         = kgdboc_post_exp_handler,
 163};
 164
 165module_init(init_kgdboc);
 166module_exit(cleanup_kgdboc);
 167module_param_call(kgdboc, param_set_kgdboc_var, param_get_string, &kps, 0644);
 168MODULE_PARM_DESC(kgdboc, "<serial_device>[,baud]");
 169MODULE_DESCRIPTION("KGDB Console TTY Driver");
 170MODULE_LICENSE("GPL");
 171