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:  *	@(#)ht.c	2.2 (2.11BSD GTE) 1/2/93
   7:  */
   8: 
   9: /*
  10:  * TJU77/TWU77/TJE16/TWE16 tape driver
  11:  */
  12: #include "ht.h"
  13: #if NHT > 0
  14: #include "param.h"
  15: #include "buf.h"
  16: #include "ioctl.h"
  17: #include "conf.h"
  18: #include "file.h"
  19: #include "user.h"
  20: #include "mtio.h"
  21: #include "fs.h"
  22: #include "htreg.h"
  23: #include "systm.h"
  24: 
  25: struct  buf httab, chtbuf;
  26: static  short   rh70;       /* ht.c was ONLY user of B_RH70 and that bit
  27: 				 * was wanted for something else (B_LOCKED)
  28: 				*/
  29: struct  htdevice    *HTADDR;
  30: 
  31: #define INF 32760
  32: 
  33: struct  softc   {
  34:     char    sc_openf;
  35:     char    sc_lastiow;
  36:     daddr_t sc_blkno;
  37:     daddr_t sc_nxrec;
  38:     u_short sc_erreg;
  39:     u_short sc_fsreg;
  40:     short   sc_resid;
  41:     short   sc_dens;
  42: }   tu_softc[NHT];
  43: 
  44: 
  45: #define SIO 1
  46: #define SSFOR   2
  47: #define SSREV   3
  48: #define SRETRY  4
  49: #define SCOM    5
  50: #define SOK 6
  51: 
  52: 
  53: /* bits in minor device */
  54: #define TUUNIT(dev) (minor(dev) & 03)
  55: #define H_NOREWIND  004
  56: #define H_1600BPI   010
  57: 
  58: htattach(addr, unit)
  59: register struct htdevice *addr;
  60: {
  61:     /*
  62: 	 * This driver supports only one controller.
  63: 	 */
  64:     if (unit == 0) {
  65:         HTADDR = addr;
  66:         if (fioword(&(addr->htbae)) != -1)
  67:             rh70 = 1;
  68:         return(1);
  69:     }
  70:     return(0);
  71: }
  72: 
  73: htopen(dev, flag)
  74: dev_t   dev;
  75: {
  76:     register ds;
  77:     register htunit = TUUNIT(dev);
  78:     register struct softc *sc = &tu_softc[htunit];
  79:     int olddens, dens;
  80: 
  81:     httab.b_flags |= B_TAPE;
  82:     if (!HTADDR || htunit >= NHT)
  83:         return(ENXIO);
  84:     if (sc->sc_openf)
  85:         return(EBUSY);
  86:     sc->sc_blkno = (daddr_t) 0;
  87:     sc->sc_nxrec = (daddr_t) INF;
  88:     sc->sc_lastiow = 0;
  89:     olddens = sc->sc_dens;
  90:     dens = sc->sc_dens =
  91:         ((minor(dev)&H_1600BPI)?HTTC_1600BPI:HTTC_800BPI)|
  92:         HTTC_PDP11|htunit;
  93:     ds = htcommand(dev, HT_SENSE, 1);
  94:     sc->sc_dens = olddens;
  95:     if ((ds & HTFS_MOL) == 0) {
  96:         uprintf("tu%d: not online\n", htunit);
  97:         return(EIO);
  98:     }
  99:     if ((flag & FWRITE) && (ds & HTFS_WRL)) {
 100:         uprintf("tu%d: no write ring\n", htunit);
 101:         return(EIO);
 102:     }
 103:     if ((flag & FWRITE) && (ds & HTFS_BOT) == 0 &&
 104:         dens != sc->sc_dens) {
 105:         uprintf("tu%d: can't change density in mid-tape\n", htunit);
 106:         return (EIO);
 107:     }
 108:     sc->sc_openf = 1;
 109:     sc->sc_dens = dens;
 110:     return(0);
 111: }
 112: 
 113: htclose(dev, flag)
 114: dev_t   dev;
 115: {
 116:     register struct softc *sc = &tu_softc[TUUNIT(dev)];
 117: 
 118:     if (flag == FWRITE || ((flag & FWRITE) && sc->sc_lastiow)) {
 119:         htcommand(dev, HT_WEOF, 1);
 120:         htcommand(dev, HT_WEOF, 1);
 121:         htcommand(dev, HT_SREV, 1);
 122:     }
 123:     if ((minor(dev) & H_NOREWIND) == 0)
 124:         htcommand(dev, HT_REW, 1);
 125:     sc->sc_openf = 0;
 126: }
 127: 
 128: /*ARGSUSED*/
 129: htcommand(dev, com, count)
 130: u_short count;
 131: dev_t   dev;
 132: {
 133:     register s;
 134:     register struct buf *bp;
 135: 
 136:     bp = &chtbuf;
 137:     s = splbio();
 138:     while(bp->b_flags & B_BUSY) {
 139:         /*
 140: 		 * This special check is because B_BUSY never
 141: 		 * gets cleared in the non-waiting rewind case.
 142: 		 */
 143:         if (bp->b_repcnt == 0 && (bp->b_flags & B_DONE))
 144:             break;
 145:         bp->b_flags |= B_WANTED;
 146:         sleep((caddr_t) bp, PRIBIO);
 147:     }
 148:     bp->b_flags = B_BUSY | B_READ;
 149:     splx(s);
 150:     bp->b_dev = dev;
 151:     if (com == HT_SFORW || com == HT_SREV)
 152:         bp->b_repcnt = count;
 153:     bp->b_command = com;
 154:     bp->b_blkno = (daddr_t) 0;
 155:     htstrategy(bp);
 156:     /*
 157: 	 * In case of rewind from close, don't wait.
 158: 	 * This is the only case where count can be 0.
 159: 	 */
 160:     if (count == 0)
 161:         return(0);
 162:     iowait(bp);
 163:     if(bp->b_flags & B_WANTED)
 164:         wakeup((caddr_t)bp);
 165:     bp->b_flags &= B_ERROR;
 166:     return (bp->b_resid);
 167: }
 168: 
 169: htstrategy(bp)
 170: register struct buf *bp;
 171: {
 172:     register int s;
 173:     register struct softc *sc = &tu_softc[TUUNIT(bp->b_dev)];
 174: 
 175:     if (rh70 == 0)
 176:         mapalloc(bp);
 177:     if (bp->b_flags & B_PHYS) {
 178:         sc->sc_blkno = sc->sc_nxrec = dbtofsb(bp->b_blkno);
 179:         sc->sc_nxrec++;
 180:     }
 181:     bp->av_forw = NULL;
 182:     s = splbio();
 183:     if (httab.b_actf == NULL)
 184:         httab.b_actf = bp;
 185:     else
 186:         httab.b_actl->av_forw = bp;
 187:     httab.b_actl = bp;
 188:     if (httab.b_active == 0)
 189:         htstart();
 190:     splx(s);
 191: }
 192: 
 193: htstart()
 194: {
 195:     register struct buf *bp;
 196:     register den;
 197:     daddr_t blkno;
 198:     register struct softc *sc;
 199: 
 200:     loop:
 201:     if ((bp = httab.b_actf) == NULL)
 202:         return;
 203:     sc = &tu_softc[TUUNIT(bp->b_dev)];
 204:     sc->sc_erreg = HTADDR->hter;
 205:     sc->sc_fsreg = HTADDR->htfs;
 206:     sc->sc_resid = HTADDR->htfc;
 207:     HTADDR->htcs2 = 0;  /* controller 0 - do we need this? */
 208:     if ((HTADDR->httc & 03777) != sc->sc_dens)
 209:         HTADDR->httc = sc->sc_dens;
 210:     sc->sc_lastiow = 0;
 211:     if (sc->sc_openf < 0 || HTADDR->htcs2 & HTCS2_NEF || !(HTADDR->htfs & HTFS_MOL))
 212:         goto abort;
 213:     if (bp == &chtbuf) {
 214:         if (bp->b_command == HT_SENSE) {
 215:             bp->b_resid = HTADDR->htfs;
 216:             goto next;
 217:         }
 218:         httab.b_active = SCOM;
 219:         HTADDR->htfc = 0;
 220:         HTADDR->htcs1 = bp->b_command | HT_IE | HT_GO;
 221:         return;
 222:     }
 223:     if (dbtofsb(bp->b_blkno) > sc->sc_nxrec)
 224:         goto abort;
 225:     if (dbtofsb(bp->b_blkno) == sc->sc_nxrec && bp->b_flags & B_READ) {
 226:         /*
 227: 		 * Reading at end of file returns 0 bytes.
 228: 		 * Buffer will be cleared (if written) in rwip.
 229: 		*/
 230:         bp->b_resid = bp->b_bcount;
 231:         goto next;
 232:     }
 233:     if ((bp->b_flags & B_READ) == 0)
 234:         /*
 235: 		 * Writing sets EOF
 236: 		*/
 237:         sc->sc_nxrec = dbtofsb(bp->b_blkno) + 1;
 238:     if ((blkno = sc->sc_blkno) == dbtofsb(bp->b_blkno)) {
 239:         httab.b_active = SIO;
 240:         HTADDR->htba = bp->b_un.b_addr;
 241:         if (rh70)
 242:             HTADDR->htbae = bp->b_xmem;
 243:         HTADDR->htfc = -bp->b_bcount;
 244:         HTADDR->htwc = -(bp->b_bcount >> 1);
 245:         den = ((bp->b_xmem & 3) << 8) | HT_IE | HT_GO;
 246:         if(bp->b_flags & B_READ)
 247:             den |= HT_RCOM;
 248:         else {
 249:             if(HTADDR->htfs & HTFS_EOT) {
 250:                 bp->b_resid = bp->b_bcount;
 251:                 bp->b_error = ENXIO;
 252:                 httab.b_active = 0;
 253:                 goto next;
 254:             }
 255:             den |= HT_WCOM;
 256:         }
 257:         HTADDR->htcs1 = den;
 258:     } else {
 259:         if (blkno < dbtofsb(bp->b_blkno)) {
 260:             httab.b_active = SSFOR;
 261:             HTADDR->htfc = blkno - dbtofsb(bp->b_blkno);
 262:             HTADDR->htcs1 = HT_SFORW | HT_IE | HT_GO;
 263:         } else {
 264:             httab.b_active = SSREV;
 265:             HTADDR->htfc = dbtofsb(bp->b_blkno) - blkno;
 266:             HTADDR->htcs1 = HT_SREV | HT_IE | HT_GO;
 267:         }
 268:     }
 269:     return;
 270: 
 271:     abort:
 272:     bp->b_flags |= B_ERROR;
 273: 
 274:     next:
 275:     httab.b_actf = bp->av_forw;
 276:     iodone(bp);
 277:     goto loop;
 278: }
 279: 
 280: htintr()
 281: {
 282:     register struct buf *bp;
 283:     register state;
 284:     int err, htunit;
 285:     register struct softc *sc;
 286: 
 287:     if ((bp = httab.b_actf) == NULL)
 288:         return;
 289:     htunit = TUUNIT(bp->b_dev);
 290:     sc = &tu_softc[htunit];
 291:     sc->sc_erreg = HTADDR->hter;
 292:     sc->sc_fsreg = HTADDR->htfs;
 293:     sc->sc_resid = HTADDR->htfc;
 294:     if ((bp->b_flags & B_READ) == 0)
 295:         sc->sc_lastiow = 1;
 296:     state = httab.b_active;
 297:     httab.b_active = 0;
 298:     if (HTADDR->htcs1 & HT_TRE) {
 299:         err = HTADDR->hter;
 300:         if (HTADDR->htcs2 & HTCS2_ERR || (err & HTER_HARD))
 301:             state = 0;
 302:         if (bp->b_flags & B_PHYS)
 303:             err &= ~HTER_FCE;
 304:         if ((bp->b_flags & B_READ) && (HTADDR->htfs & HTFS_PES))
 305:             err &= ~(HTER_CSITM | HTER_CORCRC);
 306:         if ((HTADDR->htfs & HTFS_MOL) == 0) {
 307:             if(sc->sc_openf)
 308:                 sc->sc_openf = -1;
 309:         }
 310:         else
 311:             if (HTADDR->htfs & HTFS_TM) {
 312:                 HTADDR->htwc = -(bp->b_bcount >> 1);
 313:                 sc->sc_nxrec = dbtofsb(bp->b_blkno);
 314:                 state = SOK;
 315:             }
 316:             else
 317:                 if (state && err == 0)
 318:                     state = SOK;
 319:         if (httab.b_errcnt > 4)
 320:             printf("tu%d: hard error bn %D er=%b ds=%b\n",
 321:                    htunit, bp->b_blkno,
 322:                    sc->sc_erreg, HTER_BITS,
 323:                    sc->sc_fsreg, HTFS_BITS);
 324:         htinit();
 325:         if (state == SIO && ++httab.b_errcnt < 10) {
 326:             httab.b_active = SRETRY;
 327:             sc->sc_blkno++;
 328:             HTADDR->htfc = -1;
 329:             HTADDR->htcs1 = HT_SREV | HT_IE | HT_GO;
 330:             return;
 331:         }
 332:         if (state != SOK) {
 333:             bp->b_flags |= B_ERROR;
 334:             state = SIO;
 335:         }
 336:     } else
 337:         if (HTADDR->htcs1 & HT_SC)
 338:             if(HTADDR->htfs & HTFS_ERR)
 339:                 htinit();
 340: 
 341:     switch (state) {
 342:         case SIO:
 343:         case SOK:
 344:             sc->sc_blkno++;
 345: 
 346:         case SCOM:
 347:             httab.b_errcnt = 0;
 348:             httab.b_actf = bp->av_forw;
 349:             iodone(bp);
 350:             bp->b_resid = -(HTADDR->htwc << 1);
 351:             break;
 352: 
 353:         case SRETRY:
 354:             if((bp->b_flags & B_READ) == 0) {
 355:                 httab.b_active = SSFOR;
 356:                 HTADDR->htcs1 = HT_ERASE | HT_IE | HT_GO;
 357:                 return;
 358:             }
 359: 
 360:         case SSFOR:
 361:         case SSREV:
 362:             if(HTADDR->htfs & HTFS_TM) {
 363:                 if(state == SSREV) {
 364:                     sc->sc_nxrec = dbtofsb(bp->b_blkno) - HTADDR->htfc;
 365:                     sc->sc_blkno = sc->sc_nxrec;
 366:                 } else
 367:                     {
 368:                     sc->sc_nxrec = dbtofsb(bp->b_blkno) + HTADDR->htfc - 1;
 369:                     sc->sc_blkno = sc->sc_nxrec + 1;
 370:                 }
 371:             } else
 372:                 sc->sc_blkno = dbtofsb(bp->b_blkno);
 373:             break;
 374: 
 375:         default:
 376:             return;
 377:     }
 378:     htstart();
 379: }
 380: 
 381: htinit()
 382: {
 383:     register ocs2;
 384:     register omttc;
 385: 
 386:     omttc = HTADDR->httc & 03777;   /* preserve old slave select, dens, format */
 387:     ocs2 = HTADDR->htcs2 & 07;  /* preserve old unit */
 388: 
 389:     HTADDR->htcs2 = HTCS2_CLR;
 390:     HTADDR->htcs2 = ocs2;
 391:     HTADDR->httc = omttc;
 392:     HTADDR->htcs1 = HT_DCLR | HT_GO;
 393: }
 394: 
 395: /*ARGSUSED*/
 396: htioctl(dev, cmd, data, flag)
 397:     dev_t dev;
 398:     u_int cmd;
 399:     caddr_t data;
 400:     int flag;
 401: {
 402:     register struct buf *bp = &chtbuf;
 403:     register struct softc *sc = &tu_softc[minor(dev)&07];
 404:     register callcount;
 405:     int fcount;
 406:     struct  mtop *mtop;
 407:     struct  mtget *mtget;
 408:     /* we depend on the values and order of the MT codes here */
 409:     static  htops[] = {HT_WEOF, HT_SFORW, HT_SREV, HT_SFORW,
 410:         HT_SREV, HT_REW, HT_REWOFFL, HT_SENSE};
 411: 
 412:     switch (cmd) {
 413:     case MTIOCTOP:
 414:         mtop = (struct mtop *)data;
 415:         switch (mtop->mt_op) {
 416:         case MTWEOF:
 417:             callcount = mtop->mt_count;
 418:             fcount = 1;
 419:             break;
 420:         case MTFSF: case MTBSF:
 421:             callcount = mtop->mt_count;
 422:             fcount = INF;
 423:             break;
 424:         case MTFSR: case MTBSR:
 425:             callcount = 1;
 426:             fcount = mtop->mt_count;
 427:             break;
 428:         case MTREW: case MTOFFL: case MTNOP:
 429:             callcount = 1;
 430:             fcount = 1;
 431:             break;
 432:         default:
 433:             return (ENXIO);
 434:         }
 435:         if (callcount <= 0 || fcount <= 0)
 436:             return (EINVAL);
 437:         while (--callcount >= 0) {
 438:             htcommand(dev, htops[mtop->mt_op], fcount);
 439:             if ((mtop->mt_op == MTFSR || mtop->mt_op == MTBSR) &&
 440:                 bp->b_resid)
 441:                 return (EIO);
 442:             if ((bp->b_flags&B_ERROR) || sc->sc_fsreg&HTFS_BOT)
 443:                 break;
 444:         }
 445:         return (geterror(bp));
 446:     case MTIOCGET:
 447:         mtget = (struct mtget *)data;
 448:         mtget->mt_dsreg = sc->sc_fsreg;
 449:         mtget->mt_erreg = sc->sc_erreg;
 450:         mtget->mt_resid = sc->sc_resid;
 451:         mtget->mt_type = MT_ISHT;
 452:         break;
 453:     default:
 454:         return (ENXIO);
 455:     }
 456:     return (0);
 457: }
 458: #endif NHT

Defined functions

htattach defined in line 58; never used
htclose defined in line 113; never used
htcommand defined in line 129; used 6 times
htinit defined in line 381; used 2 times
htintr defined in line 280; used 1 times
htioctl defined in line 396; never used
htopen defined in line 73; never used
htstart defined in line 193; used 2 times
htstrategy defined in line 169; used 1 times

Defined variables

HTADDR defined in line 29; used 48 times
chtbuf defined in line 25; used 3 times
httab defined in line 25; used 22 times
rh70 defined in line 26; used 3 times
tu_softc defined in line 42; used 6 times

Defined struct's

softc defined in line 33; used 12 times

Defined macros

H_1600BPI defined in line 56; used 1 times
  • in line 91
H_NOREWIND defined in line 55; used 1 times
INF defined in line 31; used 2 times
SCOM defined in line 49; used 1 times
SIO defined in line 45; used 3 times
SOK defined in line 50; used 3 times
SRETRY defined in line 48; used 1 times
SSFOR defined in line 46; used 2 times
SSREV defined in line 47; used 2 times
TUUNIT defined in line 54; used 5 times
Last modified: 1993-01-03
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 4528
Valid CSS Valid XHTML 1.0 Strict