1: /*
   2:  * TJU77/TWU77/TJE16/TWE16 tape driver
   3:  */
   4: 
   5: /*
   6:  *	SCCS id	@(#)ht.c	2.1 (Berkeley)	8/5/83
   7:  */
   8: 
   9: #include "ht.h"
  10: #if NHT > 0
  11: #include "param.h"
  12: #include <sys/systm.h>
  13: #include <sys/buf.h>
  14: #include <sys/conf.h>
  15: #include <sys/dir.h>
  16: #include <sys/file.h>
  17: #include <sys/user.h>
  18: #include <sys/htreg.h>
  19: #ifdef  HT_IOCTL
  20: #include <sys/mtio.h>
  21: #endif
  22: 
  23: struct  buf httab;
  24: struct  buf rhtbuf;
  25: struct  buf chtbuf;
  26: 
  27: struct  htdevice    *HTADDR;
  28: 
  29: #define INF 32760
  30: 
  31: struct  softc   {
  32:     char    sc_openf;
  33:     char    sc_lastiow;
  34:     daddr_t sc_blkno;
  35:     daddr_t sc_nxrec;
  36:     u_short sc_erreg;
  37:     u_short sc_fsreg;
  38: #ifdef  HT_IOCTL
  39:     short   sc_resid;
  40: #endif
  41: }   tu_softc[NHT];
  42: 
  43: 
  44: #define SIO 1
  45: #define SSFOR   2
  46: #define SSREV   3
  47: #define SRETRY  4
  48: #define SCOM    5
  49: #define SOK 6
  50: 
  51: #define TUUNIT(dev) (minor(dev) & 077)
  52: 
  53: /* bits in minor device */
  54: #define H_800BPI    0100
  55: #define H_NOREWIND  0200
  56: 
  57: htattach(addr, unit)
  58: register struct htdevice *addr;
  59: {
  60:     /*
  61: 	 * This driver supports only one controller.
  62: 	 */
  63:     if (unit != 0)
  64:         return(0);
  65:     if ((addr != (struct htdevice *) NULL) && (fioword(addr) != -1)) {
  66:         HTADDR = addr;
  67: #if PDP11 == 70 || PDP11 == GENERIC
  68:         if (fioword(&(addr->htbae)) != -1)
  69:             httab.b_flags |= B_RH70;
  70: #endif
  71:         return(1);
  72:     }
  73:     HTADDR = (struct hpdevice *) NULL;
  74:     return(0);
  75: }
  76: 
  77: htopen(dev, flag)
  78: dev_t   dev;
  79: {
  80:     register ds;
  81:     register htunit = TUUNIT(dev);
  82:     register struct tu_softc *sc = &tu_softc[htunit];
  83: 
  84:     httab.b_flags |= B_TAPE;
  85:     htunit = minor(dev) & 077;
  86:     if (HTADDR == (struct htdevice *) NULL || htunit >= NHT) {
  87:         u.u_error = ENXIO;
  88:         return;
  89:     }
  90:     else
  91:         if (sc->sc_openf) {
  92:             u.u_error = EBUSY;
  93:             return;
  94:         }
  95:     sc->sc_blkno = (daddr_t) 0;
  96:     sc->sc_nxrec = (daddr_t) INF;
  97:     sc->sc_lastiow = 0;
  98:     ds = htcommand(dev, HT_SENSE, 1);
  99:     if ((ds & HTFS_MOL) == 0) {
 100:         uprintf("tu%d: not online\n", htunit);
 101:         u.u_error = EIO;
 102:         return;
 103:     }
 104:     if ((flag & FWRITE) && (ds & HTFS_WRL)) {
 105:         uprintf("tu%d: no write ring\n", htunit);
 106:         u.u_error = EIO;
 107:         return;
 108:     }
 109:     if (u.u_error == 0)
 110:         sc->sc_openf++;
 111: }
 112: 
 113: htclose(dev, flag)
 114: dev_t   dev;
 115: {
 116:     register struct tu_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 = spl5();
 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: #ifdef  HT_IOCTL
 152:     if (com == HT_SFORW || com == HT_SREV)
 153:         bp->b_repcnt = count;
 154: #endif
 155:     bp->b_command = com;
 156:     bp->b_blkno = (daddr_t) 0;
 157:     htstrategy(bp);
 158:     /*
 159: 	 * In case of rewind from close, don't wait.
 160: 	 * This is the only case where count can be 0.
 161: 	 */
 162:     if (count == 0)
 163:         return;
 164:     iowait(bp);
 165:     if(bp->b_flags & B_WANTED)
 166:         wakeup((caddr_t)bp);
 167:     bp->b_flags &= B_ERROR;
 168:     return (bp->b_resid);
 169: }
 170: 
 171: htstrategy(bp)
 172: register struct buf *bp;
 173: {
 174:     int s;
 175:     register daddr_t *p;
 176:     register struct tu_softc *sc = &tu_softc[TUUNIT(bp->b_dev)];
 177: 
 178:     if(bp != &chtbuf) {
 179: #ifdef  UNIBUS_MAP
 180:         if ((httab.b_flags & B_RH70) == 0)
 181:             mapalloc(bp);
 182: #endif
 183:         p = &sc->sc_nxrec;
 184:         if(dbtofsb(bp->b_blkno) > *p) {
 185:             bp->b_flags |= B_ERROR;
 186:             bp->b_error = ENXIO;
 187:             iodone(bp);
 188:             return;
 189:         }
 190:         if(dbtofsb(bp->b_blkno) == *p && bp->b_flags & B_READ) {
 191:             bp->b_resid = bp->b_bcount;
 192:             iodone(bp);
 193:             return;
 194:         }
 195:         if ((bp->b_flags & B_READ) == 0) {
 196:             *p = dbtofsb(bp->b_blkno) + 1;
 197:             sc->sc_lastiow = 1;
 198:         }
 199:     }
 200:     bp->av_forw = NULL;
 201:     s = spl5();
 202:     if (httab.b_actf == NULL)
 203:         httab.b_actf = bp;
 204:     else
 205:         httab.b_actl->av_forw = bp;
 206:     httab.b_actl = bp;
 207:     if (httab.b_active == 0)
 208:         htstart();
 209:     splx(s);
 210: }
 211: 
 212: htstart()
 213: {
 214:     register struct buf *bp;
 215:     register den;
 216:     int htunit;
 217:     daddr_t blkno;
 218:     register struct softc *sc;
 219: 
 220:     loop:
 221:     if ((bp = httab.b_actf) == NULL)
 222:         return;
 223:     htunit = minor(bp->b_dev) & 0177;
 224:     sc = &tu_softc[TUUNIT(bp->b_dev)];
 225:     sc->sc_erreg = HTADDR->hter;
 226:     sc->sc_fsreg = HTADDR->htfs;
 227: #ifdef  HT_IOCTL
 228:     sc->sc_resid = HTADDR->htfc;
 229: #endif
 230:     HTADDR->htcs2 = ((htunit >> 3) & 07);
 231:     den = HTTC_1600BPI | HTTC_PDP11 | (htunit & 07);
 232:     if (htunit & H_800BPI)
 233:         den = HTTC_800BPI | HTTC_PDP11 | (htunit & 07);
 234:     if ((HTADDR->httc & 03777) != den)
 235:         HTADDR->httc = den;
 236:     if (HTADDR->htcs2 & HTCS2_NEF || (HTADDR->htfs & HTFS_MOL) == 0)
 237:         goto abort;
 238:     htunit &= 077;
 239:     blkno = sc->sc_blkno;
 240:     if (bp == &chtbuf) {
 241:         if (bp->b_command == HT_SENSE) {
 242:             bp->b_resid = HTADDR->htfs;
 243:             goto next;
 244:         }
 245:         httab.b_active = SCOM;
 246:         HTADDR->htfc = 0;
 247:         HTADDR->htcs1 = bp->b_command | HT_IE | HT_GO;
 248:         return;
 249:     }
 250:     if (sc->sc_openf < 0 || dbtofsb(bp->b_blkno) > sc->sc_nxrec)
 251:         goto abort;
 252:     if (blkno == dbtofsb(bp->b_blkno)) {
 253:         httab.b_active = SIO;
 254:         HTADDR->htba = bp->b_un.b_addr;
 255: #if PDP11 == 70 || PDP11 == GENERIC
 256:         if(httab.b_flags & B_RH70)
 257:             HTADDR->htbae = bp->b_xmem;
 258: #endif
 259:         HTADDR->htfc = -bp->b_bcount;
 260:         HTADDR->htwc = -(bp->b_bcount >> 1);
 261:         den = ((bp->b_xmem & 3) << 8) | HT_IE | HT_GO;
 262:         if(bp->b_flags & B_READ)
 263:             den |= HT_RCOM;
 264:         else {
 265:             if(HTADDR->htfs & HTFS_EOT) {
 266:                 bp->b_resid = bp->b_bcount;
 267:                 goto next;
 268:             }
 269:             den |= HT_WCOM;
 270:         }
 271:         HTADDR->htcs1 = den;
 272:     } else {
 273:         if (blkno < dbtofsb(bp->b_blkno)) {
 274:             httab.b_active = SSFOR;
 275:             HTADDR->htfc = blkno - dbtofsb(bp->b_blkno);
 276:             HTADDR->htcs1 = HT_SFORW | HT_IE | HT_GO;
 277:         } else {
 278:             httab.b_active = SSREV;
 279:             HTADDR->htfc = dbtofsb(bp->b_blkno) - blkno;
 280:             HTADDR->htcs1 = HT_SREV | HT_IE | HT_GO;
 281:         }
 282:     }
 283:     return;
 284: 
 285:     abort:
 286:     bp->b_flags |= B_ERROR;
 287: 
 288:     next:
 289:     httab.b_actf = bp->av_forw;
 290:     iodone(bp);
 291:     goto loop;
 292: }
 293: 
 294: htintr()
 295: {
 296:     register struct buf *bp;
 297:     register state;
 298:     int err, htunit;
 299:     register struct softc *sc;
 300: 
 301:     if ((bp = httab.b_actf) == NULL)
 302:         return;
 303:     htunit = TUUNIT(bp->b_dev);
 304:     state = httab.b_active;
 305:     httab.b_active = 0;
 306:     sc = &tu_softc[htunit];
 307:     sc->sc_erreg = HTADDR->hter;
 308:     sc->sc_fsreg = HTADDR->htfs;
 309: #ifdef  HT_IOCTL
 310:     sc->sc_resid = HTADDR->htfc;
 311: #endif
 312:     if (HTADDR->htcs1 & HT_TRE) {
 313:         err = HTADDR->hter;
 314:         if (HTADDR->htcs2 & HTCS2_ERR || (err & HTER_HARD))
 315:             state = 0;
 316:         if (bp == &rhtbuf)
 317:             err &= ~HTER_FCE;
 318:         if ((bp->b_flags & B_READ) && (HTADDR->htfs & HTFS_PES))
 319:             err &= ~(HTER_CSITM | HTER_CORCRC);
 320:         if ((HTADDR->htfs & HTFS_MOL) == 0) {
 321:             if(sc->sc_openf)
 322:                 sc->sc_openf = -1;
 323:         }
 324:         else
 325:             if (HTADDR->htfs & HTFS_TM) {
 326:                 HTADDR->htwc = -(bp->b_bcount >> 1);
 327:                 sc->sc_nxrec = dbtofsb(bp->b_blkno);
 328:                 state = SOK;
 329:             }
 330:             else
 331:                 if (state && err == 0)
 332:                     state = SOK;
 333:         if (httab.b_errcnt > 4)
 334: #ifdef  UCB_DEVERR
 335:             printf("tu%d: hard error bn %D er=%b ds=%b\n",
 336:                    htunit, bp->b_blkno,
 337:                    sc->sc_erreg, HTER_BITS,
 338:                    sc->sc_fsreg, HTFS_BITS);
 339: #else
 340:             deverror(bp, sc->sc_erreg, sc->sc_fsreg);
 341: #endif
 342:         htinit();
 343:         if (state == SIO && ++httab.b_errcnt < 10) {
 344:             httab.b_active = SRETRY;
 345:             sc->sc_blkno++;
 346:             HTADDR->htfc = -1;
 347:             HTADDR->htcs1 = HT_SREV | HT_IE | HT_GO;
 348:             return;
 349:         }
 350:         if (state != SOK) {
 351:             bp->b_flags |= B_ERROR;
 352:             state = SIO;
 353:         }
 354:     } else
 355:         if (HTADDR->htcs1 & HT_SC)
 356:             if(HTADDR->htfs & HTFS_ERR)
 357:                 htinit();
 358: 
 359:     switch (state) {
 360:         case SIO:
 361:         case SOK:
 362:             sc->sc_blkno++;
 363: 
 364:         case SCOM:
 365:             httab.b_errcnt = 0;
 366:             httab.b_actf = bp->av_forw;
 367:             iodone(bp);
 368:             bp->b_resid = -(HTADDR->htwc << 1);
 369:             break;
 370: 
 371:         case SRETRY:
 372:             if((bp->b_flags & B_READ) == 0) {
 373:                 httab.b_active = SSFOR;
 374:                 HTADDR->htcs1 = HT_ERASE | HT_IE | HT_GO;
 375:                 return;
 376:             }
 377: 
 378:         case SSFOR:
 379:         case SSREV:
 380:             if(HTADDR->htfs & HTFS_TM) {
 381:                 if(state == SSREV) {
 382:                     sc->sc_nxrec = dbtofsb(bp->b_blkno) - HTADDR->htfc;
 383:                     sc->sc_blkno = sc->sc_nxrec;
 384:                 } else
 385:                     {
 386:                     sc->sc_nxrec = dbtofsb(bp->b_blkno) + HTADDR->htfc - 1;
 387:                     sc->sc_blkno = sc->sc_nxrec + 1;
 388:                 }
 389:             } else
 390:                 sc->sc_blkno = dbtofsb(bp->b_blkno);
 391:             break;
 392: 
 393:         default:
 394:             return;
 395:     }
 396:     htstart();
 397: }
 398: 
 399: htinit()
 400: {
 401:     register ocs2;
 402:     register omttc;
 403: 
 404:     omttc = HTADDR->httc & 03777;   /* preserve old slave select, dens, format */
 405:     ocs2 = HTADDR->htcs2 & 07;  /* preserve old unit */
 406: 
 407:     HTADDR->htcs2 = HTCS2_CLR;
 408:     HTADDR->htcs2 = ocs2;
 409:     HTADDR->httc = omttc;
 410:     HTADDR->htcs1 = HT_DCLR | HT_GO;
 411: }
 412: 
 413: htread(dev)
 414: register dev_t  dev;
 415: {
 416:     htphys(dev);
 417:     bphysio(htstrategy, &rhtbuf, dev, B_READ);
 418: }
 419: 
 420: htwrite(dev)
 421: register dev_t  dev;
 422: {
 423:     htphys(dev);
 424:     bphysio(htstrategy, &rhtbuf, dev, B_WRITE);
 425: }
 426: 
 427: htphys(dev)
 428: dev_t dev;
 429: {
 430:     daddr_t a;
 431:     register struct tu_softc *sc = &tu_softc[TUUNIT(dev)];
 432: 
 433:     a = dbtofsb(u.u_offset >> 9);
 434:     sc->sc_blkno = a;
 435:     sc->sc_nxrec = a + 1;
 436: }
 437: 
 438: #ifdef  HT_IOCTL
 439: 
 440: /*ARGSUSED*/
 441: htioctl(dev, cmd, addr, flag)
 442: dev_t   dev;
 443: caddr_t addr;
 444: {
 445:     register struct buf *bp = &chtbuf;
 446:     register struct softc *sc = &tu_softc[minor(dev)&07];
 447:     register callcount;
 448:     int fcount;
 449:     struct  mtop mtop;
 450:     struct  mtget mtget;
 451:     /* we depend on the values and order of the MT codes here */
 452:     static  htops[] = {HT_WEOF, HT_SFORW, HT_SREV, HT_SFORW,
 453:         HT_SREV, HT_REW, HT_REWOFFL, HT_SENSE};
 454: 
 455:     switch (cmd)    {
 456: 
 457:         case MTIOCTOP:
 458:             if (copyin(addr, (caddr_t) &mtop, sizeof(mtop))) {
 459:                 u.u_error = EFAULT;
 460:                 return;
 461:             }
 462:             switch(mtop.mt_op) {
 463:                 case MTWEOF:
 464:                     callcount = mtop.mt_count;
 465:                     fcount = 1;
 466:                     break;
 467:                 case MTFSF:
 468:                 case MTBSF:
 469:                     callcount = mtop.mt_count;
 470:                     fcount = INF;
 471:                     break;
 472:                 case MTFSR:
 473:                 case MTBSR:
 474:                     callcount = 1;
 475:                     fcount = mtop.mt_count;
 476:                     break;
 477:                 case MTREW:
 478:                 case MTOFFL:
 479:                 case MTNOP:
 480:                     callcount = 1;
 481:                     fcount = 1;
 482:                     break;
 483:                 default:
 484:                     u.u_error = ENXIO;
 485:                     return;
 486:             }
 487:             if (callcount <= 0 || fcount <= 0) {
 488:                 u.u_error = ENXIO;
 489:                 return;
 490:             }
 491:             while (--callcount >= 0) {
 492:                 htcommand(dev, htops[mtop.mt_op], fcount);
 493:                 if ((mtop.mt_op == MTFSR || mtop.mt_op == MTBSR)
 494:                     && bp->b_resid) {
 495:                     u.u_error = EIO;
 496:                     break;
 497:                 }
 498:                 if ((bp->b_flags & B_ERROR)
 499:                     || sc->sc_fsreg & HTFS_BOT)
 500:                     break;
 501:             }
 502:             geterror(bp);
 503:             return;
 504:         case MTIOCGET:
 505:             mtget.mt_erreg = sc->sc_erreg;
 506:             mtget.mt_dsreg = sc->sc_fsreg;
 507:             mtget.mt_resid = sc->sc_resid;
 508:             mtget.mt_type = MT_ISHT;
 509:             if (copyout((caddr_t) &mtget, addr, sizeof(mtget)))
 510:                 u.u_error = EFAULT;
 511:             return;
 512:         default:
 513:             u.u_error = ENXIO;
 514:     }
 515: }
 516: #endif	HT_IOCTL
 517: #endif	NHT

