165dc59116
This patch simplifies the opening and closing of host console devices and the registration and deregistration of IRQs. The intent is to make it obvious that an IRQ can't exist without an open file descriptor. chan_enable will now open the channel, and when both opening and IRQ registration are desired, this should be used. Opening only is done for the initial console, so that interface still needs to exist. The free_irqs_later interface is now gone. It was intended to avoid freeing an IRQ while it was being processed. It did this, but it didn't eliminate the possiblity of free_irq being called from an interrupt, which is bad. In its place is a list of irqs to be freed, which is processed by the signal handler just before exiting. close_one_chan now disables irqs. When a host device disappears, it is just closed, and that disables IRQs. The device id registered with the IRQ is now the chan structure, not the tty. This is because the interrupt arrives on a descriptor associated with the channel. This caused equivalent changes in the arguments to line_timer_cb. line_disable is gone since it is not used any more. The count field in the line structure is gone. tty->count is used instead. The complicated logic in sigio_handler with freeing IRQs when necessary and making sure its idea of the next irq is correct is now much simpler. The irq list can't be rearranged underneath it, so it is now a simple list walk. Signed-off-by: Jeff Dike <jdike@addtoit.com> Cc: Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
112 lines
3 KiB
C
112 lines
3 KiB
C
/*
|
|
* Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
|
|
* Licensed under the GPL
|
|
*/
|
|
|
|
#ifndef __LINE_H__
|
|
#define __LINE_H__
|
|
|
|
#include "linux/list.h"
|
|
#include "linux/workqueue.h"
|
|
#include "linux/tty.h"
|
|
#include "linux/interrupt.h"
|
|
#include "linux/spinlock.h"
|
|
#include "chan_user.h"
|
|
#include "mconsole_kern.h"
|
|
|
|
struct line_driver {
|
|
char *name;
|
|
char *device_name;
|
|
char *devfs_name;
|
|
short major;
|
|
short minor_start;
|
|
short type;
|
|
short subtype;
|
|
int read_irq;
|
|
char *read_irq_name;
|
|
int write_irq;
|
|
char *write_irq_name;
|
|
char *symlink_from;
|
|
char *symlink_to;
|
|
struct mc_device mc;
|
|
};
|
|
|
|
struct line {
|
|
struct tty_struct *tty;
|
|
char *init_str;
|
|
int init_pri;
|
|
struct list_head chan_list;
|
|
int valid;
|
|
int count;
|
|
/*This lock is actually, mostly, local to*/
|
|
spinlock_t lock;
|
|
|
|
/* Yes, this is a real circular buffer.
|
|
* XXX: And this should become a struct kfifo!
|
|
*
|
|
* buffer points to a buffer allocated on demand, of length
|
|
* LINE_BUFSIZE, head to the start of the ring, tail to the end.*/
|
|
char *buffer;
|
|
char *head;
|
|
char *tail;
|
|
|
|
int sigio;
|
|
struct work_struct task;
|
|
struct line_driver *driver;
|
|
int have_irq;
|
|
};
|
|
|
|
#define LINE_INIT(str, d) \
|
|
{ init_str : str, \
|
|
init_pri : INIT_STATIC, \
|
|
valid : 1, \
|
|
lock : SPIN_LOCK_UNLOCKED, \
|
|
buffer : NULL, \
|
|
head : NULL, \
|
|
tail : NULL, \
|
|
sigio : 0, \
|
|
driver : d, \
|
|
have_irq : 0 }
|
|
|
|
struct lines {
|
|
int num;
|
|
};
|
|
|
|
#define LINES_INIT(n) { num : n }
|
|
|
|
extern void line_close(struct tty_struct *tty, struct file * filp);
|
|
extern int line_open(struct line *lines, struct tty_struct *tty);
|
|
extern int line_setup(struct line *lines, unsigned int sizeof_lines,
|
|
char *init);
|
|
extern int line_write(struct tty_struct *tty, const unsigned char *buf,
|
|
int len);
|
|
extern void line_put_char(struct tty_struct *tty, unsigned char ch);
|
|
extern void line_set_termios(struct tty_struct *tty, struct termios * old);
|
|
extern int line_chars_in_buffer(struct tty_struct *tty);
|
|
extern void line_flush_buffer(struct tty_struct *tty);
|
|
extern void line_flush_chars(struct tty_struct *tty);
|
|
extern int line_write_room(struct tty_struct *tty);
|
|
extern int line_ioctl(struct tty_struct *tty, struct file * file,
|
|
unsigned int cmd, unsigned long arg);
|
|
|
|
extern char *add_xterm_umid(char *base);
|
|
extern int line_setup_irq(int fd, int input, int output, struct line *line,
|
|
void *data);
|
|
extern void line_close_chan(struct line *line);
|
|
extern struct tty_driver * line_register_devfs(struct lines *set,
|
|
struct line_driver *line_driver,
|
|
struct tty_operations *driver,
|
|
struct line *lines,
|
|
int nlines);
|
|
extern void lines_init(struct line *lines, int nlines, struct chan_opts *opts);
|
|
extern void close_lines(struct line *lines, int nlines);
|
|
|
|
extern int line_config(struct line *lines, unsigned int sizeof_lines,
|
|
char *str, struct chan_opts *opts);
|
|
extern int line_id(char **str, int *start_out, int *end_out);
|
|
extern int line_remove(struct line *lines, unsigned int sizeof_lines, int n);
|
|
extern int line_get_config(char *dev, struct line *lines,
|
|
unsigned int sizeof_lines, char *str,
|
|
int size, char **error_out);
|
|
|
|
#endif
|