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