Defined functions

htattach defined in line 57; never used
htclose defined in line 113; never used
htcommand defined in line 129; used 6 times
htinit defined in line 399; used 2 times
htintr defined in line 294; used 4 times
htioctl defined in line 441; never used
htopen defined in line 77; never used
htphys defined in line 427; used 2 times
htread defined in line 413; never used
htstart defined in line 212; used 2 times
htstrategy defined in line 171; used 3 times
htwrite defined in line 420; never used

Defined variables

HTADDR defined in line 27; used 49 times
chtbuf defined in line 25; used 4 times
httab defined in line 23; used 26 times
rhtbuf defined in line 24; used 3 times
tu_softc defined in line 41; used 7 times

Defined struct's

softc defined in line 31; used 6 times

Defined macros

H_800BPI defined in line 54; used 1 times
H_NOREWIND defined in line 55; used 1 times
INF defined in line 29; used 2 times
SCOM defined in line 48; used 1 times
SIO defined in line 44; used 3 times
SOK defined in line 49; used 3 times
SRETRY defined in line 47; used 1 times
SSFOR defined in line 45; used 2 times
SSREV defined in line 46; used 2 times
TUUNIT defined in line 51; used 6 times
Last modified: 1983-08-06
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1434
Valid CSS Valid XHTML 1.0 Strict