home *** CD-ROM | disk | FTP | other *** search
/ minnie.tuhs.org / unixen.tar / unixen / PDP-11 / Trees / V7 / usr / sys / dev / mx1.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-02-03  |  8.4 KB  |  490 lines

  1. #include "../h/param.h"
  2. #include "../h/systm.h"
  3. #include "../h/dir.h"
  4. #include "../h/user.h"
  5. #include "../h/reg.h"
  6. #include "../h/proc.h"
  7. #include "../h/tty.h"
  8. #include "../h/inode.h"
  9. #define    KERNEL    1
  10. #include "../h/mx.h"
  11. #include "../h/file.h"
  12. #include "../h/conf.h"
  13.  
  14. /*
  15.  * Multiplexor:   clist version
  16.  *
  17.  * installation:
  18.  *    requires a line in cdevsw -
  19.  *        mxopen, mxclose, mxread, mxwrite, mxioctl, 0,
  20.  *
  21.  *    also requires a line in linesw -
  22.  *        mxopen, mxclose, mcread, mcwrite, mxioctl, nulldev, nulldev,
  23.  *
  24.  *    The linesw entry for mpx should be the last one in the table.
  25.  *    'nldisp' (number of line disciplines) should not include the
  26.  *    mpx line.  This is to prevent mpx from being enabled by an ioctl.
  27.  
  28.  *    mxtty.c must be loaded instead of tty.c so that certain
  29.  *    sleeps will not be done if a typewriter is connected to
  30.  *    a channel and so that sdata will be called from ttyinput.
  31.  *    
  32.  */
  33. struct    chan    chans[NCHANS];
  34. struct    schan    schans[NPORTS];
  35. struct    group    *groups[NGROUPS];
  36. int    mpxline;
  37. struct chan *xcp();
  38. dev_t    mpxdev    = -1;
  39.  
  40.  
  41. char    mcdebugs[NDEBUGS];
  42.  
  43.  
  44. /*
  45.  * Allocate a channel, set c_index to index.
  46.  */
  47. struct    chan *
  48. challoc(index, isport)
  49. {
  50. register s;
  51.  
  52.     s = spl6();
  53.     if (isport) {
  54.         register struct schan *cp, *lastcp;
  55.         cp = schans;
  56.         lastcp = &schans[NPORTS];
  57.         for (; cp < lastcp; cp++)
  58.             if (cp->c_group==NULL) {
  59.                 cp->c_index = index;
  60.                 cp->c_pgrp = 0;
  61.                 cp->c_flags = 0;
  62.                 splx(s);
  63.                 return((struct chan *)cp);
  64.             }
  65.         goto out;
  66.     } else {
  67.         register struct chan *cp, *lastcp;
  68.         cp = chans;
  69.         lastcp = &chans[NCHANS];
  70.         for(; cp < lastcp; cp++) 
  71.             if(cp->c_group==NULL) {
  72.                 cp->c_index = index;
  73.                 cp->c_pgrp = 0;
  74.                 cp->c_flags = 0;
  75.                 splx(s);
  76.                 return(cp);
  77.             }
  78.     }
  79. out:
  80.     splx(s);
  81.     return(NULL);
  82. }
  83.  
  84.  
  85.  
  86. /*
  87.  * Allocate a group table cell.
  88.  */
  89. gpalloc()
  90. {
  91. register i,s;
  92.  
  93.     s = spl6();
  94.     for(i = NGROUPS-1; i>=0; i--)
  95.         if (groups[i]==NULL) {
  96.             groups[i]++;
  97.             break;
  98.         }
  99.     splx(s);
  100.     return(i);
  101. }
  102.  
  103.  
  104. /*
  105.  * Add a channel to the group in
  106.  * inode ip.
  107.  */
  108. struct chan *
  109. addch(ip, isport)
  110. struct inode *ip;
  111. {
  112. register struct chan *cp;
  113. register struct group *gp;
  114. register i;
  115.  
  116.     plock(ip);
  117.     gp = &ip->i_un.i_group;
  118.     for(i=0;i<NINDEX;i++) {
  119.         cp = (struct chan *)gp->g_chans[i];
  120.         if (cp == NULL) {
  121.             if ((cp=challoc(i, isport)) != NULL) {
  122.                 gp->g_chans[i] = cp;
  123.                 cp->c_group = gp;
  124.             }
  125.             break;
  126.         }
  127.         cp = NULL;
  128.     }
  129.     prele(ip);
  130.     return(cp);
  131. }
  132.  
  133.  
  134.  
  135.  
  136. /*
  137.  * mpxchan system call
  138.  */
  139. mpxchan()
  140. {
  141. struct    inode *ip, *gip;
  142. register int i;
  143. extern    mxopen(), mcread();
  144. extern    sdata(), scontrol();
  145. dev_t    dev;
  146. struct    tty *tp;
  147. struct    file *fp, *chfp, *gfp;
  148. struct    chan *cp;
  149. struct    group *gp, *ngp;
  150. struct    a {
  151.     int    cmd;
  152.     int    *argvec;
  153. } *uap;
  154. struct mx_args vec;
  155.  
  156.  
  157.     /*
  158.      * common setup code.
  159.      */
  160.     uap = (struct a *)u.u_ap;
  161.     copyin((caddr_t)uap->argvec, (caddr_t)&vec, sizeof vec);
  162.     gp = NULL;
  163.     switch(uap->cmd) {
  164.     case NPGRP:
  165.         if (vec.m_arg[1] < 0)
  166.             goto sw;
  167.     case CHAN:
  168.     case JOIN:
  169.     case EXTR:
  170.     case ATTACH:
  171.     case DETACH:
  172.     case CSIG:
  173.         gfp = getf(vec.m_arg[1]);
  174.         if (gfp==NULL)
  175.             goto bad;
  176.         gip = gfp->f_inode;
  177.         gp = &gip->i_un.i_group;
  178.         if (gp->g_inode != gip)
  179.             goto bad;
  180.     }
  181.  
  182. sw:
  183.     switch(uap->cmd) {
  184.     /*
  185.      * creat an mpx file.
  186.      */
  187.     case MPX:
  188.     case MPXN:
  189.         if (mpxdev < 0) {
  190.             for(i=0; linesw[i].l_open; i++) 
  191.                 if (linesw[i].l_read == mcread) {
  192.                     mpxline = i;
  193.                     goto found1;
  194.                 }
  195.             goto bad;
  196.  
  197.         found1:
  198.             for(i=0; cdevsw[i].d_open; i++) {
  199.                 if (cdevsw[i].d_open == mxopen)
  200.                     goto found2;
  201.             }
  202.         bad:
  203.             u.u_error = ENXIO;
  204.             return;
  205.         found2:
  206.             mpxdev = (dev_t)(i<<8);
  207.         }
  208.         if (uap->cmd==MPXN) {
  209.             if ((ip=ialloc(rootdev))==NULL)
  210.                 goto bad;
  211.             ip->i_mode = 0666+IFCHR;
  212.             goto merge;
  213.         }
  214.         u.u_dirp = vec.m_name;
  215.         ip = namei(uchar,1);
  216.         if (ip != NULL) {
  217.             u.u_error = EEXIST;
  218.             iput(ip);
  219.             return;
  220.         }
  221.         if (u.u_error)
  222.             return;
  223.         ip = maknode((vec.m_arg[0]&0777)+IFCHR);
  224.         if (ip == NULL)
  225.             return;
  226.     merge:
  227.         if ((i = gpalloc()) < 0) {
  228.             iput(ip);
  229.             goto bad;
  230.         }
  231.         ip->i_un.i_rdev = (daddr_t)(mpxdev+i);
  232.         gp = &ip->i_un.i_group;
  233.         groups[i] = gp;
  234.         gp->g_inode = ip;
  235.         gp->g_state = COPEN;
  236.         gp->g_group = NULL;
  237.         gp->g_index = 0;
  238.         gp->g_rotmask = 1;
  239.         gp->g_rot = 0;
  240.         gp->g_datq = 0;
  241.         open1(ip,FREAD+FWRITE,2);
  242.         if (u.u_error) {
  243.             groups[i] = NULL;
  244.             iput(ip);
  245.             goto bad;
  246.         }
  247.         ip->i_mode = (ip->i_mode & ~IFMT) | IFMPC;
  248.         ip->i_count++;
  249.         ip->i_flag |= IACC|IUPD|ICHG;
  250.         fp = u.u_ofile[u.u_r.r_val1];
  251.         fp->f_flag |= FMP;
  252.         fp->f_un.f_chan = NULL;
  253.         gp->g_file = fp;
  254.         for(i=0;i<NINDEX;)
  255.             gp->g_chans[i++] = NULL;
  256.         return;
  257.     /*
  258.      * join file descriptor (arg 0) to group (arg 1)
  259.      * return channel number
  260.      */
  261.     case JOIN:
  262.         if ((fp=getf(vec.m_arg[0]))==NULL)
  263.             goto bad;
  264.         ip = fp->f_inode;
  265.         i = ip->i_mode & IFMT;
  266.         if (i == IFMPC) {
  267.             if ((fp->f_flag&FMP) != FMP) {
  268.                 goto bad;
  269.             }
  270.             ngp = &ip->i_un.i_group;
  271.             mlink (ngp, gp);
  272.             fp->f_count++;
  273.             return;
  274.         }
  275.         if (i != IFCHR) 
  276.             goto bad;
  277.         dev = (dev_t)ip->i_un.i_rdev;
  278.         tp = cdevsw[major(dev)].d_ttys;
  279.         if (tp==NULL)
  280.             goto bad;
  281.         tp = &tp[minor(dev)];
  282.         if (tp->t_chan)
  283.             goto bad;
  284.         if ((cp=addch(gip, 1))==NULL)
  285.             goto bad;
  286.         tp->t_chan = cp;
  287.         cp->c_fy = fp;
  288.         fp->f_count++;
  289.         cp->c_ttyp = tp;
  290.         cp->c_line = tp->t_line;
  291.         cp->c_flags = XGRP+PORT;
  292.         u.u_r.r_val1 = cpx(cp);
  293.         return;
  294.     /*
  295.      * attach channel (arg 0) to group (arg 1)
  296.      */
  297.     case ATTACH:
  298.         cp = xcp(gp, vec.m_arg[0]);
  299.         if (cp==NULL)
  300.             goto bad;
  301.         u.u_r.r_val1 = cpx(cp);
  302.         wakeup((caddr_t)cp);
  303.         return;
  304.     case DETACH:
  305.         cp = xcp(gp, vec.m_arg[0]);
  306.         if (cp==NULL)
  307.             goto bad;
  308.         detach(cp);
  309.         return;
  310.     /*
  311.      * extract channel (arg 0) from group (arg 1).
  312.      */
  313.     case EXTR:
  314.         cp = xcp(gp, vec.m_arg[0]);
  315.         if (cp==NULL) {
  316.             goto bad;
  317.         }
  318.         if (cp->c_flags & ISGRP) {
  319.             mxfalloc(((struct group *)cp)->g_file);
  320.             return;
  321.         }
  322.         if ((fp = cp->c_fy) != NULL) {
  323.             mxfalloc(fp);
  324.             return;
  325.         }
  326.         if ((fp = falloc()) == NULL) {
  327.             return;
  328.         }
  329.         fp->f_inode = gip;
  330.         gip->i_count++;
  331.         fp->f_un.f_chan = cp;
  332.         fp->f_flag = (vec.m_arg[2]) ?
  333.                 (FREAD|FWRITE|FMPY) : (FREAD|FWRITE|FMPX);
  334.         cp->c_fy = fp;
  335.         return;
  336.     /*
  337.      * make new chan on group (arg 1)
  338.      */
  339.     case CHAN:
  340.         if ((cp=addch(gip, 0))==NULL)
  341.             goto bad;
  342.         cp->c_flags = XGRP;
  343.         cp->c_fy = NULL;
  344.         cp->c_ttyp = cp->c_ottyp = (struct tty *)cp;
  345.         cp->c_line = cp->c_oline = mpxline;
  346.         u.u_r.r_val1 = cpx(cp);
  347.         return;
  348.     /*
  349.      * connect fd (arg 0) to channel fd (arg 1)
  350.      * (arg 2 <  0) => fd to chan only
  351.      * (arg 2 >  0) => chan to fd only
  352.      * (arg 2 == 0) => both directions
  353.      */
  354.     case CONNECT:
  355.         if ((fp=getf(vec.m_arg[0]))==NULL)
  356.             goto bad;
  357.         if ((chfp=getf(vec.m_arg[1]))==NULL)
  358.             goto bad;
  359.         ip = fp->f_inode;
  360.         i = ip->i_mode&IFMT;
  361.         if (i!=IFCHR)
  362.             goto bad;
  363.         dev = (dev_t)ip->i_un.i_rdev;
  364.         tp = cdevsw[major(dev)].d_ttys;
  365.         if (tp==NULL)
  366.             goto bad;
  367.         tp = &tp[minor(dev)];
  368.         if (!(chfp->f_flag&FMPY)) {
  369.             goto bad;
  370.         }
  371.         cp = chfp->f_un.f_chan;
  372.         if (cp==NULL || cp->c_flags&PORT) {
  373.             goto bad;
  374.         }
  375.         i = vec.m_arg[2];
  376.         if (i>=0) {
  377.             cp->c_ottyp = tp;
  378.             cp->c_oline = tp->t_line;
  379.         }
  380.         if (i<=0)  {
  381.             tp->t_chan = cp;
  382.             cp->c_ttyp = tp;
  383.             cp->c_line = tp->t_line;
  384.         }
  385.         return;
  386.     case NPGRP: {
  387.         register struct proc *pp;
  388.  
  389.         if (gp != NULL) {
  390.             cp = xcp(gp, vec.m_arg[0]);
  391.             if (cp==NULL)
  392.                 goto bad;
  393.         }
  394.         pp = u.u_procp;
  395.         pp->p_pgrp = pp->p_pid;
  396.         if (vec.m_arg[2])
  397.             pp->p_pgrp = vec.m_arg[2];
  398.         if (gp != NULL)
  399.             cp->c_pgrp = pp->p_pgrp;
  400.         return;
  401.     }
  402.     case CSIG:
  403.         cp = xcp(gp, vec.m_arg[0]);
  404.         if (cp==NULL)
  405.             goto bad;
  406.         signal(cp->c_pgrp, vec.m_arg[2]);
  407.         return;
  408.     case DEBUG:
  409.         i = vec.m_arg[0];
  410.         if (i<0 || i>NDEBUGS)
  411.             return;
  412.         mcdebugs[i] = vec.m_arg[1];
  413.         if (i==ALL)
  414.             for(i=0;i<NDEBUGS;i++)
  415.                 mcdebugs[i] = vec.m_arg[1];
  416.         return;
  417.     default:
  418.         goto bad;
  419.     }
  420. }
  421.  
  422. detach(cp)
  423. register struct chan *cp;
  424. {
  425.     register struct group *gp;
  426.     register int i;
  427.  
  428.     if (cp->c_flags&ISGRP) {
  429.         gp = (struct group *)cp;
  430.         closef(gp->g_file);
  431.         i = ((struct group *)cp)->g_index;
  432.         gp->g_chans[i] = NULL;
  433.         return;
  434.     } else if (cp->c_flags&PORT && cp->c_ttyp != NULL) {
  435.         closef(cp->c_fy);
  436.         chdrain(cp);
  437.         chfree(cp);
  438.         return;
  439.     }
  440.     if (cp->c_fy && (cp->c_flags&WCLOSE)==0) {
  441.         cp->c_flags |= WCLOSE;
  442.         chwake(cp);
  443.     } else {
  444.         chdrain(cp);
  445.         chfree(cp);
  446.     }
  447. }
  448.  
  449.  
  450. mxfalloc(fp)
  451. register struct file *fp;
  452. {
  453. register i;
  454.  
  455.     if (fp==NULL) {
  456.         u.u_error = ENXIO;
  457.         return;
  458.     }
  459.  
  460.     i = ufalloc();
  461.     if (i < 0)
  462.         return;
  463.     u.u_ofile[i] = fp;
  464.     fp->f_count++;
  465.     u.u_r.r_val1 = i;
  466.     return;
  467. }
  468.  
  469.  
  470.  
  471.  
  472. mlink(sub,master)
  473. struct group *sub, *master;
  474. {
  475. register i;
  476.  
  477.  
  478.     for(i=0;i<NINDEX;i++) {
  479.         if (master->g_chans[i] != NULL)
  480.             continue;
  481.         master->g_chans[i] = (struct chan *)sub;
  482.         sub->g_group = master;
  483.         sub->g_index = i;
  484.         u.u_r.r_val1 = i;
  485.         return;
  486.     }
  487.     u.u_error = ENXIO;
  488.     return;
  489. }
  490.