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

  1. #define    KERNEL    1
  2. #include "../h/pk.p"
  3.  
  4. /*
  5.  * packet driver
  6.  */
  7.  
  8. char next[8]    ={ 1,2,3,4,5,6,7,0};    /* packet sequence numbers */
  9. char mask[8]    ={ 1,2,4,010,020,040,0100,0200 };
  10.  
  11. struct pack *pklines[NPLINES];
  12.  
  13.  
  14. /*
  15.  * receive control messages
  16.  */
  17.  
  18. pkcntl(cntl, pk)
  19. register cntl;
  20. register struct pack *pk;
  21. {
  22. register val;
  23. register m;
  24.  
  25.     val = cntl & MOD8;
  26.  
  27.     if ( NOTCNTL(cntl) ) {
  28.         pkbadframe(pk);
  29.         return;
  30.     }
  31.  
  32.     cntl >>= 3;
  33.     pk->p_state &= ~BADFRAME;
  34.     m = pk->p_msg;
  35.  
  36.     switch(cntl) {
  37.  
  38.     case INITB:
  39.         val++;
  40.         pk->p_xsize = pksizes[val];
  41.         pk->p_lpsize = val;
  42.         pk->p_bits = DTOM(pk->p_xsize);
  43.         if (pk->p_state & LIVE) {
  44.             pk->p_msg |= M_INITC;
  45.             break;
  46.         }
  47.         pk->p_state |= INITb;
  48.         if ((pk->p_state & INITa)==0) {
  49.             break;
  50.         }
  51.         pk->p_rmsg &= ~M_INITA;
  52.         pk->p_msg |= M_INITC;
  53.         break;
  54.  
  55.     case INITC:
  56.         if ((pk->p_state&INITab)==INITab) {
  57.             pk->p_state = LIVE;
  58.             WAKEUP(&pk->p_state);
  59.             pk->p_rmsg &= ~(M_INITA|M_INITB);
  60.         } else
  61.             if ((pk->p_state&LIVE)==0)
  62.                 pk->p_msg |= M_INITB;
  63.         if (val)
  64.             pk->p_swindow = val;
  65.         break;
  66.     case INITA:
  67.         if (val==0 && pk->p_state&LIVE) {
  68.             printf("alloc change\n");
  69.             break;
  70.         }
  71.         if (val) {
  72.             pk->p_state |= INITa;
  73.             pk->p_msg |= M_INITB;
  74.             pk->p_rmsg |= M_INITB;
  75.             pk->p_swindow = val;
  76.         }
  77.         break;
  78.     case RJ:
  79.         pk->p_state |= RXMIT;
  80.         pk->p_msg |= M_RR;
  81.     case RR:
  82.         pk->p_rpr = val;
  83.         if (pksack(pk)==0) {
  84.             WAKEUP(&pk->p_ps);
  85.         }
  86.         break;
  87.     case CLOSE:
  88.         pk->p_state = DOWN+RCLOSE;
  89.         pk->p_rmsg = 0;
  90.         WAKEUP(&pk->p_pr);
  91.         WAKEUP(&pk->p_ps);
  92.         WAKEUP(&pk->p_state);
  93.         return;
  94.     }
  95.     if (pk->p_msg==0)
  96.         pk->p_msg |= pk->p_rmsg;
  97.  
  98.  
  99.     if (m==0 && pk->p_msg)
  100.         pkoutput(pk);
  101. }
  102.  
  103.  
  104. /*
  105.  * Send RJ message on first framing error.
  106.  * Cleared by receiving a good frame 
  107.  * (pkcntl or pkdata).
  108.  */
  109. pkbadframe(pk)
  110. register struct pack *pk;
  111. {
  112.     WAKEUP(&pk->p_pr);
  113.     if (pk->p_state & BADFRAME)
  114.         return;
  115.     pk->p_state |= BADFRAME;
  116.     pk->p_timer = 2;
  117. }
  118.  
  119.  
  120.  
  121.  
  122. /*
  123.  * Look at sequence numbers (mostly).
  124.  */
  125. pkaccept(pk)
  126. register struct pack *pk;
  127. {
  128. register x, seq;
  129. char m, cntl, *p, imask, **bp;
  130. int bad, accept, skip, s, t, cc;
  131. unsigned short sum;
  132.  
  133.     bad = accept = skip = 0;
  134.     /*
  135.      * wait for input
  136.      */
  137.     LOCK;
  138.     x = next[pk->p_pr];
  139.     if((imask=pk->p_imap)==0 && pk->p_rcount==0) {
  140.         UNLOCK;
  141.         goto out;
  142.     }
  143.     pk->p_imap = 0;
  144.     UNLOCK;
  145.  
  146.  
  147.     /*
  148.      * determine input window in m.
  149.      */
  150.     t = (~(-1<<pk->p_rwindow)) <<x;
  151.     m = t;
  152.     m |= t>>8;
  153.  
  154.  
  155.     /*
  156.      * mark newly accepted input buffers
  157.      */
  158.     for(x=0; x<8; x++) {
  159.  
  160.         if ((imask & mask[x]) == 0)
  161.             continue;
  162.  
  163.         if (((cntl=pk->p_is[x])&0200)==0) {
  164.             bad++;
  165. free:
  166.             bp = (char **)pk->p_ib[x];
  167.             LOCK;
  168.             *bp = (char *)pk->p_ipool;
  169.             pk->p_ipool = bp;
  170.             pk->p_is[x] = 0;
  171.             UNLOCK;
  172.             continue;
  173.         }
  174.  
  175.         pk->p_is[x] = ~(B_COPY+B_MARK);
  176.         sum = (unsigned)chksum(pk->p_ib[x], pk->p_rsize) ^ (unsigned)cntl;
  177.         sum += pk->p_isum[x];
  178.         if (sum == CHECK) {
  179.             seq = (cntl>>3) & MOD8;
  180.             if (m & mask[seq]) {
  181.                 if (pk->p_is[seq] & (B_COPY | B_MARK)) {
  182.                 dup:
  183.                     skip++;
  184.                     goto free;
  185.                 }
  186.                 if (x != seq) {
  187.                     LOCK;
  188.                     p = pk->p_ib[x];
  189.                     pk->p_ib[x] = pk->p_ib[seq];
  190.                     pk->p_is[x] = pk->p_is[seq];
  191.                     pk->p_ib[seq] = p;
  192.                     UNLOCK;
  193.                 }
  194.                 pk->p_is[seq] = B_MARK;
  195.                 accept++;
  196.                 cc = 0;
  197.                 if (cntl&B_SHORT) {
  198.                     pk->p_is[seq] = B_MARK+B_SHORT;
  199.                     p = pk->p_ib[seq];
  200.                     cc = (unsigned)*p++;
  201.                     if (cc & 0200) {
  202.                         cc &= 0177;
  203.                         cc |= *p << 7;
  204.                     }
  205.                 }
  206.                 pk->p_isum[seq] = pk->p_rsize - cc;
  207.             } else {
  208.                 goto dup;
  209.             }
  210.         } else {
  211.             bad++;
  212.             goto free;
  213.         }
  214.     }
  215.  
  216.     /*
  217.      * scan window again turning marked buffers into
  218.      * COPY buffers and looking for missing sequence
  219.      * numbers.
  220.      */
  221.     accept = 0;
  222.     for(x=next[pk->p_pr],t= -1; m & mask[x]; x = next[x]) {
  223.         if (pk->p_is[x] & B_MARK)
  224.             pk->p_is[x] |= B_COPY;
  225.         if (pk->p_is[x] & B_COPY) {
  226.             if (t >= 0) {
  227.                 bp = (char **)pk->p_ib[x];
  228.                 LOCK;
  229.                 *bp = (char *)pk->p_ipool;
  230.                 pk->p_ipool = bp;
  231.                 pk->p_is[x] = 0;
  232.                 UNLOCK;
  233.                 skip++;
  234.             } else 
  235.                 accept++;
  236.         } else {
  237.             if (t<0)
  238.                 t = x;
  239.         }
  240.     }
  241.  
  242.     if (bad) {
  243.         pk->p_msg |= M_RJ;
  244.     } else 
  245.  
  246.     if (skip) {
  247.         pk->p_msg |= M_RR;
  248.     }
  249.  
  250.     pk->p_rcount = accept;
  251. out:
  252.     if (pk->p_msg)
  253.         pkoutput(pk);
  254.     return(accept);
  255. }
  256.  
  257.  
  258. pkread(S)
  259. SDEF;
  260. {
  261. register struct pack *pk;
  262. register x,s;
  263. int is,cc,xfr,count;
  264. char *cp, **bp;
  265.  
  266.     pk = PADDR;
  267.     xfr = 0;
  268.     count = -1;
  269.     while (pkaccept(pk) == 0) {
  270.         PKGETPKT(pk);
  271.         if (pk->p_state&DOWN) {
  272.             SETERROR;
  273.             goto out;
  274.         }
  275.         if (SLEEPNO) {
  276.             count++;
  277.             goto out;
  278.         }
  279.         SLEEP(&pk->p_pr, PKIPRI);
  280.     }
  281.     count = 0;
  282.  
  283.  
  284.     while (UCOUNT) {
  285.  
  286.         x = next[pk->p_pr];
  287.         is = pk->p_is[x];
  288.  
  289.         if (is & B_COPY) {
  290.             cc = MIN(pk->p_isum[x], UCOUNT);
  291.             if (cc==0 && xfr) {
  292.                 break;
  293.             }
  294.             if (is & B_RESID)
  295.                 cp = pk->p_rptr;
  296.             else {
  297.                 cp = pk->p_ib[x];
  298.                 if (is & B_SHORT) {
  299.                     if (*cp++ & 0200)
  300.                         *cp++;
  301.                 }
  302.             }
  303.             IOMOVE(cp,cc,B_READ);
  304.             count += cc;
  305.             xfr++;
  306.             pk->p_isum[x] -= cc;
  307.             if (pk->p_isum[x] == 0) {
  308.                 LOCK;
  309.                 pk->p_pr = x;
  310.                 bp = (char **)pk->p_ib[x];
  311.                 *bp = (char *)pk->p_ipool;
  312.                 pk->p_ipool = bp;
  313.                 pk->p_is[x] = 0;
  314.                 pk->p_rcount--;
  315.                 UNLOCK;
  316.                 pk->p_msg |= M_RR;
  317.             } else {
  318.                 pk->p_rptr = cp+cc;
  319.                 pk->p_is[x] |= B_RESID;
  320.             }
  321.             if (cc==0)
  322.                 break;
  323.         } else
  324.             break;
  325.     }
  326.     pkoutput(pk);
  327.     if (SLEEPNO)
  328.         count = pk->p_rcount;
  329. out:
  330.     return(count);
  331. }
  332.  
  333.  
  334.  
  335.  
  336. pkwrite(S)
  337. SDEF;
  338. {
  339. register struct pack *pk;
  340. register x;
  341. int partial;
  342. caddr_t cp;
  343. int cc, s, fc, count;
  344. int pktimeout();
  345.  
  346.     pk = PADDR;
  347.     if ((pk->p_state&LIVE)==0) {
  348.     down:
  349.         SIGNAL;
  350.         SETERROR;
  351.         return(-1);
  352.     }
  353.  
  354.     count = UCOUNT;
  355.     do {
  356.         LOCK;
  357.         while (pk->p_xcount>=pk->p_swindow)  {
  358.             pkoutput(pk);
  359.             PKGETPKT(pk);
  360.             SLEEP(&pk->p_ps,PKOPRI);
  361.             if (pk->p_state&DOWN)
  362.                 goto down;
  363.         }
  364.         x = next[pk->p_pscopy];
  365.         while (pk->p_os[x]!=B_NULL)  {
  366.             goto down;
  367.         }
  368.         pk->p_os[x] = B_MARK;
  369.         pk->p_pscopy = x;
  370.         pk->p_xcount++;
  371.         UNLOCK;
  372.  
  373.         cp = pk->p_ob[x] = (char *)GETEPACK;
  374.         partial = 0;
  375.         if ((int)UCOUNT < pk->p_xsize) {
  376.             cc = UCOUNT;
  377.             fc = pk->p_xsize - cc;
  378.             *cp = fc&0177;
  379.             if (fc > 127) {
  380.                 *cp++ |= 0200;
  381.                 *cp++ = fc>>7;
  382.             } else
  383.                 cp++;
  384.             partial = B_SHORT;
  385.         } else
  386.             cc = pk->p_xsize;
  387.         IOMOVE(cp,cc,B_WRITE);
  388.         pk->p_osum[x] = chksum(pk->p_ob[x], pk->p_xsize);
  389.         pk->p_os[x] = B_READY+partial;
  390.         pkoutput(pk);
  391.     } while (UCOUNT);
  392.  
  393.     return(count-UCOUNT);
  394. }
  395.  
  396. pksack(pk)
  397. register struct pack *pk;
  398. {
  399. register x, i;
  400. int s;
  401.  
  402.     i = 0;
  403.     LOCK;
  404.     for(x=pk->p_ps; x!=pk->p_rpr; ) {
  405.         x = next[x];
  406.         if (pk->p_os[x]&B_SENT) {
  407.             i++;
  408.             FREEPACK(pk->p_ob[x], pk->p_bits);
  409.             pk->p_os[x] = B_NULL;
  410.             pk->p_state &= ~WAITO;
  411.             pk->p_xcount--;
  412.             pk->p_ps = x;
  413.             WAKEUP(&pk->p_ps);
  414.         }
  415.     }
  416.     UNLOCK;
  417.     return(i);
  418. }
  419.  
  420.  
  421.  
  422. pkoutput(pk)
  423. register struct pack *pk;
  424. {
  425. register x;
  426. int s;
  427. char bstate;
  428. int i;
  429. SDEF;
  430. extern pkzot;
  431.  
  432.     ISYSTEM;
  433.     LOCK;
  434.     if (OBUSY) {
  435.         UNLOCK;
  436.         return;
  437.     }
  438.  
  439.  
  440.     /*
  441.      * find seq number and buffer state
  442.      * of next output packet
  443.      */
  444.     if (pk->p_state&RXMIT)  {
  445.         pk->p_nxtps = next[pk->p_rpr];
  446.         pk->p_state &= ~RXMIT;
  447.     }
  448.     x = pk->p_nxtps;
  449.     bstate = pk->p_os[x];
  450.  
  451.  
  452.     /*
  453.      * Send control packet if indicated
  454.      */
  455.     if (pk->p_msg) {
  456.         if (pk->p_msg & ~M_RR || !(bstate&B_READY) ) {
  457.             x = pk->p_msg;
  458.             for(i=0; i<8; i++) 
  459.                 if (x&1)
  460.                     break; else
  461.                 x >>= 1;
  462.             x = i;
  463.             x <<= 3;
  464.             switch(i) {
  465.             case CLOSE:
  466.                 break;
  467.             case RJ:
  468.             case RR:
  469.                 x += pk->p_pr;
  470.                 break;
  471.             case SRJ:
  472.                 break;
  473.             case INITB:
  474.                 x += pksize(pk->p_rsize);
  475.                 break;
  476.             case INITC:
  477.                 x += pk->p_rwindow;
  478.                 break;
  479.             case INITA:
  480.                 x += pk->p_rwindow;
  481.                 break;
  482.             }
  483.  
  484.             pk->p_msg &= ~mask[i];
  485.             pkxstart(pk, x, -1);
  486.             goto out;
  487.         }
  488.     }
  489.  
  490.  
  491.     /*
  492.      * Don't send data packets if line is marked dead.
  493.      */
  494.     if (pk->p_state&DOWN || (pk->p_state&LIVE)==0) {
  495.         WAKEUP(&pk->p_ps);
  496.         goto out;
  497.     }
  498.     /*
  499.      * Start transmission (or retransmission) of data packets.
  500.      */
  501.     if (bstate & (B_READY|B_SENT)) {
  502.         char seq;
  503.  
  504.         bstate |= B_SENT;
  505.         seq = x;
  506.         pk->p_nxtps = next[x];
  507.  
  508.         x = 0200+pk->p_pr+(seq<<3);
  509.         if (bstate & B_SHORT)
  510.             x |= 0100;
  511.         pkxstart(pk, x, seq);
  512.         if (pk->p_os[seq])
  513.             pk->p_os[seq] = bstate;
  514.         pk->p_nout++;
  515.         goto out;
  516.     }
  517.     /*
  518.      * enable timeout if there's nothing to send
  519.      * and transmission buffers are languishing
  520.      */
  521.     if (pk->p_xcount) {
  522.         pk->p_timer = 10+pkzot;
  523.         pk->p_state |= WAITO;
  524.     } else
  525.         pk->p_state &= ~WAITO;
  526.     WAKEUP(&pk->p_ps);
  527. out:
  528.     pk->p_obusy = 0;
  529.     UNLOCK;
  530. }
  531.  
  532.  
  533. /*
  534.  * shut down line by
  535.  *    ignoring new input
  536.  *    letting output drain
  537.  *    releasing space and turning off line discipline
  538.  */
  539. pkclose(S)
  540. SDEF;
  541. {
  542. register struct pack *pk;
  543. register i,s,rbits;
  544. char **bp;
  545.  
  546. #define    NTRIES    1
  547.  
  548.     pk = PADDR;
  549.     pk->p_state |= DRAINO;
  550.  
  551.  
  552.     /*
  553.      * try to flush output
  554.      */
  555.     i = 0;
  556.     LOCK;
  557.     if (pklive(pk)==0) {
  558.         pk->p_state = DOWN;
  559.         UNLOCK;
  560.         goto final;
  561.     }
  562.     pk->p_timer = 2;
  563.     while (pk->p_xcount && pk->p_state&LIVE) {
  564.         if (pk->p_state&(RCLOSE+DOWN) || ++i > NTRIES)
  565.             break;
  566.         pkoutput(pk);
  567.         SLEEP(&pk->p_ps,PKOPRI);
  568.     }
  569.     pk->p_timer = 0;
  570.     pk->p_state |= DOWN;
  571.     UNLOCK;
  572.  
  573.  
  574.     /*
  575.      * try to exchange CLOSE messages
  576.      */
  577.     i = 0;
  578.     while ((pk->p_state&RCLOSE)==0 && i<NTRIES) {
  579.         pk->p_msg = M_CLOSE;
  580.         pk->p_timer = 2;
  581.         pkoutput(pk);
  582.         SLEEP(&pk->p_ps, PKOPRI);
  583.         i++;
  584.     }
  585.  
  586.  
  587. final:
  588.     TURNOFF;
  589.  
  590.  
  591.     /*
  592.      * free space
  593.      */
  594.     rbits = DTOM(pk->p_rsize);
  595.     for (i=0;i<8;i++) {
  596.         if (pk->p_os[i]!=B_NULL) {
  597.             FREEPACK(pk->p_ob[i],pk->p_bits);
  598.             pk->p_xcount--;
  599.         }
  600.         if (pk->p_is[i]!=B_NULL)  {
  601.             FREEPACK(pk->p_ib[i],rbits);
  602.         }
  603.     }
  604.     LOCK;
  605.     while (pk->p_ipool != NULL) {
  606.         bp = pk->p_ipool;
  607.         pk->p_ipool = (char **)*bp;
  608.         FREEPACK((caddr_t)bp, rbits);
  609.     }
  610.     UNLOCK;
  611.     for(i=0;i<NPLINES;i++)
  612.         if (pklines[i]==pk)  {
  613.             pklines[i] = NULL;
  614.         }
  615.     FREEPACK((caddr_t)pk, npbits);
  616. }
  617.  
  618.  
  619.  
  620. pkreset(pk)
  621. register struct pack *pk;
  622. {
  623.  
  624.     pk->p_ps = pk->p_pr =  pk->p_rpr = 0;
  625.     pk->p_nxtps = 1;
  626. }
  627.  
  628. chksum(s,n)
  629. register char *s;
  630. register n;
  631. {
  632.     register short sum;
  633.     register unsigned t;
  634.     register x;
  635.  
  636.     sum = -1;
  637.     x = 0;
  638.  
  639.     do {
  640.         if (sum<0) {
  641.             sum <<= 1;
  642.             sum++;
  643.         } else
  644.             sum <<= 1;
  645.         t = sum;
  646.         sum += (unsigned)*s++;
  647.         x += sum^n;
  648.         if ((unsigned)sum <= t) {
  649.             sum ^= x;
  650.         }
  651.     } while (--n > 0);
  652.  
  653.     return(sum);
  654. }
  655.  
  656. pkline(pk)
  657. register struct pack *pk;
  658. {
  659. register i;
  660.     for(i=0;i<NPLINES;i++) {
  661.         if (pklines[i]==pk)
  662.             return(i);
  663.     }
  664.     return(-i);
  665. }
  666.  
  667. pkzero(s,n)
  668. register char *s;
  669. register n;
  670. {
  671.     while (n--)
  672.         *s++ = 0;
  673. }
  674.  
  675. pksize(n)
  676. register n;
  677. {
  678. register k;
  679.  
  680.     n >>= 5;
  681.     for(k=0; n >>= 1; k++);
  682.     return(k);
  683. }
  684.