|
|
1.1 ! root 1: /* ! 2: * simple CURE datakit driver ! 3: * -- assumes it is the first CURE, and only one allowed for now ! 4: * (the latter not severe, as 256 channels are permitted) ! 5: */ ! 6: #include "sys/param.h" ! 7: #include "sys/stream.h" ! 8: #include "sys/dkio.h" ! 9: #include "sys/ubaddr.h" ! 10: #include "sys/conf.h" ! 11: #include "sys/kc.h" ! 12: #include "sys/dkstat.h" ! 13: #include "sys/dkmod.h" ! 14: #include "sys/buf.h" ! 15: ! 16: /* ! 17: * hardware stuff ! 18: */ ! 19: struct device { ! 20: unsigned short buf; ! 21: unsigned char csr; ! 22: char fill1; ! 23: short fill2; ! 24: char reset; ! 25: }; ! 26: ! 27: /* ! 28: * status bits ! 29: */ ! 30: #define SSEQ 01 /* 1-bit command sequence # */ ! 31: #define SRRDY 02 /* receive ready */ ! 32: #define SXRDY 04 /* transmit ready */ ! 33: #define SUBERR 010 /* unibus error */ ! 34: #define SERR 020 /* protocol error */ ! 35: #define STATE 0300 /* booting state mask... */ ! 36: #define SOK 0200 /* ready for real IO */ ! 37: #define SBOOT 0100 /* ready for download (just been reset) */ ! 38: #define SBOOTING 0 /* in middle of download */ ! 39: #define SRESET 0300 /* finished download, must reset UB base, vector */ ! 40: ! 41: /* ! 42: * command bits ! 43: */ ! 44: #define CSEND 02 /* send */ ! 45: #define CSETB 03 /* announce location of control buffers */ ! 46: #define CRCV 04 /* receive */ ! 47: #define CBA 06 /* set bus address */ ! 48: #define CBC 010 /* set buffer count */ ! 49: #define CINTR 012 /* set vector address */ ! 50: #define CRESET 014 /* reset interface */ ! 51: #define CIACK 016 /* ack interrupt or reset */ ! 52: ! 53: #define CXA 0140 /* high address bits */ ! 54: #define XASHIFT 11 /* shift high address bits this much */ ! 55: ! 56: typedef short Env; /* datakit envelope in our buffers */ ! 57: ! 58: /* ! 59: * bits in transmit buffer ! 60: */ ! 61: #define XDATA 0400 /* data, not control */ ! 62: ! 63: /* ! 64: * bits in receive buffer ! 65: */ ! 66: #define RMARK 01000 /* channel mark */ ! 67: #define RDATA 0400 /* this is data */ ! 68: #define RSPCL 0100000 /* special (sign bit): mark or control */ ! 69: #define REOT (RSPCL|RMARK) /* end of receive buffer, if short */ ! 70: ! 71: /* ! 72: * per-channel stuff ! 73: */ ! 74: #define NCHAN 256 ! 75: struct kc kc[NCHAN]; ! 76: int kccnt = NCHAN; ! 77: char kcstate[NCHAN]; ! 78: ! 79: /* ! 80: * kc flags ! 81: */ ! 82: #define DKXCL 01 /* exclusive open */ ! 83: #define DKXWANT 02 /* output pending this channel */ ! 84: ! 85: /* ! 86: * per-controller stuff; ! 87: * always just one for now ! 88: */ ! 89: ! 90: extern struct ubaddr cureaddr[]; ! 91: struct kccure kccure[1]; ! 92: #define KBNO 0 /* always this kc for now */ ! 93: int kcxfirst; ! 94: int kcxnext; ! 95: int kcrfirst; ! 96: int kcrnext; ! 97: ! 98: /* ! 99: * kccure flags ! 100: */ ! 101: #define XBUSY 01 /* transmit busy */ ! 102: #define XWANT 02 /* output needed */ ! 103: #define INIT 04 ! 104: ! 105: /* ! 106: * illicit linkage to other datakit code ! 107: */ ! 108: ! 109: struct dkstat dkstat; ! 110: ! 111: #define KNO 0 ! 112: ! 113: #define DKISML 16 /* smallest interesting allocation */ ! 114: #define DKITHRES 200 ! 115: ! 116: long kcopen(); ! 117: int kcclose(), kcput(), kcosrv(); ! 118: ! 119: static struct qinit kcrinit = { noput, NULL, kcopen, kcclose, 0, 0 }; ! 120: struct qinit kcwinit = { kcput, kcosrv, kcopen, kcclose, 1500, 600 }; ! 121: struct streamtab kcinfo = { &kcrinit, &kcwinit }; ! 122: struct cdevsw curecdev = cstrinit(&kcinfo); ! 123: ! 124: static kclastseq; ! 125: ! 126: /* ! 127: * open DK channel ! 128: */ ! 129: long ! 130: kcopen(q, dev) ! 131: register struct queue *q; ! 132: register dev_t dev; ! 133: { ! 134: register struct kc *dkp; ! 135: register struct kccure *kk; ! 136: register chan; ! 137: extern struct dkmodule *dkmodall(); ! 138: int kcclock(); ! 139: ! 140: chan = minor(dev); ! 141: if (chan<=0 || chan>=kccnt) ! 142: return(0); ! 143: kk = &kccure[KBNO]; ! 144: if ((kk->flags & INIT) == 0) { ! 145: if ((kk->modp = dkmodall(dev, 0, kccnt)) == NULL) ! 146: return (0); ! 147: kk->modp->dkstate = kcstate; ! 148: if (kcinit(kk, 1) == 0) ! 149: return (0); ! 150: kk->flags |= INIT; ! 151: timeout(kcclock, (caddr_t)minor(dev), 10*HZ); ! 152: } ! 153: dkp = &kc[chan]; ! 154: if (kcstate[chan] != DKCLOSED) { /* already open */ ! 155: if (dkp->flag & DKXCL) ! 156: return(0); ! 157: if (kcstate[chan] != DKOPEN) ! 158: return(0); /* closing channels can't reopen */ ! 159: return(1); ! 160: } ! 161: dkp->dkrq = q; ! 162: q->ptr = (caddr_t)dkp; ! 163: WR(q)->ptr = (caddr_t)dkp; ! 164: WR(q)->flag |= QNOENB|QBIGB; ! 165: dkp->flag = DKXCL; ! 166: kcstate[chan] = DKOPEN; ! 167: return(1); ! 168: } ! 169: ! 170: /* ! 171: * make sure cure is alive; ! 172: * init data structures once ! 173: * it might be better to deal with BDPs dynamically somehow, ! 174: * e.g. on the comet where there are very few ! 175: */ ! 176: kcinit(kk, firsttime) ! 177: register struct kccure *kk; ! 178: { ! 179: register struct device *reg; ! 180: register int i; ! 181: register struct kc *dkp; ! 182: static ubm_t map; ! 183: uaddr_t uaddr; ! 184: extern cure0int(), kcreset(); ! 185: ! 186: kk->kno = KNO; ! 187: if ((reg = (struct device *)ubaddr(&cureaddr[0])) == NULL ! 188: || badaddr(reg, 2)) { ! 189: printf("cure0 absent\n"); ! 190: return (0); ! 191: } ! 192: for (i = kccnt - 1, dkp = &kc[i]; i >= 0; --dkp, --i) ! 193: dkp->chan = i; ! 194: kk->addr = reg; ! 195: if ((reg->csr&STATE) != SRESET && (reg->csr&STATE) != SOK) ! 196: return(0); /* check downloaded OK */ ! 197: kclastseq = (reg->csr^SSEQ) & SSEQ; ! 198: if (kcwcmd(kk, CINTR, cureaddr[0].vec) == 0) ! 199: return (0); ! 200: /* allocate and announce command buffers */ ! 201: if (firsttime) ! 202: map = ubmalloc(kk->ubno, (2*NCBUF+1)*sizeof(struct cmd), 0); ! 203: else { /* resetting; free blocks in use */ ! 204: for (i=0; i<NCBUF; i++) { ! 205: if (kk->ibp[i]) ! 206: freeb(kk->ibp[i]); ! 207: if (kk->obp[i]) ! 208: freeb(kk->obp[i]); ! 209: kk->ibp[i] = NULL; ! 210: kk->obp[i] = NULL; ! 211: } ! 212: kcxfirst = kcrfirst = kcxnext = kcrnext = 0; ! 213: } ! 214: uaddr = ubmaddr(kk->ubno, kk->xcbuf, (2*NCBUF+1)*sizeof(struct cmd), map); ! 215: printf("cure reset, uaddr %x map %x\n", uaddr, map); ! 216: kcwcmd(kk, CBA, uaddr); ! 217: kcwcmd(kk, CBC, NCBUF); ! 218: kcwcmd(kk, CSETB|((uaddr>>XASHIFT)&CXA), 0); ! 219: kcwcmd(kk, CIACK, 0); /* to delay until CSETB processed */ ! 220: if ((reg->csr&STATE)!=SOK) { ! 221: printf("cure not ready, state %o\n", reg->csr); ! 222: return(0); ! 223: } ! 224: kcistart(kk); ! 225: return (1); ! 226: } ! 227: ! 228: /* ! 229: * close DK channel ! 230: */ ! 231: kcclose(q) ! 232: register struct queue *q; ! 233: { ! 234: register struct kc *dkp; ! 235: register struct kccure *kk; ! 236: ! 237: kk = &kccure[KBNO]; ! 238: dkp = (struct kc *)q->ptr; ! 239: if (dkp == NULL) ! 240: panic("kcclose"); ! 241: dkp->dkrq = NULL; ! 242: dkp->flag = 0; ! 243: if (kcstate[dkp->chan] == DKRCLOSE || kk->modp->listnrq==NULL) ! 244: kcstate[dkp->chan] = DKCLOSED; ! 245: else if (kcstate[dkp->chan] == DKOPEN) ! 246: kcstate[dkp->chan] = DKLCLOSE; ! 247: if (kk->modp->listnrq) ! 248: putctl2(RD(kk->modp->listnrq), M_PRICTL, DKMCLOSE, dkp->chan); ! 249: } ! 250: ! 251: /* ! 252: * interrupt ! 253: */ ! 254: cure1int(dev) {} ! 255: cure0int(dev) ! 256: { ! 257: register struct kccure *kk; ! 258: register struct device *reg; ! 259: register doneb, i, csr; ! 260: ! 261: ! 262: kk = &kccure[KBNO]; ! 263: if ((reg = kk->addr) == NULL) ! 264: return; ! 265: csr = reg->csr; ! 266: i = csr&STATE; ! 267: if (i!=SOK && i!=SRESET) ! 268: return; ! 269: if (csr & (SERR|SUBERR)) ! 270: printf("cure status %o\n", reg->csr); ! 271: doneb = reg->buf; ! 272: i = doneb&0377; /* first rcv buf not done */ ! 273: while (i != kcrfirst) { ! 274: kcrecv(kk, kcrfirst); ! 275: kcrfirst = (kcrfirst+1)%NCBUF; ! 276: } ! 277: kcistart(kk); ! 278: i = (doneb>>8)&0377; /* first xmit buf not done */ ! 279: while (i != kcxfirst) { ! 280: kk->flags &=~ XBUSY; ! 281: if (kk->obp[kcxfirst]) { ! 282: freeb(kk->obp[kcxfirst]); ! 283: ubmfree(kk->ubno, kk->omap[kcxfirst]); ! 284: } ! 285: kk->obp[kcxfirst] = NULL; ! 286: kcxfirst = (kcxfirst+1)%NCBUF; ! 287: } ! 288: if (kk->xfirst) ! 289: kcosrv((struct queue *)NULL); ! 290: } ! 291: ! 292: /* ! 293: * receive a buffer ! 294: */ ! 295: kcrecv(kk, i) ! 296: register struct kccure *kk; ! 297: { ! 298: register struct block *bp, *nbp; ! 299: register struct queue *q; ! 300: register c; ! 301: struct cmd rcbuf; ! 302: ! 303: rcbuf = kk->rcbuf[i]; ! 304: bp = kk->ibp[i]; ! 305: if (bp==NULL) { ! 306: printf("null bp in kcrecv\n"); ! 307: return; ! 308: } ! 309: kk->ibp[i] = NULL; ! 310: c = rcbuf.chan; ! 311: if (c==0 || c>=kccnt || (q = kc[c].dkrq)==NULL) { ! 312: if (c==0) ! 313: dkstat.pack0++; ! 314: else if (c>=kccnt) ! 315: dkstat.packstrange++; ! 316: else ! 317: dkstat.closepack++; ! 318: freeb(bp); ! 319: return; ! 320: } ! 321: if (q->next->flag&QFULL) { /* channel overflow */ ! 322: freeb(bp); ! 323: return; ! 324: } ! 325: if (rcbuf.count==0) ! 326: freeb(bp); ! 327: else { /* use small buffer if not much data */ ! 328: if (rcbuf.count<=64 && (nbp=allocb(rcbuf.count))) { ! 329: bcopy(bp->rptr, nbp->rptr, rcbuf.count); ! 330: freeb(bp); ! 331: bp = nbp; ! 332: } ! 333: bp->wptr += rcbuf.count; ! 334: dkstat.input += rcbuf.count; ! 335: (*q->next->qinfo->putp)(q->next, bp); ! 336: } ! 337: for (c=0; c<NCTL; c++) { ! 338: if (rcbuf.ctl[c]==0) ! 339: continue; ! 340: bp = allocb(1); ! 341: *bp->wptr++ = rcbuf.ctl[c]; ! 342: if ((rcbuf.ctl[c]&RDATA)==0) ! 343: bp->type = M_CTL; ! 344: (*q->next->qinfo->putp)(q->next, bp); ! 345: } ! 346: } ! 347: ! 348: /* ! 349: * start new input buffers ! 350: */ ! 351: kcistart(kk) ! 352: register struct kccure *kk; ! 353: { ! 354: register struct device *reg; ! 355: register struct block *bp; ! 356: register i; ! 357: ! 358: if ((reg = kk->addr) == NULL) ! 359: return; ! 360: while((kcrnext+1)%NCBUF != kcrfirst) { ! 361: i = kcrnext; ! 362: kk->ibp[i] = bp = allocb(1024); ! 363: kk->imap[i] = ubmblk(kk->ubno, bp, 0); ! 364: kk->rcbuf[i].ubaddr = ubadrptr(kk->ubno, bp, kk->imap[i]); ! 365: kk->rcbuf[i].count = bp->lim - bp->base; ! 366: kcwcmd(kk, CRCV, i); ! 367: kcrnext = (i+1)%NCBUF; ! 368: } ! 369: } ! 370: ! 371: /* ! 372: * put procedure for output ! 373: */ ! 374: kcput(q, bp) ! 375: register struct queue *q; ! 376: register struct block *bp; ! 377: { ! 378: register struct kc *dkp; ! 379: register struct kccure *kk; ! 380: register int n; ! 381: ! 382: dkp = (struct kc *)q->ptr; ! 383: kk = &kccure[KBNO]; ! 384: switch (bp->type) { ! 385: ! 386: case M_IOCTL: ! 387: switch (stiocom(bp)) { ! 388: case DIOCNXCL: ! 389: dkp->flag &=~ DKXCL; ! 390: bp->wptr = bp->rptr; ! 391: bp->type = M_IOCACK; ! 392: break; ! 393: ! 394: case KIOCINIT: ! 395: /* eventually, reset things here */ ! 396: ! 397: default: ! 398: bp->type = M_IOCNAK; ! 399: break; ! 400: } ! 401: qreply(q, bp); ! 402: return; ! 403: ! 404: case M_CTL: ! 405: case M_DATA: ! 406: dkstat.output += bp->wptr - bp->rptr; ! 407: putq(q, bp); ! 408: n = spl5(); ! 409: if ((dkp->flag & DKXWANT) == 0) { ! 410: if (kk->xfirst == NULL) ! 411: kk->xfirst = dkp; ! 412: else ! 413: kk->xlast->link = dkp; ! 414: dkp->link = NULL; ! 415: kk->xlast = dkp; ! 416: dkp->flag |= DKXWANT; ! 417: } ! 418: if ((kk->flags & XBUSY) == 0) ! 419: qenable(q); ! 420: splx(n); ! 421: return; ! 422: ! 423: case M_PRICTL: ! 424: switch (*bp->rptr) { ! 425: case DKMCLOSE: ! 426: n = bp->rptr[1]; ! 427: if (n < kccnt) { ! 428: if (kcstate[n] == DKOPEN) { ! 429: kcstate[n] = DKRCLOSE; ! 430: putctl(kc[n].dkrq->next, M_HANGUP); ! 431: } else if (kcstate[n] == DKLCLOSE) ! 432: kcstate[n] = DKCLOSED; ! 433: } ! 434: freeb(bp); ! 435: return; ! 436: ! 437: case DKMXINIT: ! 438: n = bp->rptr[1]; ! 439: if (n < kccnt && kcstate[n] == DKOPEN) ! 440: (*kc[n].dkrq->next->qinfo->putp)(kc[n].dkrq->next, bp); ! 441: else ! 442: freeb(bp); ! 443: return; ! 444: ! 445: default: ! 446: freeb(bp); ! 447: return; ! 448: } ! 449: ! 450: default: ! 451: freeb(bp); ! 452: return; ! 453: } ! 454: } ! 455: ! 456: kcosrv(junk) ! 457: struct queue *junk; ! 458: { ! 459: register struct kccure *kk = &kccure[KBNO]; ! 460: register s; ! 461: ! 462: s = spl5(); ! 463: while (kk->xfirst) { ! 464: if ((kcxnext+1)%NCBUF == kcxfirst) { ! 465: kk->flags |= XBUSY; ! 466: return; ! 467: } ! 468: if (kcosrvbuf(kcxnext)) ! 469: kcxnext = (kcxnext+1)%NCBUF; ! 470: } ! 471: splx(s); ! 472: } ! 473: ! 474: /* ! 475: * fill up one buffer and send it ! 476: */ ! 477: ! 478: kcosrvbuf(i) ! 479: register i; ! 480: { ! 481: ! 482: register struct kccure *kk; ! 483: register struct block *bp; ! 484: register struct queue *q; ! 485: register struct device *reg; ! 486: register struct kc *dkp; ! 487: int c; ! 488: ! 489: kk = &kccure[KBNO]; ! 490: reg = kk->addr; ! 491: dkp = kk->xfirst; ! 492: more: ! 493: if (dkp==NULL) { ! 494: printf("null dkp in kcosrvbuf\n"); ! 495: return 0; ! 496: } ! 497: if (dkp->dkrq==NULL) { ! 498: dkp->flag &=~ DKXWANT; ! 499: dkp = dkp->link; ! 500: if ((kk->xfirst = dkp) == NULL) { ! 501: kk->xlast = NULL; ! 502: return 0; ! 503: } ! 504: goto more; ! 505: } ! 506: q = WR(dkp->dkrq); ! 507: kk->xcbuf[i].chan = dkp->chan; ! 508: c = 0; ! 509: kk->xcbuf[i].count = 0; ! 510: while ((bp = getq(q)) != NULL) { ! 511: if (bp->type == M_CTL || bp->rptr+NCTL >= bp->wptr) { ! 512: while (bp->rptr < bp->wptr && c < NCTL) { ! 513: kk->xcbuf[i].ctl[c++] = *bp->rptr++ | ! 514: (bp->type==M_CTL?0:XDATA); ! 515: bp->type = M_DATA; ! 516: } ! 517: if (bp->rptr >= bp->wptr) { ! 518: freeb(bp); ! 519: continue; ! 520: } ! 521: } else if (c==0 && kk->xcbuf[i].count==0) { ! 522: kk->omap[i] = ubmblk(kk->ubno, bp, 0); ! 523: kk->xcbuf[i].ubaddr = ubadrptr(kk->ubno, bp, kk->omap[i]); ! 524: kk->xcbuf[i].count = bp->wptr - bp->rptr; ! 525: kk->obp[i] = bp; ! 526: continue; ! 527: } ! 528: putbq(q, bp); ! 529: break; ! 530: } ! 531: if (bp==NULL) { ! 532: dkp->flag &=~ DKXWANT; ! 533: dkp = dkp->link; ! 534: if ((kk->xfirst = dkp) == NULL) ! 535: kk->xlast = NULL; ! 536: } ! 537: while (c<NCTL) ! 538: kk->xcbuf[i].ctl[c++] = 0; ! 539: kcwcmd(kk, CSEND, i); ! 540: return 1; ! 541: } ! 542: ! 543: kcwcmd(kk, cmd, buf) ! 544: register struct kccure *kk; ! 545: { ! 546: register ocsr; ! 547: register count = 0; ! 548: register state; ! 549: ! 550: ocsr = kk->addr->csr; ! 551: state = ocsr&STATE; ! 552: if (state != SOK) { ! 553: if (state!=SRESET) ! 554: return(0); ! 555: switch(cmd&037) { ! 556: case CSETB: ! 557: case CBA: ! 558: case CBC: ! 559: case CINTR: ! 560: case CIACK: ! 561: break; ! 562: default: ! 563: if (kcinit(kk, 0)==0) ! 564: return(0); ! 565: break; ! 566: } ! 567: } ! 568: /* wait for last command to be accepted */ ! 569: while ((kk->addr->csr&SSEQ) == kclastseq) { ! 570: if (++count > 100000) { ! 571: printf("cure not responding: csr %o\n", kk->addr->csr); ! 572: return(0); ! 573: } ! 574: } ! 575: if (kk->addr->csr & (SERR|SUBERR)) ! 576: printf("cure csr %o\n", kk->addr->csr); ! 577: kclastseq = kk->addr->csr&SSEQ; ! 578: kk->addr->buf = buf; ! 579: kk->addr->csr = cmd; ! 580: return(1); ! 581: } ! 582: ! 583: kcclock(dev) ! 584: caddr_t dev; ! 585: { ! 586: cure0int(minor((int)dev)); ! 587: timeout(kcclock, dev, 10*HZ); ! 588: } ! 589: ! 590: /* ! 591: * raw cure device for downloading ! 592: */ ! 593: long rcureopen(); ! 594: int rcureclose(), rcureoput(); ! 595: ! 596: static struct qinit rcurerinit = { ! 597: noput, NULL, rcureopen, nulldev, 0, 0 ! 598: }; ! 599: static struct qinit rcurewinit = { ! 600: rcureoput, NULL, rcureopen, nulldev, 200, 100 ! 601: }; ! 602: struct streamtab rcureinfo = { ! 603: &rcurerinit, &rcurewinit ! 604: }; ! 605: ! 606: /* ! 607: * config glue ! 608: */ ! 609: extern struct ubaddr rcureaddr[]; /* one per device */ ! 610: extern int rcurecnt; /* one per device or what? */ ! 611: struct cdevsw rcurecdev = cstrinit(&rcureinfo); ! 612: ! 613: long ! 614: rcureopen(q, d) ! 615: register struct queue *q; ! 616: { ! 617: register dev; ! 618: register struct device *mp; ! 619: ! 620: if((dev = minor(d)) >= rcurecnt) ! 621: return 0; ! 622: if((mp = (struct device *)ubaddr(&rcureaddr[dev])) == 0 ! 623: || badaddr(mp, sizeof(u_char))) { ! 624: printf("cure %d absent\n", d); ! 625: return 0; ! 626: } ! 627: WR(q)->ptr = q->ptr = (caddr_t) dev; ! 628: return 1; ! 629: } ! 630: ! 631: rcureoput(q, bp) ! 632: register struct queue *q; ! 633: register struct block *bp; ! 634: { ! 635: #define DV 017 /* actual device number */ ! 636: #define BOOTOK 020 /* initialization flag */ ! 637: ! 638: register struct device *mp = ! 639: (struct device *)ubaddr(&rcureaddr[(int)q->ptr & DV]); ! 640: register int csr, n; ! 641: ! 642: switch(bp->type) { ! 643: ! 644: case M_IOCTL: ! 645: bp->type = M_IOCNAK; ! 646: bp->wptr = bp->rptr; ! 647: switch(stiocom(bp)) { ! 648: case KIOCINIT: /* reboot cure */ ! 649: mp->reset = 1; ! 650: delay(10); ! 651: mp->reset = 0; ! 652: bp->type = M_IOCACK; ! 653: break; ! 654: } ! 655: qreply(q, bp); ! 656: return; ! 657: ! 658: case M_DATA: ! 659: if (((int)q->ptr&BOOTOK) == 0) { /* first write */ ! 660: if ((mp->csr&STATE) != SBOOT) { ! 661: printf("cure not ready to load, %o\n", mp->csr); ! 662: goto err; ! 663: } ! 664: mp->buf = 070707; /* magic number starts bootload */ ! 665: delay(10); ! 666: if ((mp->csr&STATE) != SBOOTING) { ! 667: printf("cure load err0 %o\n", mp->csr); ! 668: goto err; ! 669: } ! 670: q->ptr = (caddr_t)((int)q->ptr | BOOTOK); ! 671: } ! 672: while (bp->rptr < bp->wptr) { ! 673: if ((mp->csr&STATE) != SBOOTING) { ! 674: printf("cure load err1\n"); ! 675: goto err; ! 676: } ! 677: csr = mp->csr; ! 678: mp->buf = *bp->rptr++; ! 679: for (n=0; ((csr ^ mp->csr)&SSEQ)==0 && n<100000; ++n) { ! 680: if (mp->csr&SERR || (mp->csr&STATE)!=SBOOTING) { ! 681: printf("cure load err2 %o\n", mp->csr); ! 682: goto err; ! 683: } ! 684: } ! 685: if (n==100000) { ! 686: printf("cure load err3\n"); ! 687: goto err; ! 688: } ! 689: } ! 690: break; ! 691: } ! 692: freeb(bp); ! 693: return; ! 694: err: ! 695: bp->type = M_HANGUP; ! 696: qreply(q, bp); ! 697: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.