]>
Commit | Line | Data |
---|---|---|
1da177e4 LT |
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. */ | |
22 | extern char memcons_output[], memcons_output_end; | |
23 | ||
24 | /* Current offset into the buffer. */ | |
25 | static unsigned long memcons_offs = 0; | |
26 | ||
27 | /* Spinlock protecting memcons_offs. */ | |
28 | static DEFINE_SPINLOCK(memcons_lock); | |
29 | ||
30 | ||
31 | static size_t write (const char *buf, size_t len) | |
32 | { | |
c53421b1 | 33 | unsigned long flags; |
1da177e4 LT |
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 | \f | |
53 | /* Low-level console. */ | |
54 | ||
55 | static void memcons_write (struct console *co, const char *buf, unsigned len) | |
56 | { | |
57 | while (len > 0) | |
58 | len -= write (buf, len); | |
59 | } | |
60 | ||
61 | static struct tty_driver *tty_driver; | |
62 | ||
63 | static struct tty_driver *memcons_device (struct console *co, int *index) | |
64 | { | |
65 | *index = co->index; | |
66 | return tty_driver; | |
67 | } | |
68 | ||
69 | static struct console memcons = | |
70 | { | |
71 | .name = "memcons", | |
72 | .write = memcons_write, | |
73 | .device = memcons_device, | |
74 | .flags = CON_PRINTBUFFER, | |
75 | .index = -1, | |
76 | }; | |
77 | ||
78 | void memcons_setup (void) | |
79 | { | |
80 | register_console (&memcons); | |
81 | printk (KERN_INFO "Console: static memory buffer (memcons)\n"); | |
82 | } | |
83 | \f | |
84 | /* Higher level TTY interface. */ | |
85 | ||
86 | int memcons_tty_open (struct tty_struct *tty, struct file *filp) | |
87 | { | |
88 | return 0; | |
89 | } | |
90 | ||
91 | int memcons_tty_write (struct tty_struct *tty, const unsigned char *buf, int len) | |
92 | { | |
93 | return write (buf, len); | |
94 | } | |
95 | ||
96 | int memcons_tty_write_room (struct tty_struct *tty) | |
97 | { | |
98 | return &memcons_output_end - (memcons_output + memcons_offs); | |
99 | } | |
100 | ||
101 | int memcons_tty_chars_in_buffer (struct tty_struct *tty) | |
102 | { | |
103 | /* We have no buffer. */ | |
104 | return 0; | |
105 | } | |
106 | ||
b68e31d0 | 107 | static const struct tty_operations ops = { |
1da177e4 LT |
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 | ||
114 | int __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); |