1/* 2 * arch/v850/kernel/memcons.c -- Console I/O to a memory buffer 3 * 4 * Copyright (C) 2001,02 NEC Corporation 5 * Copyright (C) 2001,02 Miles Bader <miles@gnu.org> 6 * 7 * This file is subject to the terms and conditions of the GNU General 8 * Public License. See the file COPYING in the main directory of this 9 * archive for more details. 10 * 11 * Written by Miles Bader <miles@gnu.org> 12 */ 13 14#include <linux/kernel.h> 15#include <linux/console.h> 16#include <linux/tty.h> 17#include <linux/tty_driver.h> 18#include <linux/init.h> 19 20/* If this device is enabled, the linker map should define start and 21 end points for its buffer. */ 22extern char memcons_output[], memcons_output_end; 23 24/* Current offset into the buffer. */ 25static unsigned long memcons_offs = 0; 26 27/* Spinlock protecting memcons_offs. */ 28static DEFINE_SPINLOCK(memcons_lock); 29 30 31static size_t write (const char *buf, size_t len) 32{ 33 unsigned long flags; 34 char *point; 35 36 spin_lock_irqsave (memcons_lock, flags); 37 38 point = memcons_output + memcons_offs; 39 if (point + len >= &memcons_output_end) { 40 len = &memcons_output_end - point; 41 memcons_offs = 0; 42 } else 43 memcons_offs += len; 44 45 spin_unlock_irqrestore (memcons_lock, flags); 46 47 memcpy (point, buf, len); 48 49 return len; 50} 51 52 53/* Low-level console. */ 54 55static void memcons_write (struct console *co, const char *buf, unsigned len) 56{ 57 while (len > 0) 58 len -= write (buf, len); 59} 60 61static struct tty_driver *tty_driver; 62 63static struct tty_driver *memcons_device (struct console *co, int *index) 64{ 65 *index = co->index; 66 return tty_driver; 67} 68 69static struct console memcons = 70{ 71 .name = "memcons", 72 .write = memcons_write, 73 .device = memcons_device, 74 .flags = CON_PRINTBUFFER, 75 .index = -1, 76}; 77 78void memcons_setup (void) 79{ 80 register_console (&memcons); 81 printk (KERN_INFO "Console: static memory buffer (memcons)\n"); 82} 83 84/* Higher level TTY interface. */ 85 86int memcons_tty_open (struct tty_struct *tty, struct file *filp) 87{ 88 return 0; 89} 90 91int memcons_tty_write (struct tty_struct *tty, const unsigned char *buf, int len) 92{ 93 return write (buf, len); 94} 95 96int memcons_tty_write_room (struct tty_struct *tty) 97{ 98 return &memcons_output_end - (memcons_output + memcons_offs); 99} 100 101int memcons_tty_chars_in_buffer (struct tty_struct *tty) 102{ 103 /* We have no buffer. */ 104 return 0; 105} 106 107static const struct tty_operations ops = { 108 .open = memcons_tty_open, 109 .write = memcons_tty_write, 110 .write_room = memcons_tty_write_room, 111 .chars_in_buffer = memcons_tty_chars_in_buffer, 112}; 113 114int __init memcons_tty_init (void) 115{ 116 int err; 117 struct tty_driver *driver = alloc_tty_driver(1); 118 if (!driver) 119 return -ENOMEM; 120 121 driver->name = "memcons"; 122 driver->major = TTY_MAJOR; 123 driver->minor_start = 64; 124 driver->type = TTY_DRIVER_TYPE_SYSCONS; 125 driver->init_termios = tty_std_termios; 126 tty_set_operations(driver, &ops); 127 err = tty_register_driver(driver); 128 if (err) { 129 put_tty_driver(driver); 130 return err; 131 } 132 tty_driver = driver; 133 return 0; 134} 135__initcall (memcons_tty_init); 136