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