| #include "linux/posix_types.h" |
| #include "linux/tty.h" |
| #include "linux/types.h" |
| #include "linux/major.h" |
| #include "linux/kdev_t.h" |
| #include "linux/console.h" |
| #include "linux/string.h" |
| #include "linux/sched.h" |
| #include "linux/init.h" |
| #include "linux/interrupt.h" |
| #include "asm/current.h" |
| #include "asm/softirq.h" |
| #include "stdio_console.h" |
| #include "user_util.h" |
| #include "kern_util.h" |
| |
| #define MAX_TTYS (8) |
| |
| static struct tty_driver console_driver; |
| static struct tty_struct *console_table[MAX_TTYS]; |
| static struct termios *console_termios[MAX_TTYS]; |
| static struct termios *console_termios_locked[MAX_TTYS]; |
| static int console_refcount; |
| |
| static struct vt { |
| int fd; |
| int count; |
| int xterm_pid; |
| } vts[MAX_TTYS] = { { 0, 0, -1 }, [ 1 ... MAX_TTYS - 1 ] = { -1, 0, -1 } }; |
| |
| DECLARE_MUTEX(stdio_sem); |
| |
| static int con_open(struct tty_struct * tty, struct file * filp) |
| { |
| int line; |
| |
| line = MINOR(tty->device) - tty->driver.minor_start; |
| vts[line].count++; |
| if(line != 0){ |
| down(&stdio_sem); |
| if(vts[line].fd == -1){ |
| vts[line].fd = open_vt(line, &vts[line].xterm_pid); |
| input_new_fd(stdio_rcv_proc, vts[line].fd); |
| } |
| up(&stdio_sem); |
| } |
| return(0); |
| } |
| |
| static void con_close(struct tty_struct * tty, struct file * filp) |
| { |
| int line; |
| |
| line = MINOR(tty->device) - tty->driver.minor_start; |
| vts[line].count--; |
| if(vts[line].count == 0){ |
| if(vts[line].xterm_pid != -1) kill_pid(vts[line].xterm_pid); |
| if(line == 0) vts[line] = ((struct vt) { 0, 0, -1}); |
| else vts[line] = ((struct vt) { -1, 0, -1}); |
| } |
| } |
| |
| static int con_write(struct tty_struct * tty, int from_user, |
| const unsigned char *buf, int count) |
| { |
| int line; |
| |
| line = MINOR(tty->device) - tty->driver.minor_start; |
| stdio_write(vts[line].fd, buf, count); |
| return(count); |
| } |
| |
| static int write_room(struct tty_struct * tty) |
| { |
| return(1024); |
| } |
| |
| static void set_termios(struct tty_struct *tty, struct termios * old) |
| { |
| } |
| |
| static int chars_in_buffer(struct tty_struct *tty) |
| { |
| return(0); |
| } |
| |
| DECLARE_TASKLET_DISABLED(input_tasklet, input_handler, 0); |
| |
| extern void tty_register_devfs (struct tty_driver *driver, unsigned int flags, |
| unsigned int minor); |
| extern void tty_unregister_devfs (struct tty_driver *driver, unsigned minor); |
| |
| int stdio_init(void) |
| { |
| int i; |
| |
| printk("Initializing stdio console driver\n"); |
| memset(&console_driver, 0, sizeof(struct tty_driver)); |
| console_driver.magic = TTY_DRIVER_MAGIC; |
| console_driver.driver_name = "stdio console"; |
| console_driver.name = "ttys/%d"; |
| console_driver.major = TTY_MAJOR; |
| console_driver.minor_start = 0; |
| console_driver.num = 8; |
| console_driver.type = TTY_DRIVER_TYPE_CONSOLE; |
| console_driver.subtype = SYSTEM_TYPE_CONSOLE; |
| console_driver.init_termios = tty_std_termios; |
| console_driver.init_termios.c_oflag |= OCRNL; |
| console_driver.flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS; |
| console_driver.refcount = &console_refcount; |
| console_driver.table = console_table; |
| console_driver.termios = console_termios; |
| console_driver.termios_locked = console_termios_locked; |
| |
| console_driver.open = con_open; |
| console_driver.close = con_close; |
| console_driver.write = con_write; |
| console_driver.put_char = NULL; |
| console_driver.flush_chars = NULL; |
| console_driver.write_room = write_room; |
| console_driver.chars_in_buffer = chars_in_buffer; |
| console_driver.flush_buffer = NULL; |
| console_driver.ioctl = NULL; |
| console_driver.throttle = NULL; |
| console_driver.unthrottle = NULL; |
| console_driver.send_xchar = NULL; |
| console_driver.set_termios = set_termios; |
| console_driver.stop = NULL; |
| console_driver.start = NULL; |
| console_driver.hangup = NULL; |
| console_driver.break_ctl = NULL; |
| console_driver.wait_until_sent = NULL; |
| console_driver.read_proc = NULL; |
| if (tty_register_driver(&console_driver)) |
| panic("Couldn't register console driver\n"); |
| for(i=0;i<MAX_TTYS;i++){ |
| tty_register_devfs(&console_driver, 0, i); |
| } |
| setup_fd(0); |
| tasklet_enable(&input_tasklet); |
| input_new_fd(stdio_rcv_proc, 0); |
| return(0); |
| } |
| |
| __initcall(stdio_init); |
| |
| static void console_write(struct console *console, const char *string, |
| unsigned len) |
| { |
| stdio_write(console->index, string, len); |
| } |
| |
| static kdev_t console_device(struct console *c) |
| { |
| return MKDEV(TTY_MAJOR, c->index); |
| } |
| |
| static int console_setup(struct console *co, char *options) |
| { |
| return(0); |
| } |
| |
| static struct console stdiocons = { |
| "tty", |
| console_write, |
| NULL, |
| console_device, |
| NULL, |
| NULL, |
| console_setup, |
| CON_PRINTBUFFER, |
| -1, |
| 0, |
| NULL |
| }; |
| |
| void stdio_console_init(void) |
| { |
| register_console(&stdiocons); |
| } |
| |
| void stdio_receive_char(int fd, char ch) |
| { |
| struct tty_struct *tty; |
| int i; |
| |
| for(i=0;i<MAX_TTYS;i++){ |
| if(vts[i].fd == fd) break; |
| } |
| if(i == MAX_TTYS){ |
| printk("Input received on unknown terminal - fd = %d\n", fd); |
| return; |
| } |
| tty = console_table[i]; |
| if(tty == NULL) return; |
| if(tty->flip.count >= TTY_FLIPBUF_SIZE) return; |
| tty->flip.count++; |
| *tty->flip.flag_buf_ptr++ = 0; |
| *tty->flip.char_buf_ptr++ = ch; |
| tty_flip_buffer_push(tty); |
| } |