1: /*
   2:  * Copyright (c) 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:  *	@(#)tm.c	2.4 (2.11BSD GTE) 1997/4/14
   7:  */
   8: 
   9: /*
  10:  * TM11 tape drive
  11:  */
  12: 
  13: #include "tm.h"
  14: #if NTM > 0
  15: #include "param.h"
  16: #include "buf.h"
  17: #include "conf.h"
  18: #include "file.h"
  19: #include "user.h"
  20: #include "ioctl.h"
  21: #include "fs.h"
  22: #include "mtio.h"
  23: #include "kernel.h"
  24: #include "systm.h"
  25: #include "tmreg.h"
  26: #include "syslog.h"
  27: #include "map.h"
  28: #include "uba.h"
  29: 
  30: struct  tmdevice *TMADDR;
  31: 
  32: struct  buf tmtab;
  33: struct  buf ctmbuf;
  34: 
  35: /*
  36:  * Software state per tape transport:
  37:  *
  38:  * 1. A tape drive is a unique-open device:  we refuse opens when it is already.
  39:  * 2. We keep track of the current position on a block tape and seek
  40:  *    before operations by forward/back spacing if necessary.
  41:  * 3. We remember if the last operation was a write on a tape, so if a tape
  42:  *    is open read write and the last thing done is a write we can
  43:  *    write a standard end of tape mark (two eofs).
  44:  * 4. We remember the status registers after the last command, using
  45:  *    them internally and returning them to the SENSE ioctl.
  46:  * 5. We remember the last density the tape was used at.  If it is
  47:  *    not a BOT when we start using it and we are writing, we don't
  48:  *    let the density be changed.
  49:  */
  50: 
  51: struct te_softc {
  52:     char    sc_openf;
  53:     char    sc_lastiow;
  54:     daddr_t sc_blkno;
  55:     daddr_t sc_nxrec;
  56:     u_short sc_erreg;
  57:     u_short sc_dsreg;
  58:     short   sc_resid;
  59:     u_short sc_dens;
  60:     short   sc_timo;
  61:     short   sc_tact;
  62: } te_softc[NTM];
  63: 
  64: 
  65: /*
  66:  * States for tmtab.b_active, the state flag.
  67:  * This is used to sequence control in the driver.
  68:  */
  69: #define SSEEK   1
  70: #define SIO 2
  71: #define SCOM    3
  72: #define SREW    4
  73: 
  74: /*
  75:  * Bits in minor device.
  76:  */
  77: #define TEUNIT(dev) (minor(dev) & 03)
  78: #define T_NOREWIND  04
  79: #ifdef AVIV
  80: #define TEDENS(dev) ((minor(dev) & 030) >> 3)
  81: #else
  82: #define TEDENS(dev) ((minor(dev) & 010) >> 3)
  83: #endif
  84: 
  85: #define INF 32760
  86: 
  87: int tmtimer ();
  88: 
  89: #ifdef  SOFUB_MAP
  90:     static  int tmsoftmap = -1; /* -1 = OK to check for softmap
  91: 					 *  0 = Never use softmap
  92: 					 *  1 = Always use softmap
  93: 					*/
  94: #endif
  95: 
  96: tmattach(addr, unit)
  97: struct tmdevice *addr;
  98: int unit;
  99: {
 100:     /*
 101: 	 * This driver supports only one controller.
 102: 	 */
 103:     if  (unit)
 104:         return(0);
 105: #ifdef  SOFUB_MAP
 106:     if  (!ubmap && tmsoftmap == -1)
 107:         tmsoftmap = 1;
 108: #endif
 109:     TMADDR = addr;
 110:     return(1);
 111: }
 112: 
 113: /*
 114:  * Open the device.  Tapes are unique open
 115:  * devices so we refuse if it is already open.
 116:  * We also check that the tape is available and
 117:  * don't block waiting here:  if you want to wait
 118:  * for a tape you should timeout in user code.
 119:  */
 120: 
 121: u_short tmdens[4] = { TM_D800, TM_D1600, TM_D6250, TM_D800 };
 122: 
 123: tmopen(dev, flag)
 124: register dev_t dev;
 125: {
 126:     int s;
 127:     u_short olddens, dens;
 128:     register teunit = TEUNIT(dev);
 129:     register struct te_softc *sc = &te_softc[teunit];
 130: 
 131:     if (teunit >= NTM || TMADDR == (struct tmdevice *) NULL)
 132:         return(ENXIO);
 133:     else if (sc->sc_openf)
 134:         return(EBUSY);
 135:     olddens = sc->sc_dens;
 136:     dens = TM_IE | TM_GO | (teunit << 8) | tmdens[TEDENS(dev)];
 137:     sc->sc_dens = dens;
 138: 
 139:     tmtab.b_flags |= B_TAPE;
 140: get:
 141:     tmcommand(dev, TM_SENSE, 1);
 142:     if (sc->sc_erreg & TMER_SDWN) {
 143:         sleep ((caddr_t) &lbolt, PZERO+1);
 144:         goto get;
 145:     }
 146:     sc->sc_dens = olddens;
 147: 
 148:     if ((sc->sc_erreg & (TMER_SELR | TMER_TUR)) != (TMER_SELR | TMER_TUR)) {
 149:         uprintf("te%d: not online\n", teunit);
 150:         return(EIO);
 151:     }
 152:     if ((flag & FWRITE) && (sc->sc_erreg & TMER_WRL)) {
 153:         uprintf("te%d: no write ring\n", teunit);
 154:         return(EIO);
 155:     }
 156:     if ((sc->sc_erreg & TMER_BOT) == 0 && (flag & FWRITE) && dens != sc->sc_dens) {
 157:         uprintf("te%d: can't change density in mid-tape\n", teunit);
 158:         return(EIO);
 159:     }
 160:     sc->sc_openf = 1;
 161:     sc->sc_blkno = (daddr_t) 0;
 162:     sc->sc_nxrec = (daddr_t) 65535;
 163:     sc->sc_lastiow = 0;
 164:     sc->sc_dens = dens;
 165:     s = splclock();
 166:     if (sc->sc_tact == 0) {
 167:         sc->sc_timo = INF;
 168:         sc->sc_tact = 1;
 169:         timeout(tmtimer, (caddr_t) dev, 5 * hz);
 170:     }
 171:     splx(s);
 172:     return(0);
 173: }
 174: 
 175: /*
 176:  * Close tape device.
 177:  *
 178:  * If tape was open for writing or last operation was
 179:  * a write, then write two EOF's and backspace over the last one.
 180:  * Unless this is a non-rewinding special file, rewind the tape.
 181:  * Make the tape available to others.
 182:  */
 183: tmclose(dev, flag)
 184: register dev_t dev;
 185: register flag;
 186: {
 187:     register struct te_softc *sc = &te_softc[TEUNIT(dev)];
 188: 
 189:     if (flag == FWRITE || (flag & FWRITE) && sc->sc_lastiow) {
 190:         tmcommand(dev, TM_WEOF, 1);
 191:         tmcommand(dev, TM_WEOF, 1);
 192:         tmcommand(dev, TM_SREV, 1);
 193:     }
 194:     if ((minor(dev) & T_NOREWIND) == 0)
 195:         /*
 196: 		 * 0 count means don't hang waiting for rewind complete.
 197: 		 * Rather ctmbuf stays busy until the operation completes
 198: 		 * preventing further opens from completing by
 199: 		 * preventing a TM_SENSE from completing.
 200: 		 */
 201:         tmcommand(dev, TM_REW, 0);
 202:     sc->sc_openf = 0;
 203: }
 204: 
 205: /*
 206:  * Execute a command on the tape drive
 207:  * a specified number of times.
 208:  */
 209: tmcommand(dev, com, count)
 210: register dev_t dev;
 211: register u_short count;
 212: {
 213:     int s;
 214:     register struct buf *bp;
 215: 
 216:     bp = &ctmbuf;
 217:     s = splbio();
 218:     while (bp->b_flags & B_BUSY) {
 219:         /*
 220: 		 * This special check is because B_BUSY never
 221: 		 * gets cleared in the non-waiting rewind case.
 222: 		 */
 223:         if (bp->b_repcnt == 0 && (bp->b_flags & B_DONE))
 224:             break;
 225:         bp->b_flags |= B_WANTED;
 226:         sleep((caddr_t)bp, PRIBIO);
 227:     }
 228:     bp->b_flags = B_BUSY | B_READ;
 229:     splx(s);
 230:     bp->b_dev = dev;
 231:     bp->b_repcnt = -count;
 232:     bp->b_command = com;
 233:     bp->b_blkno = (daddr_t) 0;
 234:     tmstrategy(bp);
 235:     /*
 236: 	 * In case of rewind from close, don't wait.
 237: 	 * This is the only case where count can be 0.
 238: 	 */
 239:     if (count == 0)
 240:         return;
 241:     iowait(bp);
 242:     if (bp->b_flags & B_WANTED)
 243:         wakeup((caddr_t)bp);
 244:     bp->b_flags &= B_ERROR;
 245: }
 246: 
 247: /*
 248:  * Queue a tape operation.
 249:  */
 250: tmstrategy(bp)
 251: register struct buf *bp;
 252: {
 253:     register s;
 254:     register struct te_softc *sc = &te_softc[TEUNIT(bp->b_dev)];
 255: 
 256: #ifdef  SOFUB_MAP
 257: /*
 258:  * The 'soft' map must be allocated here because the transfer may be (although
 259:  * it very rarely is) going to the buffer cache rather than a user process.
 260:  * This has the side effect that a rewinding tape can keep the 'soft' map busy
 261:  * for a fairly long time.  In practice this is not much of a problem since
 262:  * the main use of 18 bit TM controllers on a 22 bit system is with a PDP-11
 263:  * simulator - in which case there's no tape to wait for.
 264: */
 265:     if  (tmsoftmap == 1)
 266:         {
 267:         if  (sofub_alloc(bp) == 0)
 268:             return;
 269:         }
 270: #endif
 271:     if (bp->b_flags & B_PHYS) {
 272: #ifdef  SOFUB_MAP
 273:         if  (tmsoftmap <= 0)
 274: #endif
 275:         mapalloc(bp);
 276:         sc->sc_blkno = sc->sc_nxrec = dbtofsb(bp->b_blkno);
 277:         sc->sc_nxrec++;
 278:     }
 279:     bp->av_forw = NULL;
 280:     s = splbio();
 281:     if (tmtab.b_actf == NULL)
 282:         tmtab.b_actf = bp;
 283:     else
 284:         tmtab.b_actl->av_forw = bp;
 285:     tmtab.b_actl = bp;
 286:     /*
 287: 	 * If the controller is not busy, get
 288: 	 * it going.
 289: 	 */
 290:     if (tmtab.b_active == 0)
 291:         tmstart();
 292:     splx(s);
 293: }
 294: 
 295: tmstart()
 296: {
 297:     daddr_t blkno;
 298:     int cmd, teunit;
 299:     register struct tmdevice *tmaddr = TMADDR;
 300:     register struct buf *bp;
 301:     register struct te_softc *sc;
 302: 
 303: loop:
 304:     if ((bp = tmtab.b_actf) == NULL)
 305:         return;
 306:     teunit = TEUNIT(bp->b_dev);
 307:     /*
 308: 	 * Record pre-transfer status (e.g. for TM_SENSE).
 309: 	 */
 310:     sc = &te_softc[teunit];
 311:     tmaddr->tmcs = teunit << 8;
 312:     sc->sc_erreg = tmaddr->tmer;
 313:     sc->sc_dsreg = tmaddr->tmcs;
 314:     sc->sc_resid = tmaddr->tmbc;
 315:     /*
 316: 	 * Default is that the last command was NOT a write command;
 317: 	 * if we do a write command we will notice this in tmintr().
 318: 	 */
 319:     sc->sc_lastiow = 0;
 320:     if (sc->sc_openf < 0 || (tmaddr->tmcs & TM_CUR) == 0) {
 321:         /*
 322: 		 * Have had a hard error on a non-raw tape
 323: 		 * or the tape unit is now unavailable
 324: 		 * (e.g. taken off line).
 325: 		 */
 326:         bp->b_flags |= B_ERROR;
 327:         goto next;
 328:     }
 329:     if (bp == &ctmbuf) {
 330:         /*
 331: 		 * Execute control operation with the specified count.
 332: 		 */
 333:         if (bp->b_command == TM_SENSE) {
 334:             goto next;
 335:         }
 336:         /*
 337: 		 * Set next state; give 5 minutes to complete
 338: 		 * rewind or 10 seconds per iteration (minimum 60
 339: 		 * seconds and max 5 minutes) to complete other ops.
 340: 		 */
 341:         if (bp->b_command == TM_REW) {
 342:             tmtab.b_active = SREW;
 343:             sc->sc_timo = 5 * 60;
 344:         } else {
 345:             tmtab.b_active = SCOM;
 346:             sc->sc_timo = MIN(MAX(10 * bp->b_repcnt, 60), 5 * 60);
 347:         }
 348:         if (bp->b_command == TM_SFORW || bp->b_command == TM_SREV)
 349:             tmaddr->tmbc = bp->b_repcnt;
 350:         goto dobpcmd;
 351:     }
 352:     /*
 353: 	 * The following checks handle boundary cases for operation
 354: 	 * on non-raw tapes.  On raw tapes the initialization of
 355: 	 * sc->sc_nxrec on entry causes them to be skipped normally
 356: 	 * (except in the case of retries).
 357: 	 */
 358:     if (dbtofsb(bp->b_blkno) > sc->sc_nxrec) {
 359:         /*
 360: 		 * Can't read past known end-of-file.
 361: 		 */
 362:         bp->b_flags |= B_ERROR;
 363:         bp->b_error = ENXIO;
 364:         goto next;
 365:     }
 366:     if (dbtofsb(bp->b_blkno) == sc->sc_nxrec && bp->b_flags & B_READ) {
 367:         /*
 368: 		 * Reading at end of file returns 0 bytes.
 369: 		 * Buffer will be cleared (if written) in rwip.
 370: 		 */
 371:         bp->b_resid = bp->b_bcount;
 372:         goto next;
 373:     }
 374:     if ((bp->b_flags & B_READ) == 0)
 375:         /*
 376: 		 * Writing sets EOF.
 377: 		 */
 378:         sc->sc_nxrec = dbtofsb(bp->b_blkno) + (daddr_t) 1;
 379:     /*
 380: 	 * If the data transfer command is in the correct place,
 381: 	 * set up all registers and do the transfer.
 382: 	 */
 383:     if ((blkno = sc->sc_blkno) == dbtofsb(bp->b_blkno)) {
 384:         tmaddr->tmbc = -bp->b_bcount;
 385:         if ((bp->b_flags & B_READ) == 0) {
 386:             if (tmtab.b_errcnt)
 387:                 cmd = TM_WIRG;
 388:             else
 389:                 cmd = TM_WCOM;
 390:         } else
 391:             cmd = TM_RCOM;
 392:         tmtab.b_active = SIO;
 393:         tmaddr->tmba = bp->b_un.b_addr;
 394:         cmd = sc->sc_dens | ((bp->b_xmem & 03) << 4) | cmd;
 395:         sc->sc_timo = 60;   /* premature, but should serve */
 396:         tmaddr->tmcs = cmd;
 397:         return;
 398:     }
 399:     /*
 400: 	 * Tape positioned incorrectly;
 401: 	 * set to seek forward or backward to the correct spot.
 402: 	 * This happens for raw tapes only on error retries.
 403: 	 */
 404:     tmtab.b_active = SSEEK;
 405:     if (blkno < dbtofsb(bp->b_blkno)) {
 406:         bp->b_command = TM_SFORW;
 407:         tmaddr->tmbc = (short) (blkno - dbtofsb(bp->b_blkno));
 408:     } else {
 409:         bp->b_command = TM_SREV;
 410:         tmaddr->tmbc = (short) (dbtofsb(bp->b_blkno) - blkno);
 411:     }
 412:     sc->sc_timo = MIN(MAX(10 * -tmaddr->tmbc, 60), 5 * 60);
 413: 
 414: dobpcmd:
 415:     /*
 416: 	 * Do the command in bp.
 417: 	 */
 418:     tmaddr->tmcs = (sc->sc_dens | bp->b_command);
 419:     return;
 420: 
 421: next:
 422:     /*
 423: 	 * Done with this operation due to error or
 424: 	 * the fact that it doesn't do anything.
 425: 	 * Dequeue the transfer and continue processing.
 426: 	 */
 427:     tmtab.b_errcnt = 0;
 428:     tmtab.b_actf = bp->av_forw;
 429: #ifdef  SOFUB_MAP
 430:     if  (tmsoftmap == 1)
 431:         sofub_relse(bp, bp->b_bcount - bp->b_resid);
 432: #endif
 433:     iodone(bp);
 434:     goto loop;
 435: }
 436: 
 437: /*
 438:  * The interrupt routine.
 439:  */
 440: tmintr()
 441: {
 442:     register struct tmdevice *tmaddr = TMADDR;
 443:     register struct buf *bp;
 444:     int teunit;
 445:     int state;
 446:     register struct te_softc *sc;
 447: 
 448:     if ((bp = tmtab.b_actf) == NULL)
 449:         return;
 450:     teunit = TEUNIT(bp->b_dev);
 451:     sc = &te_softc[teunit];
 452:     /*
 453: 	 * If last command was a rewind, and tape is still
 454: 	 * rewinding, wait for the rewind complete interrupt.
 455: 	 */
 456:     if (tmtab.b_active == SREW) {
 457:         tmtab.b_active = SCOM;
 458:         if (tmaddr->tmer & TMER_RWS) {
 459:             sc->sc_timo = 5 * 60;       /* 5 minutes */
 460:             return;
 461:         }
 462:     }
 463:     /*
 464: 	 * An operation completed... record status.
 465: 	 */
 466:     sc->sc_timo = INF;
 467:     sc->sc_erreg = tmaddr->tmer;
 468:     sc->sc_dsreg = tmaddr->tmcs;
 469:     sc->sc_resid = tmaddr->tmbc;
 470:     if ((bp->b_flags & B_READ) == 0)
 471:         sc->sc_lastiow = 1;
 472:     state = tmtab.b_active;
 473:     tmtab.b_active = 0;
 474:     /*
 475: 	 * Check for errors.
 476: 	 */
 477:     if (tmaddr->tmcs & TM_ERR) {
 478:         while(tmaddr->tmer & TMER_SDWN)
 479:             ;           /* await settle down */
 480:         /*
 481: 		 * If we hit the end of the tape file, update our position.
 482: 		 */
 483:         if (tmaddr->tmer & TMER_EOF) {
 484:             tmseteof(bp);       /* set blkno and nxrec */
 485:             state = SCOM;       /* force completion */
 486:             /*
 487: 			 * Stuff bc so it will be unstuffed correctly
 488: 			 * later to get resid.
 489: 			 */
 490:             tmaddr->tmbc = -bp->b_bcount;
 491:             goto opdone;
 492:         }
 493:         /*
 494: 		 * If we were reading raw tape and the only error was that the
 495: 		 * record was too long, then we don't consider this an error.
 496: 		 */
 497:         if ((bp->b_flags & B_PHYS) && (bp->b_flags & B_READ) &&
 498:             (tmaddr->tmer & (TMER_HARD | TMER_SOFT)) == TMER_RLE)
 499:             goto ignoreerr;
 500:         /*
 501: 		 * If error is not hard, and this was an i/o operation
 502: 		 * retry up to 8 times.
 503: 		 */
 504:         if ((tmaddr->tmer & TMER_HARD) == 0 && state == SIO) {
 505:             if (++tmtab.b_errcnt < 7) {
 506:                 sc->sc_blkno++;
 507:                 goto opcont;
 508:             }
 509:         } else
 510:             /*
 511: 			 * Hard or non-i/o errors on non-raw tape
 512: 			 * cause it to close.
 513: 			 */
 514:             if (sc->sc_openf > 0 && !(bp->b_flags & B_PHYS))
 515:                 sc->sc_openf = -1;
 516:         /*
 517: 		 * Couldn't recover error
 518: 		 */
 519:         uprintf("te%d: hard error bn%D er=%b\n",
 520:            teunit, bp->b_blkno, sc->sc_erreg, TMER_BITS);
 521:         bp->b_flags |= B_ERROR;
 522:         goto opdone;
 523:     }
 524:     /*
 525: 	 * Advance tape control finite state machine.
 526: 	 */
 527: ignoreerr:
 528:     switch (state) {
 529:     case SIO:
 530:         /*
 531: 		 * Read/write increments tape block number.
 532: 		 */
 533:         sc->sc_blkno++;
 534:         goto opdone;
 535:     case SCOM:
 536:         /*
 537: 		 * For forward/backward space record update current position.
 538: 		 */
 539:         if (bp == &ctmbuf)
 540:             switch (bp->b_command) {
 541:             case TM_SFORW:
 542:                 sc->sc_blkno -= (daddr_t) (bp->b_repcnt);
 543:                 break;
 544:             case TM_SREV:
 545:                 sc->sc_blkno += (daddr_t) (bp->b_repcnt);
 546:                 break;
 547:             }
 548:         goto opdone;
 549:     case SSEEK:
 550:         sc->sc_blkno = dbtofsb(bp->b_blkno);
 551:         goto opcont;
 552:     default:
 553:         panic("tmintr");
 554:     }
 555: opdone:
 556:     /*
 557: 	 * Reset error count and remove
 558: 	 * from device queue.
 559: 	 */
 560:     tmtab.b_errcnt = 0;
 561:     tmtab.b_actf = bp->av_forw;
 562:     bp->b_resid = -tmaddr->tmbc;
 563: #ifdef  SOFUB_MAP
 564:     if  (tmsoftmap == 1)
 565:         sofub_relse(bp, bp->b_bcount - bp->b_resid);
 566: #endif
 567:     iodone(bp);
 568: 
 569: opcont:
 570:     tmstart();
 571: }
 572: 
 573: tmtimer(dev)
 574: register dev_t  dev;
 575: {
 576:     register int s;
 577:     register struct te_softc *sc = &te_softc[TEUNIT(dev)];
 578: 
 579:     if (sc->sc_timo != INF && (sc->sc_timo -= 5) < 0) {
 580:         log(LOG_NOTICE, "te%d: lost interrupt\n", TEUNIT(dev));
 581:         sc->sc_timo = INF;
 582:         s = splbio();
 583:         tmintr();
 584:         splx(s);
 585:     }
 586:     timeout(tmtimer, (caddr_t) dev, 5 * hz);
 587: }
 588: 
 589: tmseteof(bp)
 590: register struct buf *bp;
 591: {
 592:     register struct tmdevice *tmaddr = TMADDR;
 593:     daddr_t bn = dbtofsb(bp->b_blkno);
 594:     register struct te_softc *sc = &te_softc[TEUNIT(bp->b_dev)];
 595: 
 596:     if (bp == &ctmbuf) {
 597:         if (sc->sc_blkno > bn) {
 598:             /* reversing */
 599:             sc->sc_nxrec = bn - (daddr_t) (tmaddr->tmbc);
 600:             sc->sc_blkno = sc->sc_nxrec;
 601:         } else {
 602:             /* spacing forward */
 603:             sc->sc_blkno = bn + (daddr_t) (tmaddr->tmbc);
 604:             sc->sc_nxrec = sc->sc_blkno - (daddr_t) 1;
 605:         }
 606:         return;
 607:     }
 608:     /* eof on read */
 609:     sc->sc_nxrec = bn;
 610: }
 611: 
 612: /*ARGSUSED*/
 613: tmioctl(dev, cmd, data, flag)
 614:     dev_t dev;
 615:     u_int cmd;
 616:     caddr_t data;
 617: {
 618:     register struct buf *bp = &ctmbuf;
 619:     register struct te_softc *sc = &te_softc[TEUNIT(dev)];
 620:     register callcount;
 621:     u_short fcount;
 622:     struct mtop *mtop;
 623:     struct mtget *mtget;
 624:     /* we depend on the values and order of the MT codes here */
 625:     static tmops[] = {TM_WEOF,TM_SFORW,TM_SREV,TM_SFORW,TM_SREV,TM_REW,TM_OFFL,TM_SENSE};
 626: 
 627:     switch (cmd) {
 628: 
 629:     case MTIOCTOP:  /* tape operation */
 630:         mtop = (struct mtop *)data;
 631:         switch(mtop->mt_op) {
 632:         case MTWEOF:
 633:             callcount = mtop->mt_count;
 634:             fcount = 1;
 635:             break;
 636:         case MTFSF: case MTBSF:
 637:             callcount = mtop->mt_count;
 638:             fcount = INF;
 639:             break;
 640:         case MTFSR: case MTBSR:
 641:             callcount = 1;
 642:             fcount = mtop->mt_count;
 643:             break;
 644:         case MTREW: case MTOFFL: case MTNOP:
 645:             callcount = 1;
 646:             fcount = 1;
 647:             break;
 648:         default:
 649:             return (ENXIO);
 650:         }
 651:         if (callcount <= 0 || fcount <= 0)
 652:             return (EINVAL);
 653:         while (--callcount >= 0) {
 654:             tmcommand(dev, tmops[mtop->mt_op], fcount);
 655:             if ((mtop->mt_op == MTFSR || mtop->mt_op == MTBSR) &&
 656:                 bp->b_resid)
 657:                 return (EIO);
 658:             if ((bp->b_flags & B_ERROR) || sc->sc_erreg & TMER_BOT)
 659:                 break;
 660:         }
 661:         return (geterror(bp));
 662:     case MTIOCGET:
 663:         mtget = (struct mtget *)data;
 664:         mtget->mt_dsreg = sc->sc_dsreg;
 665:         mtget->mt_erreg = sc->sc_erreg;
 666:         mtget->mt_resid = sc->sc_resid;
 667:         mtget->mt_type = MT_ISTM;
 668:         break;
 669:     default:
 670:         return (ENXIO);
 671:     }
 672:     return (0);
 673: }
 674: #endif NTM

Defined functions

tmattach defined in line 96; never used
tmclose defined in line 183; never used
tmcommand defined in line 209; used 6 times
tmintr defined in line 440; used 2 times
tmioctl defined in line 613; never used
tmopen defined in line 123; never used
tmseteof defined in line 589; used 1 times
tmstart defined in line 295; used 2 times
tmstrategy defined in line 250; used 1 times
tmtimer defined in line 573; used 3 times

Defined variables

TMADDR defined in line 30; used 5 times
ctmbuf defined in line 33; used 5 times
te_softc defined in line 62; used 8 times
tmdens defined in line 121; used 1 times
tmsoftmap defined in line 90; used 6 times
tmtab defined in line 32; used 22 times

Defined struct's

te_softc defined in line 51; used 16 times

Defined macros

INF defined in line 85; used 5 times
SCOM defined in line 71; used 3 times
SIO defined in line 70; used 2 times
SREW defined in line 72; used 2 times
SSEEK defined in line 69; used 1 times
TEDENS defined in line 82; used 1 times
TEUNIT defined in line 77; used 9 times
T_NOREWIND defined in line 78; used 1 times
Last modified: 1997-02-15
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 178
Valid CSS Valid XHTML 1.0 Strict