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