# 2.11BSD#431 - /usr/src/sys/pdpuba/ts.c

##### Functions

    tsattach          X
    tsclose           X
    tscommand         X
    tsinit            X
    tsintr            X
    tsioctl           X
    tsopen            X
    tsseteof          X
    tsstart           X
    tsstrategy        X

##### Variables

    ctsbuf            X
    softspace         X
    ts_softc          X
    tstab             X

##### Macros

    INF               X
    SCOM              X
    SIO               X
    SREW              X
    SSEEK             X
    TSCTLR            X
    TSUNIT            X
    T_NOREWIND        X

##### struct's

    ts_softc          X

       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

- in line 159, 192-194(3), 203, 688

tsinit defined in line 605; used 1 times

- in line 153

tsintr defined in line 407; used 1 times

- in /usr/src/sys/pdp/scb.s line 376

tsioctl defined in line 648; never used
tsopen defined in line 144; never used
tsseteof defined in line 578; used 1 times

- in line 458

tsstart defined in line 284; used 2 times

- in line 277, 575

tsstrategy defined in line 252; used 1 times

- in line 236

#### Defined variables

TS_ubadr defined in line 55; used 3 times

- in line 119, 125-130(2)

ctsbuf defined in line 67; used 5 times

- in line 218, 316, 540, 584, 655

softspace defined in line 85; used 5 times

- in line 94, 117-123(3), 131

ts_softc defined in line 53; used 9 times

- in line 128, 149, 189, 257, 300, 412, 582, 607, 654

tsmsg1 defined in line 87; used 2 times

- in line 161, 503

tsmsg2 defined in line 88; used 2 times

- in line 166, 501

tstab defined in line 57; used 4 times

- in line 158, 258, 292, 411

#### Defined struct's

ts_softc defined in line 40; used 24 times

- in line 85(2), 95(2), 116(2), 128(2), 149(2), 189(2), 257(2), 289(2), 412(2), 582(2), 607(2), 654(2)

#### Defined macros

INF defined in line 69; used 1 times

- in line 171

SCOM defined in line 82; used 3 times

- in line 320, 425, 459

SIO defined in line 81; used 3 times

- in line 355, 483, 500

SREW defined in line 83; used 2 times

- in line 320, 424

SSEEK defined in line 80; used 1 times

- in line 374

TSCTLR defined in line 73; used 6 times

- in line 148, 189, 218, 256, 581, 653

TSUNIT defined in line 72; never used
T_NOREWIND defined in line 74; used 1 times

- in line 196

Last modified: 1994-11-27 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 1613 |