113663Ssam #ifndef lint 2*25706Sbloom static char sccsid[] = "@(#)pk0.c 5.5 (Berkeley) 01/06/86"; 313663Ssam #endif 413663Ssam 518620Sralph #include "uucp.h" 613663Ssam #include "pk.h" 713663Ssam 813663Ssam /* 913663Ssam * packet driver 1013663Ssam */ 1113663Ssam 1217836Sralph char next[8] = { 1, 2, 3, 4, 5, 6, 7, 0}; /* packet sequence numbers */ 1317836Sralph char mask[8] = { 1, 2, 4, 010, 020, 040, 0100, 0200 }; 1413663Ssam 1513663Ssam struct pack *pklines[NPLINES]; 1613663Ssam 17*25706Sbloom #define PKTIME 4 18*25706Sbloom extern int pktimeout, Ntimeout; 19*25706Sbloom 2013663Ssam /* 2113663Ssam * receive control messages 2213663Ssam */ 2313663Ssam pkcntl(c, pk) 2413663Ssam register struct pack *pk; 2513663Ssam { 2617836Sralph register cntl, val; 2713663Ssam 2813663Ssam val = c & MOD8; 2913663Ssam cntl = (c>>3) & MOD8; 3013663Ssam 3117836Sralph if (!ISCNTL(c)) { 3217836Sralph logent("PK0", "not cntl"); 3313663Ssam return; 3413663Ssam } 3513663Ssam 3613663Ssam switch(cntl) { 3713663Ssam case INITB: 3813663Ssam val++; 3913663Ssam pk->p_xsize = pksizes[val]; 4013663Ssam pk->p_lpsize = val; 4117836Sralph pk->p_bits = 1; 4213663Ssam if (pk->p_state & LIVE) { 4313663Ssam pk->p_msg |= M_INITC; 4413663Ssam break; 4513663Ssam } 4613663Ssam pk->p_state |= INITb; 4713663Ssam if ((pk->p_state & INITa)==0) { 4813663Ssam break; 4913663Ssam } 5013663Ssam pk->p_rmsg &= ~M_INITA; 5113663Ssam pk->p_msg |= M_INITC; 5213663Ssam break; 5313663Ssam 5413663Ssam case INITC: 5513663Ssam if ((pk->p_state&INITab)==INITab) { 5613663Ssam pk->p_state = LIVE; 5713663Ssam pk->p_rmsg &= ~M_INITB; 5813663Ssam } else 5913663Ssam pk->p_msg |= M_INITB; 6013663Ssam if (val) 6113663Ssam pk->p_swindow = val; 6213663Ssam break; 6313663Ssam case INITA: 6417836Sralph if (val == 0 && pk->p_state&LIVE) { 6517836Sralph logent("PK0", "alloc change not implemented"); 6613663Ssam break; 6713663Ssam } 6813663Ssam if (val) { 6913663Ssam pk->p_state |= INITa; 7013663Ssam pk->p_msg |= M_INITB; 7113663Ssam pk->p_rmsg |= M_INITB; 7213663Ssam pk->p_swindow = val; 7313663Ssam } 7413663Ssam break; 7513663Ssam case RJ: 7613663Ssam pk->p_state |= RXMIT; 7713663Ssam pk->p_msg |= M_RR; 7813663Ssam case RR: 7913663Ssam pk->p_rpr = val; 8017836Sralph (void) pksack(pk); 8113663Ssam break; 8213663Ssam case SRJ: 8317836Sralph logent("PK0", "srj not implemented"); 8413663Ssam break; 8513663Ssam case CLOSE: 8613663Ssam pk->p_state = DOWN+RCLOSE; 8713663Ssam return; 8813663Ssam } 8913663Ssam if (pk->p_msg) 9013663Ssam pkoutput(pk); 9113663Ssam } 9213663Ssam 9313663Ssam pkaccept(pk) 9413663Ssam register struct pack *pk; 9513663Ssam { 9617836Sralph register x, seq; 9717836Sralph char m, cntl, *p, imask, **bp; 9817836Sralph int bad, accept, skip, t, cc; 9917836Sralph unsigned short sum; 10013663Ssam 10113663Ssam bad = accept = skip = 0; 10213663Ssam /* 10313663Ssam * wait for input 10413663Ssam */ 10513663Ssam x = next[pk->p_pr]; 10617836Sralph while ((imask=pk->p_imap) == 0 && pk->p_rcount == 0) { 10717836Sralph pkgetpack(pk); 10813663Ssam } 10913663Ssam pk->p_imap = 0; 11013663Ssam 11113663Ssam /* 11213663Ssam * determine input window in m. 11313663Ssam */ 11413663Ssam t = (~(-1<<(int)(pk->p_rwindow))) <<x; 11513663Ssam m = t; 11613663Ssam m |= t>>8; 11713663Ssam 11813663Ssam /* 11913663Ssam * mark newly accepted input buffers 12013663Ssam */ 12113663Ssam for(x=0; x<8; x++) { 12213663Ssam if ((imask & mask[x]) == 0) 12313663Ssam continue; 12413663Ssam 12517836Sralph if (((cntl=pk->p_is[x])&0200) == 0) { 12613663Ssam bad++; 12713663Ssam free: 12813663Ssam bp = (char **)pk->p_ib[x]; 12913663Ssam *bp = (char *)pk->p_ipool; 13013663Ssam pk->p_ipool = bp; 13113663Ssam pk->p_is[x] = 0; 13213663Ssam continue; 13313663Ssam } 13413663Ssam 13513663Ssam pk->p_is[x] = ~(B_COPY+B_MARK); 13613663Ssam sum = (unsigned)chksum(pk->p_ib[x], pk->p_rsize) ^ (unsigned)(cntl&0377); 13713663Ssam sum += pk->p_isum[x]; 13813663Ssam if (sum == CHECK) { 13913663Ssam seq = (cntl>>3) & MOD8; 14013663Ssam if (m & mask[seq]) { 14113663Ssam if (pk->p_is[seq] & (B_COPY | B_MARK)) { 14213663Ssam dup: 14313663Ssam pk->p_msg |= M_RR; 14413663Ssam skip++; 14513663Ssam goto free; 14613663Ssam } 14713663Ssam if (x != seq) { 14813663Ssam p = pk->p_ib[x]; 14913663Ssam pk->p_ib[x] = pk->p_ib[seq]; 15013663Ssam pk->p_is[x] = pk->p_is[seq]; 15113663Ssam pk->p_ib[seq] = p; 15213663Ssam } 15313663Ssam pk->p_is[seq] = B_MARK; 15413663Ssam accept++; 15513663Ssam cc = 0; 15613663Ssam if (cntl&B_SHORT) { 15713663Ssam pk->p_is[seq] = B_MARK+B_SHORT; 15813663Ssam p = pk->p_ib[seq]; 15913663Ssam cc = (unsigned)*p++ & 0377; 16013663Ssam if (cc & 0200) { 16113663Ssam cc &= 0177; 16213663Ssam cc |= *p << 7; 16313663Ssam } 16413663Ssam } 16513663Ssam pk->p_isum[seq] = pk->p_rsize - cc; 16613663Ssam } else { 16713663Ssam goto dup; 16813663Ssam } 16913663Ssam } else { 17013663Ssam bad++; 17113663Ssam goto free; 17213663Ssam } 17313663Ssam } 17413663Ssam 17513663Ssam /* 17613663Ssam * scan window again turning marked buffers into 17713663Ssam * COPY buffers and looking for missing sequence 17813663Ssam * numbers. 17913663Ssam */ 18013663Ssam accept = 0; 18117836Sralph t = -1; 18217836Sralph for(x=next[pk->p_pr]; m & mask[x]; x = next[x]) { 18313663Ssam if (pk->p_is[x] & B_MARK) 18413663Ssam pk->p_is[x] |= B_COPY; 18517836Sralph 18613663Ssam if (pk->p_is[x] & B_COPY) { 18713663Ssam if (t >= 0) { 18813663Ssam bp = (char **)pk->p_ib[x]; 18913663Ssam *bp = (char *)pk->p_ipool; 19013663Ssam pk->p_ipool = bp; 19113663Ssam pk->p_is[x] = 0; 19213663Ssam skip++; 19317836Sralph } else 19413663Ssam accept++; 19513663Ssam } else { 19613663Ssam if (t<0) 19713663Ssam t = x; 19813663Ssam } 19913663Ssam } 20013663Ssam 20113663Ssam if (bad) { 20213663Ssam pk->p_msg |= M_RJ; 20313663Ssam } 20413663Ssam 20513663Ssam if (skip) { 20613663Ssam pk->p_msg |= M_RR; 20713663Ssam } 20813663Ssam 20913663Ssam pk->p_rcount = accept; 21017836Sralph return accept; 21113663Ssam } 21213663Ssam 21317836Sralph /*ARGSUSED*/ 21423614Sbloom pkread(pk, ibuf, icount) 21523614Sbloom register struct pack *pk; 21623614Sbloom char *ibuf; 21717836Sralph int icount; 21813663Ssam { 21917836Sralph register x; 22017836Sralph int is, cc, xfr, count; 22117836Sralph char *cp, **bp; 22213663Ssam 22313663Ssam xfr = 0; 22413663Ssam count = 0; 225*25706Sbloom pktimeout = PKTIME; 226*25706Sbloom Ntimeout = 0; 22717836Sralph while (pkaccept(pk) == 0) 22817836Sralph ; 22913663Ssam 23017836Sralph while (icount) { 23113663Ssam x = next[pk->p_pr]; 23213663Ssam is = pk->p_is[x]; 23313663Ssam 23413663Ssam if (is & B_COPY) { 23517836Sralph cc = MIN(pk->p_isum[x], icount); 23613663Ssam if (cc==0 && xfr) { 23713663Ssam break; 23813663Ssam } 23913663Ssam if (is & B_RESID) 24013663Ssam cp = pk->p_rptr; 24113663Ssam else { 24213663Ssam cp = pk->p_ib[x]; 24313663Ssam if (is & B_SHORT) { 24413663Ssam if (*cp++ & 0200) 24513663Ssam cp++; 24613663Ssam } 24713663Ssam } 24817836Sralph pkmove(cp, ibuf, cc, B_READ); 24917836Sralph ibuf += cc; 25017836Sralph icount -= cc; 25113663Ssam count += cc; 25213663Ssam xfr++; 25313663Ssam pk->p_isum[x] -= cc; 25413663Ssam if (pk->p_isum[x] == 0) { 25513663Ssam pk->p_pr = x; 25613663Ssam bp = (char **)pk->p_ib[x]; 25713663Ssam *bp = (char *)pk->p_ipool; 25813663Ssam pk->p_ipool = bp; 25913663Ssam pk->p_is[x] = 0; 26013663Ssam pk->p_rcount--; 26113663Ssam pk->p_msg |= M_RR; 26213663Ssam } else { 26313663Ssam pk->p_rptr = cp+cc; 26413663Ssam pk->p_is[x] |= B_RESID; 26513663Ssam } 26613663Ssam if (cc==0) 26713663Ssam break; 26813663Ssam } else 26913663Ssam break; 27013663Ssam } 27113663Ssam pkoutput(pk); 27217836Sralph return count; 27313663Ssam } 27413663Ssam 27517836Sralph /*ARGSUSED*/ 27623614Sbloom pkwrite(pk, ibuf, icount) 27723614Sbloom register struct pack *pk; 27817836Sralph char *ibuf; 27917836Sralph int icount; 28013663Ssam { 28117836Sralph register x; 28217836Sralph int partial; 28317836Sralph caddr_t cp; 28417836Sralph int cc, fc, count; 28513663Ssam 28613663Ssam if (pk->p_state&DOWN || !pk->p_state&LIVE) { 28717836Sralph return -1; 28813663Ssam } 28913663Ssam 290*25706Sbloom pktimeout = PKTIME; 291*25706Sbloom Ntimeout = 0; 29217836Sralph count = icount; 29313663Ssam do { 29413663Ssam while (pk->p_xcount>=pk->p_swindow) { 29513663Ssam pkoutput(pk); 29617836Sralph pkgetpack(pk); 29713663Ssam } 29813663Ssam x = next[pk->p_pscopy]; 29913663Ssam while (pk->p_os[x]!=B_NULL) { 30017836Sralph pkgetpack(pk); 30113663Ssam } 30213663Ssam pk->p_os[x] = B_MARK; 30313663Ssam pk->p_pscopy = x; 30413663Ssam pk->p_xcount++; 30513663Ssam 30617836Sralph cp = pk->p_ob[x] = malloc((unsigned)pk->p_xsize); 30713663Ssam partial = 0; 30817836Sralph if ((int)icount < pk->p_xsize) { 30917836Sralph cc = icount; 31013663Ssam fc = pk->p_xsize - cc; 31113663Ssam *cp = fc&0177; 31213663Ssam if (fc > 127) { 31313663Ssam *cp++ |= 0200; 31413663Ssam *cp++ = fc>>7; 31513663Ssam } else 31613663Ssam cp++; 31713663Ssam partial = B_SHORT; 31813663Ssam } else 31913663Ssam cc = pk->p_xsize; 32017836Sralph pkmove(cp, ibuf, cc, B_WRITE); 32117836Sralph ibuf += cc; 32217836Sralph icount -= cc; 32313663Ssam pk->p_osum[x] = chksum(pk->p_ob[x], pk->p_xsize); 32413663Ssam pk->p_os[x] = B_READY+partial; 32513663Ssam pkoutput(pk); 32617836Sralph } while (icount); 32713663Ssam 32817836Sralph return count; 32913663Ssam } 33013663Ssam 33113663Ssam pksack(pk) 33213663Ssam register struct pack *pk; 33313663Ssam { 33417836Sralph register x, i; 33513663Ssam 33613663Ssam i = 0; 33713663Ssam for(x=pk->p_ps; x!=pk->p_rpr; ) { 33813663Ssam x = next[x]; 33913663Ssam if (pk->p_os[x]&B_SENT) { 34013663Ssam i++; 34113663Ssam pk->p_os[x] = B_NULL; 34213663Ssam pk->p_state &= ~WAITO; 34313663Ssam pk->p_xcount--; 34417836Sralph free((char *)pk->p_ob[x]); 34513663Ssam pk->p_ps = x; 34613663Ssam } 34713663Ssam } 34817836Sralph return i; 34913663Ssam } 35013663Ssam 35113663Ssam pkoutput(pk) 35213663Ssam register struct pack *pk; 35313663Ssam { 35417836Sralph register x; 35517836Sralph int i; 35617836Sralph char bstate; 35713663Ssam 35817836Sralph if (pk->p_obusy++) { 35913663Ssam pk->p_obusy--; 36013663Ssam return; 36113663Ssam } 36213663Ssam 36313663Ssam /* 36413663Ssam * find seq number and buffer state 36513663Ssam * of next output packet 36613663Ssam */ 36713663Ssam if (pk->p_state&RXMIT) { 36813663Ssam pk->p_nxtps = next[pk->p_rpr]; 36913663Ssam } 37013663Ssam x = pk->p_nxtps; 37113663Ssam bstate = pk->p_os[x]; 37213663Ssam 37313663Ssam /* 37413663Ssam * Send control packet if indicated 37513663Ssam */ 37613663Ssam if (pk->p_msg) { 37713663Ssam if (pk->p_msg & ~M_RR || !(bstate&B_READY) ) { 37813663Ssam x = pk->p_msg; 37917836Sralph for(i=0; i<8; i++) 38013663Ssam if (x&1) 38117836Sralph break; 38217836Sralph else 38317836Sralph x >>= 1; 38413663Ssam x = i; 38513663Ssam x <<= 3; 38613663Ssam switch(i) { 38713663Ssam case CLOSE: 38813663Ssam break; 38913663Ssam case RJ: 39013663Ssam case RR: 39113663Ssam x += pk->p_pr; 39213663Ssam break; 39313663Ssam case SRJ: 39413663Ssam break; 39513663Ssam case INITB: 39613663Ssam x += pksize(pk->p_rsize); 39713663Ssam break; 39813663Ssam case INITC: 39913663Ssam x += pk->p_rwindow; 40013663Ssam break; 40113663Ssam case INITA: 40213663Ssam x += pk->p_rwindow; 40313663Ssam break; 40413663Ssam } 40513663Ssam 40613663Ssam pk->p_msg &= ~mask[i]; 40713663Ssam pkxstart(pk, x, -1); 40813663Ssam goto out; 40913663Ssam } 41013663Ssam } 41113663Ssam 41213663Ssam 41313663Ssam /* 41413663Ssam * Don't send data packets if line is marked dead. 41513663Ssam */ 41613663Ssam if (pk->p_state&DOWN) { 41713663Ssam goto out; 41813663Ssam } 41913663Ssam /* 42013663Ssam * Start transmission (or retransmission) of data packets. 42113663Ssam */ 42213663Ssam if (bstate & (B_READY|B_SENT)) { 42313663Ssam char seq; 42413663Ssam 42513663Ssam bstate |= B_SENT; 42613663Ssam seq = x; 42713663Ssam pk->p_nxtps = next[x]; 42813663Ssam 42913663Ssam x = 0200+pk->p_pr+(seq<<3); 43013663Ssam if (bstate & B_SHORT) 43113663Ssam x |= 0100; 43213663Ssam pkxstart(pk, x, seq); 43313663Ssam pk->p_os[seq] = bstate; 43413663Ssam pk->p_state &= ~RXMIT; 43513663Ssam pk->p_nout++; 43613663Ssam goto out; 43713663Ssam } 43813663Ssam /* 43913663Ssam * enable timeout if there's nothing to send 44013663Ssam * and transmission buffers are languishing 44113663Ssam */ 44213663Ssam if (pk->p_xcount) { 44313663Ssam pk->p_timer = 2; 44413663Ssam pk->p_state |= WAITO; 44513663Ssam } else 44613663Ssam pk->p_state &= ~WAITO; 44713663Ssam out: 44813663Ssam pk->p_obusy = 0; 44913663Ssam } 45013663Ssam 45113663Ssam /* 45213663Ssam * shut down line by 45313663Ssam * ignoring new input 45413663Ssam * letting output drain 45513663Ssam * releasing space and turning off line discipline 45613663Ssam */ 45717836Sralph /*ARGSUSED*/ 45823614Sbloom pkclose(pk) 45923614Sbloom register struct pack *pk; 46013663Ssam { 46118620Sralph register i; 46217836Sralph char **bp; 46318620Sralph int rcheck = 0; 46413663Ssam 46513663Ssam pk->p_state |= DRAINO; 46613663Ssam 46713663Ssam /* 46813663Ssam * try to flush output 46913663Ssam */ 47013663Ssam i = 0; 47113663Ssam pk->p_timer = 2; 47213663Ssam while (pk->p_xcount && pk->p_state&LIVE) { 47313663Ssam if (pk->p_state&(RCLOSE+DOWN) || ++i > 2) 47413663Ssam break; 47513663Ssam pkoutput(pk); 47613663Ssam } 47713663Ssam pk->p_timer = 0; 47813663Ssam pk->p_state |= DOWN; 47913663Ssam 48013663Ssam /* 48113663Ssam * try to exchange CLOSE messages 48213663Ssam */ 48313663Ssam i = 0; 48413663Ssam while ((pk->p_state&RCLOSE)==0 && i<2) { 48513663Ssam pk->p_msg = M_CLOSE; 48613663Ssam pk->p_timer = 2; 48713663Ssam pkoutput(pk); 48813663Ssam i++; 48913663Ssam } 49013663Ssam 49113663Ssam for(i=0;i<NPLINES;i++) 49213663Ssam if (pklines[i]==pk) { 49313663Ssam pklines[i] = NULL; 49413663Ssam } 49513663Ssam 49613663Ssam /* 49713663Ssam * free space 49813663Ssam */ 49913663Ssam rcheck = 0; 50013663Ssam for (i=0;i<8;i++) { 50117836Sralph if (pk->p_os[i] != B_NULL) { 50217836Sralph free((char *)pk->p_ob[i]); 50313663Ssam pk->p_xcount--; 50413663Ssam } 50517836Sralph if (pk->p_is[i] != B_NULL) { 50617836Sralph free((char *)pk->p_ib[i]); 50713663Ssam rcheck++; 50813663Ssam } 50913663Ssam } 51013663Ssam while (pk->p_ipool != NULL) { 51113663Ssam bp = pk->p_ipool; 51213663Ssam pk->p_ipool = (char **)*bp; 51313663Ssam rcheck++; 51417836Sralph free((char *)bp); 51513663Ssam } 51617836Sralph if (rcheck != pk->p_rwindow) { 51717836Sralph logent("PK0", "pkclose rcheck != p_rwindow"); 51813663Ssam } 51917836Sralph free((char *)pk); 52013663Ssam } 52113663Ssam 52213663Ssam pkreset(pk) 52313663Ssam register struct pack *pk; 52413663Ssam { 52513663Ssam 52613663Ssam pk->p_ps = pk->p_pr = pk->p_rpr = 0; 52713663Ssam pk->p_nxtps = 1; 52813663Ssam } 52913663Ssam 53017836Sralph #ifndef BSD4_2 53117836Sralph bzero(s,n) 53213663Ssam register char *s; 53313663Ssam register n; 53413663Ssam { 53513663Ssam while (n--) 53613663Ssam *s++ = 0; 53713663Ssam } 53817836Sralph #endif !BSD4_2 53913663Ssam 54013663Ssam pksize(n) 54113663Ssam register n; 54213663Ssam { 54317836Sralph register k; 54413663Ssam 54513663Ssam n >>= 5; 54617836Sralph for(k=0; n >>= 1; k++) 54717836Sralph ; 54817836Sralph return k; 54913663Ssam } 550