1 /* ht.c 4.35 82/12/17 */ 2 3 #include "tu.h" 4 #if NHT > 0 5 /* 6 * TM03/TU?? tape driver 7 * 8 * TODO: 9 * cleanup messages on errors 10 * test ioctl's 11 * see how many rewind interrups we get if we kick when not at BOT 12 * fixup rle error on block tape code 13 */ 14 #include "../machine/pte.h" 15 16 #include "../h/param.h" 17 #include "../h/systm.h" 18 #include "../h/buf.h" 19 #include "../h/conf.h" 20 #include "../h/dir.h" 21 #include "../h/file.h" 22 #include "../h/user.h" 23 #include "../h/map.h" 24 #include "../h/ioctl.h" 25 #include "../h/mtio.h" 26 #include "../h/cmap.h" 27 #include "../h/uio.h" 28 29 #include "../vax/cpu.h" 30 #include "../vaxmba/mbareg.h" 31 #include "../vaxmba/mbavar.h" 32 #include "../vaxmba/htreg.h" 33 34 struct buf rhtbuf[NHT]; 35 struct buf chtbuf[NHT]; 36 37 short httypes[] = 38 { MBDT_TM03, MBDT_TE16, MBDT_TU45, MBDT_TU77, 0 }; 39 struct mba_device *htinfo[NHT]; 40 int htattach(), htslave(), htustart(), htndtint(), htdtint(); 41 struct mba_driver htdriver = 42 { htattach, htslave, htustart, 0, htdtint, htndtint, 43 httypes, "ht", "tu", htinfo }; 44 45 #define MASKREG(r) ((r) & 0xffff) 46 47 /* bits in minor device */ 48 #define TUUNIT(dev) (minor(dev)&03) 49 #define H_NOREWIND 04 50 #define H_1600BPI 08 51 52 #define HTUNIT(dev) (tutoht[TUUNIT(dev)]) 53 54 #define INF (daddr_t)1000000L /* a block number that wont exist */ 55 56 struct tu_softc { 57 char sc_openf; 58 char sc_flags; 59 daddr_t sc_blkno; 60 daddr_t sc_nxrec; 61 u_short sc_erreg; 62 u_short sc_dsreg; 63 short sc_resid; 64 short sc_dens; 65 struct mba_device *sc_mi; 66 int sc_slave; 67 } tu_softc[NTU]; 68 short tutoht[NTU]; 69 70 /* 71 * Bits for sc_flags. 72 */ 73 #define H_WRITTEN 1 /* last operation was a write */ 74 #define H_ERASED 2 /* last write retry was an erase gap */ 75 #define H_REWIND 4 /* last unit start was a rewind */ 76 77 char hter_bits[] = HTER_BITS; 78 char htds_bits[] = HTDS_BITS; 79 80 /*ARGSUSED*/ 81 htattach(mi) 82 struct mba_device *mi; 83 { 84 85 } 86 87 htslave(mi, ms, sn) 88 struct mba_device *mi; 89 struct mba_slave *ms; 90 int sn; 91 { 92 register struct tu_softc *sc = &tu_softc[ms->ms_unit]; 93 register struct htdevice *htaddr = (struct htdevice *)mi->mi_drv; 94 95 htaddr->httc = sn; 96 if (htaddr->htdt & HTDT_SPR) { 97 sc->sc_mi = mi; 98 sc->sc_slave = sn; 99 tutoht[ms->ms_unit] = mi->mi_unit; 100 return (1); 101 } else 102 return (0); 103 } 104 105 htopen(dev, flag) 106 dev_t dev; 107 int flag; 108 { 109 register int tuunit; 110 register struct mba_device *mi; 111 register struct tu_softc *sc; 112 int olddens, dens; 113 114 tuunit = TUUNIT(dev); 115 if (tuunit >= NTU || (sc = &tu_softc[tuunit])->sc_openf || 116 (mi = htinfo[HTUNIT(dev)]) == 0 || mi->mi_alive == 0) 117 return (ENXIO); 118 olddens = sc->sc_dens; 119 dens = sc->sc_dens = 120 ((minor(dev)&H_1600BPI)?HTTC_1600BPI:HTTC_800BPI)| 121 HTTC_PDP11|sc->sc_slave; 122 htcommand(dev, HT_SENSE, 1); 123 sc->sc_dens = olddens; 124 if ((sc->sc_dsreg & HTDS_MOL) == 0) { 125 uprintf("tu%d: not online\n", tuunit); 126 return (EIO); 127 } 128 if ((flag&FWRITE) && (sc->sc_dsreg&HTDS_WRL)) { 129 uprintf("tu%d: no write ring\n", tuunit); 130 return (EIO); 131 } 132 if ((sc->sc_dsreg & HTDS_BOT) == 0 && (flag&FWRITE) && 133 dens != sc->sc_dens) { 134 uprintf("tu%d: can't change density in mid-tape\n", tuunit); 135 return (EIO); 136 } 137 sc->sc_openf = 1; 138 sc->sc_blkno = (daddr_t)0; 139 sc->sc_nxrec = INF; 140 sc->sc_flags = 0; 141 sc->sc_dens = dens; 142 return (0); 143 } 144 145 htclose(dev, flag) 146 register dev_t dev; 147 register flag; 148 { 149 register struct tu_softc *sc = &tu_softc[TUUNIT(dev)]; 150 151 if (flag == FWRITE || ((flag&FWRITE) && (sc->sc_flags&H_WRITTEN))) { 152 htcommand(dev, HT_WEOF, 1); 153 htcommand(dev, HT_WEOF, 1); 154 htcommand(dev, HT_SREV, 1); 155 } 156 if ((minor(dev)&H_NOREWIND) == 0) 157 htcommand(dev, HT_REW, 0); 158 sc->sc_openf = 0; 159 } 160 161 htcommand(dev, com, count) 162 dev_t dev; 163 int com, count; 164 { 165 register struct buf *bp; 166 register int s; 167 168 bp = &chtbuf[HTUNIT(dev)]; 169 s = spl5(); 170 while (bp->b_flags&B_BUSY) { 171 if(bp->b_repcnt == 0 && (bp->b_flags&B_DONE)) 172 break; 173 bp->b_flags |= B_WANTED; 174 sleep((caddr_t)bp, PRIBIO); 175 } 176 bp->b_flags = B_BUSY|B_READ; 177 splx(s); 178 bp->b_dev = dev; 179 bp->b_command = com; 180 bp->b_repcnt = count; 181 bp->b_blkno = 0; 182 htstrategy(bp); 183 if (count == 0) 184 return; 185 iowait(bp); 186 if (bp->b_flags&B_WANTED) 187 wakeup((caddr_t)bp); 188 bp->b_flags &= B_ERROR; 189 } 190 191 htstrategy(bp) 192 register struct buf *bp; 193 { 194 register struct mba_device *mi = htinfo[HTUNIT(bp->b_dev)]; 195 register struct buf *dp; 196 register int s; 197 198 bp->av_forw = NULL; 199 dp = &mi->mi_tab; 200 s = spl5(); 201 if (dp->b_actf == NULL) 202 dp->b_actf = bp; 203 else 204 dp->b_actl->av_forw = bp; 205 dp->b_actl = bp; 206 if (dp->b_active == 0) 207 mbustart(mi); 208 splx(s); 209 } 210 211 htustart(mi) 212 register struct mba_device *mi; 213 { 214 register struct htdevice *htaddr = 215 (struct htdevice *)mi->mi_drv; 216 register struct buf *bp = mi->mi_tab.b_actf; 217 register struct tu_softc *sc = &tu_softc[TUUNIT(bp->b_dev)]; 218 daddr_t blkno; 219 220 htaddr->httc = sc->sc_dens; 221 if (bp == &chtbuf[HTUNIT(bp->b_dev)] && bp->b_command == HT_SENSE) { 222 htaddr->htcs1 = HT_SENSE|HT_GO; 223 mbclrattn(mi); 224 } 225 sc->sc_dsreg = htaddr->htds; 226 sc->sc_erreg = htaddr->hter; 227 sc->sc_resid = htaddr->htfc; 228 sc->sc_flags &= ~(H_WRITTEN|H_REWIND); 229 if ((htaddr->htdt & HTDT_SPR) == 0 || (htaddr->htds & HTDS_MOL) == 0) 230 if (sc->sc_openf > 0) 231 sc->sc_openf = -1; 232 if (sc->sc_openf < 0) { 233 bp->b_flags |= B_ERROR; 234 return (MBU_NEXT); 235 } 236 if (bp != &chtbuf[HTUNIT(bp->b_dev)]) { 237 if (bdbtofsb(bp->b_blkno) > sc->sc_nxrec) { 238 bp->b_flags |= B_ERROR; 239 bp->b_error = ENXIO; 240 return (MBU_NEXT); 241 } 242 if (bdbtofsb(bp->b_blkno) == sc->sc_nxrec && 243 bp->b_flags&B_READ) { 244 bp->b_resid = bp->b_bcount; 245 clrbuf(bp); 246 return (MBU_NEXT); 247 } 248 if ((bp->b_flags&B_READ)==0) 249 sc->sc_nxrec = bdbtofsb(bp->b_blkno) + 1; 250 } else { 251 if (bp->b_command == HT_SENSE) 252 return (MBU_NEXT); 253 if (bp->b_command == HT_REW) 254 sc->sc_flags |= H_REWIND; 255 else 256 htaddr->htfc = -bp->b_bcount; 257 htaddr->htcs1 = bp->b_command|HT_GO; 258 return (MBU_STARTED); 259 } 260 if ((blkno = sc->sc_blkno) == bdbtofsb(bp->b_blkno)) { 261 htaddr->htfc = -bp->b_bcount; 262 if ((bp->b_flags&B_READ) == 0) { 263 if (mi->mi_tab.b_errcnt) { 264 if ((sc->sc_flags & H_ERASED) == 0) { 265 sc->sc_flags |= H_ERASED; 266 htaddr->htcs1 = HT_ERASE | HT_GO; 267 return (MBU_STARTED); 268 } 269 sc->sc_flags &= ~H_ERASED; 270 } 271 if (htaddr->htds & HTDS_EOT) { 272 bp->b_resid = bp->b_bcount; 273 bp->b_flags |= B_ERROR; 274 return (MBU_NEXT); 275 } 276 } 277 return (MBU_DODATA); 278 } 279 if (blkno < bdbtofsb(bp->b_blkno)) { 280 htaddr->htfc = blkno - bdbtofsb(bp->b_blkno); 281 htaddr->htcs1 = HT_SFORW|HT_GO; 282 } else { 283 htaddr->htfc = bdbtofsb(bp->b_blkno) - blkno; 284 htaddr->htcs1 = HT_SREV|HT_GO; 285 } 286 return (MBU_STARTED); 287 } 288 289 htdtint(mi, mbsr) 290 register struct mba_device *mi; 291 int mbsr; 292 { 293 register struct htdevice *htaddr = (struct htdevice *)mi->mi_drv; 294 register struct buf *bp = mi->mi_tab.b_actf; 295 register struct tu_softc *sc; 296 int ds, er, mbs; 297 298 sc = &tu_softc[TUUNIT(bp->b_dev)]; 299 ds = sc->sc_dsreg = MASKREG(htaddr->htds); 300 er = sc->sc_erreg = MASKREG(htaddr->hter); 301 sc->sc_resid = MASKREG(htaddr->htfc); 302 mbs = mbsr; 303 sc->sc_blkno++; 304 if((bp->b_flags & B_READ) == 0) 305 sc->sc_flags |= H_WRITTEN; 306 if ((ds&(HTDS_ERR|HTDS_MOL)) != HTDS_MOL || mbs & MBSR_EBITS) { 307 htaddr->htcs1 = HT_DCLR|HT_GO; 308 mbclrattn(mi); 309 if (bp == &rhtbuf[HTUNIT(bp->b_dev)]) { 310 er &= ~HTER_FCE; 311 mbs &= ~(MBSR_DTABT|MBSR_MBEXC); 312 } 313 if (bp->b_flags & B_READ && ds & HTDS_PES) 314 er &= ~(HTER_CSITM|HTER_CORCRC); 315 if (er&HTER_HARD || mbs&MBSR_EBITS || (ds&HTDS_MOL) == 0 || 316 er && ++mi->mi_tab.b_errcnt >= 7) { 317 if ((ds & HTDS_MOL) == 0 && sc->sc_openf > 0) 318 sc->sc_openf = -1; 319 if ((er&HTER_HARD) == HTER_FCE && 320 (mbs&MBSR_EBITS) == (MBSR_DTABT|MBSR_MBEXC) && 321 (ds&HTDS_MOL)) 322 goto noprint; 323 printf("tu%d: hard error bn%d mbsr=%b er=%b ds=%b\n", 324 TUUNIT(bp->b_dev), bp->b_blkno, 325 mbsr, mbsr_bits, 326 sc->sc_erreg, hter_bits, 327 sc->sc_dsreg, htds_bits); 328 noprint: 329 bp->b_flags |= B_ERROR; 330 return (MBD_DONE); 331 } 332 if (er) 333 return (MBD_RETRY); 334 } 335 bp->b_resid = 0; 336 if (bp->b_flags & B_READ) 337 if (ds&HTDS_TM) { /* must be a read, right? */ 338 bp->b_resid = bp->b_bcount; 339 sc->sc_nxrec = bdbtofsb(bp->b_blkno); 340 } else if(bp->b_bcount > MASKREG(htaddr->htfc)) 341 bp->b_resid = bp->b_bcount - MASKREG(htaddr->htfc); 342 return (MBD_DONE); 343 } 344 345 htndtint(mi) 346 register struct mba_device *mi; 347 { 348 register struct htdevice *htaddr = (struct htdevice *)mi->mi_drv; 349 register struct buf *bp = mi->mi_tab.b_actf; 350 register struct tu_softc *sc; 351 int er, ds, fc; 352 353 ds = MASKREG(htaddr->htds); 354 er = MASKREG(htaddr->hter); 355 fc = MASKREG(htaddr->htfc); 356 if (er) { 357 htaddr->htcs1 = HT_DCLR|HT_GO; 358 mbclrattn(mi); 359 } 360 if (bp == 0) 361 return (MBN_SKIP); 362 sc = &tu_softc[TUUNIT(bp->b_dev)]; 363 sc->sc_dsreg = ds; 364 sc->sc_erreg = er; 365 sc->sc_resid = fc; 366 if (bp == &chtbuf[HTUNIT(bp->b_dev)]) { 367 switch (bp->b_command) { 368 case HT_REWOFFL: 369 /* offline is on purpose; don't do anything special */ 370 ds |= HTDS_MOL; 371 break; 372 case HT_SREV: 373 /* if backspace file hit bot, its not an error */ 374 if (er == (HTER_NEF|HTER_FCE) && ds&HTDS_BOT && 375 bp->b_repcnt == INF) 376 er &= ~HTER_NEF; 377 break; 378 } 379 er &= ~HTER_FCE; 380 if (er == 0) 381 ds &= ~HTDS_ERR; 382 } 383 if ((ds & (HTDS_ERR|HTDS_MOL)) != HTDS_MOL) { 384 if ((ds & HTDS_MOL) == 0 && sc->sc_openf > 0) 385 sc->sc_openf = -1; 386 printf("tu%d: hard error bn%d er=%b ds=%b\n", 387 TUUNIT(bp->b_dev), bp->b_blkno, 388 sc->sc_erreg, hter_bits, sc->sc_dsreg, htds_bits); 389 bp->b_flags |= B_ERROR; 390 return (MBN_DONE); 391 } 392 if (bp == &chtbuf[HTUNIT(bp->b_dev)]) { 393 if (sc->sc_flags & H_REWIND) 394 return (ds & HTDS_BOT ? MBN_DONE : MBN_RETRY); 395 bp->b_resid = -sc->sc_resid; 396 return (MBN_DONE); 397 } 398 if (ds & HTDS_TM) 399 if (sc->sc_blkno > bdbtofsb(bp->b_blkno)) { 400 sc->sc_nxrec = bdbtofsb(bp->b_blkno) - fc; 401 sc->sc_blkno = sc->sc_nxrec; 402 } else { 403 sc->sc_blkno = bdbtofsb(bp->b_blkno) + fc; 404 sc->sc_nxrec = sc->sc_blkno - 1; 405 } 406 else 407 sc->sc_blkno = bdbtofsb(bp->b_blkno); 408 return (MBN_RETRY); 409 } 410 411 htread(dev, uio) 412 dev_t dev; 413 struct uio *uio; 414 { 415 int errno; 416 417 errno = htphys(dev, uio); 418 if (errno) 419 return (errno); 420 return (physio(htstrategy, &rhtbuf[HTUNIT(dev)], dev, B_READ, minphys, uio)); 421 } 422 423 htwrite(dev, uio) 424 dev_t dev; 425 struct uio *uio; 426 { 427 int errno; 428 429 errno = htphys(dev, uio); 430 if (errno) 431 return (errno); 432 return (physio(htstrategy, &rhtbuf[HTUNIT(dev)], dev, B_WRITE, minphys, uio)); 433 } 434 435 htphys(dev, uio) 436 dev_t dev; 437 struct uio *uio; 438 { 439 register int htunit; 440 /*###439 [lint] htphys arg. 2 used inconsistently ht.c(439) :: ht.c(430)%%%*/ 441 register struct tu_softc *sc; 442 register struct mba_device *mi; 443 daddr_t a; 444 445 htunit = HTUNIT(dev); 446 if (htunit >= NHT || (mi = htinfo[htunit]) == 0 || mi->mi_alive == 0) 447 return (ENXIO); 448 a = uio->uio_offset >> 9; 449 sc = &tu_softc[TUUNIT(dev)]; 450 sc->sc_blkno = bdbtofsb(a); 451 sc->sc_nxrec = bdbtofsb(a)+1; 452 return (0); 453 } 454 455 /*ARGSUSED*/ 456 htioctl(dev, cmd, data, flag) 457 dev_t dev; 458 int cmd; 459 caddr_t data; 460 int flag; 461 { 462 register struct tu_softc *sc = &tu_softc[TUUNIT(dev)]; 463 register struct buf *bp = &chtbuf[HTUNIT(dev)]; 464 register callcount; 465 int fcount; 466 struct mtop *mtop; 467 struct mtget *mtget; 468 /* we depend of the values and order of the MT codes here */ 469 static htops[] = 470 {HT_WEOF,HT_SFORW,HT_SREV,HT_SFORW,HT_SREV,HT_REW,HT_REWOFFL,HT_SENSE}; 471 472 switch (cmd) { 473 474 case MTIOCTOP: /* tape operation */ 475 mtop = (struct mtop *)data; 476 switch (mtop->mt_op) { 477 478 case MTWEOF: 479 callcount = mtop->mt_count; 480 fcount = 1; 481 break; 482 483 case MTFSF: case MTBSF: 484 callcount = mtop->mt_count; 485 fcount = INF; 486 break; 487 488 case MTFSR: case MTBSR: 489 callcount = 1; 490 fcount = mtop->mt_count; 491 break; 492 493 case MTREW: case MTOFFL: 494 callcount = 1; 495 fcount = 1; 496 break; 497 498 default: 499 return (ENXIO); 500 } 501 if (callcount <= 0 || fcount <= 0) 502 return (EINVAL); 503 while (--callcount >= 0) { 504 htcommand(dev, htops[mtop->mt_op], fcount); 505 if ((mtop->mt_op == MTFSR || mtop->mt_op == MTBSR) && 506 bp->b_resid) 507 return (EIO); 508 if ((bp->b_flags&B_ERROR) || sc->sc_dsreg&HTDS_BOT) 509 break; 510 } 511 return (geterror(bp)); 512 513 case MTIOCGET: 514 mtget = (struct mtget *)data; 515 mtget->mt_dsreg = sc->sc_dsreg; 516 mtget->mt_erreg = sc->sc_erreg; 517 mtget->mt_resid = sc->sc_resid; 518 mtget->mt_type = MT_ISHT; 519 break; 520 521 default: 522 return (ENXIO); 523 } 524 return (0); 525 } 526 527 #define DBSIZE 20 528 529 htdump() 530 { 531 register struct mba_device *mi; 532 register struct mba_regs *mp; 533 register struct htdevice *htaddr; 534 int blk, num; 535 int start; 536 537 start = 0; 538 num = maxfree; 539 #define phys(a,b) ((b)((int)(a)&0x7fffffff)) 540 if (htinfo[0] == 0) 541 return (ENXIO); 542 mi = phys(htinfo[0], struct mba_device *); 543 mp = phys(mi->mi_hd, struct mba_hd *)->mh_physmba; 544 mp->mba_cr = MBCR_IE; 545 htaddr = (struct htdevice *)&mp->mba_drv[mi->mi_drive]; 546 htaddr->httc = HTTC_PDP11|HTTC_1600BPI; 547 htaddr->htcs1 = HT_DCLR|HT_GO; 548 while (num > 0) { 549 blk = num > DBSIZE ? DBSIZE : num; 550 htdwrite(start, blk, htaddr, mp); 551 start += blk; 552 num -= blk; 553 } 554 hteof(htaddr); 555 hteof(htaddr); 556 htwait(htaddr); 557 if (htaddr->htds&HTDS_ERR) 558 return (EIO); 559 htaddr->htcs1 = HT_REW|HT_GO; 560 return (0); 561 } 562 563 htdwrite(dbuf, num, htaddr, mp) 564 register dbuf, num; 565 register struct htdevice *htaddr; 566 struct mba_regs *mp; 567 { 568 register struct pte *io; 569 register int i; 570 571 htwait(htaddr); 572 io = mp->mba_map; 573 for (i = 0; i < num; i++) 574 *(int *)io++ = dbuf++ | PG_V; 575 htaddr->htfc = -(num*NBPG); 576 mp->mba_sr = -1; 577 mp->mba_bcr = -(num*NBPG); 578 mp->mba_var = 0; 579 htaddr->htcs1 = HT_WCOM|HT_GO; 580 } 581 582 htwait(htaddr) 583 struct htdevice *htaddr; 584 { 585 register s; 586 587 do 588 s = htaddr->htds; 589 while ((s & HTDS_DRY) == 0); 590 } 591 592 hteof(htaddr) 593 struct htdevice *htaddr; 594 { 595 596 htwait(htaddr); 597 htaddr->htcs1 = HT_WEOF|HT_GO; 598 } 599 #endif 600