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