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

Defined functions

mtattach defined in line 110; used 2 times
mtclose defined in line 215; never used
mtcommand defined in line 230; used 5 times
mtcreset defined in line 761; used 5 times
mtdtint defined in line 395; used 2 times
mtdump defined in line 962; never used
mtdwrite defined in line 1000; used 1 times
mteof defined in line 1029; used 2 times
mtintfail defined in line 1039; used 3 times
mtioctl defined in line 821; never used
mtndtint defined in line 587; used 3 times
mtopen defined in line 162; never used
mtphys defined in line 801; used 2 times
mtread defined in line 776; never used
mtslave defined in line 115; used 2 times
mtstart defined in line 380; used 2 times
mtstrategy defined in line 261; used 3 times
mtustart defined in line 291; used 2 times
mtwait defined in line 1019; used 3 times
mtwrite defined in line 789; never used

Defined variables

cmtbuf defined in line 95; used 9 times
mt_do_readrev defined in line 68; used 1 times
mtdriver defined in line 103; used 3 times
mtds_bits defined in line 99; used 3 times
mtinfo defined in line 97; used 6 times
mttypes defined in line 100; used 1 times
mu_softc defined in line 92; used 8 times
mutomt defined in line 98; used 2 times
rmtbuf defined in line 94; used 7 times

Defined struct's

mu_softc defined in line 73; used 18 times

Defined macros

DBSIZE defined in line 960; used 2 times
  • in line 986(2)
H_6250BPI defined in line 61; used 1 times
H_EOT defined in line 54; used 4 times
H_IEOT defined in line 55; used 3 times
H_NOREWIND defined in line 60; used 1 times
H_WRITTEN defined in line 53; used 4 times
INF defined in line 48; used 3 times
MASKREG defined in line 49; used 13 times
MTTIMEOUT defined in line 47; used 2 times
MTUNIT defined in line 63; used 19 times
MUUNIT defined in line 59; used 25 times
phys defined in line 971; used 2 times
Last modified: 1986-06-05
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 3909
Valid CSS Valid XHTML 1.0 Strict