2 * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
6 #include <linux/stddef.h>
7 #include <linux/kernel.h>
8 #include <linux/list.h>
9 #include <linux/slab.h>
10 #include <linux/tty.h>
11 #include <linux/string.h>
12 #include <linux/tty_flip.h>
14 #include "chan_kern.h"
21 #ifdef CONFIG_NOCONFIG_CHAN
22 static void *not_configged_init(char *str, int device,
23 const struct chan_opts *opts)
25 printk("Using a channel type which is configured out of "
30 static int not_configged_open(int input, int output, int primary, void *data,
33 printk("Using a channel type which is configured out of "
38 static void not_configged_close(int fd, void *data)
40 printk("Using a channel type which is configured out of "
44 static int not_configged_read(int fd, char *c_out, void *data)
46 printk("Using a channel type which is configured out of "
51 static int not_configged_write(int fd, const char *buf, int len, void *data)
53 printk("Using a channel type which is configured out of "
58 static int not_configged_console_write(int fd, const char *buf, int len)
60 printk("Using a channel type which is configured out of "
65 static int not_configged_window_size(int fd, void *data, unsigned short *rows,
68 printk("Using a channel type which is configured out of "
73 static void not_configged_free(void *data)
75 printk("Using a channel type which is configured out of "
79 static const struct chan_ops not_configged_ops = {
80 .init = not_configged_init,
81 .open = not_configged_open,
82 .close = not_configged_close,
83 .read = not_configged_read,
84 .write = not_configged_write,
85 .console_write = not_configged_console_write,
86 .window_size = not_configged_window_size,
87 .free = not_configged_free,
90 #endif /* CONFIG_NOCONFIG_CHAN */
92 void generic_close(int fd, void *unused)
97 int generic_read(int fd, char *c_out, void *unused)
101 n = os_read_file(fd, c_out, sizeof(*c_out));
110 /* XXX Trivial wrapper around os_write_file */
112 int generic_write(int fd, const char *buf, int n, void *unused)
114 return os_write_file(fd, buf, n);
117 int generic_window_size(int fd, void *unused, unsigned short *rows_out,
118 unsigned short *cols_out)
123 ret = os_window_size(fd, &rows, &cols);
127 ret = ((*rows_out != rows) || (*cols_out != cols));
135 void generic_free(void *data)
140 static void tty_receive_char(struct tty_struct *tty, char ch)
142 if(tty == NULL) return;
144 if(I_IXON(tty) && !I_IXOFF(tty) && !tty->raw) {
145 if(ch == STOP_CHAR(tty)){
149 else if(ch == START_CHAR(tty)){
155 tty_insert_flip_char(tty, ch, TTY_NORMAL);
158 static int open_one_chan(struct chan *chan)
165 if(chan->ops->open == NULL)
167 else fd = (*chan->ops->open)(chan->input, chan->output, chan->primary,
168 chan->data, &chan->dev);
177 int open_chan(struct list_head *chans)
179 struct list_head *ele;
183 list_for_each(ele, chans){
184 chan = list_entry(ele, struct chan, list);
185 ret = open_one_chan(chan);
192 void chan_enable_winch(struct list_head *chans, struct tty_struct *tty)
194 struct list_head *ele;
197 list_for_each(ele, chans){
198 chan = list_entry(ele, struct chan, list);
199 if(chan->primary && chan->output && chan->ops->winch){
200 register_winch(chan->fd, tty);
206 int enable_chan(struct line *line)
208 struct list_head *ele;
212 list_for_each(ele, &line->chan_list){
213 chan = list_entry(ele, struct chan, list);
214 err = open_one_chan(chan);
224 err = line_setup_irq(chan->fd, chan->input, chan->output, line,
235 close_chan(&line->chan_list, 0);
239 /* Items are added in IRQ context, when free_irq can't be called, and
240 * removed in process context, when it can.
241 * This handles interrupt sources which disappear, and which need to
242 * be permanently disabled. This is discovered in IRQ context, but
243 * the freeing of the IRQ must be done later.
245 static DEFINE_SPINLOCK(irqs_to_free_lock);
246 static LIST_HEAD(irqs_to_free);
252 struct list_head *ele;
255 spin_lock_irqsave(&irqs_to_free_lock, flags);
256 list_splice_init(&irqs_to_free, &list);
257 spin_unlock_irqrestore(&irqs_to_free_lock, flags);
259 list_for_each(ele, &list){
260 chan = list_entry(ele, struct chan, free_list);
263 free_irq(chan->line->driver->read_irq, chan);
265 free_irq(chan->line->driver->write_irq, chan);
270 static void close_one_chan(struct chan *chan, int delay_free_irq)
278 spin_lock_irqsave(&irqs_to_free_lock, flags);
279 list_add(&chan->free_list, &irqs_to_free);
280 spin_unlock_irqrestore(&irqs_to_free_lock, flags);
284 free_irq(chan->line->driver->read_irq, chan);
286 free_irq(chan->line->driver->write_irq, chan);
289 if(chan->ops->close != NULL)
290 (*chan->ops->close)(chan->fd, chan->data);
296 void close_chan(struct list_head *chans, int delay_free_irq)
300 /* Close in reverse order as open in case more than one of them
301 * refers to the same device and they save and restore that device's
302 * state. Then, the first one opened will have the original state,
303 * so it must be the last closed.
305 list_for_each_entry_reverse(chan, chans, list) {
306 close_one_chan(chan, delay_free_irq);
310 void deactivate_chan(struct list_head *chans, int irq)
312 struct list_head *ele;
315 list_for_each(ele, chans) {
316 chan = list_entry(ele, struct chan, list);
318 if(chan->enabled && chan->input)
319 deactivate_fd(chan->fd, irq);
323 void reactivate_chan(struct list_head *chans, int irq)
325 struct list_head *ele;
328 list_for_each(ele, chans) {
329 chan = list_entry(ele, struct chan, list);
331 if(chan->enabled && chan->input)
332 reactivate_fd(chan->fd, irq);
336 int write_chan(struct list_head *chans, const char *buf, int len,
339 struct list_head *ele;
340 struct chan *chan = NULL;
343 list_for_each(ele, chans) {
344 chan = list_entry(ele, struct chan, list);
345 if (!chan->output || (chan->ops->write == NULL))
347 n = chan->ops->write(chan->fd, buf, len, chan->data);
350 if ((ret == -EAGAIN) || ((ret >= 0) && (ret < len)))
351 reactivate_fd(chan->fd, write_irq);
357 int console_write_chan(struct list_head *chans, const char *buf, int len)
359 struct list_head *ele;
363 list_for_each(ele, chans){
364 chan = list_entry(ele, struct chan, list);
365 if(!chan->output || (chan->ops->console_write == NULL))
367 n = chan->ops->console_write(chan->fd, buf, len);
368 if(chan->primary) ret = n;
373 int console_open_chan(struct line *line, struct console *co)
377 err = open_chan(&line->chan_list);
381 printk("Console initialized on /dev/%s%d\n", co->name, co->index);
385 int chan_window_size(struct list_head *chans, unsigned short *rows_out,
386 unsigned short *cols_out)
388 struct list_head *ele;
391 list_for_each(ele, chans){
392 chan = list_entry(ele, struct chan, list);
394 if(chan->ops->window_size == NULL)
396 return chan->ops->window_size(chan->fd, chan->data,
403 static void free_one_chan(struct chan *chan, int delay_free_irq)
405 list_del(&chan->list);
407 close_one_chan(chan, delay_free_irq);
409 if(chan->ops->free != NULL)
410 (*chan->ops->free)(chan->data);
412 if(chan->primary && chan->output) ignore_sigio_fd(chan->fd);
416 static void free_chan(struct list_head *chans, int delay_free_irq)
418 struct list_head *ele, *next;
421 list_for_each_safe(ele, next, chans){
422 chan = list_entry(ele, struct chan, list);
423 free_one_chan(chan, delay_free_irq);
427 static int one_chan_config_string(struct chan *chan, char *str, int size,
433 CONFIG_CHUNK(str, size, n, "none", 1);
437 CONFIG_CHUNK(str, size, n, chan->ops->type, 0);
439 if(chan->dev == NULL){
440 CONFIG_CHUNK(str, size, n, "", 1);
444 CONFIG_CHUNK(str, size, n, ":", 0);
445 CONFIG_CHUNK(str, size, n, chan->dev, 0);
450 static int chan_pair_config_string(struct chan *in, struct chan *out,
451 char *str, int size, char **error_out)
455 n = one_chan_config_string(in, str, size, error_out);
460 CONFIG_CHUNK(str, size, n, "", 1);
464 CONFIG_CHUNK(str, size, n, ",", 1);
465 n = one_chan_config_string(out, str, size, error_out);
468 CONFIG_CHUNK(str, size, n, "", 1);
473 int chan_config_string(struct list_head *chans, char *str, int size,
476 struct list_head *ele;
477 struct chan *chan, *in = NULL, *out = NULL;
479 list_for_each(ele, chans){
480 chan = list_entry(ele, struct chan, list);
489 return chan_pair_config_string(in, out, str, size, error_out);
494 const struct chan_ops *ops;
497 static const struct chan_type chan_table[] = {
500 #ifdef CONFIG_NULL_CHAN
501 { "null", &null_ops },
503 { "null", ¬_configged_ops },
506 #ifdef CONFIG_PORT_CHAN
507 { "port", &port_ops },
509 { "port", ¬_configged_ops },
512 #ifdef CONFIG_PTY_CHAN
516 { "pty", ¬_configged_ops },
517 { "pts", ¬_configged_ops },
520 #ifdef CONFIG_TTY_CHAN
523 { "tty", ¬_configged_ops },
526 #ifdef CONFIG_XTERM_CHAN
527 { "xterm", &xterm_ops },
529 { "xterm", ¬_configged_ops },
533 static struct chan *parse_chan(struct line *line, char *str, int device,
534 const struct chan_opts *opts, char **error_out)
536 const struct chan_type *entry;
537 const struct chan_ops *ops;
544 for(i = 0; i < ARRAY_SIZE(chan_table); i++){
545 entry = &chan_table[i];
546 if(!strncmp(str, entry->key, strlen(entry->key))){
548 str += strlen(entry->key);
553 *error_out = "No match for configured backends";
557 data = (*ops->init)(str, device, opts);
559 *error_out = "Configuration failed";
563 chan = kmalloc(sizeof(*chan), GFP_ATOMIC);
565 *error_out = "Memory allocation failed";
568 *chan = ((struct chan) { .list = LIST_HEAD_INIT(chan->list),
570 LIST_HEAD_INIT(chan->free_list),
583 int parse_chan_pair(char *str, struct line *line, int device,
584 const struct chan_opts *opts, char **error_out)
586 struct list_head *chans = &line->chan_list;
587 struct chan *new, *chan;
590 if(!list_empty(chans)){
591 chan = list_entry(chans->next, struct chan, list);
593 INIT_LIST_HEAD(chans);
596 out = strchr(str, ',');
601 new = parse_chan(line, in, device, opts, error_out);
606 list_add(&new->list, chans);
608 new = parse_chan(line, out, device, opts, error_out);
612 list_add(&new->list, chans);
616 new = parse_chan(line, str, device, opts, error_out);
620 list_add(&new->list, chans);
627 int chan_out_fd(struct list_head *chans)
629 struct list_head *ele;
632 list_for_each(ele, chans){
633 chan = list_entry(ele, struct chan, list);
634 if(chan->primary && chan->output)
640 void chan_interrupt(struct list_head *chans, struct delayed_work *task,
641 struct tty_struct *tty, int irq)
643 struct list_head *ele, *next;
648 list_for_each_safe(ele, next, chans){
649 chan = list_entry(ele, struct chan, list);
650 if(!chan->input || (chan->ops->read == NULL)) continue;
652 if (tty && !tty_buffer_request_room(tty, 1)) {
653 schedule_delayed_work(task, 1);
656 err = chan->ops->read(chan->fd, &c, chan->data);
658 tty_receive_char(tty, c);
661 if(err == 0) reactivate_fd(chan->fd, irq);
666 close_chan(chans, 1);
669 else close_one_chan(chan, 1);
673 if(tty) tty_flip_buffer_push(tty);