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