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