|
|
1.1 ! root 1: /* mt.c 6.1.1 84/03/28 */ ! 2: ! 3: #include "mu.h" ! 4: #if NMT > 0 ! 5: /* ! 6: * TM78/TU78 tape driver ! 7: * ! 8: * Original author - ? ! 9: * Most error recovery bug fixes - ggs (ulysses!ggs) ! 10: * ! 11: * OPTIONS: ! 12: * MTLERRM - Long error message text - twd, Brown University ! 13: * MTRDREV - `read reverse' error recovery - ggs (ulysses!ggs) ! 14: * ! 15: * TODO: ! 16: * Add odd byte count kludge from VMS driver (?) ! 17: * Write dump routine ! 18: */ ! 19: ! 20: #define MTLERRM 0 ! 21: #define MTRDREV 0 ! 22: ! 23: #include "../h/param.h" ! 24: #include "../h/systm.h" ! 25: #include "../h/buf.h" ! 26: #include "../h/conf.h" ! 27: #include "../h/dir.h" ! 28: #include "../h/file.h" ! 29: #include "../h/user.h" ! 30: #include "../h/map.h" ! 31: #include "../h/pte.h" ! 32: #include "../h/mbareg.h" ! 33: #include "../h/mbavar.h" ! 34: #include "../h/mtio.h" ! 35: #include "../h/ioctl.h" ! 36: #include "../h/cmap.h" ! 37: #include "../h/cpu.h" ! 38: ! 39: #include "../h/mtreg.h" ! 40: ! 41: #define MTTIMEOUT 10000 /* loop limit for controller test */ ! 42: #define INF 1000000L /* a block number that won't exist */ ! 43: #define MASKREG(r) ((r) & 0xffff) /* the control registers have 16 bits */ ! 44: ! 45: /* Bits for sc_flags */ ! 46: ! 47: #define H_WRITTEN 01 /* last operation was a write */ ! 48: #define H_EOT 02 /* end of tape encountered */ ! 49: #define H_IEOT 04 /* ignore EOT condition */ ! 50: ! 51: /* Bits in minor device */ ! 52: ! 53: #define MUUNIT(dev) (minor(dev)&03) ! 54: #define H_NOREWIND 04 ! 55: #define H_6250BPI 010 ! 56: ! 57: #define MTUNIT(dev) (mutomt[MUUNIT(dev)]) ! 58: ! 59: #ifdef MTRDREV ! 60: int mt_do_readrev = 1; ! 61: #else ! 62: int mt_do_readrev = 0; ! 63: #endif ! 64: ! 65: /* Per unit status information */ ! 66: ! 67: struct mu_softc { ! 68: char sc_openf; /* unit is open if != 0 */ ! 69: char sc_flags; /* state flags */ ! 70: daddr_t sc_blkno; /* current physical block number */ ! 71: daddr_t sc_nxrec; /* firewall input block number */ ! 72: int sc_erreg; /* copy of mter or mtner */ ! 73: int sc_dsreg; /* copy of mtds */ ! 74: short sc_resid; /* residual function count for ioctl */ ! 75: short sc_dens; /* density code - MT_GCR or zero */ ! 76: struct mba_device *sc_mi; /* massbus structure for unit */ ! 77: int sc_slave; /* slave number for unit */ ! 78: int sc_i_mtas; /* mtas at slave attach time */ ! 79: int sc_i_mtner; /* mtner at slave attach time */ ! 80: int sc_i_mtds; /* mtds at slave attach time */ ! 81: #ifdef MTLERRM ! 82: char *sc_mesg; /* text for interrupt type code */ ! 83: char *sc_fmesg; /* text for tape error code */ ! 84: #endif ! 85: } mu_softc[NMU]; ! 86: ! 87: struct buf rmtbuf[NMT]; /* data transfer buffer structures */ ! 88: struct buf cmtbuf[NMT]; /* tape command buffer structures */ ! 89: ! 90: struct mba_device *mtinfo[NMT]; /* unit massbus structure pointers */ ! 91: short mutomt[NMU]; /* tape unit to controller number map */ ! 92: char mtds_bits[] = MTDS_BITS; /* mtds bit names for error messages */ ! 93: short mttypes[] = { MBDT_TU78, 0 }; ! 94: ! 95: int mtattach(), mtslave(), mtustart(), mtstart(), mtndtint(), mtdtint(); ! 96: struct mba_driver mtdriver = ! 97: { mtattach, mtslave, mtustart, mtstart, mtdtint, mtndtint, ! 98: mttypes, "mt", "mu", mtinfo }; ! 99: ! 100: void mtcreset(); ! 101: ! 102: /*ARGSUSED*/ ! 103: mtattach(mi) ! 104: struct mba_device *mi; ! 105: { ! 106: #ifdef lint ! 107: mtread(0); mtwrite(0); mtioctl(0, 0, 0, 0); ! 108: #endif ! 109: } ! 110: ! 111: mtslave(mi, ms) ! 112: struct mba_device *mi; ! 113: struct mba_slave *ms; ! 114: { ! 115: register struct mu_softc *sc = &mu_softc[ms->ms_unit]; ! 116: register struct mtdevice *mtaddr = (struct mtdevice *)mi->mi_drv; ! 117: int s = spl7(), rtn = 0, i; ! 118: ! 119: /* Just in case the controller is ill, reset it. Then issue */ ! 120: /* a sense operation and wait about a second for it to respond. */ ! 121: ! 122: mtcreset(mtaddr); ! 123: mtaddr->mtas = -1; ! 124: mtaddr->mtncs[ms->ms_slave] = MT_SENSE|MT_GO; ! 125: for (i = MTTIMEOUT; i> 0; i--) { ! 126: DELAY(50); ! 127: if (MASKREG(mtaddr->mtas) != 0) ! 128: break; ! 129: } ! 130: sc->sc_i_mtas = mtaddr->mtas; ! 131: sc->sc_i_mtner = mtaddr->mtner; ! 132: sc->sc_i_mtds = mtaddr->mtds; ! 133: ! 134: /* If no response, whimper. If wrong response, call it an */ ! 135: /* unsolicited interrupt and use mtndtint to log and correct. */ ! 136: /* Otherwise, note whether this slave exists. */ ! 137: ! 138: if (i <= 0) { ! 139: printf("mt: controller hung\n"); ! 140: } else if ((mtaddr->mtner & MTER_INTCODE) != MTER_DONE) { ! 141: (void) mtndtint(mi); ! 142: } else if (mtaddr->mtds & MTDS_PRES) { ! 143: sc->sc_mi = mi; ! 144: sc->sc_slave = ms->ms_slave; ! 145: mutomt[ms->ms_unit] = mi->mi_unit; ! 146: rtn = 1; ! 147: } ! 148: ! 149: /* Cancel the interrupt, then wait a little while for it to go away. */ ! 150: ! 151: mtaddr->mtas = mtaddr->mtas; ! 152: DELAY(10); ! 153: splx(s); ! 154: return (rtn); ! 155: } ! 156: ! 157: mtopen(dev, flag) ! 158: dev_t dev; ! 159: int flag; ! 160: { ! 161: register int muunit; ! 162: register struct mba_device *mi; ! 163: register struct mu_softc *sc; ! 164: ! 165: muunit = MUUNIT(dev); ! 166: if ( (muunit >= NMU) ! 167: || ((mi = mtinfo[MTUNIT(dev)]) == 0) ! 168: || (mi->mi_alive == 0) ) { ! 169: u.u_error = ENXIO; ! 170: return; ! 171: } ! 172: if ((sc = &mu_softc[muunit])->sc_openf) { ! 173: u.u_error = EBUSY; ! 174: return; ! 175: } ! 176: sc->sc_dens = (minor(dev) & H_6250BPI) ? MT_GCR : 0; ! 177: mtcommand(dev, MT_SENSE, 1); ! 178: if ((sc->sc_dsreg & MTDS_ONL) == 0) { ! 179: uprintf("mu%d: not online\n", muunit); ! 180: u.u_error = EIO; ! 181: return; ! 182: } ! 183: if ((sc->sc_dsreg & MTDS_AVAIL) == 0) { ! 184: uprintf("mu%d: not online (port selector)\n", muunit); ! 185: u.u_error = EIO; ! 186: return; ! 187: } ! 188: if ((flag & FWRITE) && (sc->sc_dsreg & MTDS_FPT)) { ! 189: uprintf("mu%d: no write ring\n", muunit); ! 190: u.u_error = EIO; ! 191: return; ! 192: } ! 193: if ( ((sc->sc_dsreg & MTDS_BOT) == 0) ! 194: && (flag & FWRITE) ! 195: && ( ( (sc->sc_dens == MT_GCR) ! 196: && (sc->sc_dsreg & MTDS_PE) ) ! 197: || ( (sc->sc_dens != MT_GCR) ! 198: && ((sc->sc_dsreg & MTDS_PE) == 0)))) { ! 199: uprintf("mu%d: can't change density in mid-tape\n", muunit); ! 200: u.u_error = EIO; ! 201: return; ! 202: } ! 203: sc->sc_openf = 1; ! 204: sc->sc_blkno = (daddr_t)0; ! 205: ! 206: /* Since cooked I/O may do a read-ahead before a write, trash */ ! 207: /* on a tape can make the first write fail. Suppress the first */ ! 208: /* read-ahead unless definitely doing read-write */ ! 209: ! 210: sc->sc_nxrec = ((flag & (FREAD | FWRITE)) == FWRITE) ! 211: ? (daddr_t)0 ! 212: : (daddr_t)INF; ! 213: sc->sc_flags = 0; ! 214: } ! 215: ! 216: mtclose(dev, flag) ! 217: register dev_t dev; ! 218: register int flag; ! 219: { ! 220: register struct mu_softc *sc = &mu_softc[MUUNIT(dev)]; ! 221: ! 222: if ( ((flag & (FREAD | FWRITE)) == FWRITE) ! 223: || ( (flag & FWRITE) ! 224: && (sc->sc_flags & H_WRITTEN) )) ! 225: mtcommand(dev, MT_CLS|sc->sc_dens, 1); ! 226: if ((minor(dev) & H_NOREWIND) == 0) ! 227: mtcommand(dev, MT_REW, 0); ! 228: sc->sc_openf = 0; ! 229: } ! 230: ! 231: mtcommand(dev, com, count) ! 232: dev_t dev; ! 233: int com, count; ! 234: { ! 235: register struct buf *bp; ! 236: register int s; ! 237: ! 238: bp = &cmtbuf[MTUNIT(dev)]; ! 239: s = spl5(); ! 240: while (bp->b_flags & B_BUSY) { ! 241: if((bp->b_repcnt == 0) && (bp->b_flags & B_DONE)) ! 242: break; ! 243: bp->b_flags |= B_WANTED; ! 244: sleep((caddr_t)bp, PRIBIO); ! 245: } ! 246: bp->b_flags = B_BUSY|B_READ; ! 247: splx(s); ! 248: bp->b_dev = dev; ! 249: bp->b_command = com; ! 250: bp->b_repcnt = count; ! 251: bp->b_blkno = 0; ! 252: bp->b_error = 0; ! 253: mtstrategy(bp); ! 254: if (count == 0) ! 255: return; ! 256: iowait(bp); ! 257: if (bp->b_flags & B_WANTED) ! 258: wakeup((caddr_t)bp); ! 259: bp->b_flags &= B_ERROR; ! 260: } ! 261: ! 262: mtstrategy(bp) ! 263: register struct buf *bp; ! 264: { ! 265: register struct mba_device *mi = mtinfo[MTUNIT(bp->b_dev)]; ! 266: register struct buf *dp; ! 267: register int s; ! 268: ! 269: /* If this is a data transfer operation, set the resid to a */ ! 270: /* default value (EOF) to simplify getting it right during */ ! 271: /* error recovery or bail out. */ ! 272: ! 273: if (bp != &cmtbuf[MTUNIT(bp->b_dev)]) ! 274: bp->b_resid = bp->b_bcount; ! 275: ! 276: /* Link this request onto the end of the queue for this */ ! 277: /* controller, then start I/O if not already active. */ ! 278: ! 279: bp->av_forw = NULL; ! 280: dp = &mi->mi_tab; ! 281: s = spl5(); ! 282: if (dp->b_actf == NULL) ! 283: dp->b_actf = bp; ! 284: else ! 285: dp->b_actl->av_forw = bp; ! 286: dp->b_actl = bp; ! 287: if (dp->b_active == 0) ! 288: mbustart(mi); ! 289: splx(s); ! 290: } ! 291: ! 292: mtustart(mi) ! 293: register struct mba_device *mi; ! 294: { ! 295: register struct mtdevice *mtaddr = (struct mtdevice *)mi->mi_drv; ! 296: register struct buf *bp = mi->mi_tab.b_actf; ! 297: register struct mu_softc *sc = &mu_softc[MUUNIT(bp->b_dev)]; ! 298: daddr_t blkno; ! 299: ! 300: if (sc->sc_openf < 0) { ! 301: bp->b_flags |= B_ERROR; ! 302: return (MBU_NEXT); ! 303: } ! 304: if (bp != &cmtbuf[MTUNIT(bp->b_dev)]) { ! 305: ! 306: /* Signal "no space" if out of tape unless suppressed */ ! 307: /* by MTIOCIEOT. */ ! 308: ! 309: if ( ((sc->sc_flags & (H_EOT | H_IEOT)) == H_EOT) ! 310: && ((bp->b_flags & B_READ) == 0) ) { ! 311: bp->b_flags |= B_ERROR; ! 312: bp->b_error = ENOSPC; ! 313: return (MBU_NEXT); ! 314: } ! 315: ! 316: /* special case tests for cooked mode */ ! 317: ! 318: if (bp != &rmtbuf[MTUNIT(bp->b_dev)]) { ! 319: ! 320: /* seek beyond end of file */ ! 321: ! 322: if (dbtofsb(0, bp->b_blkno) > sc->sc_nxrec) { ! 323: bp->b_flags |= B_ERROR; ! 324: bp->b_error = ENXIO; ! 325: return (MBU_NEXT); ! 326: } ! 327: ! 328: /* This should be end of file, but the buffer */ ! 329: /* system wants a one-block look-ahead. Humor it. */ ! 330: ! 331: if ( (dbtofsb(0, bp->b_blkno) == sc->sc_nxrec) ! 332: && (bp->b_flags & B_READ) ) { ! 333: clrbuf(bp); ! 334: return (MBU_NEXT); ! 335: } ! 336: ! 337: /* If writing, mark the next block invalid. */ ! 338: ! 339: if ((bp->b_flags & B_READ) == 0) ! 340: sc->sc_nxrec = dbtofsb(0, bp->b_blkno) + 1; ! 341: } ! 342: } else { ! 343: ! 344: /* It's a command, do it now. */ ! 345: ! 346: mtaddr->mtncs[MUUNIT(bp->b_dev)] = ! 347: (bp->b_repcnt<<8)|bp->b_command|MT_GO; ! 348: return (MBU_STARTED); ! 349: } ! 350: ! 351: /* If raw I/O, or if the tape is positioned correctly for */ ! 352: /* cooked I/O, set the byte count, unit number and repeat count */ ! 353: /* then tell the MASSBUS to proceed. Note that a negative */ ! 354: /* bcount tells mbstart to map the buffer for "read backwards". */ ! 355: ! 356: if ( (bp == &rmtbuf[MTUNIT(bp->b_dev)]) ! 357: || ((blkno = sc->sc_blkno) == dbtofsb(0, bp->b_blkno)) ) { ! 358: if (mi->mi_tab.b_errcnt == 2) { ! 359: mtaddr->mtbc = -(bp->b_bcount); ! 360: mtaddr->mtca = MUUNIT(bp->b_dev); ! 361: } else { ! 362: mtaddr->mtbc = bp->b_bcount; ! 363: mtaddr->mtca = (1<<2)|MUUNIT(bp->b_dev); ! 364: } ! 365: return (MBU_DODATA); ! 366: } ! 367: ! 368: /* Issue skip operations to position the next block for cooked I/O. */ ! 369: ! 370: if (blkno < dbtofsb(0, bp->b_blkno)) ! 371: mtaddr->mtncs[MUUNIT(bp->b_dev)] = ! 372: (min(dbtofsb(0, bp->b_blkno) - blkno, 0377)<<8)| MT_SFORW|MT_GO; ! 373: else ! 374: mtaddr->mtncs[MUUNIT(bp->b_dev)] = ! 375: (min(blkno - dbtofsb(0, bp->b_blkno), 0377)<<8)| MT_SREV|MT_GO; ! 376: return (MBU_STARTED); ! 377: } ! 378: ! 379: mtstart(mi) ! 380: register struct mba_device *mi; ! 381: { ! 382: register struct buf *bp = mi->mi_tab.b_actf; ! 383: register struct mu_softc *sc = &mu_softc[MUUNIT(bp->b_dev)]; ! 384: ! 385: if (bp->b_flags & B_READ) ! 386: if (mi->mi_tab.b_errcnt == 2) ! 387: return(MT_READREV|MT_GO); ! 388: else ! 389: return(MT_READ|MT_GO); ! 390: else ! 391: return(MT_WRITE|sc->sc_dens|MT_GO); ! 392: } ! 393: ! 394: mtdtint(mi, mbsr) ! 395: register struct mba_device *mi; ! 396: int mbsr; ! 397: { ! 398: register struct mtdevice *mtaddr = (struct mtdevice *)mi->mi_drv; ! 399: register struct buf *bp = mi->mi_tab.b_actf; ! 400: register struct mu_softc *sc; ! 401: register int er; ! 402: ! 403: /* I'M still NOT SURE IF THIS SHOULD ALWAYS BE THE CASE SO FOR NOW... */ ! 404: ! 405: if ((mtaddr->mtca & 3) != MUUNIT(bp->b_dev)) { ! 406: printf("mt: wrong unit!\n"); ! 407: mtaddr->mtca = MUUNIT(bp->b_dev); ! 408: } ! 409: ! 410: er = MASKREG(mtaddr->mter); ! 411: sc = &mu_softc[MUUNIT(bp->b_dev)]; ! 412: sc->sc_erreg = er; ! 413: if (bp->b_flags & B_READ) ! 414: sc->sc_flags &= ~H_WRITTEN; ! 415: else ! 416: sc->sc_flags |= H_WRITTEN; ! 417: switch (er & MTER_INTCODE) { ! 418: ! 419: case MTER_EOT: ! 420: sc->sc_flags |= H_EOT; ! 421: ! 422: /* fall into MTER_DONE */ ! 423: ! 424: case MTER_DONE: ! 425: sc->sc_blkno++; ! 426: if (mi->mi_tab.b_errcnt == 2) { ! 427: bp->b_bcount = bp->b_resid; ! 428: bp->b_resid -= MASKREG(mtaddr->mtbc); ! 429: if ( (bp->b_resid > 0) ! 430: && (bp != &rmtbuf[MTUNIT(bp->b_dev)]) ) ! 431: bp->b_flags |= B_ERROR; ! 432: } else { ! 433: bp->b_resid = 0; ! 434: } ! 435: break; ! 436: ! 437: case MTER_SHRTREC: ! 438: sc->sc_blkno++; ! 439: bp->b_bcount = bp->b_resid; ! 440: bp->b_resid -= MASKREG(mtaddr->mtbc); ! 441: if (bp != &rmtbuf[MTUNIT(bp->b_dev)]) ! 442: bp->b_flags |= B_ERROR; ! 443: break; ! 444: ! 445: case MTER_RETRY: ! 446: ! 447: /* Simple re-try. Since resid is always a copy of the */ ! 448: /* original byte count, use it to restore the count. */ ! 449: ! 450: mi->mi_tab.b_errcnt = 1; ! 451: bp->b_bcount = bp->b_resid; ! 452: return(MBD_RETRY); ! 453: ! 454: case MTER_RDOPP: ! 455: ! 456: /* The controller just decided to read it backwards. */ ! 457: /* The byte count in the controller may be larger than */ ! 458: /* the size of the buffer, so don't bother to re-try if */ ! 459: /* it will eventually be an error anyway. If the */ ! 460: /* controller returns a byte count of zero, change it */ ! 461: /* to 1, since zero encodes 65536, which isn't quite */ ! 462: /* what we had in mind. If the count is reasonable, */ ! 463: /* set bcount to the negative of the controller's */ ! 464: /* version of the byte count so that the start address */ ! 465: /* for the transfer is set up correctly. */ ! 466: ! 467: if (MASKREG(mtaddr->mtbc) <= bp->b_resid) { ! 468: if (mt_do_readrev) { ! 469: mi->mi_tab.b_errcnt = 2; ! 470: if ((bp->b_bcount = -MASKREG(mtaddr->mtbc)) == 0) ! 471: bp->b_bcount = -1; ! 472: return(MBD_RETRY); ! 473: } else { ! 474: sc->sc_blkno++; ! 475: bp->b_bcount = bp->b_resid; ! 476: bp->b_resid -= MASKREG(mtaddr->mtbc); ! 477: bp->b_flags |= B_ERROR; ! 478: break; ! 479: } ! 480: } ! 481: bp->b_flags |= B_ERROR; ! 482: ! 483: /* fall into MTER_LONGREC */ ! 484: ! 485: case MTER_LONGREC: ! 486: sc->sc_blkno++; ! 487: bp->b_bcount = bp->b_resid; ! 488: bp->b_resid = 0; ! 489: bp->b_error = ENOMEM; ! 490: bp->b_flags |= B_ERROR; ! 491: break; ! 492: ! 493: case MTER_NOTCAP: ! 494: printf("mu%d: blank tape\n", MUUNIT(bp->b_dev)); ! 495: goto err; ! 496: ! 497: case MTER_TM: ! 498: ! 499: /* End of file. Since the default byte count has */ ! 500: /* already been set, just count the block and proceed. */ ! 501: ! 502: sc->sc_blkno++; ! 503: err: ! 504: if (bp != &rmtbuf[MTUNIT(bp->b_dev)]) ! 505: sc->sc_nxrec = dbtofsb(0, bp->b_blkno); ! 506: break; ! 507: ! 508: case MTER_OFFLINE: ! 509: if (sc->sc_openf > 0) { ! 510: sc->sc_openf = -1; ! 511: printf("mu%d: offline\n", MUUNIT(bp->b_dev)); ! 512: } ! 513: bp->b_flags |= B_ERROR; ! 514: break; ! 515: ! 516: case MTER_NOTAVL: ! 517: if (sc->sc_openf > 0) { ! 518: sc->sc_openf = -1; ! 519: printf("mu%d: offline (port selector)\n", MUUNIT(bp->b_dev)); ! 520: } ! 521: bp->b_flags |= B_ERROR; ! 522: break; ! 523: ! 524: case MTER_FPT: ! 525: printf("mu%d: no write ring\n", MUUNIT(bp->b_dev)); ! 526: bp->b_flags |= B_ERROR; ! 527: break; ! 528: ! 529: case MTER_UNREAD: ! 530: sc->sc_blkno++; ! 531: bp->b_bcount = bp->b_resid; ! 532: bp->b_resid -= min(MASKREG(mtaddr->mtbc), bp->b_bcount); ! 533: ! 534: /* Code 010 means a garbage record, nothing serious. */ ! 535: ! 536: if (((er & MTER_FAILCODE) >> 10) == 010) { ! 537: printf("mu%d: rn=%d bn=%d unreadable record\n", ! 538: MUUNIT(bp->b_dev), sc->sc_blkno, bp->b_blkno); ! 539: bp->b_flags |= B_ERROR; ! 540: break; ! 541: } ! 542: ! 543: /* Anything else might be a hardware problem, */ ! 544: /* fall into the error report. */ ! 545: ! 546: default: ! 547: ! 548: /* The bits in sc->sc_dsreg are from the last sense */ ! 549: /* command. To get the most recent copy, you have to */ ! 550: /* do a sense at interrupt level, which requires nested */ ! 551: /* error processing. This is a bit messy, so leave */ ! 552: /* well enough alone. */ ! 553: ! 554: printf("mu%d: hard error (data transfer) rn=%d bn=%d mbsr=%b er=%o (octal) ds=%b\n", ! 555: MUUNIT(bp->b_dev), sc->sc_blkno, bp->b_blkno, ! 556: mbsr, mbsr_bits, er, ! 557: MASKREG(sc->sc_dsreg), mtds_bits); ! 558: #ifdef MTLERRM ! 559: mtintfail(sc); ! 560: printf(" interrupt code = %o (octal) <%s>\n failure code = %o (octal) <%s>\n", ! 561: er & MTER_INTCODE, sc->sc_mesg, ! 562: (er & MTER_FAILCODE) >> 10, sc->sc_fmesg); ! 563: #endif ! 564: bp->b_flags |= B_ERROR; ! 565: ! 566: /* The TM78 manual says to reset the controller after */ ! 567: /* TM fault B or MASSBUS fault. */ ! 568: ! 569: if ( ((er & MTER_INTCODE) == MTER_TMFLTB) ! 570: || ((er & MTER_INTCODE) == MTER_MBFLT) ) { ! 571: mtcreset(mtaddr); ! 572: } ! 573: } ! 574: ! 575: /* Just in case some strange error slipped through, (drive off */ ! 576: /* line during read-reverse error recovery comes to mind) make */ ! 577: /* sure the byte count is reasonable. */ ! 578: ! 579: if (bp->b_bcount < 0) ! 580: bp->b_bcount = bp->b_resid; ! 581: return (MBD_DONE); ! 582: } ! 583: ! 584: mtndtint(mi) ! 585: register struct mba_device *mi; ! 586: { ! 587: register struct mtdevice *mtaddr = (struct mtdevice *)mi->mi_drv; ! 588: register struct buf *bp = mi->mi_tab.b_actf; ! 589: register struct mu_softc *sc; ! 590: register int er, fc; ! 591: int unit; ! 592: ! 593: unit = (mtaddr->mtner >> 8) & 3; ! 594: er = MASKREG(mtaddr->mtner); ! 595: sc = &mu_softc[unit]; ! 596: sc->sc_erreg = er; ! 597: ! 598: /* Check for unsolicited interrupts. */ ! 599: ! 600: if (bp == 0 || unit != MUUNIT(bp->b_dev)) { /* consistency check */ ! 601: if ((er & MTER_INTCODE) != MTER_ONLINE) { ! 602: printf("mt: unit %d unexpected interrupt (non data transfer) er=%o (octal) ds=%b\n", ! 603: unit, er, MASKREG(sc->sc_dsreg), mtds_bits); ! 604: #ifdef MTLERRM ! 605: mtintfail(sc); ! 606: printf(" interrupt code = %o (octal) <%s>\n failure code = %o (octal) <%s>\n", ! 607: er & MTER_INTCODE, sc->sc_mesg, ! 608: (er & MTER_FAILCODE) >> 10, sc->sc_fmesg); ! 609: #endif ! 610: if ( ((er & MTER_INTCODE) == MTER_TMFLTB) ! 611: || ((er & MTER_INTCODE) == MTER_MBFLT) ) { ! 612: ! 613: /* Reset the controller, then set error */ ! 614: /* status if there was anything active */ ! 615: /* when the fault occurred. This may */ ! 616: /* shoot an innocent bystander, but */ ! 617: /* it's better than letting an error */ ! 618: /* slip through. */ ! 619: ! 620: mtcreset(mtaddr); ! 621: if (bp != 0) { ! 622: bp->b_flags |= B_ERROR; ! 623: return (MBN_DONE); ! 624: } ! 625: } ! 626: } ! 627: return (MBN_SKIP); ! 628: } ! 629: if (bp == 0) ! 630: return (MBN_SKIP); ! 631: ! 632: fc = (mtaddr->mtncs[unit] >> 8) & 0xff; ! 633: sc->sc_resid = fc; ! 634: ! 635: /* Clear the "written" flag after any operation that changes */ ! 636: /* the position of the tape. */ ! 637: ! 638: if ( (bp != &cmtbuf[MTUNIT(bp->b_dev)]) ! 639: || (bp->b_command != MT_SENSE) ) ! 640: sc->sc_flags &= ~H_WRITTEN; ! 641: ! 642: switch (er & MTER_INTCODE) { ! 643: ! 644: case MTER_EOT: ! 645: sc->sc_flags |= H_EOT; ! 646: ! 647: /* fall into MTER_DONE */ ! 648: ! 649: case MTER_DONE: ! 650: ! 651: /* If this is a command buffer, just update the status. */ ! 652: ! 653: if (bp == &cmtbuf[MTUNIT(bp->b_dev)]) { ! 654: done: ! 655: if (bp->b_command == MT_SENSE) ! 656: sc->sc_dsreg = MASKREG(mtaddr->mtds); ! 657: return (MBN_DONE); ! 658: } ! 659: ! 660: /* It's not a command buffer, must be a cooked I/O */ ! 661: /* skip operation (perhaps a shaky assumption, but it */ ! 662: /* wasn't my idea). */ ! 663: ! 664: if ((fc = dbtofsb(0, bp->b_blkno) - sc->sc_blkno) < 0) ! 665: sc->sc_blkno -= min(0377, -fc); ! 666: else ! 667: sc->sc_blkno += min(0377, fc); ! 668: return (MBN_RETRY); ! 669: ! 670: case MTER_ONLINE: /* ddj -- shouldn't happen but did */ ! 671: case MTER_RWDING: ! 672: return (MBN_SKIP); /* ignore "rewind started" interrupt */ ! 673: ! 674: case MTER_NOTCAP: ! 675: printf("mu%d: blank tape\n", MUUNIT(bp->b_dev)); ! 676: bp->b_flags |= B_ERROR; ! 677: return (MBN_DONE); ! 678: ! 679: case MTER_TM: ! 680: case MTER_LEOT: ! 681: ! 682: /* For an ioctl skip operation, count a tape mark as */ ! 683: /* a record. If there's anything left to do, update */ ! 684: /* the repeat count and re-start the command. */ ! 685: ! 686: if (bp == &cmtbuf[MTUNIT(bp->b_dev)]) { ! 687: if ((sc->sc_resid = bp->b_repcnt = fc - 1) == 0) ! 688: return (MBN_DONE); ! 689: else ! 690: return (MBN_RETRY); ! 691: ! 692: /* Cooked I/O again. Just update the books and wait */ ! 693: /* for someone else to return end of file or complain */ ! 694: /* about a bad seek. */ ! 695: ! 696: } else if (sc->sc_blkno > dbtofsb(0, bp->b_blkno)) { ! 697: sc->sc_nxrec = dbtofsb(0, bp->b_blkno) + fc - 1; ! 698: sc->sc_blkno = sc->sc_nxrec; ! 699: } else { ! 700: sc->sc_nxrec = dbtofsb(0, bp->b_blkno) - fc; ! 701: sc->sc_blkno = sc->sc_nxrec + 1; ! 702: } ! 703: return (MBN_RETRY); ! 704: ! 705: case MTER_FPT: ! 706: printf("mu%d: no write ring\n", MUUNIT(bp->b_dev)); ! 707: bp->b_flags |= B_ERROR; ! 708: return (MBN_DONE); ! 709: ! 710: case MTER_OFFLINE: ! 711: ! 712: /* If `off line' was intentional, don't complain. */ ! 713: ! 714: if ( (bp == &cmtbuf[MTUNIT(bp->b_dev)]) ! 715: && (bp->b_command == MT_UNLOAD) ) ! 716: return(MBN_DONE); ! 717: if (sc->sc_openf > 0) { ! 718: sc->sc_openf = -1; ! 719: printf("mu%d: offline\n", MUUNIT(bp->b_dev)); ! 720: } ! 721: bp->b_flags |= B_ERROR; ! 722: return (MBN_DONE); ! 723: ! 724: case MTER_NOTAVL: ! 725: if (sc->sc_openf > 0) { ! 726: sc->sc_openf = -1; ! 727: printf("mu%d: offline (port selector)\n", MUUNIT(bp->b_dev)); ! 728: } ! 729: bp->b_flags |= B_ERROR; ! 730: return (MBN_DONE); ! 731: ! 732: case MTER_BOT: ! 733: if (bp == &cmtbuf[MTUNIT(bp->b_dev)]) ! 734: goto done; ! 735: ! 736: /* fall through */ ! 737: ! 738: default: ! 739: printf("mu%d: hard error (non data transfer) rn=%d bn=%d er=%o (octal) ds=%b\n", ! 740: MUUNIT(bp->b_dev), sc->sc_blkno, bp->b_blkno, ! 741: er, MASKREG(sc->sc_dsreg), mtds_bits); ! 742: #ifdef MTLERRM ! 743: mtintfail(sc); ! 744: printf(" interrupt code = %o (octal) <%s>\n failure code = %o (octal) <%s>\n", ! 745: (er & MTER_INTCODE), sc->sc_mesg, ! 746: (er & MTER_FAILCODE) >> 10, sc->sc_fmesg); ! 747: #endif ! 748: if ( ((er & MTER_INTCODE) == MTER_TMFLTB) ! 749: || ((er & MTER_INTCODE) == MTER_MBFLT) ) { ! 750: mtcreset(mtaddr); /* reset the controller */ ! 751: } ! 752: bp->b_flags |= B_ERROR; ! 753: return (MBN_DONE); ! 754: } ! 755: /* NOTREACHED */ ! 756: } ! 757: ! 758: void mtcreset(mtaddr) ! 759: register struct mtdevice *mtaddr; ! 760: { ! 761: register int i; ! 762: ! 763: mtaddr->mtid = MTID_CLR; /* reset the TM78 */ ! 764: DELAY(200); ! 765: for (i = MTTIMEOUT; i > 0; i--) { ! 766: DELAY(50); /* don't nag */ ! 767: if ((mtaddr->mtid & MTID_RDY) != 0) ! 768: return; /* exit when ready */ ! 769: } ! 770: printf("mt: controller hung\n"); ! 771: } ! 772: ! 773: mtread(dev) ! 774: dev_t dev; ! 775: { ! 776: ! 777: mtphys(dev); ! 778: if (u.u_error) ! 779: return; ! 780: physio(mtstrategy, &rmtbuf[MTUNIT(dev)], dev, B_READ, minphys); ! 781: } ! 782: ! 783: ! 784: mtwrite(dev) ! 785: { ! 786: ! 787: mtphys(dev); ! 788: if (u.u_error) ! 789: return; ! 790: physio(mtstrategy, &rmtbuf[MTUNIT(dev)], dev, B_WRITE, minphys); ! 791: } ! 792: ! 793: mtphys(dev) ! 794: dev_t dev; ! 795: { ! 796: register int mtunit; ! 797: struct mba_device *mi; ! 798: ! 799: mtunit = MTUNIT(dev); ! 800: if ( (mtunit >= NMT) ! 801: || ((mi = mtinfo[mtunit]) == 0) ! 802: || (mi->mi_alive == 0) ) { ! 803: u.u_error = ENXIO; ! 804: return; ! 805: } ! 806: } ! 807: ! 808: /*ARGSUSED*/ ! 809: mtioctl(dev, cmd, addr, flag) ! 810: dev_t dev; ! 811: int cmd; ! 812: caddr_t addr; ! 813: int flag; ! 814: { ! 815: register struct mu_softc *sc = &mu_softc[MUUNIT(dev)]; ! 816: register struct buf *bp = &cmtbuf[MTUNIT(dev)]; ! 817: struct mtop mtop; ! 818: struct mtget mtget; ! 819: register int callcount, fcount; ! 820: register int op; ! 821: ! 822: /* We depend on the values and order of the MT codes here. */ ! 823: ! 824: static mtops[] = ! 825: {MT_WTM,MT_SFORWF,MT_SREVF,MT_SFORW,MT_SREV,MT_REW,MT_UNLOAD,MT_SENSE}; ! 826: ! 827: switch (cmd) { ! 828: ! 829: /* tape operation */ ! 830: ! 831: case MTIOCTOP: ! 832: if (copyin((caddr_t)addr, (caddr_t)&mtop, sizeof(mtop))) { ! 833: u.u_error = EFAULT; ! 834: return; ! 835: } ! 836: switch(mtop.mt_op) { ! 837: case MTWEOF: ! 838: callcount = mtop.mt_count; ! 839: fcount = 1; ! 840: break; ! 841: case MTFSF: case MTBSF: ! 842: callcount = mtop.mt_count; ! 843: fcount = 1; ! 844: break; ! 845: case MTFSR: case MTBSR: ! 846: callcount = 1; ! 847: fcount = mtop.mt_count; ! 848: break; ! 849: case MTREW: case MTOFFL: ! 850: callcount = 1; ! 851: fcount = 1; ! 852: break; ! 853: default: ! 854: u.u_error = ENXIO; ! 855: return; ! 856: } ! 857: if ((callcount <= 0) || (fcount <= 0)) { ! 858: u.u_error = EINVAL; ! 859: return; ! 860: } ! 861: op = mtops[mtop.mt_op]; ! 862: if (op == MT_WTM) ! 863: op |= sc->sc_dens; ! 864: while (--callcount >= 0) { ! 865: register int n, fc = fcount; ! 866: ! 867: do { ! 868: n = min(fc, 0xff); ! 869: mtcommand(dev, op, n); ! 870: n -= sc->sc_resid; ! 871: fc -= n; ! 872: switch (mtop.mt_op) { ! 873: ! 874: case MTWEOF: ! 875: sc->sc_blkno += (daddr_t)n; ! 876: sc->sc_nxrec = sc->sc_blkno - 1; ! 877: break; ! 878: ! 879: case MTOFFL: ! 880: case MTREW: ! 881: case MTFSF: ! 882: sc->sc_blkno = (daddr_t)0; ! 883: sc->sc_nxrec = (daddr_t)INF; ! 884: break; ! 885: ! 886: case MTBSF: ! 887: if (sc->sc_resid) { ! 888: sc->sc_blkno = (daddr_t)0; ! 889: sc->sc_nxrec = (daddr_t)INF; ! 890: } else { ! 891: sc->sc_blkno = (daddr_t)(-1); ! 892: sc->sc_nxrec = (daddr_t)(-1); ! 893: } ! 894: break; ! 895: ! 896: case MTFSR: ! 897: sc->sc_blkno += (daddr_t)n; ! 898: break; ! 899: ! 900: case MTBSR: ! 901: sc->sc_blkno -= (daddr_t)n; ! 902: break; ! 903: } ! 904: if (sc->sc_resid) ! 905: break; ! 906: } while (fc); ! 907: if (fc) { ! 908: sc->sc_resid = callcount + fc; ! 909: if ( (mtop.mt_op == MTFSR) ! 910: || (mtop.mt_op == MTBSR) ) { ! 911: u.u_error = EIO; ! 912: break; ! 913: } ! 914: else ! 915: break; ! 916: } ! 917: if (bp->b_flags & B_ERROR) ! 918: break; ! 919: } ! 920: geterror(bp); ! 921: return; ! 922: ! 923: /* tape status */ ! 924: ! 925: case MTIOCGET: ! 926: mtget.mt_erreg = sc->sc_erreg; ! 927: mtget.mt_resid = sc->sc_resid; ! 928: mtcommand(dev, MT_SENSE, 1); /* update drive status */ ! 929: mtget.mt_dsreg = sc->sc_dsreg; ! 930: mtget.mt_type = MT_ISMT; ! 931: if (copyout((caddr_t)&mtget, addr, sizeof(mtget))) ! 932: u.u_error = EFAULT; ! 933: return; ! 934: ! 935: /* ignore EOT condition */ ! 936: ! 937: case MTIOCIEOT: ! 938: sc->sc_flags |= H_IEOT; ! 939: break; ! 940: ! 941: /* enable EOT condition */ ! 942: ! 943: case MTIOCEEOT: ! 944: sc->sc_flags &= ~H_IEOT; ! 945: break; ! 946: ! 947: default: ! 948: u.u_error = ENXIO; ! 949: } ! 950: } ! 951: ! 952: #define DBSIZE 20 ! 953: ! 954: mtdump() ! 955: { ! 956: register struct mba_device *mi; ! 957: register struct mba_regs *mp; ! 958: int blk, num; ! 959: int start; ! 960: ! 961: start = 0; ! 962: num = maxfree; ! 963: #define phys(a,b) ((b)((int)(a)&0x7fffffff)) ! 964: if (mtinfo[0] == 0) ! 965: return (ENXIO); ! 966: mi = phys(mtinfo[0], struct mba_device *); ! 967: mp = phys(mi->mi_hd, struct mba_hd *)->mh_physmba; ! 968: mp->mba_cr = MBCR_IE; ! 969: #if lint ! 970: blk = 0; num = blk; start = num; blk = start; ! 971: return (0); ! 972: #endif ! 973: #ifdef notyet ! 974: mtaddr = (struct mtdevice *)&mp->mba_drv[mi->mi_drive]; ! 975: mtaddr->mttc = MTTC_PDP11|MTTC_1600BPI; ! 976: mtaddr->mtcs1 = MT_DCLR|MT_GO; ! 977: while (num > 0) { ! 978: blk = num > DBSIZE ? DBSIZE : num; ! 979: mtdwrite(start, blk, mtaddr, mp); ! 980: start += blk; ! 981: num -= blk; ! 982: } ! 983: mteof(mtaddr); ! 984: mteof(mtaddr); ! 985: mtwait(mtaddr); ! 986: if (mtaddr->mtds&MTDS_ERR) ! 987: return (EIO); ! 988: mtaddr->mtcs1 = MT_REW|MT_GO; ! 989: return (0); ! 990: } ! 991: ! 992: mtdwrite(dbuf, num, mtaddr, mp) ! 993: register dbuf, num; ! 994: register struct mtdevice *mtaddr; ! 995: struct mba_regs *mp; ! 996: { ! 997: register struct pte *io; ! 998: register int i; ! 999: ! 1000: mtwait(mtaddr); ! 1001: io = mp->mba_map; ! 1002: for (i = 0; i < num; i++) ! 1003: *(int *)io++ = dbuf++ | PG_V; ! 1004: mtaddr->mtfc = -(num*NBPG); ! 1005: mp->mba_sr = -1; ! 1006: mp->mba_bcr = -(num*NBPG); ! 1007: mp->mba_var = 0; ! 1008: mtaddr->mtcs1 = MT_WCOM|MT_GO; ! 1009: } ! 1010: ! 1011: mtwait(mtaddr) ! 1012: struct mtdevice *mtaddr; ! 1013: { ! 1014: register s; ! 1015: ! 1016: do ! 1017: s = mtaddr->mtds; ! 1018: while ((s & MTDS_DRY) == 0); ! 1019: } ! 1020: ! 1021: mteof(mtaddr) ! 1022: struct mtdevice *mtaddr; ! 1023: { ! 1024: ! 1025: mtwait(mtaddr); ! 1026: mtaddr->mtcs1 = MT_WEOF|MT_GO; ! 1027: #endif notyet ! 1028: } ! 1029: ! 1030: #ifdef MTLERRM ! 1031: mtintfail(sc) ! 1032: register struct mu_softc *sc; ! 1033: { ! 1034: switch (sc->sc_erreg & MTER_INTCODE) { ! 1035: ! 1036: /* unexpected BOT detected */ ! 1037: ! 1038: case MTER_BOT: ! 1039: sc->sc_mesg = "unexpected BOT"; ! 1040: switch ((sc->sc_erreg & MTER_FAILCODE) >> 10) { ! 1041: case 01: ! 1042: sc->sc_fmesg = "tape was at BOT"; ! 1043: break; ! 1044: case 02: ! 1045: sc->sc_fmesg = "BOT seen after tape started"; ! 1046: break; ! 1047: case 03: ! 1048: sc->sc_fmesg = "ARA ID detected"; ! 1049: break; ! 1050: default: ! 1051: sc->sc_fmesg = "unclassified failure code"; ! 1052: } ! 1053: break; ! 1054: ! 1055: /* unexpected LEOT detected */ ! 1056: ! 1057: case MTER_LEOT: ! 1058: sc->sc_mesg = "unexpected LEOT"; ! 1059: sc->sc_fmesg = ""; ! 1060: break; ! 1061: ! 1062: /* rewinding */ ! 1063: ! 1064: case MTER_RWDING: ! 1065: sc->sc_mesg = "tape rewinding"; ! 1066: sc->sc_fmesg = ""; ! 1067: break; ! 1068: ! 1069: /* not ready */ ! 1070: ! 1071: case MTER_NOTRDY: ! 1072: sc->sc_mesg = "drive not ready"; ! 1073: switch ((sc->sc_erreg & MTER_FAILCODE) >> 10) { ! 1074: case 01: ! 1075: sc->sc_fmesg = "TU on-line but not ready"; ! 1076: break; ! 1077: case 02: ! 1078: sc->sc_fmesg = "fatal error has occurred"; ! 1079: break; ! 1080: case 03: ! 1081: sc->sc_fmesg = "access allowed but not really"; ! 1082: break; ! 1083: default: ! 1084: sc->sc_fmesg = "unclassified failure code"; ! 1085: } ! 1086: break; ! 1087: ! 1088: /* not available */ ! 1089: ! 1090: case MTER_NOTAVL: ! 1091: sc->sc_mesg = "drive not available"; ! 1092: sc->sc_fmesg = ""; ! 1093: break; ! 1094: ! 1095: /* unit does not exist */ ! 1096: ! 1097: case MTER_NONEX: ! 1098: sc->sc_mesg = "unit does not exist"; ! 1099: sc->sc_fmesg = ""; ! 1100: break; ! 1101: ! 1102: /* not capable */ ! 1103: ! 1104: case MTER_NOTCAP: ! 1105: sc->sc_mesg = "not capable"; ! 1106: switch ((sc->sc_erreg & MTER_FAILCODE) >> 10) { ! 1107: case 01: ! 1108: sc->sc_fmesg = "no record found within 25 feet"; ! 1109: break; ! 1110: case 02: ! 1111: sc->sc_fmesg = "ID burst neither PE nor GCR"; ! 1112: break; ! 1113: case 03: ! 1114: sc->sc_fmesg = "ARA ID not found"; ! 1115: break; ! 1116: case 04: ! 1117: sc->sc_fmesg = "no gap found after ID burst"; ! 1118: break; ! 1119: default: ! 1120: sc->sc_fmesg = "unclassified failure code"; ! 1121: } ! 1122: break; ! 1123: ! 1124: /* long tape record */ ! 1125: ! 1126: case MTER_LONGREC: ! 1127: sc->sc_mesg = "long record"; ! 1128: switch ((sc->sc_erreg & MTER_FAILCODE) >> 10) { ! 1129: case 00: ! 1130: sc->sc_fmesg = "extended sense data not found"; ! 1131: break; ! 1132: case 01: ! 1133: sc->sc_fmesg = "extended sense data updated"; ! 1134: break; ! 1135: default: ! 1136: sc->sc_fmesg = "unclassified failure code"; ! 1137: } ! 1138: break; ! 1139: ! 1140: /* unreadable */ ! 1141: ! 1142: case MTER_UNREAD: ! 1143: sc->sc_mesg = "unreadable record"; ! 1144: goto code22; ! 1145: ! 1146: /* error */ ! 1147: ! 1148: case MTER_ERROR: ! 1149: sc->sc_mesg = "error"; ! 1150: goto code22; ! 1151: ! 1152: /* EOT error */ ! 1153: ! 1154: case MTER_EOTERR: ! 1155: sc->sc_mesg = "EOT error"; ! 1156: goto code22; ! 1157: ! 1158: /* tape position lost */ ! 1159: ! 1160: case MTER_BADTAPE: ! 1161: sc->sc_mesg = "bad tape"; ! 1162: code22: ! 1163: switch ((sc->sc_erreg & MTER_FAILCODE) >> 10) { ! 1164: case 01: ! 1165: sc->sc_fmesg = "GCR write error"; ! 1166: break; ! 1167: case 02: ! 1168: sc->sc_fmesg = "GCR read error"; ! 1169: break; ! 1170: case 03: ! 1171: sc->sc_fmesg = "PE read error"; ! 1172: break; ! 1173: case 04: ! 1174: sc->sc_fmesg = "PE write error"; ! 1175: break; ! 1176: case 05: ! 1177: sc->sc_fmesg = "at least 1 bit set in ECCSTA"; ! 1178: break; ! 1179: case 06: ! 1180: sc->sc_fmesg = "PE write error"; ! 1181: break; ! 1182: case 07: ! 1183: sc->sc_fmesg = "GCR write error"; ! 1184: break; ! 1185: case 010: ! 1186: sc->sc_fmesg = "RSTAT contains bad code"; ! 1187: break; ! 1188: case 011: ! 1189: sc->sc_fmesg = "PE write error"; ! 1190: break; ! 1191: case 012: ! 1192: sc->sc_fmesg = "MASSBUS parity error"; ! 1193: break; ! 1194: case 013: ! 1195: sc->sc_fmesg = "invalid data transferred"; ! 1196: break; ! 1197: default: ! 1198: sc->sc_fmesg = "unclassified failure code"; ! 1199: } ! 1200: break; ! 1201: ! 1202: /* TM fault A */ ! 1203: ! 1204: case MTER_TMFLTA: ! 1205: sc->sc_mesg = "TM fault A"; ! 1206: switch ((sc->sc_erreg & MTER_FAILCODE) >> 10) { ! 1207: case 01: ! 1208: sc->sc_fmesg = "illegal command code"; ! 1209: break; ! 1210: case 02: ! 1211: sc->sc_fmesg = "DT command issued when NDT command active"; ! 1212: break; ! 1213: case 03: ! 1214: sc->sc_fmesg = "WMC error"; ! 1215: break; ! 1216: case 04: ! 1217: sc->sc_fmesg = "RUN not received from MASSBUS controller"; ! 1218: break; ! 1219: case 05: ! 1220: sc->sc_fmesg = "mismatch in command read - function routine"; ! 1221: break; ! 1222: case 06: ! 1223: sc->sc_fmesg = "ECC ROM parity error"; ! 1224: break; ! 1225: case 07: ! 1226: sc->sc_fmesg = "XMC ROM parity error"; ! 1227: break; ! 1228: case 010: ! 1229: sc->sc_fmesg = "mismatch in command read - ID burst command"; ! 1230: break; ! 1231: case 011: ! 1232: sc->sc_fmesg = "mismatch in command read - verify ARA burst command"; ! 1233: break; ! 1234: case 012: ! 1235: sc->sc_fmesg = "mismatch in command read - verify ARA ID command"; ! 1236: break; ! 1237: case 013: ! 1238: sc->sc_fmesg = "mismatch in command read - verify gap command"; ! 1239: break; ! 1240: case 014: ! 1241: sc->sc_fmesg = "mismatch in command read - read id burst command"; ! 1242: break; ! 1243: case 015: ! 1244: sc->sc_fmesg = "mismatch in command read - verify ARA ID command"; ! 1245: break; ! 1246: case 016: ! 1247: sc->sc_fmesg = "mismatch in command read - verify gap command"; ! 1248: break; ! 1249: case 017: ! 1250: sc->sc_fmesg = "mismatch in command read - find gap command"; ! 1251: break; ! 1252: case 020: ! 1253: sc->sc_fmesg = "WMC LEFT failed to set"; ! 1254: break; ! 1255: case 021: ! 1256: sc->sc_fmesg = "XL PE set in INTSTA register"; ! 1257: break; ! 1258: case 022: ! 1259: sc->sc_fmesg = "XMC DONE did not set"; ! 1260: break; ! 1261: case 023: ! 1262: sc->sc_fmesg = "WMC ROM PE or RD PE set in WMCERR register"; ! 1263: break; ! 1264: default: ! 1265: sc->sc_fmesg = "unclassified failure code"; ! 1266: } ! 1267: break; ! 1268: ! 1269: /* TU fault A */ ! 1270: ! 1271: case MTER_TUFLTA: ! 1272: sc->sc_mesg = "TU fault A"; ! 1273: switch ((sc->sc_erreg & MTER_FAILCODE) >> 10) { ! 1274: case 01: ! 1275: sc->sc_fmesg = "TU status parity error"; ! 1276: break; ! 1277: case 02: ! 1278: sc->sc_fmesg = "TU command parity error"; ! 1279: break; ! 1280: case 03: ! 1281: sc->sc_fmesg = "rewinding tape went offline"; ! 1282: break; ! 1283: case 04: ! 1284: sc->sc_fmesg = "tape went not ready during DSE"; ! 1285: break; ! 1286: case 05: ! 1287: sc->sc_fmesg = "TU CMD status changed during DSE"; ! 1288: break; ! 1289: case 06: ! 1290: sc->sc_fmesg = "TU never came up to speed"; ! 1291: break; ! 1292: case 07: ! 1293: sc->sc_fmesg = "TU velocity changed"; ! 1294: break; ! 1295: case 010: ! 1296: sc->sc_fmesg = "TU CMD did not load correctly to start tape motion"; ! 1297: break; ! 1298: case 011: ! 1299: sc->sc_fmesg = "TU CMD did not load correctly to set drive density"; ! 1300: break; ! 1301: case 012: ! 1302: sc->sc_fmesg = "TU CMD did not load correctly to start tape motion to write BOT ID"; ! 1303: break; ! 1304: case 013: ! 1305: sc->sc_fmesg = "TU CMD did not load correctly to backup tape to BOT after failing to write BOT ID"; ! 1306: break; ! 1307: case 014: ! 1308: sc->sc_fmesg = "failed to write density ID burst"; ! 1309: break; ! 1310: case 015: ! 1311: sc->sc_fmesg = "failed to write ARA burst"; ! 1312: break; ! 1313: case 016: ! 1314: sc->sc_fmesg = "failed to write ARA ID"; ! 1315: break; ! 1316: case 017: ! 1317: sc->sc_fmesg = "ARA error bit set in MTA status B register"; ! 1318: break; ! 1319: case 021: ! 1320: sc->sc_fmesg = "could not find a gap after ID code was written correctly"; ! 1321: break; ! 1322: case 022: ! 1323: sc->sc_fmesg = "TU CMD did not load correctly to start tape motion to read ID burst"; ! 1324: break; ! 1325: case 023: ! 1326: sc->sc_fmesg = "timeout looking for BOT after detecting ARA ID burst"; ! 1327: break; ! 1328: case 024: ! 1329: sc->sc_fmesg = "failed to write tape mark"; ! 1330: break; ! 1331: case 025: ! 1332: sc->sc_fmesg = "tape never came up to speed while trying to reposition for retry of writing tape mark"; ! 1333: break; ! 1334: case 026: ! 1335: sc->sc_fmesg = "TU CMD did not load correctly to start tape motion in erase gap routine"; ! 1336: break; ! 1337: case 027: ! 1338: sc->sc_fmesg = "could not detect a gap in in erase gap routine"; ! 1339: break; ! 1340: case 030: ! 1341: sc->sc_fmesg = "could not detect a gap after writing record"; ! 1342: break; ! 1343: case 031: ! 1344: sc->sc_fmesg = "read path terminated before entire record was written"; ! 1345: break; ! 1346: case 032: ! 1347: sc->sc_fmesg = "could not find a gap after writing record and read path terminated early"; ! 1348: break; ! 1349: case 033: ! 1350: sc->sc_fmesg = "TU CMD did not load correctly to backup for retry of write tape mark"; ! 1351: break; ! 1352: case 034: ! 1353: sc->sc_fmesg = "TU velocity changed after up to speed while trying to reposition for retry of writing tape mark"; ! 1354: break; ! 1355: case 035: ! 1356: sc->sc_fmesg = "TU CMD did not load correctly to backup to retry a load of BOT ID"; ! 1357: break; ! 1358: case 036: ! 1359: sc->sc_fmesg = "timeout looking for BOT after failing to write BOT ID"; ! 1360: break; ! 1361: case 037: ! 1362: sc->sc_fmesg = "TU velocity changed while writing PE gap before starting to write record"; ! 1363: break; ! 1364: case 040: ! 1365: sc->sc_fmesg = "TU CMD did not load correctly to set PE tape density at start of write BOT ID burst"; ! 1366: break; ! 1367: case 041: ! 1368: sc->sc_fmesg = "TU CMD did not load correctly to set GCR tape density after writing Density ID"; ! 1369: break; ! 1370: case 042: ! 1371: sc->sc_fmesg = "TU CMD did not load correctly to set PE tape density at start of read from BOT"; ! 1372: break; ! 1373: case 043: ! 1374: sc->sc_fmesg = "TU CMD did not load correctly to set GCR tape density after reading a GCR Density ID burst"; ! 1375: break; ! 1376: default: ! 1377: sc->sc_fmesg = "unclassified failure code"; ! 1378: } ! 1379: break; ! 1380: ! 1381: /* TM fault B */ ! 1382: ! 1383: case MTER_TMFLTB: ! 1384: sc->sc_mesg = "TM fault B"; ! 1385: switch ((sc->sc_erreg & MTER_FAILCODE) >> 10) { ! 1386: case 00: ! 1387: sc->sc_fmesg = "RST0 interrupt occurred with TM RDY set"; ! 1388: break; ! 1389: case 01: ! 1390: sc->sc_fmesg = "power failed to interrupt"; ! 1391: break; ! 1392: case 02: ! 1393: sc->sc_fmesg = "unknown interrupt on channel 5.5"; ! 1394: break; ! 1395: case 03: ! 1396: sc->sc_fmesg = "unknown interrupt on channel 6.5"; ! 1397: break; ! 1398: case 04: ! 1399: sc->sc_fmesg = "unknown interrupt on channel 7"; ! 1400: break; ! 1401: case 05: ! 1402: sc->sc_fmesg = "unknown interrupt on channel 7.5"; ! 1403: break; ! 1404: case 06: ! 1405: sc->sc_fmesg = "CAS contention retry count expired"; ! 1406: break; ! 1407: case 07: ! 1408: sc->sc_fmesg = "CAS contention error not retryable"; ! 1409: break; ! 1410: case 010: ! 1411: sc->sc_fmesg = "queue error, could not find queue entry"; ! 1412: break; ! 1413: case 011: ! 1414: sc->sc_fmesg = "queue entry already full"; ! 1415: break; ! 1416: case 012: ! 1417: sc->sc_fmesg = "8085 ROM parity error"; ! 1418: break; ! 1419: case 013: ! 1420: case 014: ! 1421: case 015: ! 1422: case 016: ! 1423: case 017: ! 1424: case 020: ! 1425: case 021: ! 1426: case 022: ! 1427: case 023: ! 1428: case 024: ! 1429: case 025: ! 1430: case 026: ! 1431: case 027: ! 1432: case 030: ! 1433: case 031: ! 1434: case 032: ! 1435: case 033: ! 1436: case 034: ! 1437: case 035: ! 1438: case 036: ! 1439: case 037: ! 1440: case 040: ! 1441: case 041: ! 1442: case 042: ! 1443: case 043: ! 1444: case 044: ! 1445: case 045: ! 1446: case 046: ! 1447: case 047: ! 1448: case 050: ! 1449: case 051: ! 1450: case 052: ! 1451: case 053: ! 1452: case 054: ! 1453: case 055: ! 1454: case 056: ! 1455: case 057: ! 1456: sc->sc_fmesg = "inline test failed"; ! 1457: break; ! 1458: default: ! 1459: sc->sc_fmesg = "unclassified failure code"; ! 1460: } ! 1461: break; ! 1462: ! 1463: /* MASSBUS fault */ ! 1464: ! 1465: case MTER_MBFLT: ! 1466: sc->sc_mesg = "MB fault"; ! 1467: switch ((sc->sc_erreg & MTER_FAILCODE) >> 10) { ! 1468: case 01: ! 1469: sc->sc_fmesg = "control bus parity error"; ! 1470: break; ! 1471: case 02: ! 1472: sc->sc_fmesg = "illegal register referenced"; ! 1473: break; ! 1474: default: ! 1475: sc->sc_fmesg = "unclassified failure code"; ! 1476: } ! 1477: break; ! 1478: ! 1479: /* keypad entry error */ ! 1480: ! 1481: case MTER_KEYFAIL: ! 1482: sc->sc_mesg = "keypad entry error"; ! 1483: sc->sc_fmesg = ""; ! 1484: break; ! 1485: default: ! 1486: sc->sc_mesg = "unclassified error"; ! 1487: sc->sc_fmesg = ""; ! 1488: break; ! 1489: } ! 1490: } ! 1491: #endif MTLERRM ! 1492: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.