diff options
Diffstat (limited to 'arch/um/drivers/stdio_console.c')
-rw-r--r-- | arch/um/drivers/stdio_console.c | 205 |
1 files changed, 205 insertions, 0 deletions
diff --git a/arch/um/drivers/stdio_console.c b/arch/um/drivers/stdio_console.c new file mode 100644 index 000000000000..e604d7c87695 --- /dev/null +++ b/arch/um/drivers/stdio_console.c | |||
@@ -0,0 +1,205 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com) | ||
3 | * Licensed under the GPL | ||
4 | */ | ||
5 | |||
6 | #include "linux/config.h" | ||
7 | #include "linux/posix_types.h" | ||
8 | #include "linux/tty.h" | ||
9 | #include "linux/tty_flip.h" | ||
10 | #include "linux/types.h" | ||
11 | #include "linux/major.h" | ||
12 | #include "linux/kdev_t.h" | ||
13 | #include "linux/console.h" | ||
14 | #include "linux/string.h" | ||
15 | #include "linux/sched.h" | ||
16 | #include "linux/list.h" | ||
17 | #include "linux/init.h" | ||
18 | #include "linux/interrupt.h" | ||
19 | #include "linux/slab.h" | ||
20 | #include "linux/hardirq.h" | ||
21 | #include "asm/current.h" | ||
22 | #include "asm/irq.h" | ||
23 | #include "stdio_console.h" | ||
24 | #include "line.h" | ||
25 | #include "chan_kern.h" | ||
26 | #include "user_util.h" | ||
27 | #include "kern_util.h" | ||
28 | #include "irq_user.h" | ||
29 | #include "mconsole_kern.h" | ||
30 | #include "init.h" | ||
31 | #include "2_5compat.h" | ||
32 | |||
33 | #define MAX_TTYS (16) | ||
34 | |||
35 | /* ----------------------------------------------------------------------------- */ | ||
36 | |||
37 | /* Referenced only by tty_driver below - presumably it's locked correctly | ||
38 | * by the tty driver. | ||
39 | */ | ||
40 | |||
41 | static struct tty_driver *console_driver; | ||
42 | |||
43 | void stdio_announce(char *dev_name, int dev) | ||
44 | { | ||
45 | printk(KERN_INFO "Virtual console %d assigned device '%s'\n", dev, | ||
46 | dev_name); | ||
47 | } | ||
48 | |||
49 | static struct chan_opts opts = { | ||
50 | .announce = stdio_announce, | ||
51 | .xterm_title = "Virtual Console #%d", | ||
52 | .raw = 1, | ||
53 | .tramp_stack = 0, | ||
54 | .in_kernel = 1, | ||
55 | }; | ||
56 | |||
57 | static int con_config(char *str); | ||
58 | static int con_get_config(char *dev, char *str, int size, char **error_out); | ||
59 | static int con_remove(char *str); | ||
60 | |||
61 | static struct line_driver driver = { | ||
62 | .name = "UML console", | ||
63 | .device_name = "tty", | ||
64 | .devfs_name = "vc/", | ||
65 | .major = TTY_MAJOR, | ||
66 | .minor_start = 0, | ||
67 | .type = TTY_DRIVER_TYPE_CONSOLE, | ||
68 | .subtype = SYSTEM_TYPE_CONSOLE, | ||
69 | .read_irq = CONSOLE_IRQ, | ||
70 | .read_irq_name = "console", | ||
71 | .write_irq = CONSOLE_WRITE_IRQ, | ||
72 | .write_irq_name = "console-write", | ||
73 | .symlink_from = "ttys", | ||
74 | .symlink_to = "vc", | ||
75 | .mc = { | ||
76 | .name = "con", | ||
77 | .config = con_config, | ||
78 | .get_config = con_get_config, | ||
79 | .remove = con_remove, | ||
80 | }, | ||
81 | }; | ||
82 | |||
83 | static struct lines console_lines = LINES_INIT(MAX_TTYS); | ||
84 | |||
85 | /* The array is initialized by line_init, which is an initcall. The | ||
86 | * individual elements are protected by individual semaphores. | ||
87 | */ | ||
88 | struct line vts[MAX_TTYS] = { LINE_INIT(CONFIG_CON_ZERO_CHAN, &driver), | ||
89 | [ 1 ... MAX_TTYS - 1 ] = | ||
90 | LINE_INIT(CONFIG_CON_CHAN, &driver) }; | ||
91 | |||
92 | static int con_config(char *str) | ||
93 | { | ||
94 | return(line_config(vts, sizeof(vts)/sizeof(vts[0]), str)); | ||
95 | } | ||
96 | |||
97 | static int con_get_config(char *dev, char *str, int size, char **error_out) | ||
98 | { | ||
99 | return(line_get_config(dev, vts, sizeof(vts)/sizeof(vts[0]), str, | ||
100 | size, error_out)); | ||
101 | } | ||
102 | |||
103 | static int con_remove(char *str) | ||
104 | { | ||
105 | return(line_remove(vts, sizeof(vts)/sizeof(vts[0]), str)); | ||
106 | } | ||
107 | |||
108 | static int con_open(struct tty_struct *tty, struct file *filp) | ||
109 | { | ||
110 | return line_open(vts, tty, &opts); | ||
111 | } | ||
112 | |||
113 | static int con_init_done = 0; | ||
114 | |||
115 | static struct tty_operations console_ops = { | ||
116 | .open = con_open, | ||
117 | .close = line_close, | ||
118 | .write = line_write, | ||
119 | .write_room = line_write_room, | ||
120 | .chars_in_buffer = line_chars_in_buffer, | ||
121 | .set_termios = line_set_termios, | ||
122 | .ioctl = line_ioctl, | ||
123 | }; | ||
124 | |||
125 | static void uml_console_write(struct console *console, const char *string, | ||
126 | unsigned len) | ||
127 | { | ||
128 | struct line *line = &vts[console->index]; | ||
129 | |||
130 | down(&line->sem); | ||
131 | console_write_chan(&line->chan_list, string, len); | ||
132 | up(&line->sem); | ||
133 | } | ||
134 | |||
135 | static struct tty_driver *uml_console_device(struct console *c, int *index) | ||
136 | { | ||
137 | *index = c->index; | ||
138 | return console_driver; | ||
139 | } | ||
140 | |||
141 | static int uml_console_setup(struct console *co, char *options) | ||
142 | { | ||
143 | struct line *line = &vts[co->index]; | ||
144 | |||
145 | return console_open_chan(line,co,&opts); | ||
146 | } | ||
147 | |||
148 | static struct console stdiocons = { | ||
149 | .name = "tty", | ||
150 | .write = uml_console_write, | ||
151 | .device = uml_console_device, | ||
152 | .setup = uml_console_setup, | ||
153 | .flags = CON_PRINTBUFFER, | ||
154 | .index = -1, | ||
155 | .data = &vts, | ||
156 | }; | ||
157 | |||
158 | int stdio_init(void) | ||
159 | { | ||
160 | char *new_title; | ||
161 | |||
162 | console_driver = line_register_devfs(&console_lines, &driver, | ||
163 | &console_ops, vts, | ||
164 | ARRAY_SIZE(vts)); | ||
165 | if (NULL == console_driver) | ||
166 | return -1; | ||
167 | printk(KERN_INFO "Initialized stdio console driver\n"); | ||
168 | |||
169 | lines_init(vts, sizeof(vts)/sizeof(vts[0])); | ||
170 | |||
171 | new_title = add_xterm_umid(opts.xterm_title); | ||
172 | if(new_title != NULL) | ||
173 | opts.xterm_title = new_title; | ||
174 | |||
175 | con_init_done = 1; | ||
176 | register_console(&stdiocons); | ||
177 | return(0); | ||
178 | } | ||
179 | late_initcall(stdio_init); | ||
180 | |||
181 | static void console_exit(void) | ||
182 | { | ||
183 | if (!con_init_done) | ||
184 | return; | ||
185 | close_lines(vts, sizeof(vts)/sizeof(vts[0])); | ||
186 | } | ||
187 | __uml_exitcall(console_exit); | ||
188 | |||
189 | static int console_chan_setup(char *str) | ||
190 | { | ||
191 | return(line_setup(vts, sizeof(vts)/sizeof(vts[0]), str, 1)); | ||
192 | } | ||
193 | __setup("con", console_chan_setup); | ||
194 | __channel_help(console_chan_setup, "con"); | ||
195 | |||
196 | /* | ||
197 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
198 | * Emacs will notice this stuff at the end of the file and automatically | ||
199 | * adjust the settings for this buffer only. This must remain at the end | ||
200 | * of the file. | ||
201 | * --------------------------------------------------------------------------- | ||
202 | * Local variables: | ||
203 | * c-file-style: "linux" | ||
204 | * End: | ||
205 | */ | ||