home *** CD-ROM | disk | FTP | other *** search
- /*
- * pty.c - Berkeley style pseudo tty driver for system V
- *
- * Copyright (c) 1987, Jens-Uwe Mager, FOCUS Computer GmbH
- * Not derived from licensed software.
- *
- * Permission is granted to freely use, copy, modify, and redistribute
- * this software, provided that no attempt is made to gain profit from it,
- * the author is not construed to be liable for any results of using the
- * software, alterations are clearly marked as such, and this notice is
- * not modified.
- */
-
- /*
- * the following are arbitrary 3 unused bits from t_state
- * in sys/tty.h
- */
- #define MRWAIT 01000000 /* master waiting in read */
- #define t_rloc t_cc[0] /* wchannel */
- #define MWWAIT 02000000 /* master waiting in write */
- #define t_wloc t_cc[1] /* wchannel */
- #define MOPEN 04000000 /* master is open */
-
- #include "sys/param.h"
- #include "sys/types.h"
- #include "sys/sysmacros.h"
- #include "sys/seg.h"
- #include "sys/page.h"
- #include "sys/systm.h"
- #include "sys/file.h"
- #include "sys/conf.h"
- #ifndef tower
- #include "sys/region.h"
- #endif
- #include "sys/proc.h"
- #include "sys/dir.h"
- #include "sys/tty.h"
- #include "sys/signal.h"
- #include "sys/user.h"
- #include "sys/errno.h"
- #include "sys/termio.h"
- #include "sys/ttold.h"
-
- /*
- * from config
- */
- extern struct tty pts_tty[];
- extern int pts_cnt;
-
- /*
- * slave side is a fairly standard system V tty driver
- */
- ptsopen(dev, flag)
- {
- register struct tty *tp = &pts_tty[dev];
- extern int ptsproc();
-
- if (dev >= pts_cnt) {
- u.u_error = ENXIO;
- return;
- }
- if ((tp->t_state & (ISOPEN|WOPEN)) == 0) {
- ttinit(tp);
- tp->t_proc = ptsproc;
- }
- /*
- * if master is still open, don't wait for carrier
- */
- if (tp->t_state & MOPEN)
- tp->t_state |= CARR_ON;
- if (!(flag & FNDELAY)) {
- while ((tp->t_state & CARR_ON) == 0) {
- tp->t_state |= WOPEN;
- sleep((caddr_t)&tp->t_canq, TTIPRI);
- }
- }
- (*linesw[tp->t_line].l_open)(tp);
- }
-
- ptswrite(dev)
- {
- register struct tty *tp = &pts_tty[dev];
-
- (*linesw[tp->t_line].l_write)(tp);
- }
-
- ptsread(dev)
- {
- register struct tty *tp = &pts_tty[dev];
-
- (*linesw[tp->t_line].l_read)(tp);
- }
-
- ptsclose(dev)
- {
- register struct tty *tp = &pts_tty[dev];
-
- (*linesw[tp->t_line].l_close)(tp);
- tp->t_state &= ~CARR_ON;
- }
-
- ptsioctl(dev, cmd, arg, mode)
- {
- register struct tty *tp = &pts_tty[dev];
-
- ttiocom(tp, cmd, arg, mode);
- }
-
- ptsproc(tp, cmd)
- register struct tty *tp;
- {
- register struct ccblock *tbuf;
- extern ttrstrt();
-
- switch (cmd) {
- case T_TIME:
- #ifdef DEBUG
- printf("T_TIME\n");
- #endif
- tp->t_state &= ~TIMEOUT;
- goto start;
- case T_WFLUSH:
- #ifdef DEBUG
- printf("T_WFLUSH\n");
- #endif
- tp->t_tbuf.c_size -= tp->t_tbuf.c_count;
- tp->t_tbuf.c_count = 0;
- /* fall through */
- case T_RESUME:
- #ifdef DEBUG
- printf("T_RESUME\n");
- #endif
- tp->t_state &= ~TTSTOP;
- /* fall through */
- case T_OUTPUT:
- #ifdef DEBUG
- printf("T_OUTPUT\n");
- #endif
- start:
- if (tp->t_state & (TTSTOP|TIMEOUT))
- break;
- tbuf = &tp->t_tbuf;
- if (tbuf->c_ptr == NULL || tbuf->c_count == 0) {
- if (tbuf->c_ptr)
- tbuf->c_ptr -= tbuf->c_size;
- if (!(CPRES & (*linesw[tp->t_line].l_output)(tp)))
- break;
- }
- if (tbuf->c_count && (tp->t_state & MRWAIT)) {
- tp->t_state &= ~MRWAIT;
- wakeup((caddr_t)&tp->t_rloc);
- }
- break;
- case T_SUSPEND:
- #ifdef DEBUG
- printf("T_SUSPEND\n");
- #endif
- tp->t_state |= TTSTOP;
- break;
- case T_BLOCK:
- #ifdef DEBUG
- printf("T_BLOCK\n");
- #endif
- /*
- * the check for ICANON appears to be neccessary
- * to avoid a hang when overflowing input
- */
- if ((tp->t_iflag & ICANON) == 0)
- tp->t_state |= TBLOCK;
- break;
- case T_BREAK:
- #ifdef DEBUG
- printf("T_BREAK\n");
- #endif
- tp->t_state |= TIMEOUT;
- timeout(ttrstrt, tp, HZ/4);
- break;
- #ifdef T_LOG_FLUSH
- case T_LOG_FLUSH:
- #ifdef DEBUG
- printf("T_LOG_FLUSH\n");
- #endif
- case T_RFLUSH:
- #ifdef DEBUG
- printf("T_RFLUSH\n");
- #endif
- if (!(tp->t_state & TBLOCK))
- break;
- /* fall through */
- case T_UNBLOCK:
- #ifdef DEBUG
- printf("T_UNBLOCK\n");
- #endif
- tp->t_state &= ~(TTXOFF|TBLOCK);
- /* fall through */
- case T_INPUT:
- #ifdef DEBUG
- printf("T_INPUT\n");
- #endif
- if (tp->t_state & MWWAIT) {
- tp->t_state &= ~MWWAIT;
- wakeup((caddr_t)&tp->t_wloc);
- }
- break;
- #ifdef DEBUG
- default:
- printf("ptsproc: cmd %d\n",cmd);
- #endif
- }
- }
-
- /*
- * master part - not actually like a tty
- */
-
- ptmopen(dev, flag)
- {
- register struct tty *tp = &pts_tty[dev];
-
- #ifdef DEBUG
- printf("ptmopen(%d)\n",dev);
- #endif
- if (dev >= pts_cnt) {
- u.u_error = ENXIO;
- return;
- }
- /*
- * allow only one controlling process
- */
- if (tp->t_state & MOPEN) {
- u.u_error = EBUSY;
- return;
- }
- if (tp->t_state & WOPEN)
- wakeup((caddr_t)&tp->t_canq);
- tp->t_state |= CARR_ON|MOPEN;
- }
-
- ptmread(dev)
- {
- register struct tty *tp = &pts_tty[dev];
- register n;
-
- if ((tp->t_state & ISOPEN) == 0) {
- u.u_error = EIO;
- return;
- }
- #ifdef DEBUG
- printf("ptmread(%d)\n",dev);
- #endif
- while (u.u_count) {
- ptsproc(tp, T_OUTPUT);
- if ((tp->t_state & (TTSTOP|TIMEOUT))
- || tp->t_tbuf.c_ptr == NULL || tp->t_tbuf.c_count == 0) {
- if (u.u_fmode & FNDELAY)
- break;
- tp->t_state |= MRWAIT;
- sleep((caddr_t)&tp->t_rloc, TTIPRI);
- continue;
- }
- n = min(u.u_count, tp->t_tbuf.c_count);
- if (n) {
- if (copyout(tp->t_tbuf.c_ptr, u.u_base, n)) {
- u.u_error = EFAULT;
- break;
- }
- tp->t_tbuf.c_count -= n;
- tp->t_tbuf.c_ptr += n;
- u.u_base += n;
- u.u_count -= n;
- }
- }
- }
-
- ptmwrite(dev)
- {
- register struct tty *tp = &pts_tty[dev];
- register n;
-
- if ((tp->t_state & ISOPEN) == 0) {
- u.u_error = EIO;
- return;
- }
- #ifdef DEBUG
- printf("ptmwrite(%d)\n",dev);
- #endif
- while (u.u_count) {
- if ((tp->t_state & TBLOCK) || tp->t_rbuf.c_ptr == NULL) {
- if (u.u_fmode & FNDELAY)
- break;
- tp->t_state |= MWWAIT;
- sleep((caddr_t)&tp->t_wloc, TTOPRI);
- continue;
- }
- n = min(u.u_count, tp->t_rbuf.c_count);
- if (n) {
- if (copyin(u.u_base,tp->t_rbuf.c_ptr, n)) {
- u.u_error = EFAULT;
- break;
- }
- tp->t_rbuf.c_count -= n;
- u.u_base += n;
- u.u_count -= n;
- }
- #ifdef vax
- /*
- * somebody told me this is necessary on the vax
- */
- (*linesw[tp->t_line].l_input)(tp, L_BUF);
- #else
- (*linesw[tp->t_line].l_input)(tp);
- #endif
- }
- }
-
- ptmclose(dev)
- {
- register struct tty *tp = &pts_tty[dev];
-
- #ifdef DEBUG
- printf("ptmclose(%d)\n",dev);
- #endif
- if (tp->t_state & ISOPEN) {
- signal(tp->t_pgrp, SIGHUP);
- ttyflush(tp, FREAD|FWRITE);
- }
- /*
- * virtual carrier gone
- */
- tp->t_state &= ~(CARR_ON|MOPEN);
- }
-
- ptmioctl(dev, cmd, arg, mode)
- {
- register struct tty *tp = &pts_tty[dev];
-
- /*
- * sorry, but we can't fiddle with the tty struct without
- * having done LDOPEN
- */
- if (tp->t_state & ISOPEN) {
- if (cmd == TCSBRK && arg == NULL) {
- signal(tp->t_pgrp, SIGINT);
- if ((tp->t_iflag & NOFLSH) == 0)
- ttyflush(tp, FREAD|FWRITE);
- } else {
- /*
- * we must flush output to avoid hang in ttywait
- */
- if (cmd == TCSETAW || cmd == TCSETAF || cmd == TCSBRK
- || cmd == TIOCSETP)
- ttyflush(FWRITE);
- ttiocom(tp, cmd, arg, mode);
- }
- }
- }
-