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