113663Ssam #ifndef lint 2*18620Sralph static char sccsid[] = "@(#)pk0.c 5.3 (Berkeley) 04/10/85"; 313663Ssam #endif 413663Ssam 5*18620Sralph #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 int pkactive; 1717836Sralph long chksum(); 1813663Ssam 1913663Ssam /* 2013663Ssam * receive control messages 2113663Ssam */ 2213663Ssam pkcntl(c, pk) 2313663Ssam register struct pack *pk; 2413663Ssam { 2517836Sralph register cntl, val; 2613663Ssam 2713663Ssam val = c & MOD8; 2813663Ssam cntl = (c>>3) & MOD8; 2913663Ssam 3017836Sralph if (!ISCNTL(c)) { 3117836Sralph logent("PK0", "not cntl"); 3213663Ssam return; 3313663Ssam } 3413663Ssam 3513663Ssam switch(cntl) { 3613663Ssam case INITB: 3713663Ssam val++; 3813663Ssam pk->p_xsize = pksizes[val]; 3913663Ssam pk->p_lpsize = val; 4017836Sralph pk->p_bits = 1; 4113663Ssam if (pk->p_state & LIVE) { 4213663Ssam pk->p_msg |= M_INITC; 4313663Ssam break; 4413663Ssam } 4513663Ssam pk->p_state |= INITb; 4613663Ssam if ((pk->p_state & INITa)==0) { 4713663Ssam break; 4813663Ssam } 4913663Ssam pk->p_rmsg &= ~M_INITA; 5013663Ssam pk->p_msg |= M_INITC; 5113663Ssam break; 5213663Ssam 5313663Ssam case INITC: 5413663Ssam if ((pk->p_state&INITab)==INITab) { 5513663Ssam pk->p_state = LIVE; 5613663Ssam pk->p_rmsg &= ~M_INITB; 5713663Ssam } else 5813663Ssam pk->p_msg |= M_INITB; 5913663Ssam if (val) 6013663Ssam pk->p_swindow = val; 6113663Ssam break; 6213663Ssam case INITA: 6317836Sralph if (val == 0 && pk->p_state&LIVE) { 6417836Sralph logent("PK0", "alloc change not implemented"); 6513663Ssam break; 6613663Ssam } 6713663Ssam if (val) { 6813663Ssam pk->p_state |= INITa; 6913663Ssam pk->p_msg |= M_INITB; 7013663Ssam pk->p_rmsg |= M_INITB; 7113663Ssam pk->p_swindow = val; 7213663Ssam } 7313663Ssam break; 7413663Ssam case RJ: 7513663Ssam pk->p_state |= RXMIT; 7613663Ssam pk->p_msg |= M_RR; 7713663Ssam case RR: 7813663Ssam pk->p_rpr = val; 7917836Sralph (void) pksack(pk); 8013663Ssam break; 8113663Ssam case SRJ: 8217836Sralph logent("PK0", "srj not implemented"); 8313663Ssam break; 8413663Ssam case CLOSE: 8513663Ssam pk->p_state = DOWN+RCLOSE; 8613663Ssam return; 8713663Ssam } 8813663Ssam if (pk->p_msg) 8913663Ssam pkoutput(pk); 9013663Ssam } 9113663Ssam 9213663Ssam pkaccept(pk) 9313663Ssam register struct pack *pk; 9413663Ssam { 9517836Sralph register x, seq; 9617836Sralph char m, cntl, *p, imask, **bp; 9717836Sralph int bad, accept, skip, t, cc; 9817836Sralph unsigned short sum; 9913663Ssam 10013663Ssam bad = accept = skip = 0; 10113663Ssam /* 10213663Ssam * wait for input 10313663Ssam */ 10413663Ssam x = next[pk->p_pr]; 10517836Sralph while ((imask=pk->p_imap) == 0 && pk->p_rcount == 0) { 10617836Sralph pkgetpack(pk); 10713663Ssam } 10813663Ssam pk->p_imap = 0; 10913663Ssam 11013663Ssam /* 11113663Ssam * determine input window in m. 11213663Ssam */ 11313663Ssam t = (~(-1<<(int)(pk->p_rwindow))) <<x; 11413663Ssam m = t; 11513663Ssam m |= t>>8; 11613663Ssam 11713663Ssam /* 11813663Ssam * mark newly accepted input buffers 11913663Ssam */ 12013663Ssam for(x=0; x<8; x++) { 12113663Ssam if ((imask & mask[x]) == 0) 12213663Ssam continue; 12313663Ssam 12417836Sralph if (((cntl=pk->p_is[x])&0200) == 0) { 12513663Ssam bad++; 12613663Ssam free: 12713663Ssam bp = (char **)pk->p_ib[x]; 12813663Ssam *bp = (char *)pk->p_ipool; 12913663Ssam pk->p_ipool = bp; 13013663Ssam pk->p_is[x] = 0; 13113663Ssam continue; 13213663Ssam } 13313663Ssam 13413663Ssam pk->p_is[x] = ~(B_COPY+B_MARK); 13513663Ssam sum = (unsigned)chksum(pk->p_ib[x], pk->p_rsize) ^ (unsigned)(cntl&0377); 13613663Ssam sum += pk->p_isum[x]; 13713663Ssam if (sum == CHECK) { 13813663Ssam seq = (cntl>>3) & MOD8; 13913663Ssam if (m & mask[seq]) { 14013663Ssam if (pk->p_is[seq] & (B_COPY | B_MARK)) { 14113663Ssam dup: 14213663Ssam pk->p_msg |= M_RR; 14313663Ssam skip++; 14413663Ssam goto free; 14513663Ssam } 14613663Ssam if (x != seq) { 14713663Ssam p = pk->p_ib[x]; 14813663Ssam pk->p_ib[x] = pk->p_ib[seq]; 14913663Ssam pk->p_is[x] = pk->p_is[seq]; 15013663Ssam pk->p_ib[seq] = p; 15113663Ssam } 15213663Ssam pk->p_is[seq] = B_MARK; 15313663Ssam accept++; 15413663Ssam cc = 0; 15513663Ssam if (cntl&B_SHORT) { 15613663Ssam pk->p_is[seq] = B_MARK+B_SHORT; 15713663Ssam p = pk->p_ib[seq]; 15813663Ssam cc = (unsigned)*p++ & 0377; 15913663Ssam if (cc & 0200) { 16013663Ssam cc &= 0177; 16113663Ssam cc |= *p << 7; 16213663Ssam } 16313663Ssam } 16413663Ssam pk->p_isum[seq] = pk->p_rsize - cc; 16513663Ssam } else { 16613663Ssam goto dup; 16713663Ssam } 16813663Ssam } else { 16913663Ssam bad++; 17013663Ssam goto free; 17113663Ssam } 17213663Ssam } 17313663Ssam 17413663Ssam /* 17513663Ssam * scan window again turning marked buffers into 17613663Ssam * COPY buffers and looking for missing sequence 17713663Ssam * numbers. 17813663Ssam */ 17913663Ssam accept = 0; 18017836Sralph t = -1; 18117836Sralph for(x=next[pk->p_pr]; m & mask[x]; x = next[x]) { 18213663Ssam if (pk->p_is[x] & B_MARK) 18313663Ssam pk->p_is[x] |= B_COPY; 18417836Sralph 18513663Ssam if (pk->p_is[x] & B_COPY) { 18613663Ssam if (t >= 0) { 18713663Ssam bp = (char **)pk->p_ib[x]; 18813663Ssam *bp = (char *)pk->p_ipool; 18913663Ssam pk->p_ipool = bp; 19013663Ssam pk->p_is[x] = 0; 19113663Ssam skip++; 19217836Sralph } else 19313663Ssam accept++; 19413663Ssam } else { 19513663Ssam if (t<0) 19613663Ssam t = x; 19713663Ssam } 19813663Ssam } 19913663Ssam 20013663Ssam if (bad) { 20113663Ssam pk->p_msg |= M_RJ; 20213663Ssam } 20313663Ssam 20413663Ssam if (skip) { 20513663Ssam pk->p_msg |= M_RR; 20613663Ssam } 20713663Ssam 20813663Ssam pk->p_rcount = accept; 20917836Sralph return accept; 21013663Ssam } 21113663Ssam 21217836Sralph /*ARGSUSED*/ 21317836Sralph pkread(ipk, ibuf, icount) 21417836Sralph int icount; 21517836Sralph char *ibuf; 21617836Sralph struct pack *ipk; 21713663Ssam { 21817836Sralph register struct pack *pk; 21917836Sralph register x; 22017836Sralph int is, cc, xfr, count; 22117836Sralph char *cp, **bp; 22213663Ssam 22317836Sralph pk = ipk; 22413663Ssam xfr = 0; 22513663Ssam count = 0; 22617836Sralph while (pkaccept(pk) == 0) 22717836Sralph ; 22813663Ssam 22917836Sralph while (icount) { 23013663Ssam x = next[pk->p_pr]; 23113663Ssam is = pk->p_is[x]; 23213663Ssam 23313663Ssam if (is & B_COPY) { 23417836Sralph cc = MIN(pk->p_isum[x], icount); 23513663Ssam if (cc==0 && xfr) { 23613663Ssam break; 23713663Ssam } 23813663Ssam if (is & B_RESID) 23913663Ssam cp = pk->p_rptr; 24013663Ssam else { 24113663Ssam cp = pk->p_ib[x]; 24213663Ssam if (is & B_SHORT) { 24313663Ssam if (*cp++ & 0200) 24413663Ssam cp++; 24513663Ssam } 24613663Ssam } 24717836Sralph pkmove(cp, ibuf, cc, B_READ); 24817836Sralph ibuf += cc; 24917836Sralph icount -= cc; 25013663Ssam count += cc; 25113663Ssam xfr++; 25213663Ssam pk->p_isum[x] -= cc; 25313663Ssam if (pk->p_isum[x] == 0) { 25413663Ssam pk->p_pr = x; 25513663Ssam bp = (char **)pk->p_ib[x]; 25613663Ssam *bp = (char *)pk->p_ipool; 25713663Ssam pk->p_ipool = bp; 25813663Ssam pk->p_is[x] = 0; 25913663Ssam pk->p_rcount--; 26013663Ssam pk->p_msg |= M_RR; 26113663Ssam } else { 26213663Ssam pk->p_rptr = cp+cc; 26313663Ssam pk->p_is[x] |= B_RESID; 26413663Ssam } 26513663Ssam if (cc==0) 26613663Ssam break; 26713663Ssam } else 26813663Ssam break; 26913663Ssam } 27013663Ssam pkoutput(pk); 27117836Sralph return count; 27213663Ssam } 27313663Ssam 27417836Sralph /*ARGSUSED*/ 27517836Sralph pkwrite(ipk, ibuf, icount) 27617836Sralph struct pack *ipk; 27717836Sralph char *ibuf; 27817836Sralph int icount; 27913663Ssam { 28017836Sralph register struct pack *pk; 28117836Sralph register x; 28217836Sralph int partial; 28317836Sralph caddr_t cp; 28417836Sralph int cc, fc, count; 28513663Ssam 28617836Sralph pk = ipk; 28713663Ssam if (pk->p_state&DOWN || !pk->p_state&LIVE) { 28817836Sralph return -1; 28913663Ssam } 29013663Ssam 29117836Sralph count = icount; 29213663Ssam do { 29313663Ssam while (pk->p_xcount>=pk->p_swindow) { 29413663Ssam pkoutput(pk); 29517836Sralph pkgetpack(pk); 29613663Ssam } 29713663Ssam x = next[pk->p_pscopy]; 29813663Ssam while (pk->p_os[x]!=B_NULL) { 29917836Sralph pkgetpack(pk); 30013663Ssam } 30113663Ssam pk->p_os[x] = B_MARK; 30213663Ssam pk->p_pscopy = x; 30313663Ssam pk->p_xcount++; 30413663Ssam 30517836Sralph cp = pk->p_ob[x] = malloc((unsigned)pk->p_xsize); 30613663Ssam partial = 0; 30717836Sralph if ((int)icount < pk->p_xsize) { 30817836Sralph cc = icount; 30913663Ssam fc = pk->p_xsize - cc; 31013663Ssam *cp = fc&0177; 31113663Ssam if (fc > 127) { 31213663Ssam *cp++ |= 0200; 31313663Ssam *cp++ = fc>>7; 31413663Ssam } else 31513663Ssam cp++; 31613663Ssam partial = B_SHORT; 31713663Ssam } else 31813663Ssam cc = pk->p_xsize; 31917836Sralph pkmove(cp, ibuf, cc, B_WRITE); 32017836Sralph ibuf += cc; 32117836Sralph icount -= cc; 32213663Ssam pk->p_osum[x] = chksum(pk->p_ob[x], pk->p_xsize); 32313663Ssam pk->p_os[x] = B_READY+partial; 32413663Ssam pkoutput(pk); 32517836Sralph } while (icount); 32613663Ssam 32717836Sralph return count; 32813663Ssam } 32913663Ssam 33013663Ssam pksack(pk) 33113663Ssam register struct pack *pk; 33213663Ssam { 33317836Sralph register x, i; 33413663Ssam 33513663Ssam i = 0; 33613663Ssam for(x=pk->p_ps; x!=pk->p_rpr; ) { 33713663Ssam x = next[x]; 33813663Ssam if (pk->p_os[x]&B_SENT) { 33913663Ssam i++; 34013663Ssam pk->p_os[x] = B_NULL; 34113663Ssam pk->p_state &= ~WAITO; 34213663Ssam pk->p_xcount--; 34317836Sralph free((char *)pk->p_ob[x]); 34413663Ssam pk->p_ps = x; 34513663Ssam } 34613663Ssam } 34717836Sralph return i; 34813663Ssam } 34913663Ssam 35013663Ssam 35113663Ssam 35213663Ssam pkoutput(pk) 35313663Ssam register struct pack *pk; 35413663Ssam { 35517836Sralph register x; 35617836Sralph int i; 35717836Sralph char bstate; 35813663Ssam 35917836Sralph if (pk->p_obusy++) { 36013663Ssam pk->p_obusy--; 36113663Ssam return; 36213663Ssam } 36313663Ssam 36413663Ssam /* 36513663Ssam * find seq number and buffer state 36613663Ssam * of next output packet 36713663Ssam */ 36813663Ssam if (pk->p_state&RXMIT) { 36913663Ssam pk->p_nxtps = next[pk->p_rpr]; 37013663Ssam } 37113663Ssam x = pk->p_nxtps; 37213663Ssam bstate = pk->p_os[x]; 37313663Ssam 37413663Ssam /* 37513663Ssam * Send control packet if indicated 37613663Ssam */ 37713663Ssam if (pk->p_msg) { 37813663Ssam if (pk->p_msg & ~M_RR || !(bstate&B_READY) ) { 37913663Ssam x = pk->p_msg; 38017836Sralph for(i=0; i<8; i++) 38113663Ssam if (x&1) 38217836Sralph break; 38317836Sralph else 38417836Sralph x >>= 1; 38513663Ssam x = i; 38613663Ssam x <<= 3; 38713663Ssam switch(i) { 38813663Ssam case CLOSE: 38913663Ssam break; 39013663Ssam case RJ: 39113663Ssam case RR: 39213663Ssam x += pk->p_pr; 39313663Ssam break; 39413663Ssam case SRJ: 39513663Ssam break; 39613663Ssam case INITB: 39713663Ssam x += pksize(pk->p_rsize); 39813663Ssam break; 39913663Ssam case INITC: 40013663Ssam x += pk->p_rwindow; 40113663Ssam break; 40213663Ssam case INITA: 40313663Ssam x += pk->p_rwindow; 40413663Ssam break; 40513663Ssam } 40613663Ssam 40713663Ssam pk->p_msg &= ~mask[i]; 40813663Ssam pkxstart(pk, x, -1); 40913663Ssam goto out; 41013663Ssam } 41113663Ssam } 41213663Ssam 41313663Ssam 41413663Ssam /* 41513663Ssam * Don't send data packets if line is marked dead. 41613663Ssam */ 41713663Ssam if (pk->p_state&DOWN) { 41813663Ssam goto out; 41913663Ssam } 42013663Ssam /* 42113663Ssam * Start transmission (or retransmission) of data packets. 42213663Ssam */ 42313663Ssam if (bstate & (B_READY|B_SENT)) { 42413663Ssam char seq; 42513663Ssam 42613663Ssam bstate |= B_SENT; 42713663Ssam seq = x; 42813663Ssam pk->p_nxtps = next[x]; 42913663Ssam 43013663Ssam x = 0200+pk->p_pr+(seq<<3); 43113663Ssam if (bstate & B_SHORT) 43213663Ssam x |= 0100; 43313663Ssam pkxstart(pk, x, seq); 43413663Ssam pk->p_os[seq] = bstate; 43513663Ssam pk->p_state &= ~RXMIT; 43613663Ssam pk->p_nout++; 43713663Ssam goto out; 43813663Ssam } 43913663Ssam /* 44013663Ssam * enable timeout if there's nothing to send 44113663Ssam * and transmission buffers are languishing 44213663Ssam */ 44313663Ssam if (pk->p_xcount) { 44413663Ssam pk->p_timer = 2; 44513663Ssam pk->p_state |= WAITO; 44613663Ssam } else 44713663Ssam pk->p_state &= ~WAITO; 44813663Ssam out: 44913663Ssam pk->p_obusy = 0; 45013663Ssam } 45113663Ssam 45213663Ssam /* 45313663Ssam * shut down line by 45413663Ssam * ignoring new input 45513663Ssam * letting output drain 45613663Ssam * releasing space and turning off line discipline 45713663Ssam */ 45817836Sralph /*ARGSUSED*/ 45917836Sralph pkclose(ipk, ibuf, icount) 46017836Sralph struct pack *ipk; 46117836Sralph char *ibuf; 46217836Sralph int icount; 46313663Ssam { 46417836Sralph register struct pack *pk; 465*18620Sralph register i; 46617836Sralph char **bp; 467*18620Sralph int rcheck = 0; 46813663Ssam 46917836Sralph pk = ipk; 47013663Ssam pk->p_state |= DRAINO; 47113663Ssam 47213663Ssam /* 47313663Ssam * try to flush output 47413663Ssam */ 47513663Ssam i = 0; 47613663Ssam pk->p_timer = 2; 47713663Ssam while (pk->p_xcount && pk->p_state&LIVE) { 47813663Ssam if (pk->p_state&(RCLOSE+DOWN) || ++i > 2) 47913663Ssam break; 48013663Ssam pkoutput(pk); 48113663Ssam } 48213663Ssam pk->p_timer = 0; 48313663Ssam pk->p_state |= DOWN; 48413663Ssam 48513663Ssam /* 48613663Ssam * try to exchange CLOSE messages 48713663Ssam */ 48813663Ssam i = 0; 48913663Ssam while ((pk->p_state&RCLOSE)==0 && i<2) { 49013663Ssam pk->p_msg = M_CLOSE; 49113663Ssam pk->p_timer = 2; 49213663Ssam pkoutput(pk); 49313663Ssam i++; 49413663Ssam } 49513663Ssam 49613663Ssam for(i=0;i<NPLINES;i++) 49713663Ssam if (pklines[i]==pk) { 49813663Ssam pklines[i] = NULL; 49913663Ssam } 50013663Ssam 50113663Ssam /* 50213663Ssam * free space 50313663Ssam */ 50413663Ssam rcheck = 0; 50513663Ssam for (i=0;i<8;i++) { 50617836Sralph if (pk->p_os[i] != B_NULL) { 50717836Sralph free((char *)pk->p_ob[i]); 50813663Ssam pk->p_xcount--; 50913663Ssam } 51017836Sralph if (pk->p_is[i] != B_NULL) { 51117836Sralph free((char *)pk->p_ib[i]); 51213663Ssam rcheck++; 51313663Ssam } 51413663Ssam } 51513663Ssam while (pk->p_ipool != NULL) { 51613663Ssam bp = pk->p_ipool; 51713663Ssam pk->p_ipool = (char **)*bp; 51813663Ssam rcheck++; 51917836Sralph free((char *)bp); 52013663Ssam } 52117836Sralph if (rcheck != pk->p_rwindow) { 52217836Sralph logent("PK0", "pkclose rcheck != p_rwindow"); 52313663Ssam } 52417836Sralph free((char *)pk); 52513663Ssam } 52613663Ssam 52713663Ssam pkreset(pk) 52813663Ssam register struct pack *pk; 52913663Ssam { 53013663Ssam 53113663Ssam pk->p_ps = pk->p_pr = pk->p_rpr = 0; 53213663Ssam pk->p_nxtps = 1; 53313663Ssam } 53413663Ssam 53513663Ssam pkline(pk) 53613663Ssam register struct pack *pk; 53713663Ssam { 53817836Sralph register i; 53917836Sralph 54013663Ssam for(i=0;i<NPLINES;i++) { 54113663Ssam if (pklines[i]==pk) 54217836Sralph return i; 54313663Ssam } 54417836Sralph return -i; 54513663Ssam } 54613663Ssam 54717836Sralph #ifndef BSD4_2 54817836Sralph bzero(s,n) 54913663Ssam register char *s; 55013663Ssam register n; 55113663Ssam { 55213663Ssam while (n--) 55313663Ssam *s++ = 0; 55413663Ssam } 55517836Sralph #endif !BSD4_2 55613663Ssam 55713663Ssam pksize(n) 55813663Ssam register n; 55913663Ssam { 56017836Sralph register k; 56113663Ssam 56213663Ssam n >>= 5; 56317836Sralph for(k=0; n >>= 1; k++) 56417836Sralph ; 56517836Sralph return k; 56613663Ssam } 567