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