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