|
|
1.1 ! root 1: /* %M 6.2 83/10/12 */ ! 2: ! 3: #if defined(VAX750) || defined(VAX730) ! 4: /* ! 5: * TU58 DECtape II device driver ! 6: * ! 7: * TU58 console cassette driver (for VAX-11/750 or VAX-11/730). ! 8: * The TU58 is treated as a block device (only). Error detection and ! 9: * recovery is not extensive, but sufficient for most situations. It is ! 10: * assumed that the TU58 will follow the RSP (or MRSP) protocol exactly, ! 11: * very few protocol errors are checked for. It is also assumed that ! 12: * the 730 uses Modified RSP (MRSP), while the 750 may use either RSP ! 13: * or MRSP depending on whether defined(MRSP) is true or not. ! 14: * In the case of a 750 without MRSP, the only way for the CPU to ! 15: * keep up with the tu58 is to lock out virtually everything else. ! 16: * ! 17: * NOTE: Reading large amounts of data from the tu58 is likely ! 18: * to crash your system if you are running multiuser. ! 19: * ******FOR SINGLE USER USE ONLY***** ! 20: */ ! 21: #include "../h/param.h" ! 22: #include "../h/systm.h" ! 23: #include "../h/buf.h" ! 24: #include "../h/conf.h" ! 25: #include "../h/dir.h" ! 26: #include "../h/user.h" ! 27: #include "../h/kernel.h" ! 28: ! 29: #include "../vax/cpu.h" ! 30: #include "../vax/mtpr.h" ! 31: #include "../vax/rsp.h" ! 32: ! 33: #define printd if(tudebug) printf ! 34: #ifdef printd ! 35: int tudebug; /* printd */ ! 36: #endif printd ! 37: ! 38: #define NTU ((cpu == VAX_750) ? 1 : 2) ! 39: #define DNUM 01 /* mask for drive number (should match NTU) */ ! 40: #define NTUBLK 512 /* number of blocks on a TU58 cassette */ ! 41: #define WRV 02 /* bit in minor dev => write w. read verify */ ! 42: #define NTUQ 2 /* # of blocks which can be queued up */ ! 43: #define TUIPL ((cpu == VAX_750) ? 0x17 : 0x14) ! 44: ! 45: #ifndef MRSP ! 46: #define MRSP (cpu != VAX_750) ! 47: #endif ! 48: ! 49: /* ! 50: * State information ! 51: */ ! 52: struct tu { ! 53: u_char *tu_rbptr; /* pointer to buffer for read */ ! 54: int tu_rcnt; /* how much to read */ ! 55: u_char *tu_wbptr; /* pointer to buffer for write */ ! 56: int tu_wcnt; /* how much to write */ ! 57: int tu_state; /* current state of tansfer operation */ ! 58: int tu_flag; /* read in progress flag */ ! 59: char *tu_addr; /* real buffer data address */ ! 60: int tu_count; /* real requested count */ ! 61: int tu_serrs; /* count of soft errors */ ! 62: int tu_cerrs; /* count of checksum errors */ ! 63: int tu_herrs; /* count of hard errors */ ! 64: char tu_dopen[2]; /* drive is open */ ! 65: } tu; ! 66: ! 67: ! 68: /* ! 69: * Device register bits ! 70: */ ! 71: #define READY 0200 /* transmitter ready */ ! 72: #define DONE 0200 /* receiver done */ ! 73: #define IE 0100 /* interrupt enable */ ! 74: #define BREAK 1 /* send break */ ! 75: ! 76: struct packet tucmd; /* a command sent to the TU58 */ ! 77: struct packet tudata; /* a command or data returned from TU58 */ ! 78: ! 79: char *tustates[TUS_NSTATES] = { ! 80: "INIT1", "INIT2", "IDLE", "SENDH", "SENDD", "SENDC", "SENDR", ! 81: "SENDW", "GETH", "GETD", "GETC", "GET", "WAIT", "RCVERR", "CHKERR" ! 82: }; ! 83: ! 84: u_char tunull[2] = { 0, 0 }; /* nulls to send for initialization */ ! 85: u_char tuinit[2] = { TUF_INITF, TUF_INITF }; /* inits to send */ ! 86: static char tu_pcnt[2]; /* pee/vee counters */ ! 87: int tutimer = 0; ! 88: int tuwake(); ! 89: struct buf tutab; /* I/O queue header */ ! 90: ! 91: /* ! 92: * Open the TU58 ! 93: */ ! 94: /*ARGSUSED*/ ! 95: tuopen(dev, flag) ! 96: { ! 97: extern int tuwatch(); ! 98: register s; ! 99: ! 100: #ifdef lint ! 101: turintr(); tuwintr(); ! 102: #endif ! 103: if ((minor(dev)&DNUM) >= NTU) ! 104: return (ENXIO); ! 105: if (tu.tu_dopen[minor(dev)&DNUM]) ! 106: return (EBUSY); ! 107: if (tutimer++ == 0) ! 108: timeout(tuwatch, (caddr_t)0, hz); ! 109: ! 110: s = splx(TUIPL); ! 111: tu.tu_dopen[minor(dev)&DNUM]++; ! 112: /* ! 113: * If the cassette's already initialized, ! 114: * just enable interrupts and return. ! 115: */ ! 116: if (tu.tu_state == TUS_IDLE) { ! 117: mtpr(CSRS, IE); ! 118: goto ok; ! 119: } ! 120: ! 121: /* ! 122: * Must initialize, reset the cassette ! 123: * and wait for things to settle down. ! 124: */ ! 125: tureset(); ! 126: sleep((caddr_t)&tu, PZERO+1); ! 127: tutab.b_active = NULL; ! 128: if (tu.tu_state != TUS_IDLE) { ! 129: tu.tu_state = TUS_INIT1; ! 130: tu.tu_dopen[minor(dev)&DNUM] = 0; ! 131: tu.tu_rcnt = tu.tu_wcnt = 0; ! 132: mtpr(CSTS, 0); ! 133: mtpr(CSRS, 0); ! 134: splx(s); ! 135: return (EIO); ! 136: } ! 137: ok: ! 138: splx(s); ! 139: return (0); ! 140: } ! 141: ! 142: /* ! 143: * Close the TU58, but make sure all ! 144: * outstanding i/o is complete first.. ! 145: */ ! 146: tuclose(dev, flag) ! 147: dev_t dev; ! 148: int flag; ! 149: { ! 150: int s, unit = minor(dev); ! 151: struct buf *bp, *last = NULL; ! 152: ! 153: s = splx(TUIPL); ! 154: while (tu_pcnt[unit]) ! 155: sleep(&tu_pcnt[unit], PRIBIO); ! 156: /* ! 157: * No more writes are pending, scan the ! 158: * buffer queue for oustanding reads from ! 159: * this unit. ! 160: */ ! 161: for (bp = tutab.b_actf; bp; bp = bp->b_actf) { ! 162: if (bp->b_dev == dev) ! 163: last = bp; ! 164: } ! 165: if (last) { ! 166: last->b_flags |= B_CALL; ! 167: last->b_iodone = tuwake; ! 168: sleep((caddr_t)last, PRIBIO); ! 169: } ! 170: tu.tu_dopen[unit&DNUM] = 0; ! 171: if (!tu.tu_dopen[0] && !tu.tu_dopen[1]) { ! 172: tutimer = 0; ! 173: mtpr(CSRS, 0); ! 174: tu.tu_flag = 0; ! 175: } ! 176: splx(s); ! 177: } ! 178: ! 179: tuwake(bp) ! 180: struct buf *bp; ! 181: { ! 182: wakeup(bp); ! 183: } ! 184: ! 185: /* ! 186: * Reset the TU58 ! 187: */ ! 188: tureset() ! 189: { ! 190: ! 191: mtpr(CSRS, 0); ! 192: tu.tu_state = TUS_INIT1; ! 193: tu.tu_wbptr = tunull; ! 194: tu.tu_wcnt = sizeof (tunull); ! 195: tucmd.pk_flag = TUF_CMD; ! 196: tucmd.pk_mcount = sizeof (tucmd) - 4; ! 197: tucmd.pk_mod = 0; ! 198: tucmd.pk_seq = 0; ! 199: tucmd.pk_sw = MRSP ? TUSW_MRSP : 0; ! 200: tutab.b_active++; ! 201: mtpr(CSTS, IE | BREAK); ! 202: tuxintr(); /* start output */ ! 203: } ! 204: ! 205: /* ! 206: * Strategy routine for block I/O ! 207: */ ! 208: tustrategy(bp) ! 209: register struct buf *bp; ! 210: { ! 211: register int s; ! 212: ! 213: if (bp->b_blkno >= NTUBLK) { ! 214: bp->b_flags |= B_ERROR; ! 215: iodone(bp); ! 216: return; ! 217: } ! 218: if ((bp->b_flags&B_READ) == 0) ! 219: tu_pee(&tu_pcnt[minor(bp->b_dev)&DNUM]); ! 220: bp->av_forw = NULL; ! 221: s = splx(TUIPL); ! 222: if (tutab.b_actf == NULL) ! 223: tutab.b_actf = bp; ! 224: else ! 225: tutab.b_actl->av_forw = bp; ! 226: tutab.b_actl = bp; ! 227: if (tutab.b_active == NULL) ! 228: tustart(); ! 229: splx(s); ! 230: } ! 231: ! 232: /* ! 233: * Start the transfer ! 234: */ ! 235: tustart() ! 236: { ! 237: register struct buf *bp; ! 238: int s; ! 239: ! 240: if ((bp = tutab.b_actf) == NULL) ! 241: return; ! 242: s = splx(TUIPL); ! 243: if (tu.tu_state != TUS_IDLE) { ! 244: tureset(); ! 245: splx(s); ! 246: return; ! 247: } ! 248: tutab.b_active++; ! 249: tutab.b_errcnt = 0; ! 250: tucmd.pk_op = bp->b_flags&B_READ ? TUOP_READ : TUOP_WRITE; ! 251: tucmd.pk_mod = ((bp->b_flags&B_READ) == 0 && (minor(bp->b_dev)&WRV)) ? ! 252: TUMD_WRV : 0; ! 253: tucmd.pk_unit = (minor(bp->b_dev)&DNUM); ! 254: tucmd.pk_sw = MRSP ? TUSW_MRSP : 0; ! 255: tucmd.pk_count = tu.tu_count = bp->b_bcount; ! 256: tucmd.pk_block = bp->b_blkno; ! 257: tucmd.pk_chksum = ! 258: tuchk(*((short *)&tucmd), (u_short *)&tucmd.pk_op, ! 259: (int)tucmd.pk_mcount); ! 260: tu.tu_state = bp->b_flags&B_READ ? TUS_SENDR : TUS_SENDW; ! 261: tu.tu_addr = bp->b_un.b_addr; ! 262: tu.tu_wbptr = (u_char *)&tucmd; ! 263: tu.tu_wcnt = sizeof (tucmd); ! 264: tuxintr(); ! 265: splx(s); ! 266: } ! 267: ! 268: /* ! 269: * TU58 receiver interrupt ! 270: */ ! 271: turintr() ! 272: { ! 273: register struct buf *bp; ! 274: register int c; ! 275: ! 276: c = mfpr(CSRD)&0xff; ! 277: if (MRSP) { ! 278: while ((mfpr(CSTS)&READY) == 0) ! 279: ; ! 280: mtpr(CSTD, TUF_CONT); /* ACK */ ! 281: if (tu.tu_rcnt) { ! 282: *tu.tu_rbptr++ = c; ! 283: if (--tu.tu_rcnt) ! 284: return; ! 285: } ! 286: } ! 287: ! 288: /* ! 289: * Switch on the state of the transfer. ! 290: */ ! 291: switch(tu.tu_state) { ! 292: ! 293: /* ! 294: * Probably an overrun error, ! 295: * cannot happen if MRSP is used ! 296: */ ! 297: case TUS_RCVERR: ! 298: mtpr(CSRS, 0); /* flush */ ! 299: printf("overrun error, transfer restarted\n"); /* DEBUG */ ! 300: tu.tu_serrs++; ! 301: tu_restart(); ! 302: break; ! 303: ! 304: /* ! 305: * If we get an unexpected "continue", ! 306: * start all over again... ! 307: */ ! 308: case TUS_INIT2: ! 309: tu.tu_state = c == TUF_CONT ? TUS_IDLE : TUS_INIT1; ! 310: tu.tu_flag = 0; ! 311: wakeup((caddr_t)&tu); ! 312: tustart(); ! 313: break; ! 314: ! 315: /* ! 316: * Only transition from this state ! 317: * is on a "continue", so if we don't ! 318: * get it, reset the world. ! 319: */ ! 320: case TUS_WAIT: /* waiting for continue */ ! 321: switch(c) { ! 322: case TUF_CONT: /* got the expected continue */ ! 323: tu.tu_flag = 0; ! 324: tudata.pk_flag = TUF_DATA; ! 325: tudata.pk_mcount = MIN(128, tu.tu_count); ! 326: tudata.pk_chksum = ! 327: tuchk(*((short *)&tudata), (caddr_t)tu.tu_addr, ! 328: (int)tudata.pk_mcount); ! 329: tu.tu_state = TUS_SENDH; ! 330: tu.tu_wbptr = (u_char *)&tudata; ! 331: tu.tu_wcnt = 2; ! 332: tuxintr(); ! 333: break; ! 334: ! 335: case TUF_CMD: /* sending us an END packet...error */ ! 336: tu.tu_state = TUS_GET; ! 337: tu.tu_rbptr = (u_char *) &tudata; ! 338: tu.tu_rcnt = sizeof (tudata) - 1; ! 339: tu.tu_flag = 1; ! 340: mtpr (CSTS, 0); ! 341: *tu.tu_rbptr = c; ! 342: break; ! 343: ! 344: case TUF_INITF: ! 345: tureset(); ! 346: break; ! 347: ! 348: default: /* something random...bad news */ ! 349: tu.tu_state = TUS_INIT1; ! 350: break; ! 351: } ! 352: break; ! 353: ! 354: case TUS_SENDW: ! 355: if (c != TUF_CONT && c != TUF_INITF) ! 356: goto bad; ! 357: tureset(); ! 358: break; ! 359: ! 360: /* ! 361: * Got header, now get data; amount to ! 362: * fetch is included in packet. ! 363: */ ! 364: case TUS_GETH: ! 365: if (MRSP && (tudata.pk_flag == TUF_DATA)) ! 366: tu.tu_rbptr = (u_char *)tu.tu_addr; ! 367: tu.tu_rcnt = tudata.pk_mcount; ! 368: tu.tu_state = TUS_GETD; ! 369: break; ! 370: ! 371: /* ! 372: * Got the data, now fetch the checksum. ! 373: */ ! 374: case TUS_GETD: ! 375: tu.tu_rbptr = (u_char *)&tudata.pk_chksum; ! 376: tu.tu_rcnt = sizeof (tudata.pk_chksum); ! 377: tu.tu_state = TUS_GETC; ! 378: break; ! 379: ! 380: case TUS_CHKERR: /* from tudma only */ ! 381: tu.tu_cerrs++; ! 382: goto tus_get; ! 383: ! 384: case TUS_GET: ! 385: if (MRSP) ! 386: /* ! 387: * The checksum has already been calculated and ! 388: * verified in the pseudo DMA routine ! 389: */ ! 390: goto tus_get; ! 391: ! 392: case TUS_GETC: ! 393: /* got entire packet */ ! 394: if (tudata.pk_chksum != ! 395: tuchk(*((short *)&tudata), (u_short *) ! 396: (tudata.pk_flag == TUF_DATA ? ! 397: (u_short *) tu.tu_addr : (u_short *)&tudata.pk_op), ! 398: (int)tudata.pk_mcount)) ! 399: tu.tu_cerrs++; ! 400: tus_get: ! 401: if (tudata.pk_flag == TUF_DATA) { ! 402: /* data packet, advance to next */ ! 403: tu.tu_addr += tudata.pk_mcount; ! 404: tu.tu_count -= tudata.pk_mcount; ! 405: tu.tu_state = TUS_GETH; ! 406: tu.tu_rbptr = (u_char *)&tudata; /* next packet */ ! 407: tu.tu_rcnt = 2; ! 408: } else if (tudata.pk_flag==TUF_CMD && tudata.pk_op==TUOP_END) { ! 409: /* end packet, idle and reenable transmitter */ ! 410: tu.tu_state = TUS_IDLE; ! 411: tu.tu_flag = 0; ! 412: mtpr(CSTS, IE); ! 413: printd("ON "); ! 414: if ((bp = tutab.b_actf) == NULL) { ! 415: printf("tu%d: no bp, active %d\n", ! 416: tudata.pk_unit, tutab.b_active); ! 417: tustart(); ! 418: return; ! 419: } ! 420: if (tudata.pk_mod > 1) { /* hard error */ ! 421: bp->b_flags |= B_ERROR; ! 422: tu.tu_herrs++; ! 423: printf("tu%d: hard error bn%d,", ! 424: minor(bp->b_dev)&DNUM, bp->b_blkno); ! 425: printf(" pk_mod %o\n", tudata.pk_mod&0377); ! 426: } else if (tudata.pk_mod != 0) /* soft error */ ! 427: tu.tu_serrs++; ! 428: tutab.b_active = NULL; ! 429: tutab.b_actf = bp->av_forw; ! 430: bp->b_resid = tu.tu_count; ! 431: if ((bp->b_flags&B_READ) == 0) ! 432: tu_vee(&tu_pcnt[minor(bp->b_dev)&DNUM]); ! 433: iodone(bp); ! 434: tustart(); ! 435: } else { ! 436: /* ! 437: * Neither data nor end: data was lost ! 438: * somehow, restart the transfer ! 439: */ ! 440: mtpr(CSRS, 0); /* flush the rest */ ! 441: tu_restart(); ! 442: tu.tu_serrs++; ! 443: } ! 444: break; ! 445: ! 446: case TUS_IDLE: ! 447: case TUS_INIT1: ! 448: break; ! 449: ! 450: default: ! 451: bad: ! 452: if (c == TUF_INITF) { ! 453: printf("tu%d protocol error, state=", ! 454: (int)tudata.pk_unit); ! 455: printstate(tu.tu_state); ! 456: printf(", op=%x, cnt=%d, block=%d\n", ! 457: tucmd.pk_op, tucmd.pk_count, tucmd.pk_block); ! 458: tutab.b_active = NULL; ! 459: if (bp = tutab.b_actf) { ! 460: bp->b_flags |= B_ERROR; ! 461: tutab.b_actf = bp->av_forw; ! 462: if ((bp->b_flags&B_READ) == 0) ! 463: tu_vee(&tu_pcnt[minor(bp->b_dev)&DNUM]); ! 464: iodone(bp); ! 465: } ! 466: tu.tu_state = TUS_INIT1; ! 467: } else { ! 468: printf("tu%d: receive state error, state=", ! 469: (int)tudata.pk_unit); ! 470: printstate(tu.tu_state); ! 471: printf(", byte=%x\n", c & 0xff); ! 472: if (tutab.b_actf) ! 473: tu_restart(); ! 474: else ! 475: wakeup((caddr_t)&tu); ! 476: } ! 477: } ! 478: } ! 479: ! 480: /* ! 481: * TU58 transmitter interrupt ! 482: */ ! 483: tuxintr() ! 484: { ! 485: ! 486: top: ! 487: if (tu.tu_wcnt) { ! 488: /* still stuff to send, send one byte */ ! 489: while ((mfpr(CSTS) & READY) == 0) ! 490: ; ! 491: mtpr(CSTD, *tu.tu_wbptr++); ! 492: tu.tu_wcnt--; ! 493: return; ! 494: } ! 495: ! 496: /* ! 497: * Last message byte was sent out. ! 498: * Switch on state of transfer. ! 499: */ ! 500: if (tudebug) { ! 501: printf("tuxintr: state="); ! 502: printstate(tu.tu_state); ! 503: } ! 504: switch(tu.tu_state) { ! 505: ! 506: /* ! 507: * Two nulls have been sent, remove break, and send inits ! 508: */ ! 509: case TUS_INIT1: ! 510: mtpr(CSTS, IE); ! 511: printd("ON2 "); ! 512: tu.tu_state = TUS_INIT2; ! 513: tu.tu_wbptr = tuinit; ! 514: tu.tu_wcnt = sizeof (tuinit); ! 515: goto top; ! 516: ! 517: /* ! 518: * Inits have been sent, wait for a continue msg. ! 519: */ ! 520: case TUS_INIT2: ! 521: (void) mfpr(CSRD); ! 522: mtpr(CSRS, IE); ! 523: tu.tu_flag = 1; ! 524: break; ! 525: ! 526: /* ! 527: * Read cmd packet sent, get ready for data ! 528: */ ! 529: case TUS_SENDR: ! 530: tu.tu_state = TUS_GETH; ! 531: tu.tu_rbptr = (u_char *)&tudata; ! 532: tu.tu_rcnt = 2; ! 533: tu.tu_flag = 1; ! 534: mtpr(CSTS, 0); /* disable transmitter interrupts */ ! 535: printd("OFF "); ! 536: break; ! 537: ! 538: /* ! 539: * Write cmd packet sent, wait for continue ! 540: */ ! 541: case TUS_SENDW: ! 542: tu.tu_state = TUS_WAIT; ! 543: tu.tu_flag = 1; ! 544: if ((mfpr(CSRS)&IE) == 0) { ! 545: printf("NO IE\n"); ! 546: mtpr(CSRS, IE); ! 547: } ! 548: break; ! 549: ! 550: /* ! 551: * Header sent, send data. ! 552: */ ! 553: case TUS_SENDH: ! 554: tu.tu_state = TUS_SENDD; ! 555: tu.tu_wbptr = (u_char *)tu.tu_addr; ! 556: tu.tu_wcnt = tudata.pk_mcount; ! 557: goto top; ! 558: ! 559: /* ! 560: * Data sent, follow with checksum. ! 561: */ ! 562: case TUS_SENDD: ! 563: tu.tu_state = TUS_SENDC; ! 564: tu.tu_wbptr = (u_char *)&tudata.pk_chksum; ! 565: tu.tu_wcnt = sizeof tudata.pk_chksum; ! 566: goto top; ! 567: ! 568: /* ! 569: * Checksum sent, wait for continue. ! 570: */ ! 571: case TUS_SENDC: ! 572: /* ! 573: * Updata buffer address and count. ! 574: */ ! 575: tu.tu_addr += tudata.pk_mcount; ! 576: tu.tu_count -= tudata.pk_mcount; ! 577: if (tu.tu_count) { ! 578: tu.tu_state = TUS_WAIT; ! 579: tu.tu_flag = 1; ! 580: break; ! 581: } ! 582: ! 583: /* ! 584: * End of transmission, get ready for end packet. ! 585: */ ! 586: tu.tu_state = TUS_GET; ! 587: tu.tu_rbptr = (u_char *)&tudata; ! 588: tu.tu_rcnt = sizeof (tudata); ! 589: tu.tu_flag = 1; ! 590: mtpr(CSTS, 0); ! 591: printd("OFF2 "); ! 592: break; ! 593: ! 594: /* ! 595: * Random interrupt, probably from MRSP ACK ! 596: */ ! 597: case TUS_IDLE: ! 598: ! 599: default: ! 600: break; ! 601: ! 602: } ! 603: if (tudebug) { ! 604: printd(" new tu_state="); ! 605: printstate(tu.tu_state); ! 606: } ! 607: } ! 608: ! 609: /* ! 610: * Compute checksum TU58 fashion ! 611: */ ! 612: #ifdef lint ! 613: tuchk(word, cp, n) ! 614: register word; ! 615: register unsigned short *cp; ! 616: int n; ! 617: { ! 618: register int c = n >> 1; ! 619: register long temp; ! 620: ! 621: do { ! 622: temp = *cp++; /* temp, only because vax cc won't *r++ */ ! 623: word += temp; ! 624: } while (--c > 0); ! 625: if (n & 1) ! 626: word += *(unsigned char *)cp; ! 627: while (word & 0xffff0000) ! 628: word = (word & 0xffff) + ((word >> 16) & 0xffff); ! 629: return (word); ! 630: } ! 631: #else ! 632: tuchk(word0, wp, n) ! 633: register int word0; /* r11 */ ! 634: register char *wp; /* r10 */ ! 635: register int n; /* r9 */ ! 636: { ! 637: asm("loop:"); ! 638: asm(" addw2 (r10)+,r11"); /* add a word to sum */ ! 639: asm(" adwc $0,r11"); /* add in carry, end-around */ ! 640: asm(" acbl $2,$-2,r9,loop"); /* done yet? */ ! 641: asm(" blbc r9,ok"); /* odd byte count? */ ! 642: asm(" movzbw (r10),r10"); /* yes, get last byte */ ! 643: asm(" addw2 r10,r11"); /* add it in */ ! 644: asm(" adwc $0,r11"); /* and the carry */ ! 645: asm("ok:"); ! 646: asm(" movl r11,r0"); /* return sum */ ! 647: } ! 648: #endif ! 649: ! 650: tuwatch() ! 651: { ! 652: register int s; ! 653: register struct buf *bp; ! 654: ! 655: if (tutimer == 0) ! 656: return; ! 657: ! 658: if (tu.tu_flag == 0) { /* if no read in progress - skip */ ! 659: timeout(tuwatch, (caddr_t)0, hz); ! 660: return; ! 661: } ! 662: if (tu.tu_flag++ <= 40) { ! 663: timeout(tuwatch, (caddr_t)0, hz); ! 664: return; ! 665: } ! 666: printf("tu%d: read stalled\n", tudata.pk_unit); ! 667: #ifdef TUDEBUG ! 668: printf("%X %X %X %X %X %X %X %X\n", tu.tu_rbptr, tu.tu_rcnt, ! 669: tu.tu_wbptr, tu.tu_wcnt, tu.tu_state, tu.tu_flag, ! 670: tu.tu_addr, tu.tu_count); ! 671: #endif ! 672: s = splx(TUIPL); ! 673: tu.tu_flag = 0; ! 674: (void) mfpr(CSRD); ! 675: mtpr(CSRS, IE); /* in case we were flushing */ ! 676: mtpr(CSTS, IE); ! 677: tu.tu_state = TUS_IDLE; ! 678: if (!tutab.b_active) { ! 679: wakeup((caddr_t)&tu); ! 680: goto retry; ! 681: } ! 682: if (++tutab.b_errcnt <= 1) { ! 683: tustart(); ! 684: goto retry; ! 685: } ! 686: if (bp = tutab.b_actf) { ! 687: bp->b_flags |= B_ERROR; ! 688: if ((bp->b_flags&B_READ) == 0) ! 689: tu_vee(&tu_pcnt[minor(bp->b_dev)&DNUM]); ! 690: iodone(bp); ! 691: } ! 692: retry: ! 693: splx(s); ! 694: timeout(tuwatch, (caddr_t)0, hz); ! 695: } ! 696: ! 697: tu_pee(cp) ! 698: char *cp; ! 699: { ! 700: register int s; ! 701: ! 702: s = splx(TUIPL); ! 703: if (++(*cp) > NTUQ) ! 704: sleep(cp, PRIBIO); ! 705: splx(s); ! 706: } ! 707: ! 708: tu_vee(cp) ! 709: char *cp; ! 710: { ! 711: register int s; ! 712: ! 713: s = splx(TUIPL); ! 714: if (--(*cp) <= NTUQ) ! 715: wakeup(cp); ! 716: splx(s); ! 717: } ! 718: ! 719: tu_restart() ! 720: { ! 721: tureset(); ! 722: timeout(tustart, (caddr_t)0, hz * 3); ! 723: } ! 724: ! 725: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.