Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/um/drivers/ssl.c
10817 views
1
/*
2
* Copyright (C) 2000, 2002 Jeff Dike ([email protected])
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
23
static 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
29
static struct tty_driver *ssl_driver;
30
31
#define NR_PORTS 64
32
33
static 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 */
40
static struct chan_opts opts = {
41
.announce = ssl_announce,
42
.xterm_title = "Serial Line #%d",
43
.raw = 1,
44
};
45
46
static int ssl_config(char *str, char **error_out);
47
static int ssl_get_config(char *dev, char *str, int size, char **error_out);
48
static int ssl_remove(int n, char **error_out);
49
50
51
/* Const, except for .mc.list */
52
static 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
*/
76
static struct line serial_lines[NR_PORTS] =
77
{ [0 ... NR_PORTS - 1] = LINE_INIT(CONFIG_SSL_CHAN, &driver) };
78
79
static 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
85
static 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
91
static 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
97
static 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
109
static void ssl_flush_buffer(struct tty_struct *tty)
110
{
111
return;
112
}
113
114
static void ssl_stop(struct tty_struct *tty)
115
{
116
printk(KERN_ERR "Someone should implement ssl_stop\n");
117
}
118
119
static void ssl_start(struct tty_struct *tty)
120
{
121
printk(KERN_ERR "Someone should implement ssl_start\n");
122
}
123
124
void ssl_hangup(struct tty_struct *tty)
125
{
126
}
127
#endif
128
129
static 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
*/
152
static int ssl_init_done = 0;
153
154
static 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
165
static struct tty_driver *ssl_console_device(struct console *c, int *index)
166
{
167
*index = c->index;
168
return ssl_driver;
169
}
170
171
static 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 */
179
static 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
188
static 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
}
207
late_initcall(ssl_init);
208
209
static 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
217
static 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
233