linux/arch/um/drivers/ssl.c
<<
>>
Prefs
   1/* 
   2 * Copyright (C) 2000, 2002 Jeff Dike (jdike@karaya.com)
   3 * Licensed under the GPL
   4 */
   5
   6#include "linux/fs.h"
   7#include "linux/tty.h"
   8#include "linux/tty_driver.h"
   9#include "linux/major.h"
  10#include "linux/mm.h"
  11#include "linux/init.h"
  12#include "linux/console.h"
  13#include "asm/termbits.h"
  14#include "asm/irq.h"
  15#include "line.h"
  16#include "ssl.h"
  17#include "chan_kern.h"
  18#include "kern.h"
  19#include "init.h"
  20#include "irq_user.h"
  21#include "mconsole_kern.h"
  22
  23static const int ssl_version = 1;
  24
  25/* Referenced only by tty_driver below - presumably it's locked correctly
  26 * by the tty driver.
  27 */
  28
  29static struct tty_driver *ssl_driver;
  30
  31#define NR_PORTS 64
  32
  33static void ssl_announce(char *dev_name, int dev)
  34{
  35        printk(KERN_INFO "Serial line %d assigned device '%s'\n", dev,
  36               dev_name);
  37}
  38
  39/* Almost const, except that xterm_title may be changed in an initcall */
  40static struct chan_opts opts = {
  41        .announce       = ssl_announce,
  42        .xterm_title    = "Serial Line #%d",
  43        .raw            = 1,
  44};
  45
  46static int ssl_config(char *str, char **error_out);
  47static int ssl_get_config(char *dev, char *str, int size, char **error_out);
  48static int ssl_remove(int n, char **error_out);
  49
  50
  51/* Const, except for .mc.list */
  52static struct line_driver driver = {
  53        .name                   = "UML serial line",
  54        .device_name            = "ttyS",
  55        .major                  = TTY_MAJOR,
  56        .minor_start            = 64,
  57        .type                   = TTY_DRIVER_TYPE_SERIAL,
  58        .subtype                = 0,
  59        .read_irq               = SSL_IRQ,
  60        .read_irq_name          = "ssl",
  61        .write_irq              = SSL_WRITE_IRQ,
  62        .write_irq_name         = "ssl-write",
  63        .mc  = {
  64                .list           = LIST_HEAD_INIT(driver.mc.list),
  65                .name           = "ssl",
  66                .config         = ssl_config,
  67                .get_config     = ssl_get_config,
  68                .id             = line_id,
  69                .remove         = ssl_remove,
  70        },
  71};
  72
  73/* The array is initialized by line_init, at initcall time.  The
  74 * elements are locked individually as needed.
  75 */
  76static struct line serial_lines[NR_PORTS] =
  77        { [0 ... NR_PORTS - 1] = LINE_INIT(CONFIG_SSL_CHAN, &driver) };
  78
  79static int ssl_config(char *str, char **error_out)
  80{
  81        return line_config(serial_lines, ARRAY_SIZE(serial_lines), str, &opts,
  82                           error_out);
  83}
  84
  85static int ssl_get_config(char *dev, char *str, int size, char **error_out)
  86{
  87        return line_get_config(dev, serial_lines, ARRAY_SIZE(serial_lines), str,
  88                               size, error_out);
  89}
  90
  91static int ssl_remove(int n, char **error_out)
  92{
  93        return line_remove(serial_lines, ARRAY_SIZE(serial_lines), n,
  94                           error_out);
  95}
  96
  97static int ssl_open(struct tty_struct *tty, struct file *filp)
  98{
  99        int err = line_open(serial_lines, tty);
 100
 101        if (err)
 102                printk(KERN_ERR "Failed to open serial line %d, err = %d\n",
 103                       tty->index, err);
 104
 105        return err;
 106}
 107
 108#if 0
 109static void ssl_flush_buffer(struct tty_struct *tty)
 110{
 111        return;
 112}
 113
 114static void ssl_stop(struct tty_struct *tty)
 115{
 116        printk(KERN_ERR "Someone should implement ssl_stop\n");
 117}
 118
 119static void ssl_start(struct tty_struct *tty)
 120{
 121        printk(KERN_ERR "Someone should implement ssl_start\n");
 122}
 123
 124void ssl_hangup(struct tty_struct *tty)
 125{
 126}
 127#endif
 128
 129static const struct tty_operations ssl_ops = {
 130        .open                   = ssl_open,
 131        .close                  = line_close,
 132        .write                  = line_write,
 133        .put_char               = line_put_char,
 134        .write_room             = line_write_room,
 135        .chars_in_buffer        = line_chars_in_buffer,
 136        .flush_buffer           = line_flush_buffer,
 137        .flush_chars            = line_flush_chars,
 138        .set_termios            = line_set_termios,
 139        .ioctl                  = line_ioctl,
 140        .throttle               = line_throttle,
 141        .unthrottle             = line_unthrottle,
 142#if 0
 143        .stop                   = ssl_stop,
 144        .start                  = ssl_start,
 145        .hangup                 = ssl_hangup,
 146#endif
 147};
 148
 149/* Changed by ssl_init and referenced by ssl_exit, which are both serialized
 150 * by being an initcall and exitcall, respectively.
 151 */
 152static int ssl_init_done = 0;
 153
 154static void ssl_console_write(struct console *c, const char *string,
 155                              unsigned len)
 156{
 157        struct line *line = &serial_lines[c->index];
 158        unsigned long flags;
 159
 160        spin_lock_irqsave(&line->lock, flags);
 161        console_write_chan(&line->chan_list, string, len);
 162        spin_unlock_irqrestore(&line->lock, flags);
 163}
 164
 165static struct tty_driver *ssl_console_device(struct console *c, int *index)
 166{
 167        *index = c->index;
 168        return ssl_driver;
 169}
 170
 171static int ssl_console_setup(struct console *co, char *options)
 172{
 173        struct line *line = &serial_lines[co->index];
 174
 175        return console_open_chan(line, co);
 176}
 177
 178/* No locking for register_console call - relies on single-threaded initcalls */
 179static struct console ssl_cons = {
 180        .name           = "ttyS",
 181        .write          = ssl_console_write,
 182        .device         = ssl_console_device,
 183        .setup          = ssl_console_setup,
 184        .flags          = CON_PRINTBUFFER|CON_ANYTIME,
 185        .index          = -1,
 186};
 187
 188static int ssl_init(void)
 189{
 190        char *new_title;
 191
 192        printk(KERN_INFO "Initializing software serial port version %d\n",
 193               ssl_version);
 194        ssl_driver = register_lines(&driver, &ssl_ops, serial_lines,
 195                                    ARRAY_SIZE(serial_lines));
 196
 197        new_title = add_xterm_umid(opts.xterm_title);
 198        if (new_title != NULL)
 199                opts.xterm_title = new_title;
 200
 201        lines_init(serial_lines, ARRAY_SIZE(serial_lines), &opts);
 202
 203        ssl_init_done = 1;
 204        register_console(&ssl_cons);
 205        return 0;
 206}
 207late_initcall(ssl_init);
 208
 209static void ssl_exit(void)
 210{
 211        if (!ssl_init_done)
 212                return;
 213        close_lines(serial_lines, ARRAY_SIZE(serial_lines));
 214}
 215__uml_exitcall(ssl_exit);
 216
 217static int ssl_chan_setup(char *str)
 218{
 219        char *error;
 220        int ret;
 221
 222        ret = line_setup(serial_lines, ARRAY_SIZE(serial_lines), str, &error);
 223        if(ret < 0)
 224                printk(KERN_ERR "Failed to set up serial line with "
 225                       "configuration string \"%s\" : %s\n", str, error);
 226
 227        return 1;
 228}
 229
 230__setup("ssl", ssl_chan_setup);
 231__channel_help(ssl_chan_setup, "ssl");
 232