113663Ssam #ifndef lint 2*28888Sbloom static char sccsid[] = "@(#)pk0.c 5.7 (Berkeley) 05/30/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*28888Sbloom int Reacks; 1825706Sbloom 19*28888Sbloom #define PKRTIME 4 20*28888Sbloom #define PKWTIME 4 21*28888Sbloom #define PKRSKEW 3 22*28888Sbloom #define PKWSKEW 2 23*28888Sbloom extern int pktimeout, pktimeskew, Ntimeout; 24*28888Sbloom 2513663Ssam /* 2613663Ssam * receive control messages 2713663Ssam */ 2813663Ssam pkcntl(c, pk) 2913663Ssam register struct pack *pk; 3013663Ssam { 3117836Sralph register cntl, val; 3213663Ssam 3313663Ssam val = c & MOD8; 3413663Ssam cntl = (c>>3) & MOD8; 3513663Ssam 3617836Sralph if (!ISCNTL(c)) { 3717836Sralph logent("PK0", "not cntl"); 3813663Ssam return; 3913663Ssam } 4013663Ssam 4113663Ssam switch(cntl) { 4213663Ssam case INITB: 4313663Ssam val++; 4413663Ssam pk->p_xsize = pksizes[val]; 4513663Ssam pk->p_lpsize = val; 4617836Sralph pk->p_bits = 1; 4713663Ssam if (pk->p_state & LIVE) { 4813663Ssam pk->p_msg |= M_INITC; 4913663Ssam break; 5013663Ssam } 5113663Ssam pk->p_state |= INITb; 5213663Ssam if ((pk->p_state & INITa)==0) { 5313663Ssam break; 5413663Ssam } 5513663Ssam pk->p_rmsg &= ~M_INITA; 5613663Ssam pk->p_msg |= M_INITC; 5713663Ssam break; 5813663Ssam 5913663Ssam case INITC: 6013663Ssam if ((pk->p_state&INITab)==INITab) { 6113663Ssam pk->p_state = LIVE; 6213663Ssam pk->p_rmsg &= ~M_INITB; 6313663Ssam } else 6413663Ssam pk->p_msg |= M_INITB; 6513663Ssam if (val) 6613663Ssam pk->p_swindow = val; 6713663Ssam break; 6813663Ssam case INITA: 6917836Sralph if (val == 0 && pk->p_state&LIVE) { 7017836Sralph logent("PK0", "alloc change not implemented"); 7113663Ssam break; 7213663Ssam } 7313663Ssam if (val) { 7413663Ssam pk->p_state |= INITa; 7513663Ssam pk->p_msg |= M_INITB; 7613663Ssam pk->p_rmsg |= M_INITB; 7713663Ssam pk->p_swindow = val; 7813663Ssam } 7913663Ssam break; 8013663Ssam case RJ: 8113663Ssam pk->p_state |= RXMIT; 8213663Ssam pk->p_msg |= M_RR; 8313663Ssam pk->p_rpr = val; 8417836Sralph (void) pksack(pk); 8513663Ssam break; 86*28888Sbloom case RR: 87*28888Sbloom pk->p_rpr = val; 88*28888Sbloom if (pk->p_rpr == pk->p_ps) { 89*28888Sbloom DEBUG(9, "Reack count is %d\n", ++Reacks); 90*28888Sbloom if (Reacks >= 4) { 91*28888Sbloom DEBUG(6, "Reack overflow on %d\n", val); 92*28888Sbloom pk->p_state |= RXMIT; 93*28888Sbloom pk->p_msg |= M_RR; 94*28888Sbloom Reacks = 0; 95*28888Sbloom } 96*28888Sbloom } else { 97*28888Sbloom Reacks = 0; 98*28888Sbloom (void) pksack(pk); 99*28888Sbloom } 100*28888Sbloom break; 10113663Ssam case SRJ: 10217836Sralph logent("PK0", "srj not implemented"); 10313663Ssam break; 10413663Ssam case CLOSE: 10513663Ssam pk->p_state = DOWN+RCLOSE; 10613663Ssam return; 10713663Ssam } 10813663Ssam if (pk->p_msg) 10913663Ssam pkoutput(pk); 11013663Ssam } 11113663Ssam 11213663Ssam pkaccept(pk) 11313663Ssam register struct pack *pk; 11413663Ssam { 11517836Sralph register x, seq; 11617836Sralph char m, cntl, *p, imask, **bp; 11717836Sralph int bad, accept, skip, t, cc; 11817836Sralph unsigned short sum; 11913663Ssam 12013663Ssam bad = accept = skip = 0; 12113663Ssam /* 12213663Ssam * wait for input 12313663Ssam */ 12413663Ssam x = next[pk->p_pr]; 12517836Sralph while ((imask=pk->p_imap) == 0 && pk->p_rcount == 0) { 12617836Sralph pkgetpack(pk); 12713663Ssam } 12813663Ssam pk->p_imap = 0; 12913663Ssam 13013663Ssam /* 13113663Ssam * determine input window in m. 13213663Ssam */ 13313663Ssam t = (~(-1<<(int)(pk->p_rwindow))) <<x; 13413663Ssam m = t; 13513663Ssam m |= t>>8; 13613663Ssam 13713663Ssam /* 13813663Ssam * mark newly accepted input buffers 13913663Ssam */ 14013663Ssam for(x=0; x<8; x++) { 14113663Ssam if ((imask & mask[x]) == 0) 14213663Ssam continue; 14313663Ssam 14417836Sralph if (((cntl=pk->p_is[x])&0200) == 0) { 14513663Ssam bad++; 14613663Ssam free: 14713663Ssam bp = (char **)pk->p_ib[x]; 14813663Ssam *bp = (char *)pk->p_ipool; 14913663Ssam pk->p_ipool = bp; 15013663Ssam pk->p_is[x] = 0; 15113663Ssam continue; 15213663Ssam } 15313663Ssam 15413663Ssam pk->p_is[x] = ~(B_COPY+B_MARK); 15513663Ssam sum = (unsigned)chksum(pk->p_ib[x], pk->p_rsize) ^ (unsigned)(cntl&0377); 15613663Ssam sum += pk->p_isum[x]; 15713663Ssam if (sum == CHECK) { 15813663Ssam seq = (cntl>>3) & MOD8; 15913663Ssam if (m & mask[seq]) { 16013663Ssam if (pk->p_is[seq] & (B_COPY | B_MARK)) { 16113663Ssam dup: 16213663Ssam pk->p_msg |= M_RR; 16313663Ssam skip++; 16413663Ssam goto free; 16513663Ssam } 16613663Ssam if (x != seq) { 16713663Ssam p = pk->p_ib[x]; 16813663Ssam pk->p_ib[x] = pk->p_ib[seq]; 16913663Ssam pk->p_is[x] = pk->p_is[seq]; 17013663Ssam pk->p_ib[seq] = p; 17113663Ssam } 17213663Ssam pk->p_is[seq] = B_MARK; 17313663Ssam accept++; 17413663Ssam cc = 0; 17513663Ssam if (cntl&B_SHORT) { 17613663Ssam pk->p_is[seq] = B_MARK+B_SHORT; 17713663Ssam p = pk->p_ib[seq]; 17813663Ssam cc = (unsigned)*p++ & 0377; 17913663Ssam if (cc & 0200) { 18013663Ssam cc &= 0177; 18113663Ssam cc |= *p << 7; 18213663Ssam } 18313663Ssam } 18413663Ssam pk->p_isum[seq] = pk->p_rsize - cc; 18513663Ssam } else { 18613663Ssam goto dup; 18713663Ssam } 18813663Ssam } else { 18913663Ssam bad++; 19013663Ssam goto free; 19113663Ssam } 19213663Ssam } 19313663Ssam 19413663Ssam /* 19513663Ssam * scan window again turning marked buffers into 19613663Ssam * COPY buffers and looking for missing sequence 19713663Ssam * numbers. 19813663Ssam */ 19913663Ssam accept = 0; 20017836Sralph t = -1; 20117836Sralph for(x=next[pk->p_pr]; m & mask[x]; x = next[x]) { 20213663Ssam if (pk->p_is[x] & B_MARK) 20313663Ssam pk->p_is[x] |= B_COPY; 20417836Sralph 20513663Ssam if (pk->p_is[x] & B_COPY) { 20613663Ssam if (t >= 0) { 20713663Ssam bp = (char **)pk->p_ib[x]; 20813663Ssam *bp = (char *)pk->p_ipool; 20913663Ssam pk->p_ipool = bp; 21013663Ssam pk->p_is[x] = 0; 21113663Ssam skip++; 21217836Sralph } else 21313663Ssam accept++; 21413663Ssam } else { 21513663Ssam if (t<0) 21613663Ssam t = x; 21713663Ssam } 21813663Ssam } 21913663Ssam 22013663Ssam if (bad) { 22113663Ssam pk->p_msg |= M_RJ; 22213663Ssam } 22313663Ssam 22413663Ssam if (skip) { 22513663Ssam pk->p_msg |= M_RR; 22613663Ssam } 22713663Ssam 22813663Ssam pk->p_rcount = accept; 22917836Sralph return accept; 23013663Ssam } 23113663Ssam 23217836Sralph /*ARGSUSED*/ 23323614Sbloom pkread(pk, ibuf, icount) 23423614Sbloom register struct pack *pk; 23523614Sbloom char *ibuf; 23617836Sralph int icount; 23713663Ssam { 23817836Sralph register x; 23917836Sralph int is, cc, xfr, count; 24017836Sralph char *cp, **bp; 24113663Ssam 24213663Ssam xfr = 0; 24313663Ssam count = 0; 244*28888Sbloom pktimeout = PKRTIME; 245*28888Sbloom pktimeskew = PKRSKEW; 24625706Sbloom Ntimeout = 0; 24717836Sralph while (pkaccept(pk) == 0) 24817836Sralph ; 24913663Ssam 25017836Sralph while (icount) { 25113663Ssam x = next[pk->p_pr]; 25213663Ssam is = pk->p_is[x]; 25313663Ssam 25413663Ssam if (is & B_COPY) { 25517836Sralph cc = MIN(pk->p_isum[x], icount); 25613663Ssam if (cc==0 && xfr) { 25713663Ssam break; 25813663Ssam } 25913663Ssam if (is & B_RESID) 26013663Ssam cp = pk->p_rptr; 26113663Ssam else { 26213663Ssam cp = pk->p_ib[x]; 26313663Ssam if (is & B_SHORT) { 26413663Ssam if (*cp++ & 0200) 26513663Ssam cp++; 26613663Ssam } 26713663Ssam } 26817836Sralph pkmove(cp, ibuf, cc, B_READ); 26917836Sralph ibuf += cc; 27017836Sralph icount -= cc; 27113663Ssam count += cc; 27213663Ssam xfr++; 27313663Ssam pk->p_isum[x] -= cc; 27413663Ssam if (pk->p_isum[x] == 0) { 27513663Ssam pk->p_pr = x; 27613663Ssam bp = (char **)pk->p_ib[x]; 27713663Ssam *bp = (char *)pk->p_ipool; 27813663Ssam pk->p_ipool = bp; 27913663Ssam pk->p_is[x] = 0; 28013663Ssam pk->p_rcount--; 28113663Ssam pk->p_msg |= M_RR; 28213663Ssam } else { 28313663Ssam pk->p_rptr = cp+cc; 28413663Ssam pk->p_is[x] |= B_RESID; 28513663Ssam } 28613663Ssam if (cc==0) 28713663Ssam break; 28813663Ssam } else 28913663Ssam break; 29013663Ssam } 29113663Ssam pkoutput(pk); 29217836Sralph return count; 29313663Ssam } 29413663Ssam 29517836Sralph /*ARGSUSED*/ 29623614Sbloom pkwrite(pk, ibuf, icount) 29723614Sbloom register struct pack *pk; 29817836Sralph char *ibuf; 29917836Sralph int icount; 30013663Ssam { 30117836Sralph register x; 30217836Sralph int partial; 30317836Sralph caddr_t cp; 30417836Sralph int cc, fc, count; 30513663Ssam 30613663Ssam if (pk->p_state&DOWN || !pk->p_state&LIVE) { 30717836Sralph return -1; 30813663Ssam } 30913663Ssam 310*28888Sbloom pktimeout = PKWTIME; 311*28888Sbloom pktimeskew = PKWSKEW; 31225706Sbloom Ntimeout = 0; 31317836Sralph count = icount; 31413663Ssam do { 31513663Ssam while (pk->p_xcount>=pk->p_swindow) { 31613663Ssam pkoutput(pk); 31717836Sralph pkgetpack(pk); 31813663Ssam } 31913663Ssam x = next[pk->p_pscopy]; 32013663Ssam while (pk->p_os[x]!=B_NULL) { 32117836Sralph pkgetpack(pk); 32213663Ssam } 32313663Ssam pk->p_os[x] = B_MARK; 32413663Ssam pk->p_pscopy = x; 32513663Ssam pk->p_xcount++; 32613663Ssam 32717836Sralph cp = pk->p_ob[x] = malloc((unsigned)pk->p_xsize); 32813663Ssam partial = 0; 32917836Sralph if ((int)icount < pk->p_xsize) { 33017836Sralph cc = icount; 33113663Ssam fc = pk->p_xsize - cc; 33213663Ssam *cp = fc&0177; 33313663Ssam if (fc > 127) { 33413663Ssam *cp++ |= 0200; 33513663Ssam *cp++ = fc>>7; 33613663Ssam } else 33713663Ssam cp++; 33813663Ssam partial = B_SHORT; 33913663Ssam } else 34013663Ssam cc = pk->p_xsize; 34117836Sralph pkmove(cp, ibuf, cc, B_WRITE); 34217836Sralph ibuf += cc; 34317836Sralph icount -= cc; 34413663Ssam pk->p_osum[x] = chksum(pk->p_ob[x], pk->p_xsize); 34513663Ssam pk->p_os[x] = B_READY+partial; 34613663Ssam pkoutput(pk); 34717836Sralph } while (icount); 34813663Ssam 34917836Sralph return count; 35013663Ssam } 35113663Ssam 35213663Ssam pksack(pk) 35313663Ssam register struct pack *pk; 35413663Ssam { 35517836Sralph register x, i; 35613663Ssam 35713663Ssam i = 0; 35813663Ssam for(x=pk->p_ps; x!=pk->p_rpr; ) { 35913663Ssam x = next[x]; 36013663Ssam if (pk->p_os[x]&B_SENT) { 36113663Ssam i++; 36213663Ssam pk->p_os[x] = B_NULL; 36313663Ssam pk->p_state &= ~WAITO; 36413663Ssam pk->p_xcount--; 36517836Sralph free((char *)pk->p_ob[x]); 36613663Ssam pk->p_ps = x; 36713663Ssam } 36813663Ssam } 36917836Sralph return i; 37013663Ssam } 37113663Ssam 37213663Ssam pkoutput(pk) 37313663Ssam register struct pack *pk; 37413663Ssam { 37517836Sralph register x; 37617836Sralph int i; 37717836Sralph char bstate; 37813663Ssam 37917836Sralph if (pk->p_obusy++) { 38013663Ssam pk->p_obusy--; 38113663Ssam return; 38213663Ssam } 38313663Ssam 38413663Ssam /* 38513663Ssam * find seq number and buffer state 38613663Ssam * of next output packet 38713663Ssam */ 38813663Ssam if (pk->p_state&RXMIT) { 38913663Ssam pk->p_nxtps = next[pk->p_rpr]; 39013663Ssam } 39113663Ssam x = pk->p_nxtps; 39213663Ssam bstate = pk->p_os[x]; 39313663Ssam 39413663Ssam /* 39513663Ssam * Send control packet if indicated 39613663Ssam */ 39713663Ssam if (pk->p_msg) { 39813663Ssam if (pk->p_msg & ~M_RR || !(bstate&B_READY) ) { 39913663Ssam x = pk->p_msg; 40017836Sralph for(i=0; i<8; i++) 40113663Ssam if (x&1) 40217836Sralph break; 40317836Sralph else 40417836Sralph x >>= 1; 40513663Ssam x = i; 40613663Ssam x <<= 3; 40713663Ssam switch(i) { 40813663Ssam case CLOSE: 40913663Ssam break; 41013663Ssam case RJ: 41113663Ssam case RR: 41213663Ssam x += pk->p_pr; 41313663Ssam break; 41413663Ssam case SRJ: 41513663Ssam break; 41613663Ssam case INITB: 41713663Ssam x += pksize(pk->p_rsize); 41813663Ssam break; 41913663Ssam case INITC: 42013663Ssam x += pk->p_rwindow; 42113663Ssam break; 42213663Ssam case INITA: 42313663Ssam x += pk->p_rwindow; 42413663Ssam break; 42513663Ssam } 42613663Ssam 42713663Ssam pk->p_msg &= ~mask[i]; 42813663Ssam pkxstart(pk, x, -1); 42913663Ssam goto out; 43013663Ssam } 43113663Ssam } 43213663Ssam 43313663Ssam 43413663Ssam /* 43513663Ssam * Don't send data packets if line is marked dead. 43613663Ssam */ 43713663Ssam if (pk->p_state&DOWN) { 43813663Ssam goto out; 43913663Ssam } 44013663Ssam /* 44113663Ssam * Start transmission (or retransmission) of data packets. 44213663Ssam */ 44313663Ssam if (bstate & (B_READY|B_SENT)) { 44413663Ssam char seq; 44513663Ssam 44613663Ssam bstate |= B_SENT; 44713663Ssam seq = x; 44813663Ssam pk->p_nxtps = next[x]; 44913663Ssam 45013663Ssam x = 0200+pk->p_pr+(seq<<3); 45113663Ssam if (bstate & B_SHORT) 45213663Ssam x |= 0100; 45313663Ssam pkxstart(pk, x, seq); 45413663Ssam pk->p_os[seq] = bstate; 45513663Ssam pk->p_state &= ~RXMIT; 45613663Ssam pk->p_nout++; 45713663Ssam goto out; 45813663Ssam } 45913663Ssam /* 46013663Ssam * enable timeout if there's nothing to send 46113663Ssam * and transmission buffers are languishing 46213663Ssam */ 46313663Ssam if (pk->p_xcount) { 46413663Ssam pk->p_timer = 2; 46513663Ssam pk->p_state |= WAITO; 46613663Ssam } else 46713663Ssam pk->p_state &= ~WAITO; 46813663Ssam out: 46913663Ssam pk->p_obusy = 0; 47013663Ssam } 47113663Ssam 47213663Ssam /* 47313663Ssam * shut down line by 47413663Ssam * ignoring new input 47513663Ssam * letting output drain 47613663Ssam * releasing space and turning off line discipline 47713663Ssam */ 47817836Sralph /*ARGSUSED*/ 47923614Sbloom pkclose(pk) 48023614Sbloom register struct pack *pk; 48113663Ssam { 48218620Sralph register i; 48317836Sralph char **bp; 48418620Sralph int rcheck = 0; 48513663Ssam 48613663Ssam pk->p_state |= DRAINO; 48713663Ssam 48813663Ssam /* 48913663Ssam * try to flush output 49013663Ssam */ 49113663Ssam i = 0; 49213663Ssam pk->p_timer = 2; 49313663Ssam while (pk->p_xcount && pk->p_state&LIVE) { 49413663Ssam if (pk->p_state&(RCLOSE+DOWN) || ++i > 2) 49513663Ssam break; 49613663Ssam pkoutput(pk); 49713663Ssam } 49813663Ssam pk->p_timer = 0; 49913663Ssam pk->p_state |= DOWN; 50013663Ssam 50113663Ssam /* 50213663Ssam * try to exchange CLOSE messages 50313663Ssam */ 50413663Ssam i = 0; 50513663Ssam while ((pk->p_state&RCLOSE)==0 && i<2) { 50613663Ssam pk->p_msg = M_CLOSE; 50713663Ssam pk->p_timer = 2; 50813663Ssam pkoutput(pk); 50913663Ssam i++; 51013663Ssam } 51113663Ssam 51213663Ssam for(i=0;i<NPLINES;i++) 51313663Ssam if (pklines[i]==pk) { 51413663Ssam pklines[i] = NULL; 51513663Ssam } 51613663Ssam 51713663Ssam /* 51813663Ssam * free space 51913663Ssam */ 52013663Ssam rcheck = 0; 52113663Ssam for (i=0;i<8;i++) { 52217836Sralph if (pk->p_os[i] != B_NULL) { 52317836Sralph free((char *)pk->p_ob[i]); 52413663Ssam pk->p_xcount--; 52513663Ssam } 52617836Sralph if (pk->p_is[i] != B_NULL) { 52717836Sralph free((char *)pk->p_ib[i]); 52813663Ssam rcheck++; 52913663Ssam } 53013663Ssam } 53113663Ssam while (pk->p_ipool != NULL) { 53213663Ssam bp = pk->p_ipool; 53313663Ssam pk->p_ipool = (char **)*bp; 53413663Ssam rcheck++; 53517836Sralph free((char *)bp); 53613663Ssam } 53717836Sralph if (rcheck != pk->p_rwindow) { 53826929Sbloom char buf[256]; 53926929Sbloom 54026929Sbloom sprintf(buf, "PK0: rc %d rw %d", rcheck, pk->p_rwindow); 54126929Sbloom logent(buf, "pkclose rcheck != p_rwindow"); 54213663Ssam } 54317836Sralph free((char *)pk); 54413663Ssam } 54513663Ssam 54613663Ssam pkreset(pk) 54713663Ssam register struct pack *pk; 54813663Ssam { 54913663Ssam 55013663Ssam pk->p_ps = pk->p_pr = pk->p_rpr = 0; 55113663Ssam pk->p_nxtps = 1; 55213663Ssam } 55313663Ssam 55417836Sralph #ifndef BSD4_2 55517836Sralph bzero(s,n) 55613663Ssam register char *s; 55713663Ssam register n; 55813663Ssam { 55913663Ssam while (n--) 56013663Ssam *s++ = 0; 56113663Ssam } 56217836Sralph #endif !BSD4_2 56313663Ssam 56413663Ssam pksize(n) 56513663Ssam register n; 56613663Ssam { 56717836Sralph register k; 56813663Ssam 56913663Ssam n >>= 5; 57017836Sralph for(k=0; n >>= 1; k++) 57117836Sralph ; 57217836Sralph return k; 57313663Ssam } 574