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