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