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