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:  *	@(#)ts.c	2.3 (2.11BSD GTE) 11/26/94
   7:  */
   8: 
   9: /*
  10:  *	TS11 tape driver
  11:  */
  12: 
  13: #include "ts.h"
  14: #if NTS > 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 "tsreg.h"
  23: #include "mtio.h"
  24: #include "map.h"
  25: #include "uba.h"
  26: 
  27: /*
  28:  * Software state per tape transport:
  29:  *
  30:  * 1. A tape drive is a unique-open device: we refuse opens when it is already
  31:  * 2. We keep track of the current position on a block tape and seek
  32:  *    before operations by forward/back spacing if necessary.
  33:  * 3. We remember if the last operation was a write on a tape, so if a tape
  34:  *    is open read write and the last thing done is a write we can
  35:  *    write a standard end of tape mark (two eofs).
  36:  * 4. We remember the status registers after the last command, using
  37:  *    them internally and returning them to the SENSE ioctl.
  38:  */
  39: 
  40: struct  ts_softc {
  41:     struct  tsdevice *sc_addr; /* CSR of controller */
  42:     char    sc_openf;   /* lock against multiple opens */
  43:     char    sc_lastiow; /* last op was a write */
  44:     short   sc_resid;   /* copy of last bc */
  45:     daddr_t sc_blkno;   /* block number, for block device tape */
  46:     daddr_t sc_nxrec;   /* position of end of tape, if known */
  47:     struct  ts_cmd  sc_cmd; /* the command packet */
  48:     struct  ts_char sc_char;/* status packet, for returned status */
  49:     struct  ts_sts  sc_sts; /* characteristics packet */
  50:     u_short sc_uba;     /* Unibus addr of cmd pkt for tsdb */
  51:     ubadr_t sc_uadr;    /* actual unibus address */
  52:     struct  tty *sc_ttyp;   /* record user's tty for errors */
  53: } *ts_softc[NTS];
  54: 
  55: static  ubadr_t TS_ubadr;
  56: 
  57: struct  buf tstab[NTS];
  58: 
  59: /*
  60:  * There is a ctsbuf per tape controller.
  61:  * It is used as the token to pass to the internal routines
  62:  * to execute tape ioctls.
  63:  * In particular, when the tape is rewinding on close we release
  64:  * the user process but any further attempts to use the tape drive
  65:  * before the rewind completes will hang waiting for ctsbuf.
  66:  */
  67: struct  buf ctsbuf[NTS];
  68: 
  69: #define INF     ((daddr_t) ((u_short) 65535))
  70: 
  71: /* bits in minor device */
  72: #define TSUNIT(dev) (minor(dev)&03)     /* not used */
  73: #define TSCTLR(dev) ((minor(dev) >> 6) & 3)
  74: #define T_NOREWIND  04
  75: 
  76: /*
  77:  * States for tstab.b_active, the state flag.
  78:  * This is used to sequence control in the driver.
  79:  */
  80: #define SSEEK       1   /* seeking */
  81: #define SIO     2   /* doing seq. i/o */
  82: #define SCOM        3   /* sending a control command */
  83: #define SREW        4   /* sending a drive rewind */
  84: 
  85: u_short softspace[NTS][(sizeof(struct ts_softc)/2) + 1];
  86: 
  87: static  char    *tsmsg1 = "ts%d: not online\n";
  88: static  char    *tsmsg2 = "ts%d: no write ring\n";
  89: 
  90: tsattach(addr, unit)
  91: struct tsdevice *addr;
  92: register int unit;
  93: {
  94:     register u_short sp = (u_short)softspace[unit];
  95:     register struct ts_softc *sc;
  96:     struct buf tbuf;
  97: 
  98:     if (unit >= NTS)
  99:         return(0);
 100:     /*
 101: 	 * We want space for an array of NTS ts_softc structures,
 102: 	 * where the sc_cmd field of each is long-aligned, i.e. the
 103: 	 * core address is a 4-byte multiple.  The compiler only
 104: 	 * guarantees word alignment.  We reserve and extra 3 bytes
 105: 	 * so that we can slide the array down by 2 if the compiler
 106: 	 * gets it wrong.  Only allocate 1 UMR to map all of the
 107: 	 * communication area instead of a UMR per controller.
 108: 	 *
 109: 	 * On a UNIBUS system the ts_softc structure is aligned so
 110: 	 * that the UNIBUS virtual address of sc_cmd falls on a 4
 111: 	 * byte boundary - the physical address may be on a 2 byte bound.
 112: 	 *
 113: 	 * On non-UNIBUS systems the ts_softc structure is aligned so
 114: 	 * that sc_cmd falls on a physical 4 byte boundary.
 115: 	 */
 116:     sc = (struct ts_softc *)sp;
 117:     if (((u_short)&sc->sc_cmd  - (ubmap ? (u_short)softspace : 0)) & 3)
 118:         sp += 2;
 119:     if (ubmap && TS_ubadr == 0) {
 120:         tbuf.b_xmem = 0;    /* won't work above 64k any way */
 121:         tbuf.b_un.b_addr = (caddr_t) softspace;
 122:         tbuf.b_flags = B_PHYS;
 123:         tbuf.b_bcount = sizeof (softspace);
 124:         mapalloc(&tbuf);
 125:         TS_ubadr = ((long)((unsigned)tbuf.b_xmem)) << 16
 126:                 | ((long)((unsigned)tbuf.b_un.b_addr));
 127:     }
 128:     sc = ts_softc[unit] = (struct ts_softc *) sp;
 129:     sc->sc_addr = addr;
 130:     sc->sc_uadr = TS_ubadr + ((u_short)&sc->sc_cmd -
 131:                 (ubmap ? (u_short)softspace : 0));
 132:     sc->sc_uba = loint(sc->sc_uadr)
 133:            | hiint(sc->sc_uadr);    /* register format */
 134:     return(1);
 135: }
 136: 
 137: /*
 138:  * Open the device.  Tapes are unique open
 139:  * devices so we refuse if it is already open.
 140:  * We also check that a tape is available and
 141:  * don't block waiting here:  if you want to wait
 142:  * for a tape you should timeout in user code.
 143:  */
 144: tsopen(dev, flag)
 145: dev_t   dev;
 146: int flag;
 147: {
 148:     register ts11 = TSCTLR(dev);
 149:     register struct ts_softc *sc = ts_softc[ts11];
 150: 
 151:     if (ts11 >= NTS || !sc || sc->sc_openf)
 152:         return(ENXIO);
 153:     if (tsinit(ts11)) {
 154:         printf("ts%d: init failure tssr=%b\n",
 155:             ts11, sc->sc_addr->tssr, TSSR_BITS);
 156:         return(ENXIO);
 157:     }
 158:     tstab[ts11].b_flags |= B_TAPE;
 159:     tscommand(dev, TS_SENSE, 1);
 160:     if ((sc->sc_sts.s_xs0 & TS_ONL) == 0) {
 161:         uprintf(tsmsg1, ts11);
 162:         return(EIO);
 163:     }
 164:     if ((flag & (FREAD | FWRITE)) == FWRITE
 165:         && (sc->sc_sts.s_xs0 & TS_WLK)) {
 166:         uprintf(tsmsg2, ts11);
 167:         return(EIO);
 168:     }
 169:     sc->sc_openf = 1;
 170:     sc->sc_blkno = (daddr_t) 0;
 171:     sc->sc_nxrec = INF;
 172:     sc->sc_lastiow = 0;
 173:     sc->sc_ttyp = u.u_ttyp;
 174:     return(0);
 175: }
 176: 
 177: /*
 178:  * Close tape device.
 179:  *
 180:  * If tape was open for writing or last operation was
 181:  * a write, then write two EOF's and backspace over the last one.
 182:  * Unless his is a non-rewinding special file, rewind the tape.
 183:  * Make the tape available to others.
 184:  */
 185: tsclose(dev, flag)
 186: register dev_t  dev;
 187: register int flag;
 188: {
 189:     register struct ts_softc *sc = ts_softc[TSCTLR(dev)];
 190: 
 191:     if (flag == FWRITE || ((flag & FWRITE) && sc->sc_lastiow)) {
 192:         tscommand(dev, TS_WEOF, 1);
 193:         tscommand(dev, TS_WEOF, 1);
 194:         tscommand(dev, TS_SREV, 1);
 195:     }
 196:     if ((minor(dev) & T_NOREWIND) == 0 )
 197:         /*
 198: 		 * 0 count means don't hang waiting for rewind complete.
 199: 		 * Rather ctsbuf stays busy until the operation completes
 200: 		 * preventing further opens from completing by
 201: 		 * preventing a TS_SENSE from completing.
 202: 		 */
 203:         tscommand(dev, TS_REW, 0);
 204:     sc->sc_openf = 0;
 205: }
 206: 
 207: /*
 208:  * Execute a command on the tape drive
 209:  * a specified number of times.
 210:  */
 211: tscommand(dev, com, count)
 212:     dev_t   dev;
 213: register u_short count;
 214: {
 215:     register int s;
 216:     register struct buf *bp;
 217: 
 218:     bp = &ctsbuf[TSCTLR(dev)];
 219:     s = splbio();
 220:     while(bp->b_flags & B_BUSY) {
 221:         /*
 222: 		 * This special check is because B_BUSY never
 223: 		 * gets cleared in the non-waiting rewind case.
 224: 		 */
 225:         if (bp->b_repcnt == 0 && (bp->b_flags & B_DONE))
 226:             break;
 227:         bp->b_flags |= B_WANTED;
 228:         sleep((caddr_t) bp, PRIBIO);
 229:     }
 230:     bp->b_flags = B_BUSY | B_READ;
 231:     splx(s);
 232:     bp->b_dev = dev;
 233:     bp->b_repcnt = count;
 234:     bp->b_command = com;
 235:     bp->b_blkno = (daddr_t) 0;
 236:     tsstrategy(bp);
 237:     /*
 238: 	 * In case of rewind from close, don't wait.
 239: 	 * This is the only case where count can be 0.
 240: 	 */
 241:     if (count == 0)
 242:         return;
 243:     iowait(bp);
 244:     if(bp->b_flags & B_WANTED)
 245:         wakeup((caddr_t) bp);
 246:     bp->b_flags &= B_ERROR;
 247: }
 248: 
 249: /*
 250:  * Queue a tape operation.
 251:  */
 252: tsstrategy(bp)
 253: register struct buf *bp;
 254: {
 255:     register int s;
 256:     int ts11 = TSCTLR(bp->b_dev);
 257:     struct ts_softc *sc = ts_softc[ts11];
 258:     register struct buf *dp = &tstab[ts11];
 259: 
 260:     if (bp->b_flags & B_PHYS) { /* if RAW I/O call */
 261:         mapalloc(bp);
 262:         sc->sc_blkno = sc->sc_nxrec = dbtofsb(bp->b_blkno);
 263:         sc->sc_nxrec++;
 264:     }
 265:     bp->av_forw = NULL;
 266:     s = splbio();
 267:     if (dp->b_actf == NULL)
 268:         dp->b_actf = bp;
 269:     else
 270:         dp->b_actl->av_forw = bp;
 271:     dp->b_actl = bp;
 272:     /*
 273: 	 * If the controller is not busy, get
 274: 	 * it going.
 275: 	 */
 276:     if (dp->b_active == 0)
 277:         tsstart(ts11);
 278:     splx(s);
 279: }
 280: 
 281: /*
 282:  * Start activity on a ts controller.
 283:  */
 284: tsstart(ts11)
 285:     int ts11;
 286: {
 287:     daddr_t blkno;
 288:     int cmd;
 289:     register struct ts_softc *sc;
 290:     register struct ts_cmd *tc;
 291:     register struct buf *bp;
 292:     struct buf *um = &tstab[ts11];
 293: 
 294:     /*
 295: 	 * Start the controller if there is something for it to do.
 296: 	 */
 297: loop:
 298:     if ((bp = um->b_actf) == NULL)
 299:         return;
 300:     sc = ts_softc[ts11];
 301:     tc = &sc->sc_cmd;
 302:     /*
 303: 	 * Default is that last command was NOT a write command;
 304: 	 * if we do a write command we will notice this in tsintr().
 305: 	 */
 306:     sc->sc_lastiow = 0;
 307:     if (sc->sc_openf < 0 || (sc->sc_addr->tssr & TS_OFL)) {
 308:         /*
 309: 		 * Have had a hard error on a non-raw tape
 310: 		 * or the tape unit is now unavailable
 311: 		 * (e.g. taken off line).
 312: 		 */
 313:         bp->b_flags |= B_ERROR;
 314:         goto next;
 315:     }
 316:     if (bp == &ctsbuf[ts11]) {
 317:         /*
 318: 		 * Execute control operation with the specified count.
 319: 		 */
 320:         um->b_active = bp->b_command == TS_REW ?  SREW : SCOM;
 321:         goto dobpcmd;
 322:     }
 323:     /*
 324: 	 * The following checks handle boundary cases for operation
 325: 	 * on non-raw tapes.  On raw tapes the initialization of
 326: 	 * sc->sc_nxrec by tsphys causes them to be skipped normally
 327: 	 * (except in the case of retries).
 328: 	 */
 329:     if (dbtofsb(bp->b_blkno) > sc->sc_nxrec) {
 330:         /*
 331: 		 * Can't read past known end-of-file.
 332: 		 */
 333:         bp->b_flags |= B_ERROR;
 334:         bp->b_error = ENXIO;
 335:         goto next;
 336:     }
 337:     if (dbtofsb(bp->b_blkno) == sc->sc_nxrec && bp->b_flags & B_READ) {
 338:         /*
 339: 		 * Reading at end of file returns 0 bytes.
 340: 		 * Buffer will be cleared (if written) in rwip.
 341: 		 */
 342:         bp->b_resid = bp->b_bcount;
 343:         goto next;
 344:     }
 345:     if((bp->b_flags & B_READ) == 0)
 346:         /*
 347: 		 * Writing sets EOF
 348: 		 */
 349:         sc->sc_nxrec = dbtofsb(bp->b_blkno) + 1;
 350:     /*
 351: 	 * If the data transfer command is in the correct place,
 352: 	 * set up all registers and do the transfer.
 353: 	 */
 354:     if ((blkno = sc->sc_blkno) == dbtofsb(bp->b_blkno)) {
 355:         um->b_active = SIO;
 356:         tc->c_loba = (u_short)bp->b_un.b_addr;
 357:         tc->c_hiba = bp->b_xmem;
 358:         tc->c_size = bp->b_bcount;
 359:         if ((bp->b_flags & B_READ) == 0)
 360:             cmd = TS_WCOM;
 361:         else
 362:             cmd = TS_RCOM;
 363:         if (um->b_errcnt)
 364:             cmd |= TS_RETRY;
 365:         tc->c_cmd = TS_ACK | TS_CVC | TS_IE | cmd;
 366:         sc->sc_addr->tsdb = sc->sc_uba;
 367:         return;
 368:     }
 369:     /*
 370: 	 * Tape positioned incorrectly;
 371: 	 * set to seek forward or backward to the correct spot.
 372: 	 * This happens for raw tapes only on error retries.
 373: 	 */
 374:     um->b_active = SSEEK;
 375:     if (blkno < dbtofsb(bp->b_blkno)) {
 376:         bp->b_command = TS_SFORW;
 377:         bp->b_repcnt = dbtofsb(bp->b_blkno) - blkno;
 378:     } else
 379:         {
 380:         bp->b_command = TS_SREV;
 381:         bp->b_repcnt = blkno - dbtofsb(bp->b_blkno);
 382:     }
 383: dobpcmd:
 384:     tc->c_repcnt = bp->b_repcnt;
 385:     /*
 386: 	 * Do the command in bp.
 387: 	 */
 388:     tc->c_cmd = TS_ACK | TS_CVC | TS_IE | bp->b_command;
 389:     sc->sc_addr->tsdb = sc->sc_uba;
 390:     return;
 391: 
 392: next:
 393:     /*
 394: 	 * Done with this operation due to error or
 395: 	 * the fact that it doesn't do anything.
 396: 	 * Dequeue the transfer and continue processing this slave.
 397: 	 */
 398:     um->b_errcnt = 0;
 399:     um->b_actf = bp->av_forw;
 400:     iodone(bp);
 401:     goto loop;
 402: }
 403: 
 404: /*
 405:  * TS interrupt routine
 406:  */
 407: tsintr(dev)
 408:     int dev;
 409: {
 410:     int state;
 411:     register struct buf *bp, *um = &tstab[dev];
 412:     register struct ts_softc *sc = ts_softc[dev];
 413: 
 414:     if ((bp = um->b_actf) == NULL)
 415:         return;
 416: 
 417:     /*
 418: 	 * If last command was a rewind, and tape is still
 419: 	 * rewinding, wait for the rewind complete interrupt.
 420: 	 *
 421: 	 * SHOULD NEVER GET AN INTERRUPT IN THIS STATE, but it
 422: 	 * happens when a rewind completes.
 423: 	 */
 424:     if (um->b_active == SREW) {
 425:         um->b_active = SCOM;
 426:         if ((sc->sc_addr->tssr & TS_SSR) == 0)
 427:             return;
 428:     }
 429:     /*
 430: 	 * An operation completed... record status
 431: 	 */
 432:     if ((bp->b_flags & B_READ) == 0)
 433:         sc->sc_lastiow = 1;
 434:     state = um->b_active;
 435:     um->b_active = 0;
 436: 
 437:     /*
 438: 	 * Check for errors.
 439: 	 */
 440:     if (sc->sc_addr->tssr & TS_SC) {
 441:         switch (sc->sc_addr->tssr & TS_TC) {
 442:             case TS_UNREC:  /* unrecoverable */
 443:             case TS_FATAL:  /* fatal error */
 444:             case TS_ATTN:   /* attention (shouldn't happen) */
 445:             case TS_RECNM:  /* recoverable, no motion */
 446:                 break;
 447: 
 448:             case TS_SUCC:   /* successful termination */
 449:                 goto ignoreerr;
 450:                 /*NOTREACHED*/
 451: 
 452:             case TS_ALERT:  /* tape status alert */
 453:                 /*
 454: 				 * If we hit the end of the tape file,
 455: 				 * update our position.
 456: 				 */
 457:                 if (sc->sc_sts.s_xs0 & (TS_TMK | TS_EOT)) {
 458:                     tsseteof(bp);   /* set blkno and nxrec */
 459:                     state = SCOM;   /* force completion */
 460:                     /*
 461: 					 * Stuff bc so it will be unstuffed
 462: 					 * correctly later to get resid.
 463: 					 */
 464:                     sc->sc_sts.s_rbpcr = bp->b_bcount;
 465:                     goto opdone;
 466:                     /*NOTREACHED*/
 467:                 }
 468:                 /*
 469: 				 * If we were reading raw tape and the record
 470: 				 * was too long or too short, then we don't
 471: 				 * consider this an error.
 472: 				 */
 473:                 if ((bp->b_flags & B_PHYS) && (bp->b_flags & B_READ)
 474:                     && sc->sc_sts.s_xs0 & (TS_RLS | TS_RLL))
 475:                     goto ignoreerr;
 476:                     /*NOTREACHED*/
 477: 
 478:             case TS_RECOV:  /* recoverable, tape moved */
 479:                 /*
 480: 				 * If this was an i/o operation,
 481: 				 * retry up to 8 times.
 482: 				 */
 483:                 if (state == SIO) {
 484:                     if (++(um->b_errcnt) < 7)
 485:                         goto opcont;
 486:                     else
 487:                         sc->sc_blkno++;
 488:                 } else
 489:                     {
 490:                     /*
 491: 					 * Non-i/o errors on non-raw tape
 492: 					 * cause it to close.
 493: 					 */
 494:                     if (sc->sc_openf > 0 && !(bp->b_flags & B_PHYS))
 495:                         sc->sc_openf = -1;
 496:                 }
 497:                 break;
 498: 
 499:             case TS_REJECT:
 500:                 if (state == SIO && sc->sc_sts.s_xs0 & TS_WLE)
 501:                     tprintf(sc->sc_ttyp, tsmsg2, dev);
 502:                 if ((sc->sc_sts.s_xs0 & TS_ONL) == 0)
 503:                     tprintf(sc->sc_ttyp, tsmsg1, dev);
 504:                 break;
 505:         }
 506:         /*
 507: 		 * Couldn't recover error.
 508: 		 */
 509:         tprintf(sc->sc_ttyp,"ts%d: hard error bn%D xs0=%b", dev,
 510:              bp->b_blkno, sc->sc_sts.s_xs0, TSXS0_BITS);
 511:         if (sc->sc_sts.s_xs1)
 512:             tprintf(sc->sc_ttyp," xs1=%b", sc->sc_sts.s_xs1, TSXS1_BITS);
 513:         if (sc->sc_sts.s_xs2)
 514:             tprintf(sc->sc_ttyp," xs2=%b", sc->sc_sts.s_xs2, TSXS2_BITS);
 515:         if (sc->sc_sts.s_xs3)
 516:             tprintf(sc->sc_ttyp," xs3=%b", sc->sc_sts.s_xs3, TSXS3_BITS);
 517:         tprintf(sc->sc_ttyp,"\n");
 518:         bp->b_flags |= B_ERROR;
 519:         goto opdone;
 520:         /*NOTREACHED*/
 521:     }
 522:     /*
 523: 	 * Advance tape control finite state machine.
 524: 	 */
 525: ignoreerr:
 526:     switch (state) {
 527:         case SIO:
 528:             /*
 529: 			 * Read/write increments tape block number.
 530: 			 */
 531:             sc->sc_blkno++;
 532:             goto opdone;
 533:             /*NOTREACHED*/
 534: 
 535:         case SCOM:
 536:             /*
 537: 			 * For forward/backward space record
 538: 			 * update current position.
 539: 			 */
 540:             if (bp == &ctsbuf[dev])
 541:                 switch (bp->b_command) {
 542:                     case TS_SFORW:
 543:                         sc->sc_blkno += bp->b_repcnt;
 544:                         break;
 545: 
 546:                     case TS_SREV:
 547:                         sc->sc_blkno -= bp->b_repcnt;
 548:                         break;
 549:                 }
 550:             goto opdone;
 551:             /*NOTREACHED*/
 552: 
 553:         case SSEEK:
 554:             sc->sc_blkno = dbtofsb(bp->b_blkno);
 555:             goto opcont;
 556:             /*NOTREACHED*/
 557: 
 558:         default:
 559:             panic("tsintr");
 560:             /*NOTREACHED*/
 561:     }
 562: 
 563: opdone:
 564:     /*
 565: 	 * Reset error count and remove
 566: 	 * from device queue.
 567: 	 */
 568:     um->b_errcnt = 0;
 569:     um->b_actf = bp->av_forw;
 570:     bp->b_resid = sc->sc_sts.s_rbpcr;
 571:     iodone(bp);
 572:     if (um->b_actf == NULL)
 573:         return;
 574: opcont:
 575:     tsstart(dev);
 576: }
 577: 
 578: tsseteof(bp)
 579: register struct buf *bp;
 580: {
 581:     register int ts11 = TSCTLR(bp->b_dev);
 582:     register struct ts_softc *sc = ts_softc[ts11];
 583: 
 584:     if (bp == &ctsbuf[ts11]) {
 585:         if (sc->sc_blkno > dbtofsb(bp->b_blkno)) {
 586:             /* reversing */
 587:             sc->sc_nxrec = dbtofsb(bp->b_blkno) - sc->sc_sts.s_rbpcr;
 588:             sc->sc_blkno = sc->sc_nxrec;
 589:         }
 590:         else
 591:             {
 592:             /* spacing forward */
 593:             sc->sc_blkno = dbtofsb(bp->b_blkno) + sc->sc_sts.s_rbpcr;
 594:             sc->sc_nxrec = sc->sc_blkno - 1;
 595:         }
 596:         return;
 597:     }
 598:     /* eof on read */
 599:     sc->sc_nxrec = dbtofsb(bp->b_blkno);
 600: }
 601: 
 602: /*
 603:  * Initialize the TS11.
 604:  */
 605: tsinit(ts11)
 606: {
 607:     register struct ts_softc *sc = ts_softc[ts11];
 608:     register struct ts_cmd *tcmd = &sc->sc_cmd;
 609:     register struct ts_char *tchar = &sc->sc_char;
 610:     int cnt;
 611:     /*
 612: 	 * Now initialize the TS11 controller.
 613: 	 * Set the characteristics.
 614: 	 */
 615:     if (sc->sc_addr->tssr & (TS_NBA | TS_OFL)) {
 616:         tcmd->c_cmd = TS_ACK | TS_CVC | TS_INIT;
 617:         sc->sc_addr->tsdb = sc->sc_uba;
 618:         for (cnt = 0; cnt < 10000; cnt++) {
 619:             if (sc->sc_addr->tssr & TS_SSR)
 620:                 break;
 621:         }
 622:         if (cnt >= 10000)
 623:             return (1);
 624:         tchar->char_bptr = (u_short)loint(sc->sc_uadr)+
 625:             ((u_short)&sc->sc_sts-(u_short)tcmd);
 626:         tchar->char_bae = hiint(sc->sc_uadr);
 627:         tchar->char_size = sizeof(struct ts_sts);
 628:         tchar->char_mode = TS_ESS;
 629:         tcmd->c_cmd = TS_ACK | TS_CVC | TS_SETCHR;
 630:         tcmd->c_loba = (u_short)loint(sc->sc_uadr)+
 631:             ((u_short)tchar-(u_short)tcmd);
 632:         tcmd->c_hiba = hiint(sc->sc_uadr);
 633:         tcmd->c_size = sizeof(struct ts_char);
 634:         sc->sc_addr->tsdb = sc->sc_uba;
 635:         for (cnt = 0; cnt < 10000; cnt++) {
 636:             if (sc->sc_addr->tssr & TS_SSR)
 637:                 break;
 638:         }
 639:         if (sc->sc_addr->tssr & TS_NBA) {
 640:             printf("ts%d: set char. failure\n", ts11);
 641:             return (1);
 642:         }
 643:     }
 644:     return(0);
 645: }
 646: 
 647: /*ARGSUSED*/
 648: tsioctl(dev, cmd, data, flag)
 649:     dev_t dev;
 650:     u_int cmd;
 651:     caddr_t data;
 652: {
 653:     int ts11 = TSCTLR(dev);
 654:     register struct ts_softc *sc = ts_softc[ts11];
 655:     register struct buf *bp = &ctsbuf[ts11];
 656:     register callcount;
 657:     u_short fcount;
 658:     struct  mtop *mtop;
 659:     struct  mtget *mtget;
 660:     /* we depend on the values and order of the MT codes here */
 661:     static tsops[] =
 662:     {TS_WEOF,TS_SFORWF,TS_SREVF,TS_SFORW,TS_SREV,TS_REW,TS_OFFL,TS_SENSE};
 663: 
 664:     switch (cmd) {
 665: 
 666:     case MTIOCTOP:  /* tape operation */
 667:         mtop = (struct mtop *)data;
 668:         switch(mtop->mt_op) {
 669:         case MTWEOF:
 670:             callcount = mtop->mt_count;
 671:             fcount = 1;
 672:             break;
 673:         case MTFSF: case MTBSF:
 674:         case MTFSR: case MTBSR:
 675:             callcount = 1;
 676:             fcount = mtop->mt_count;
 677:             break;
 678:         case MTREW: case MTOFFL: case MTNOP:
 679:             callcount = 1;
 680:             fcount = 1;
 681:             break;
 682:         default:
 683:             return (ENXIO);
 684:         }
 685:         if (callcount <= 0 || fcount <= 0)
 686:             return (EINVAL);
 687:         while (--callcount >= 0) {
 688:             tscommand(dev, tsops[mtop->mt_op], fcount);
 689:             if ((mtop->mt_op == MTFSR || mtop->mt_op == MTBSR) &&
 690:                 bp->b_resid)
 691:                 return (EIO);
 692:             if ((bp->b_flags&B_ERROR) || sc->sc_sts.s_xs0&TS_BOT)
 693:                 break;
 694:         }
 695:         return (geterror(bp));
 696:     case MTIOCGET:
 697:         mtget = (struct mtget *)data;
 698:         mtget->mt_dsreg = 0;
 699:         mtget->mt_erreg = sc->sc_sts.s_xs0;
 700:         mtget->mt_resid = sc->sc_resid;
 701:         mtget->mt_type = MT_ISTS;
 702:         break;
 703:     default:
 704:         return (ENXIO);
 705:     }
 706:     return (0);
 707: }
 708: #endif NTS

Defined functions

tsattach defined in line 90; never used
tsclose defined in line 185; never used
tscommand defined in line 211; used 6 times
tsinit defined in line 605; used 1 times
tsintr defined in line 407; used 1 times
tsioctl defined in line 648; never used
tsopen defined in line 144; never used
tsseteof defined in line 578; used 1 times
tsstart defined in line 284; used 2 times
tsstrategy defined in line 252; used 1 times

Defined variables

TS_ubadr defined in line 55; used 3 times
ctsbuf defined in line 67; used 5 times
softspace defined in line 85; used 5 times
ts_softc defined in line 53; used 9 times
tsmsg1 defined in line 87; used 2 times
tsmsg2 defined in line 88; used 2 times
tstab defined in line 57; used 4 times

Defined struct's

ts_softc defined in line 40; used 24 times

Defined macros

INF defined in line 69; used 1 times
SCOM defined in line 82; used 3 times
SIO defined in line 81; used 3 times
SREW defined in line 83; used 2 times
SSEEK defined in line 80; used 1 times
TSCTLR defined in line 73; used 6 times
TSUNIT defined in line 72; never used
T_NOREWIND defined in line 74; used 1 times
Last modified: 1994-11-27
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 239
Valid CSS Valid XHTML 1.0 Strict