|
|
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: if (kk->modp->listnrq) ! 318: putctl2(RD(kk->modp->listnrq), M_PRICTL, DKMCLOSE, c); ! 319: dkstat.closepack++; ! 320: } ! 321: freeb(bp); ! 322: return; ! 323: } ! 324: if (q->next->flag&QFULL) { /* channel overflow */ ! 325: freeb(bp); ! 326: return; ! 327: } ! 328: if (rcbuf.count==0) ! 329: freeb(bp); ! 330: else { /* use small buffer if not much data */ ! 331: if (rcbuf.count<=64 && (nbp=allocb(rcbuf.count))) { ! 332: bcopy(bp->rptr, nbp->rptr, rcbuf.count); ! 333: freeb(bp); ! 334: bp = nbp; ! 335: } ! 336: bp->wptr += rcbuf.count; ! 337: dkstat.input += rcbuf.count; ! 338: (*q->next->qinfo->putp)(q->next, bp); ! 339: } ! 340: for (c=0; c<NCTL; c++) { ! 341: if (rcbuf.ctl[c]==0) ! 342: continue; ! 343: bp = allocb(1); ! 344: *bp->wptr++ = rcbuf.ctl[c]; ! 345: if ((rcbuf.ctl[c]&RDATA)==0) ! 346: bp->type = M_CTL; ! 347: (*q->next->qinfo->putp)(q->next, bp); ! 348: } ! 349: } ! 350: ! 351: /* ! 352: * start new input buffers ! 353: */ ! 354: kcistart(kk) ! 355: register struct kccure *kk; ! 356: { ! 357: register struct device *reg; ! 358: register struct block *bp; ! 359: register i; ! 360: ! 361: if ((reg = kk->addr) == NULL) ! 362: return; ! 363: while((kcrnext+1)%NCBUF != kcrfirst) { ! 364: i = kcrnext; ! 365: kk->ibp[i] = bp = allocb(1024); ! 366: kk->imap[i] = ubmblk(kk->ubno, bp, 0); ! 367: kk->rcbuf[i].ubaddr = ubadrptr(kk->ubno, bp, kk->imap[i]); ! 368: kk->rcbuf[i].count = bp->lim - bp->base; ! 369: kcwcmd(kk, CRCV, i); ! 370: kcrnext = (i+1)%NCBUF; ! 371: } ! 372: } ! 373: ! 374: /* ! 375: * put procedure for output ! 376: */ ! 377: kcput(q, bp) ! 378: register struct queue *q; ! 379: register struct block *bp; ! 380: { ! 381: register struct kc *dkp; ! 382: register struct kccure *kk; ! 383: register int n; ! 384: ! 385: dkp = (struct kc *)q->ptr; ! 386: kk = &kccure[KBNO]; ! 387: switch (bp->type) { ! 388: ! 389: case M_IOCTL: ! 390: switch (stiocom(bp)) { ! 391: case DIOCNXCL: ! 392: dkp->flag &=~ DKXCL; ! 393: bp->wptr = bp->rptr; ! 394: bp->type = M_IOCACK; ! 395: break; ! 396: ! 397: case KIOCINIT: ! 398: /* eventually, reset things here */ ! 399: ! 400: default: ! 401: bp->type = M_IOCNAK; ! 402: break; ! 403: } ! 404: qreply(q, bp); ! 405: return; ! 406: ! 407: case M_CTL: ! 408: case M_DATA: ! 409: dkstat.output += bp->wptr - bp->rptr; ! 410: putq(q, bp); ! 411: n = spl5(); ! 412: if ((dkp->flag & DKXWANT) == 0) { ! 413: if (kk->xfirst == NULL) ! 414: kk->xfirst = dkp; ! 415: else ! 416: kk->xlast->link = dkp; ! 417: dkp->link = NULL; ! 418: kk->xlast = dkp; ! 419: dkp->flag |= DKXWANT; ! 420: } ! 421: if ((kk->flags & XBUSY) == 0) ! 422: qenable(q); ! 423: splx(n); ! 424: return; ! 425: ! 426: case M_PRICTL: ! 427: switch (*bp->rptr) { ! 428: case DKMCLOSE: ! 429: n = bp->rptr[1]; ! 430: if (n < kccnt) { ! 431: if (kcstate[n] == DKOPEN) { ! 432: kcstate[n] = DKRCLOSE; ! 433: putctl(kc[n].dkrq->next, M_HANGUP); ! 434: } else if (kcstate[n] == DKLCLOSE) ! 435: kcstate[n] = DKCLOSED; ! 436: } ! 437: freeb(bp); ! 438: return; ! 439: ! 440: case DKMXINIT: ! 441: n = bp->rptr[1]; ! 442: if (n < kccnt && kcstate[n] == DKOPEN) ! 443: (*kc[n].dkrq->next->qinfo->putp)(kc[n].dkrq->next, bp); ! 444: else ! 445: freeb(bp); ! 446: return; ! 447: ! 448: default: ! 449: freeb(bp); ! 450: return; ! 451: } ! 452: ! 453: default: ! 454: freeb(bp); ! 455: return; ! 456: } ! 457: } ! 458: ! 459: kcosrv(junk) ! 460: struct queue *junk; ! 461: { ! 462: register struct kccure *kk = &kccure[KBNO]; ! 463: register s; ! 464: ! 465: s = spl5(); ! 466: while (kk->xfirst) { ! 467: if ((kcxnext+1)%NCBUF == kcxfirst) { ! 468: kk->flags |= XBUSY; ! 469: return; ! 470: } ! 471: if (kcosrvbuf(kcxnext)) ! 472: kcxnext = (kcxnext+1)%NCBUF; ! 473: } ! 474: splx(s); ! 475: } ! 476: ! 477: /* ! 478: * fill up one buffer and send it ! 479: */ ! 480: ! 481: kcosrvbuf(i) ! 482: register i; ! 483: { ! 484: ! 485: register struct kccure *kk; ! 486: register struct block *bp; ! 487: register struct queue *q; ! 488: register struct device *reg; ! 489: register struct kc *dkp; ! 490: int c; ! 491: ! 492: kk = &kccure[KBNO]; ! 493: reg = kk->addr; ! 494: dkp = kk->xfirst; ! 495: more: ! 496: if (dkp==NULL) { ! 497: printf("null dkp in kcosrvbuf\n"); ! 498: return 0; ! 499: } ! 500: if (dkp->dkrq==NULL) { ! 501: dkp->flag &=~ DKXWANT; ! 502: dkp = dkp->link; ! 503: if ((kk->xfirst = dkp) == NULL) { ! 504: kk->xlast = NULL; ! 505: return 0; ! 506: } ! 507: goto more; ! 508: } ! 509: q = WR(dkp->dkrq); ! 510: kk->xcbuf[i].chan = dkp->chan; ! 511: c = 0; ! 512: kk->xcbuf[i].count = 0; ! 513: while ((bp = getq(q)) != NULL) { ! 514: if (bp->type == M_CTL || bp->rptr+NCTL >= bp->wptr) { ! 515: while (bp->rptr < bp->wptr && c < NCTL) { ! 516: kk->xcbuf[i].ctl[c++] = *bp->rptr++ | ! 517: (bp->type==M_CTL?0:XDATA); ! 518: bp->type = M_DATA; ! 519: } ! 520: if (bp->rptr >= bp->wptr) { ! 521: freeb(bp); ! 522: continue; ! 523: } ! 524: } else if (c==0 && kk->xcbuf[i].count==0) { ! 525: kk->omap[i] = ubmblk(kk->ubno, bp, 0); ! 526: kk->xcbuf[i].ubaddr = ubadrptr(kk->ubno, bp, kk->omap[i]); ! 527: kk->xcbuf[i].count = bp->wptr - bp->rptr; ! 528: kk->obp[i] = bp; ! 529: continue; ! 530: } ! 531: putbq(q, bp); ! 532: break; ! 533: } ! 534: if (bp==NULL) { ! 535: dkp->flag &=~ DKXWANT; ! 536: dkp = dkp->link; ! 537: if ((kk->xfirst = dkp) == NULL) ! 538: kk->xlast = NULL; ! 539: } ! 540: while (c<NCTL) ! 541: kk->xcbuf[i].ctl[c++] = 0; ! 542: kcwcmd(kk, CSEND, i); ! 543: return 1; ! 544: } ! 545: ! 546: kcwcmd(kk, cmd, buf) ! 547: register struct kccure *kk; ! 548: { ! 549: register ocsr; ! 550: register count = 0; ! 551: register state; ! 552: ! 553: ocsr = kk->addr->csr; ! 554: state = ocsr&STATE; ! 555: if (state != SOK) { ! 556: if (state!=SRESET) ! 557: return(0); ! 558: switch(cmd&037) { ! 559: case CSETB: ! 560: case CBA: ! 561: case CBC: ! 562: case CINTR: ! 563: case CIACK: ! 564: break; ! 565: default: ! 566: if (kcinit(kk, 0)==0) ! 567: return(0); ! 568: break; ! 569: } ! 570: } ! 571: /* wait for last command to be accepted */ ! 572: while ((kk->addr->csr&SSEQ) == kclastseq) { ! 573: if (++count > 100000) { ! 574: printf("cure not responding: csr %o\n", kk->addr->csr); ! 575: return(0); ! 576: } ! 577: } ! 578: if (kk->addr->csr & (SERR|SUBERR)) ! 579: printf("cure csr %o\n", kk->addr->csr); ! 580: kclastseq = kk->addr->csr&SSEQ; ! 581: kk->addr->buf = buf; ! 582: kk->addr->csr = cmd; ! 583: return(1); ! 584: } ! 585: ! 586: kcclock(dev) ! 587: caddr_t dev; ! 588: { ! 589: cure0int(minor((int)dev)); ! 590: timeout(kcclock, dev, 10*HZ); ! 591: } ! 592: ! 593: /* ! 594: * raw cure device for downloading ! 595: */ ! 596: long rcureopen(); ! 597: int rcureclose(), rcureoput(); ! 598: ! 599: static struct qinit rcurerinit = { ! 600: noput, NULL, rcureopen, nulldev, 0, 0 ! 601: }; ! 602: static struct qinit rcurewinit = { ! 603: rcureoput, NULL, rcureopen, nulldev, 200, 100 ! 604: }; ! 605: struct streamtab rcureinfo = { ! 606: &rcurerinit, &rcurewinit ! 607: }; ! 608: ! 609: /* ! 610: * config glue ! 611: */ ! 612: extern struct ubaddr rcureaddr[]; /* one per device */ ! 613: extern int rcurecnt; /* one per device or what? */ ! 614: struct cdevsw rcurecdev = cstrinit(&rcureinfo); ! 615: ! 616: long ! 617: rcureopen(q, d) ! 618: register struct queue *q; ! 619: { ! 620: register dev; ! 621: register struct device *mp; ! 622: ! 623: if((dev = minor(d)) >= rcurecnt) ! 624: return 0; ! 625: if((mp = (struct device *)ubaddr(&rcureaddr[dev])) == 0 ! 626: || badaddr(mp, sizeof(u_char))) { ! 627: printf("cure %d absent\n", d); ! 628: return 0; ! 629: } ! 630: WR(q)->ptr = q->ptr = (caddr_t) dev; ! 631: return 1; ! 632: } ! 633: ! 634: rcureoput(q, bp) ! 635: register struct queue *q; ! 636: register struct block *bp; ! 637: { ! 638: #define DV 017 /* actual device number */ ! 639: #define BOOTOK 020 /* initialization flag */ ! 640: ! 641: register struct device *mp = ! 642: (struct device *)ubaddr(&rcureaddr[(int)q->ptr & DV]); ! 643: register int csr, n; ! 644: ! 645: switch(bp->type) { ! 646: ! 647: case M_IOCTL: ! 648: bp->type = M_IOCNAK; ! 649: bp->wptr = bp->rptr; ! 650: switch(stiocom(bp)) { ! 651: case KIOCINIT: /* reboot cure */ ! 652: mp->reset = 1; ! 653: delay(10); ! 654: mp->reset = 0; ! 655: bp->type = M_IOCACK; ! 656: break; ! 657: } ! 658: qreply(q, bp); ! 659: return; ! 660: ! 661: case M_DATA: ! 662: if (((int)q->ptr&BOOTOK) == 0) { /* first write */ ! 663: if ((mp->csr&STATE) != SBOOT) { ! 664: printf("cure not ready to load, %o\n", mp->csr); ! 665: goto err; ! 666: } ! 667: mp->buf = 070707; /* magic number starts bootload */ ! 668: delay(10); ! 669: if ((mp->csr&STATE) != SBOOTING) { ! 670: printf("cure load err0 %o\n", mp->csr); ! 671: goto err; ! 672: } ! 673: q->ptr = (caddr_t)((int)q->ptr | BOOTOK); ! 674: } ! 675: while (bp->rptr < bp->wptr) { ! 676: if ((mp->csr&STATE) != SBOOTING) { ! 677: printf("cure load err1\n"); ! 678: goto err; ! 679: } ! 680: csr = mp->csr; ! 681: mp->buf = *bp->rptr++; ! 682: for (n=0; ((csr ^ mp->csr)&SSEQ)==0 && n<100000; ++n) { ! 683: if (mp->csr&SERR || (mp->csr&STATE)!=SBOOTING) { ! 684: printf("cure load err2 %o\n", mp->csr); ! 685: goto err; ! 686: } ! 687: } ! 688: if (n==100000) { ! 689: printf("cure load err3\n"); ! 690: goto err; ! 691: } ! 692: } ! 693: break; ! 694: } ! 695: freeb(bp); ! 696: return; ! 697: err: ! 698: bp->type = M_HANGUP; ! 699: qreply(q, bp); ! 700: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.