home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume8 / pty_uport / pty.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-09-06  |  8.5 KB  |  394 lines

  1. /*
  2.  * pty.c - Berkeley style pseudo tty driver for system V
  3.  *
  4.  * Additions marked:
  5.  * TTI - for the changes made by Michael Bloom at Citicorp/TTI to make
  6.  *       it not Sperry 5000-series dependent. He did all the hard work.
  7.  *       The original code used some unused bits in the tty structure;
  8.  *       they turned out to be only unused in the Sperry/NCR Tower version.
  9.  *       He added the code to move the status bits out. He also added the
  10.  *       DEBUG code, which helped me to understand a little better how
  11.  *       the bytes flowed.
  12.  * JRM - my unsubtle hacks to make it work with Microport.
  13.  *
  14.  * Other portions:
  15.  * Copyright (c) 1987, Jens-Uwe Mager, FOCUS Computer GmbH
  16.  * Not derived from licensed software.
  17.  *
  18.  * Permission is granted to freely use, copy, modify, and redistribute
  19.  * this software, provided that no attempt is made to gain profit from it,
  20.  * the author is not construed to be liable for any results of using the
  21.  * software, alterations are clearly marked as such, and this notice is
  22.  * not modified.
  23.  */
  24. #define MAXPTYS 32
  25.  
  26. /* TTI: */
  27. #define MRWAIT    01        /* master waiting in read */
  28. #define t_rloc    t_cc[0]        /* rchannel */
  29.  
  30. #define MWWAIT    02        /* master waiting in write */
  31. #define t_wloc    t_cc[1]        /* wchannel */
  32.  
  33. #define MOPEN    04        /* master is open */
  34. /* end TTI */
  35.  
  36. #include "sys/param.h"
  37. #include "sys/types.h"
  38. #include "sys/sysmacros.h"
  39. #include "sys/seg.h"
  40. #include "sys/systm.h"
  41. #include "sys/file.h"
  42. #include "sys/conf.h"
  43.  
  44. /* JRM: following removed
  45. #include "sys/page.h"
  46. #include "sys/immu.h"
  47. #include "sys/region.h"
  48. */
  49.  
  50. #include "sys/proc.h"
  51. #include "sys/dir.h"
  52. #include "sys/tty.h"
  53. #include "sys/signal.h"
  54. #include "sys/user.h"
  55. #include "sys/errno.h"
  56. #include "sys/termio.h"
  57. #include "sys/ttold.h"
  58.  
  59. /* JRM:
  60.  * note: this is not subtle...if you know of a slick way to get this from
  61.  *       config, please tell me about it! */
  62. extern int pts_cnt;
  63. struct tty pts_tty[MAXPTYS];
  64. int pts_state[MAXPTYS];
  65.  
  66. /*
  67.  * slave side is a fairly standard system V tty driver
  68.  */
  69. ptsopen(fdev, flag) /* TTI */
  70. {
  71.     register dev = minor(fdev); /* TTI */
  72.     register struct tty *tp = &pts_tty[dev];
  73.     extern int ptsproc();
  74.  
  75.     if (dev >= pts_cnt) {
  76.         u.u_error = ENXIO;
  77.         return;
  78.     }
  79.     if ((tp->t_state & (ISOPEN|WOPEN)) == 0) {
  80.         ttinit(tp);
  81.         tp->t_proc = ptsproc;
  82.     }
  83.     /*
  84.      * if master is still open, don't wait for carrier
  85.      */
  86.     if (pts_state[dev] & MOPEN) /* TTI */
  87.         tp->t_state |= CARR_ON;
  88.     if (!(flag & FNDELAY)) {
  89.         while ((tp->t_state & CARR_ON) == 0) {
  90.             tp->t_state |= WOPEN;
  91.             sleep((caddr_t)&tp->t_canq, TTIPRI);
  92.         }
  93.     }
  94.     (*linesw[tp->t_line].l_open)(tp);
  95. }
  96.  
  97. ptswrite(fdev) /* TTI */
  98. {
  99.     register dev = minor(fdev); /* TTI */
  100.     register struct tty *tp = &pts_tty[dev];
  101.  
  102. #ifdef DEBUG
  103.         printf("T_TIME\n"); /* TTI */
  104. #endif DEBUG
  105.     (*linesw[tp->t_line].l_write)(tp);
  106. }
  107.  
  108. ptsread(fdev) /* TTI */
  109. {
  110.     register dev = minor(fdev); /* TTI */
  111.     register struct tty *tp = &pts_tty[dev];
  112.  
  113.     (*linesw[tp->t_line].l_read)(tp);
  114. }
  115.  
  116. ptsclose(fdev) /* TTI */
  117. {
  118.     register dev = minor(fdev); /* TTI */
  119.     register struct tty *tp = &pts_tty[dev];
  120.     
  121.     (*linesw[tp->t_line].l_close)(tp);
  122.     tp->t_state &= ~CARR_ON;
  123. }
  124.  
  125. ptsioctl(fdev, cmd, arg, mode)
  126. {
  127.     register dev = minor(fdev); /* TTI */
  128.     register struct tty *tp = &pts_tty[dev];
  129.  
  130.     ttiocom(tp, cmd, arg, mode);
  131. }
  132.  
  133. ptsproc(tp, cmd)
  134. register struct tty *tp;
  135. {
  136.     register struct ccblock *tbuf;
  137.     extern ttrstrt();
  138.  
  139.     switch (cmd) {
  140.     case T_TIME:
  141. #ifdef DEBUG
  142.         printf("T_TIME\n"); /* TTI */
  143. #endif
  144.         tp->t_state &= ~TIMEOUT;
  145.         goto start;
  146.     case T_WFLUSH:
  147. #ifdef DEBUG
  148.         printf("T_WFLUSH\n"); /* TTI */
  149. #endif
  150.         tp->t_tbuf.c_size  -= tp->t_tbuf.c_count;
  151.         tp->t_tbuf.c_count = 0;
  152.         /* fall through */
  153.     case T_RESUME:
  154. #ifdef DEBUG
  155.         printf("T_RESUME\n"); /* TTI */
  156. #endif
  157.         tp->t_state &= ~TTSTOP;
  158.         /* fall through */
  159.     case T_OUTPUT:
  160. #ifdef DEBUG
  161.         printf("T_OUTPUT\n"); /* TTI */
  162. #endif
  163. start:
  164.         if (tp->t_state & (TTSTOP|TIMEOUT))
  165.             break;
  166.         tbuf = &tp->t_tbuf;
  167.         if (tbuf->c_ptr == NULL || tbuf->c_count == 0) {
  168.             if (tbuf->c_ptr)
  169.                 tbuf->c_ptr -= tbuf->c_size;
  170.             if (!(CPRES & (*linesw[tp->t_line].l_output)(tp)))
  171.                 break;
  172.         }
  173.         if (tbuf->c_count && (pts_state[tp-pts_tty] & MRWAIT)) {
  174.             pts_state[tp-pts_tty] &= ~MRWAIT; /* TTI */
  175.             wakeup((caddr_t)&tp->t_rloc);
  176.         }
  177.         break;
  178.     case T_SUSPEND:
  179. #ifdef DEBUG
  180.         printf("T_SUSPEND\n"); /* TTI */
  181. #endif
  182.         tp->t_state |= TTSTOP;
  183.         break;
  184.     case T_BLOCK:
  185. #ifdef DEBUG
  186.         printf("T_BLOCK\n"); /* TTI */
  187. #endif
  188.         /*
  189.          * the check for ICANON appears to be neccessary
  190.          * to avoid a hang when overflowing input
  191.          */
  192.         if ((tp->t_iflag & ICANON) == 0)
  193.             tp->t_state |= TBLOCK;
  194.         break;
  195.     case T_BREAK:
  196. #ifdef DEBUG
  197.         printf("T_BREAK\n"); /* TTI */
  198. #endif
  199.         tp->t_state |= TIMEOUT;
  200.         timeout(ttrstrt, tp, HZ/4);
  201.         break;
  202. #ifdef T_LOG_FLUSH
  203.     case T_LOG_FLUSH:
  204. #ifdef DEBUG
  205.         printf("T_LOG_FLUSH\n"); /* TTI */
  206. #endif
  207. #endif
  208.     case T_RFLUSH:
  209. #ifdef DEBUG
  210.         printf("T_RFLUSH\n"); /* TTI */
  211. #endif
  212.         if (!(tp->t_state & TBLOCK))
  213.             break;
  214.         /* fall through */
  215.     case T_UNBLOCK:
  216. #ifdef DEBUG
  217.         printf("T_UNBLOCK\n"); /* TTI */
  218. #endif
  219.         tp->t_state &= ~(TTXOFF|TBLOCK);
  220.         /* fall through */
  221.     case T_INPUT:
  222. #ifdef DEBUG
  223.         printf("T_INPUT\n"); /* TTI */
  224. #endif
  225.         if (pts_state[tp-pts_tty] & MWWAIT) {
  226.             pts_state[tp-pts_tty] &= ~MWWAIT; /* TTI */
  227.             wakeup((caddr_t)&tp->t_wloc);
  228.         }
  229.         break;
  230. #ifdef DEBUG
  231.     default: /* TTI */
  232.         printf("ptsproc: cmd %d\n",cmd);
  233. #endif
  234.     }
  235. }
  236.  
  237. /*
  238.  * master part - not actually like a tty
  239.  */
  240.  
  241. ptmopen(fdev, flag) /* TTI */
  242. {
  243.     register dev = minor(fdev); /* TTI */
  244.     register struct tty *tp = &pts_tty[dev];
  245.  
  246. #ifdef DEBUG
  247.     printf("ptmopen(%d)\n",dev); /* TTI */
  248. #endif
  249.     if (dev >= pts_cnt) {
  250.         u.u_error = ENXIO;
  251.         return;
  252.     }
  253.     /*
  254.      * allow only one controlling process
  255.      */
  256.     if (pts_state[dev] & MOPEN) { /* TTI */
  257.         u.u_error = EBUSY;
  258.         return;
  259.     }
  260.     if (tp->t_state & WOPEN)
  261.         wakeup((caddr_t)&tp->t_canq);
  262.     tp->t_state |= CARR_ON; /* TTI */
  263.     pts_state[dev] |= MOPEN;
  264. }
  265.  
  266. ptmread(fdev) /* TTI */
  267. {
  268.     register dev = minor(fdev); /* TTI */
  269.     register struct tty *tp = &pts_tty[dev];
  270.     register n;
  271.  
  272.     if ((tp->t_state & (ISOPEN|TTIOW)) == 0) { /* TTI */
  273. #ifdef DEBUG
  274.     printf("ptmread(%d) EIO\n",dev); /* TTI */
  275. #endif
  276.         u.u_error = EIO;
  277.         return;
  278.     }
  279. #ifdef DEBUG
  280.     printf("ptmread(%d)\n",dev); /* TTI */
  281. #endif
  282.     while (u.u_count>0) { /* TTI */
  283.         ptsproc(tp, T_OUTPUT);
  284.         if ((tp->t_state & (TTSTOP|TIMEOUT))
  285.             || tp->t_tbuf.c_ptr == NULL || tp->t_tbuf.c_count == 0) {
  286.             if (u.u_fmode & FNDELAY)
  287.                 break;
  288.             pts_state[dev] |= MRWAIT; /* TTI */
  289.             sleep((caddr_t)&tp->t_rloc, TTIPRI);
  290.             continue;
  291.         }
  292.         n = min(u.u_count, tp->t_tbuf.c_count);
  293.         if (n) {
  294.             if (copyout(tp->t_tbuf.c_ptr, u.u_base, n)) {
  295.                 u.u_error = EFAULT;
  296.                 break;
  297.             }
  298.             tp->t_tbuf.c_count -= n;
  299.             tp->t_tbuf.c_ptr += n;
  300.             u.u_base += n;
  301.             u.u_count -= n;
  302.             break; /* JRM: added - without this, the flow from
  303.                            slave to master is buffered */
  304.         }
  305.     }
  306. }
  307.  
  308. ptmwrite(fdev) /* TTI */
  309. {
  310.     register dev = minor(fdev); /* TTI */
  311.     register struct tty *tp = &pts_tty[dev];
  312.     register n;
  313.  
  314.     if ((tp->t_state & ISOPEN) == 0) {
  315.         u.u_error = EIO;
  316.         return;
  317.     }
  318. #ifdef DEBUG
  319.     printf("ptmwrite(%d)\n",dev); /* TTI */
  320. #endif
  321.     while (u.u_count>0) { /* TTI */
  322.         if ((tp->t_state & TBLOCK) || tp->t_rbuf.c_ptr == NULL) {
  323.             if (u.u_fmode & FNDELAY)
  324.                 break;
  325.             pts_state[dev] |= MWWAIT; /* TTI */
  326.             sleep((caddr_t)&tp->t_wloc, TTOPRI);
  327.             continue;
  328.         }
  329.         n = min(u.u_count, tp->t_rbuf.c_count);
  330.         if (n) {
  331.             if (copyin(u.u_base,tp->t_rbuf.c_ptr, n)) {
  332.                 u.u_error = EFAULT;
  333.                 break;
  334.             }
  335.             tp->t_rbuf.c_count -= n;
  336.             u.u_base += n;
  337.             u.u_count -= n;
  338.         }
  339. #ifdef vax || m68k /* TTI */
  340.         /*
  341.          * somebody told me this is necessary on the vax
  342.          */
  343.         (*linesw[tp->t_line].l_input)(tp, L_BUF);
  344. #else
  345.         (*linesw[tp->t_line].l_input)(tp);
  346. #endif
  347.     }
  348. }
  349.  
  350. ptmclose(fdev) /* TTI */
  351. {
  352.     register dev = minor(fdev); /* TTI */
  353.     register struct tty *tp = &pts_tty[dev];
  354.  
  355. #ifdef DEBUG
  356.     printf("ptmclose(%d)\n",dev); /* TTI */
  357. #endif
  358.     if (tp->t_state & ISOPEN) {
  359.         signal(tp->t_pgrp, SIGHUP);
  360.         ttyflush(tp, FREAD|FWRITE);
  361.     }
  362.     /*
  363.      * virtual carrier gone
  364.      */
  365.     tp->t_state &= ~CARR_ON; /* TTI */
  366.     pts_state[dev] &= ~MOPEN;
  367. }
  368.  
  369. ptmioctl(fdev, cmd, arg, mode) /* TTI */
  370. {
  371.     register dev = minor(fdev); /* TTI */
  372.     register struct tty *tp = &pts_tty[dev];
  373.  
  374.     /*
  375.      * sorry, but we can't fiddle with the tty struct without
  376.      * having done LDOPEN
  377.      */
  378.     if (tp->t_state & ISOPEN) {
  379.         if (cmd == TCSBRK && arg ==  NULL) {
  380.             signal(tp->t_pgrp, SIGINT);
  381.             if ((tp->t_iflag & NOFLSH) == 0)
  382.                 ttyflush(tp, FREAD|FWRITE);
  383.         } else {
  384.             /*
  385.              * we must flush output to avoid hang in ttywait
  386.              */
  387.             if (cmd == TCSETAW || cmd == TCSETAF || cmd == TCSBRK
  388.                 || cmd == TIOCSETP)
  389.                 ttyflush(FWRITE);
  390.             ttiocom(tp, cmd, arg, mode);
  391.         }
  392.     }
  393. }
  394.