|
|
1.1 ! root 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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.