Logo Search packages:      
Sourcecode: linux version File versions  Download package

memcons.c

/*
 * arch/v850/kernel/memcons.c -- Console I/O to a memory buffer
 *
 *  Copyright (C) 2001,02  NEC Corporation
 *  Copyright (C) 2001,02  Miles Bader <miles@gnu.org>
 *
 * This file is subject to the terms and conditions of the GNU General
 * Public License.  See the file COPYING in the main directory of this
 * archive for more details.
 *
 * Written by Miles Bader <miles@gnu.org>
 */

#include <linux/kernel.h>
#include <linux/console.h>
#include <linux/tty.h>
#include <linux/tty_driver.h>
#include <linux/init.h>

/* If this device is enabled, the linker map should define start and
   end points for its buffer. */
extern char memcons_output[], memcons_output_end;

/* Current offset into the buffer.  */
static unsigned long memcons_offs = 0;

/* Spinlock protecting memcons_offs.  */
static DEFINE_SPINLOCK(memcons_lock);


static size_t write (const char *buf, size_t len)
{
      unsigned long flags;
      char *point;

      spin_lock_irqsave (memcons_lock, flags);

      point = memcons_output + memcons_offs;
      if (point + len >= &memcons_output_end) {
            len = &memcons_output_end - point;
            memcons_offs = 0;
      } else
            memcons_offs += len;

      spin_unlock_irqrestore (memcons_lock, flags);

      memcpy (point, buf, len);

      return len;
}


/*  Low-level console. */

static void memcons_write (struct console *co, const char *buf, unsigned len)
{
      while (len > 0)
            len -= write (buf, len);
}

static struct tty_driver *tty_driver;

static struct tty_driver *memcons_device (struct console *co, int *index)
{
      *index = co->index;
      return tty_driver;
}

static struct console memcons =
{
    .name   = "memcons",
    .write  = memcons_write,
    .device = memcons_device,
    .flags  = CON_PRINTBUFFER,
    .index  = -1,
};

void memcons_setup (void)
{
      register_console (&memcons);
      printk (KERN_INFO "Console: static memory buffer (memcons)\n");
}

/* Higher level TTY interface.  */

int memcons_tty_open (struct tty_struct *tty, struct file *filp)
{
      return 0;
}

int memcons_tty_write (struct tty_struct *tty, const unsigned char *buf, int len)
{
      return write (buf, len);
}

int memcons_tty_write_room (struct tty_struct *tty)
{
      return &memcons_output_end - (memcons_output + memcons_offs);
}

int memcons_tty_chars_in_buffer (struct tty_struct *tty)
{
      /* We have no buffer.  */
      return 0;
}

static const struct tty_operations ops = {
      .open = memcons_tty_open,
      .write = memcons_tty_write,
      .write_room = memcons_tty_write_room,
      .chars_in_buffer = memcons_tty_chars_in_buffer,
};

int __init memcons_tty_init (void)
{
      int err;
      struct tty_driver *driver = alloc_tty_driver(1);
      if (!driver)
            return -ENOMEM;

      driver->name = "memcons";
      driver->major = TTY_MAJOR;
      driver->minor_start = 64;
      driver->type = TTY_DRIVER_TYPE_SYSCONS;
      driver->init_termios = tty_std_termios;
      tty_set_operations(driver, &ops);
      err = tty_register_driver(driver);
      if (err) {
            put_tty_driver(driver);
            return err;
      }
      tty_driver = driver;
      return 0;
}
__initcall (memcons_tty_init);

Generated by  Doxygen 1.6.0   Back to index