📄 tubtty.c
字号:
/* * IBM/3270 Driver -- Copyright (C) 2000, 2001 UTS Global LLC * * tubtty.c -- Linemode tty driver * * * * * * Author: Richard Hitt */#include <linux/config.h>#include "tubio.h"/* Initialization & uninitialization for tubtty */int tty3270_init(void);void tty3270_fini(void);/* Interface routines from the upper tty layer to the tty driver */static int tty3270_open(struct tty_struct *, struct file *);static void tty3270_close(struct tty_struct *, struct file *);static int tty3270_write(struct tty_struct *, int, const unsigned char *, int);static void tty3270_put_char(struct tty_struct *, unsigned char);static void tty3270_flush_chars(struct tty_struct *);static int tty3270_write_room(struct tty_struct *);static int tty3270_chars_in_buffer(struct tty_struct *);static int tty3270_ioctl(struct tty_struct *, struct file *, unsigned int cmd, unsigned long arg);static void tty3270_set_termios(struct tty_struct *, struct termios *);static void tty3270_hangup(struct tty_struct *);static void tty3270_flush_buffer(struct tty_struct *);static int tty3270_read_proc(char *, char **, off_t, int, int *, void *);static int tty3270_write_proc(struct file *, const char *, unsigned long, void *);/* tty3270 utility functions */static void tty3270_bh(void *); void tty3270_sched_bh(tub_t *);static int tty3270_wait(tub_t *, long *); void tty3270_int(tub_t *, devstat_t *); int tty3270_try_logging(tub_t *);static void tty3270_start_input(tub_t *);static void tty3270_do_input(tub_t *);static void tty3270_do_enter(tub_t *, char *, int);static void tty3270_do_showi(tub_t *, char *, int); int tty3270_io(tub_t *);static int tty3270_show_tube(int, char *, int);int tty3270_major = -1;struct tty_driver tty3270_driver;int tty3270_refcount;struct tty_struct *tty3270_table[TUBMAXMINS];struct termios *tty3270_termios[TUBMAXMINS];struct termios *tty3270_termios_locked[TUBMAXMINS];#ifdef CONFIG_TN3270_CONSOLEint con3270_major = -1;struct tty_driver con3270_driver;int con3270_refcount;struct tty_struct *con3270_table[1];struct termios *con3270_termios[1];struct termios *con3270_termios_locked[1];#endif /* CONFIG_TN3270_CONSOLE */int tty3270_proc_index;int tty3270_proc_data;int tty3270_proc_misc;enum tubwhat tty3270_proc_what;/* * tty3270_init() -- Register the tty3270 driver */inttty3270_init(void){ struct tty_driver *td = &tty3270_driver; int rc; /* Initialize for tty driver */ td->magic = TTY_DRIVER_MAGIC; td->driver_name = "tty3270"; td->name = "tty3270"; td->major = IBM_TTY3270_MAJOR; td->minor_start = 0; td->num = TUBMAXMINS; td->type = TTY_DRIVER_TYPE_SYSTEM; td->subtype = SYSTEM_TYPE_TTY; td->init_termios = tty_std_termios; td->flags = TTY_DRIVER_RESET_TERMIOS;#ifdef CONFIG_DEVFS_FS td->flags |= TTY_DRIVER_NO_DEVFS;#endif td->refcount = &tty3270_refcount; td->table = tty3270_table; td->termios = tty3270_termios; td->termios_locked = tty3270_termios_locked; td->open = tty3270_open; td->close = tty3270_close; td->write = tty3270_write; td->put_char = tty3270_put_char; td->flush_chars = tty3270_flush_chars; td->write_room = tty3270_write_room; td->chars_in_buffer = tty3270_chars_in_buffer; td->ioctl = tty3270_ioctl; td->ioctl = NULL; td->set_termios = tty3270_set_termios; td->throttle = NULL; td->unthrottle = NULL; td->stop = NULL; td->start = NULL; td->hangup = tty3270_hangup; td->break_ctl = NULL; td->flush_buffer = tty3270_flush_buffer; td->set_ldisc = NULL; td->wait_until_sent = NULL; td->send_xchar = NULL; td->read_proc = tty3270_read_proc; td->write_proc = tty3270_write_proc; rc = tty_register_driver(td); if (rc) { printk(KERN_ERR "tty3270 registration failed with %d\n", rc); } else { tty3270_major = IBM_TTY3270_MAJOR; if (td->proc_entry != NULL) td->proc_entry->mode = S_IRUGO | S_IWUGO; }#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0))#ifdef CONFIG_TN3270_CONSOLE if (CONSOLE_IS_3270) { tty3270_con_driver = *td; td = &tty3270_con_driver; td->driver_name = "con3270"; td->name = "con3270"; td->major = MAJOR(S390_CONSOLE_DEV); td->minor_start = MINOR(S390_CONSOLE_DEV); td->num = 1; td->refcount = &con3270_refcount; td->table = con3270_table; td->termios = con3270_termios; td->termios_locked = con3270_termios_locked; rc = tty_register_driver(td); if (rc) { printk(KERN_ERR "con3270 registration failed with %d\n", rc); } else { con3270_major = MAJOR(S390_CONSOLE_DEV); if (td->proc_entry != NULL) td->proc_entry->mode = S_IRUGO | S_IWUGO; } }#endif /* ifdef CONFIG_TN3270_CONSOLE */#endif /* if LINUX_VERSION_CODE */ return rc;}/* * tty3270_fini() -- Uninitialize linemode tubes */voidtty3270_fini(void){ if (tty3270_major != -1) { tty_unregister_driver(&tty3270_driver); tty3270_major = -1; }#ifdef CONFIG_TN3270_CONSOLE if (CONSOLE_IS_3270 && con3270_major != -1) { tty_unregister_driver(&con3270_driver); con3270_major = -1; }#endif}static int tty3270_open(struct tty_struct *tty, struct file *filp){ tub_t *tubp; long flags; int rc; int cmd; if ((tubp = TTY2TUB(tty)) == NULL) { return -ENODEV; } tub_inc_use_count(); if ((rc = tty3270_wait(tubp, &flags)) != 0) goto do_fail; if (tubp->lnopen > 0) { tubp->lnopen++; TUBUNLOCK(tubp->irq, flags); return 0; } if (tubp->flags & TUB_OPEN_STET) { cmd = TBC_UPDLOG; } else { cmd = TBC_OPEN; tubp->flags &= ~TUB_SIZED; } if ((rc = tty3270_size(tubp, &flags)) != 0) goto do_fail; if ((rc = tty3270_rcl_init(tubp)) != 0) goto do_fail; if ((rc = tty3270_aid_init(tubp)) != 0) goto do_fail; if ((rc = tty3270_scl_init(tubp)) != 0) goto do_fail; tubp->mode = TBM_LN; tubp->intv = tty3270_int; tubp->tty = tty; tubp->lnopen = 1; tty->driver_data = tubp; tty->winsize.ws_row = tubp->geom_rows; tty->winsize.ws_col = tubp->geom_cols; tubp->tty_inattr = TF_INPUT; tubp->cmd = cmd; tty3270_build(tubp); TUBUNLOCK(tubp->irq, flags); return 0;do_fail: tty3270_scl_fini(tubp); tty3270_aid_fini(tubp); tty3270_rcl_fini(tubp); TUBUNLOCK(tubp->irq, flags); tub_dec_use_count(); return rc;}static voidtty3270_close(struct tty_struct *tty, struct file *filp){ tub_t *tubp; long flags; if ((tubp = tty->driver_data) == NULL) return; tty3270_wait(tubp, &flags); if (--tubp->lnopen > 0) goto do_return; tubp->tty = NULL; tty->driver_data = NULL; tty3270_aid_fini(tubp); tty3270_rcl_fini(tubp); tty3270_scl_fini(tubp);do_return: tub_dec_use_count(); TUBUNLOCK(tubp->irq, flags);}static int tty3270_write(struct tty_struct *tty, int fromuser, const unsigned char *buf, int count){ tub_t *tubp; long flags; bcb_t obcb; int rc = 0; if ((tubp = tty->driver_data) == NULL) return -1;#ifdef CONFIG_TN3270_CONSOLE if (CONSOLE_IS_3270 && tub3270_con_tubp == tubp) tub3270_con_copy(tubp);#endif /* CONFIG_TN3270_CONSOLE */ obcb.bc_buf = (char *)buf; obcb.bc_len = obcb.bc_cnt = obcb.bc_wr = count; obcb.bc_rd = 0; TUBLOCK(tubp->irq, flags); rc = tub3270_movedata(&obcb, &tubp->tty_bcb, fromuser); tty3270_try_logging(tubp); TUBUNLOCK(tubp->irq, flags); return rc;} static voidtty3270_put_char(struct tty_struct *tty, unsigned char ch){ long flags; tub_t *tubp; bcb_t *ob; if ((tubp = tty->driver_data) == NULL) return; TUBLOCK(tubp->irq, flags); ob = &tubp->tty_bcb; if (ob->bc_cnt < ob->bc_len) { ob->bc_buf[ob->bc_wr++] = ch; if (ob->bc_wr == ob->bc_len) ob->bc_wr = 0; ob->bc_cnt++; } tty3270_try_logging(tubp); TUBUNLOCK(tubp->irq, flags);}static voidtty3270_flush_chars(struct tty_struct *tty){ tub_t *tubp; long flags; if ((tubp = tty->driver_data) == NULL) return; TUBLOCK(tubp->irq, flags); tty3270_try_logging(tubp); TUBUNLOCK(tubp->irq, flags);}static int tty3270_write_room(struct tty_struct *tty){ tub_t *tubp; bcb_t *ob; if ((tubp = tty->driver_data) == NULL) return -1; ob = &tubp->tty_bcb; return ob->bc_len - ob->bc_cnt;}static inttty3270_chars_in_buffer(struct tty_struct *tty){ tub_t *tubp; bcb_t *ob; if ((tubp = tty->driver_data) == NULL) return -1; ob = &tubp->tty_bcb; return ob->bc_cnt;}static inttty3270_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg){ tub_t *tubp; long flags; int ret = 0; struct termios termios; if ((tubp = tty->driver_data) == NULL) return -ENODEV; TUBLOCK(tubp->irq, flags); if (tty->flags * (1 << TTY_IO_ERROR)) { ret = -EIO; goto do_return; } switch(cmd) { case TCGETS: ret = -ENOIOCTLCMD; goto do_return; case TCFLSH: /* arg: 2 or 0 */ ret = -ENOIOCTLCMD; goto do_return; case TCSETSF: if (user_termios_to_kernel_termios(&termios, (struct termios *)arg)) { ret = -EFAULT; goto do_return; } ret = -ENOIOCTLCMD; goto do_return; case TCGETA: ret = -ENOIOCTLCMD; goto do_return; case TCSETA: if (user_termio_to_kernel_termios(&termios, (struct termio *)arg)) { ret = -EFAULT; goto do_return; } ret = -ENOIOCTLCMD; goto do_return; default: ret = -ENOIOCTLCMD; break; }do_return: TUBUNLOCK(tubp->irq, flags); return ret;}static voidtty3270_set_termios(struct tty_struct *tty, struct termios *old){ tub_t *tubp; long flags; int new; if ((tubp = tty->driver_data) == NULL) return; if (tty3270_wait(tubp, &flags) != 0) { TUBUNLOCK(tubp->irq, flags); return; } new = L_ICANON(tty)? L_ECHO(tty)? TF_INPUT: TF_INPUTN: tubp->tty_inattr; if (new != tubp->tty_inattr) { tubp->tty_inattr = new; tubp->cmd = TBC_CLRINPUT; tty3270_build(tubp); } TUBUNLOCK(tubp->irq, flags);}static voidtty3270_flush_buffer(struct tty_struct *tty){ tub_t *tubp; bcb_t *ob; long flags; if ((tubp = tty->driver_data) == NULL) return; if (tubp->mode == TBM_FS && tubp->fs_pid != 0) { kill_proc(tubp->fs_pid, SIGHUP, 1); } if ((tubp->flags & TUB_OPEN_STET) == 0) { ob = &tubp->tty_bcb; TUBLOCK(tubp->irq, flags); ob->bc_rd = 0; ob->bc_wr = 0; ob->bc_cnt = 0; TUBUNLOCK(tubp->irq, flags); } wake_up_interruptible(&tty->write_wait); if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup) (tty->ldisc.write_wakeup)(tty);}static inttty3270_read_proc(char *buf, char **start, off_t off, int count, int *eof, void *data){ tub_t *tubp; int begin = 0; int i; int rc; int len = 0; if (tty3270_proc_what == TW_CONFIG) { /* * Describe the 3270 configuration in ascii lines. * Line 1: 0 <fsmajor> 0 * Console line: <devnum> CONSOLE <minor> * Other lines: <devnum> <ttymajor> <minor> */ len += sprintf(buf + len, "0 %d 0\n", fs3270_major); for (i = 1; i <= tubnummins; i++) { tubp = (*tubminors)[i];#ifdef CONFIG_TN3270_CONSOLE if (CONSOLE_IS_3270 && tubp == tub3270_con_tubp) len += sprintf(buf + len, "%.3x CONSOLE %d\n", tubp->devno, i); else#endif len += sprintf(buf + len, "%.3x %d %d\n", tubp->devno, tty3270_major, i); if (begin + len > off + count) break; if (begin + len < off) { begin += len; len = 0; } } if (i > tubnummins) *eof = 1; if (off >= begin + len) { rc = 0; } else { *start = buf + off - begin; rc = MIN(count, begin + len - off); } if (*eof && rc == 0) tty3270_proc_what = TW_BOGUS; return rc; } len += sprintf(buf, "There are %d devices. fs major is %d, " "tty major is %d.\n", tubnummins, fs3270_major, tty3270_major); len += sprintf(buf+len, " index=%d data=%d misc=%d\n",
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -