1 /* mt.c 4.14 82/10/20 */ 2 3 #include "mu.h" 4 #if NMT > 0 5 /* 6 * TM78/TU78 tape driver 7 * 8 * Behavior in complex error situations is uncertain... 9 * 10 * TODO: 11 * test error recovery 12 * add odd byte count kludge from VMS driver 13 * write dump routine 14 */ 15 #include "../h/param.h" 16 #include "../h/systm.h" 17 #include "../h/buf.h" 18 #include "../h/conf.h" 19 #include "../h/dir.h" 20 #include "../h/file.h" 21 #include "../h/user.h" 22 #include "../h/map.h" 23 #include "../h/pte.h" 24 #include "../h/ioctl.h" 25 #include "../h/mtio.h" 26 #include "../h/cmap.h" 27 #include "../h/uio.h" 28 29 #include "../vax/cpu.h" 30 #include "../vaxmba/mbareg.h" 31 #include "../vaxmba/mbavar.h" 32 #include "../vaxmba/mtreg.h" 33 34 struct buf rmtbuf[NMT]; 35 struct buf cmtbuf[NMT]; 36 37 short mttypes[] = 38 { MBDT_TU78, 0 }; 39 struct mba_device *mtinfo[NMT]; 40 int mtattach(), mtslave(), mtustart(), mtstart(), mtndtint(), mtdtint(); 41 struct mba_driver mtdriver = 42 { mtattach, mtslave, mtustart, mtstart, mtdtint, mtndtint, 43 mttypes, "mt", "mu", mtinfo }; 44 45 #define MASKREG(r) ((r) & 0xffff) 46 47 /* bits in minor device */ 48 #define MUUNIT(dev) (minor(dev)&03) 49 #define H_NOREWIND 04 50 #define H_6250BPI 08 51 52 #define MTUNIT(dev) (mutomt[MUUNIT(dev)]) 53 54 #define INF (daddr_t)1000000L /* a block number that wont exist */ 55 56 struct mu_softc { 57 char sc_openf; 58 char sc_flags; 59 daddr_t sc_blkno; 60 daddr_t sc_nxrec; 61 u_short sc_erreg; 62 u_short sc_dsreg; 63 short sc_resid; 64 short sc_dens; 65 struct mba_device *sc_mi; 66 int sc_slave; 67 } mu_softc[NMU]; 68 short mutomt[NMU]; 69 70 /* 71 * Bits for sc_flags. 72 */ 73 #define H_WRITTEN 1 /* last operation was a write */ 74 75 char mtds_bits[] = MTDS_BITS; 76 77 /*ARGSUSED*/ 78 mtattach(mi) 79 struct mba_device *mi; 80 { 81 82 } 83 84 mtslave(mi, ms, sn) 85 struct mba_device *mi; 86 struct mba_slave *ms; 87 int sn; 88 { 89 register struct mu_softc *sc = &mu_softc[ms->ms_unit]; 90 register struct mtdevice *mtaddr = (struct mtdevice *)mi->mi_drv; 91 int s = spl7(), rtn = 0; 92 93 mtaddr->mtas = -1; 94 mtaddr->mtncs[sn] = MT_SENSE|MT_GO; 95 while (mtaddr->mtas == 0) 96 ; 97 if ((mtaddr->mtner & MTER_INTCODE) == MTER_DONE && 98 (mtaddr->mtds & MTDS_PRES)) { 99 sc->sc_mi = mi; 100 sc->sc_slave = sn; 101 mutomt[ms->ms_unit] = mi->mi_unit; 102 rtn = 1; 103 } 104 mtaddr->mtas = mtaddr->mtas; 105 splx(s); 106 return (rtn); 107 } 108 109 mtopen(dev, flag) 110 dev_t dev; 111 int flag; 112 { 113 register int muunit; 114 register struct mba_device *mi; 115 register struct mu_softc *sc; 116 int olddens, dens; 117 118 muunit = MUUNIT(dev); 119 if (muunit >= NMU || (sc = &mu_softc[muunit])->sc_openf || 120 (mi = mtinfo[MTUNIT(dev)]) == 0 || mi->mi_alive == 0) 121 return (ENXIO); 122 olddens = sc->sc_dens; 123 dens = sc->sc_dens = (minor(dev)&H_6250BPI) ? MT_GCR : 0; 124 mtcommand(dev, MT_SENSE, 1); 125 sc->sc_dens = olddens; 126 if ((sc->sc_dsreg & MTDS_ONL) == 0) { 127 uprintf("mu%d: not online\n", muunit); 128 return (EIO); 129 } 130 if ((flag&FWRITE) && (sc->sc_dsreg&MTDS_FPT)) { 131 uprintf("mu%d: no write ring\n", muunit); 132 return (EIO); 133 } 134 if ((sc->sc_dsreg & MTDS_BOT) == 0 && (flag&FWRITE) && 135 dens != sc->sc_dens) { 136 uprintf("mu%d: can't change density in mid-tape\n", muunit); 137 return (EIO); 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 return (0); 145 } 146 147 mtclose(dev, flag) 148 register dev_t dev; 149 register flag; 150 { 151 register struct mu_softc *sc = &mu_softc[MUUNIT(dev)]; 152 153 if (flag == FWRITE || ((flag&FWRITE) && (sc->sc_flags&H_WRITTEN))) 154 mtcommand(dev, MT_CLS|sc->sc_dens, 1); 155 if ((minor(dev)&H_NOREWIND) == 0) 156 mtcommand(dev, MT_REW, 0); 157 sc->sc_openf = 0; 158 } 159 160 mtcommand(dev, com, count) 161 dev_t dev; 162 int com, count; 163 { 164 register struct buf *bp; 165 register int s; 166 167 bp = &cmtbuf[MTUNIT(dev)]; 168 s = spl5(); 169 while (bp->b_flags&B_BUSY) { 170 if(bp->b_repcnt == 0 && (bp->b_flags&B_DONE)) 171 break; 172 bp->b_flags |= B_WANTED; 173 sleep((caddr_t)bp, PRIBIO); 174 } 175 bp->b_flags = B_BUSY|B_READ; 176 splx(s); 177 bp->b_dev = dev; 178 bp->b_command = com; 179 bp->b_repcnt = count; 180 bp->b_blkno = 0; 181 mtstrategy(bp); 182 if (count == 0) 183 return; 184 iowait(bp); 185 if (bp->b_flags&B_WANTED) 186 wakeup((caddr_t)bp); 187 bp->b_flags &= B_ERROR; 188 } 189 190 mtstrategy(bp) 191 register struct buf *bp; 192 { 193 register struct mba_device *mi = mtinfo[MTUNIT(bp->b_dev)]; 194 register struct buf *dp; 195 register int s; 196 197 bp->av_forw = NULL; 198 dp = &mi->mi_tab; 199 s = spl5(); 200 if (dp->b_actf == NULL) 201 dp->b_actf = bp; 202 else 203 dp->b_actl->av_forw = bp; 204 dp->b_actl = bp; 205 if (dp->b_active == 0) 206 mbustart(mi); 207 splx(s); 208 } 209 210 mtustart(mi) 211 register struct mba_device *mi; 212 { 213 register struct mtdevice *mtaddr = 214 (struct mtdevice *)mi->mi_drv; 215 register struct buf *bp = mi->mi_tab.b_actf; 216 register struct mu_softc *sc = &mu_softc[MUUNIT(bp->b_dev)]; 217 daddr_t blkno; 218 219 sc->sc_flags &= ~H_WRITTEN; 220 if (sc->sc_openf < 0) { 221 bp->b_flags |= B_ERROR; 222 return (MBU_NEXT); 223 } 224 if (bp != &cmtbuf[MTUNIT(bp->b_dev)]) { 225 if (bdbtofsb(bp->b_blkno) > sc->sc_nxrec) { 226 bp->b_flags |= B_ERROR; 227 bp->b_error = ENXIO; 228 return (MBU_NEXT); 229 } 230 if (bdbtofsb(bp->b_blkno) == sc->sc_nxrec && 231 bp->b_flags&B_READ) { 232 bp->b_resid = bp->b_bcount; 233 clrbuf(bp); 234 return (MBU_NEXT); 235 } 236 if ((bp->b_flags&B_READ)==0) 237 sc->sc_nxrec = bdbtofsb(bp->b_blkno) + 1; 238 } else { 239 mtaddr->mtncs[MUUNIT(bp->b_dev)] = 240 (bp->b_repcnt<<8)|bp->b_command|MT_GO; 241 return (MBU_STARTED); 242 } 243 if ((blkno = sc->sc_blkno) == bdbtofsb(bp->b_blkno)) { 244 if (mi->mi_tab.b_errcnt == 2) { 245 mtaddr->mtca = MUUNIT(bp->b_dev); 246 } else { 247 mtaddr->mtbc = bp->b_bcount; 248 mtaddr->mtca = (1<<2)|MUUNIT(bp->b_dev); 249 } 250 return (MBU_DODATA); 251 } 252 if (blkno < bdbtofsb(bp->b_blkno)) 253 mtaddr->mtncs[MUUNIT(bp->b_dev)] = 254 (min((unsigned)(bdbtofsb(bp->b_blkno) - blkno), 0377) << 8) | 255 MT_SFORW|MT_GO; 256 else 257 mtaddr->mtncs[MUUNIT(bp->b_dev)] = 258 (min((unsigned)(blkno - bdbtofsb(bp->b_blkno)), 0377) << 8) | 259 MT_SREV|MT_GO; 260 return (MBU_STARTED); 261 } 262 263 mtstart(mi) 264 register struct mba_device *mi; 265 { 266 register struct buf *bp = mi->mi_tab.b_actf; 267 register struct mu_softc *sc = &mu_softc[MUUNIT(bp->b_dev)]; 268 269 if (bp->b_flags & B_READ) 270 if (mi->mi_tab.b_errcnt == 2) 271 return(MT_READREV|MT_GO); 272 else 273 return(MT_READ|MT_GO); 274 else 275 return(MT_WRITE|sc->sc_dens|MT_GO); 276 } 277 278 mtdtint(mi, mbsr) 279 register struct mba_device *mi; 280 int mbsr; 281 { 282 register struct mtdevice *mtaddr = (struct mtdevice *)mi->mi_drv; 283 register struct buf *bp = mi->mi_tab.b_actf; 284 register struct mu_softc *sc; 285 286 /* I'M NOT SURE IF THIS SHOULD ALWAYS BE THE CASE SO FOR NOW... */ 287 if ((mtaddr->mtca&3) != MUUNIT(bp->b_dev)) { 288 printf("mt: wrong unit!\n"); 289 mtaddr->mtca = MUUNIT(bp->b_dev); 290 } 291 sc = &mu_softc[MUUNIT(bp->b_dev)]; 292 sc->sc_erreg = mtaddr->mter; 293 if((bp->b_flags & B_READ) == 0) 294 sc->sc_flags |= H_WRITTEN; 295 switch (sc->sc_erreg & MTER_INTCODE) { 296 case MTER_DONE: 297 case MTER_LONGREC: 298 if (mi->mi_tab.b_errcnt != 2) 299 sc->sc_blkno++; 300 bp->b_resid = 0; 301 break; 302 303 case MTER_NOTCAP: 304 printf("mu%d: blank tape\n", MUUNIT(bp->b_dev)); 305 goto err; 306 307 case MTER_TM: 308 case MTER_EOT: 309 sc->sc_blkno++; 310 err: 311 bp->b_resid = bp->b_bcount; 312 sc->sc_nxrec = bdbtofsb(bp->b_blkno); 313 break; 314 315 case MTER_SHRTREC: 316 sc->sc_blkno++; 317 if (bp != &rmtbuf[MTUNIT(bp->b_dev)]) 318 bp->b_flags |= B_ERROR; 319 if (mi->mi_tab.b_errcnt == 2) 320 bp->b_bcount = bp->b_resid; /* restore saved value */ 321 bp->b_resid = bp->b_bcount - mtaddr->mtbc; 322 break; 323 324 case MTER_RDOPP: 325 mi->mi_tab.b_errcnt = 2; /* indicate "read opposite" */ 326 bp->b_resid = bp->b_bcount; /* save it */ 327 bp->b_bcount = mtaddr->mtbc; /* use this instead */ 328 return(MBD_RETRY); 329 330 case MTER_RETRY: 331 mi->mi_tab.b_errcnt = 1; /* indicate simple retry */ 332 return(MBD_RETRY); 333 334 case MTER_OFFLINE: 335 if (sc->sc_openf > 0) { 336 sc->sc_openf = -1; 337 printf("mu%d: offline\n", MUUNIT(bp->b_dev)); 338 } 339 bp->b_flags |= B_ERROR; 340 break; 341 342 case MTER_FPT: 343 printf("mu%d: no write ring\n", MUUNIT(bp->b_dev)); 344 bp->b_flags |= B_ERROR; 345 break; 346 347 default: 348 printf("mu%d: hard error bn%d mbsr=%b er=%x ds=%b\n", 349 MUUNIT(bp->b_dev), bp->b_blkno, 350 mbsr, mbsr_bits, sc->sc_erreg, 351 sc->sc_dsreg, mtds_bits); 352 bp->b_flags |= B_ERROR; 353 mtaddr->mtid = MTID_CLR; /* reset the TM78 */ 354 DELAY(250); 355 while ((mtaddr->mtid & MTID_RDY) == 0) /* wait for it */ 356 ; 357 return (MBD_DONE); 358 } 359 /* CHECK FOR MBA ERROR WHEN NO OTHER ERROR INDICATED? */ 360 return (MBD_DONE); 361 } 362 363 mtndtint(mi) 364 register struct mba_device *mi; 365 { 366 register struct mtdevice *mtaddr = (struct mtdevice *)mi->mi_drv; 367 register struct buf *bp = mi->mi_tab.b_actf; 368 register struct mu_softc *sc; 369 int er, fc, unit; 370 371 unit = (mtaddr->mtner >> 8) & 3; 372 er = MASKREG(mtaddr->mtner); 373 /* WILL THIS OCCUR IF ANOTHER DRIVE COMES ONLINE? */ 374 if (bp == 0 || unit != MUUNIT(bp->b_dev)) { /* consistency check */ 375 if ((er & MTER_INTCODE) != MTER_ONLINE) 376 printf("mt: unit %d random interrupt\n", unit); 377 return (MBN_SKIP); 378 } 379 if (bp == 0) 380 return (MBN_SKIP); 381 fc = (mtaddr->mtncs[unit] >> 8) & 0xff; 382 sc = &mu_softc[unit]; 383 sc->sc_erreg = er; 384 sc->sc_resid = fc; 385 switch (er & MTER_INTCODE) { 386 case MTER_DONE: 387 if (bp == &cmtbuf[MTUNIT(bp->b_dev)]) { 388 done: 389 if (bp->b_command == MT_SENSE) 390 sc->sc_dsreg = MASKREG(mtaddr->mtds); 391 bp->b_resid = fc; 392 return (MBN_DONE); 393 } 394 /* this is UGLY! (but is it correct?) */ 395 if ((fc = bdbtofsb(bp->b_blkno) - sc->sc_blkno) < 0) 396 sc->sc_blkno -= MIN(0377, -fc); 397 else 398 sc->sc_blkno += MIN(0377, fc); 399 return (MBN_RETRY); 400 401 case MTER_RWDING: 402 return (MBN_SKIP); /* ignore "rewind started" interrupt */ 403 404 case MTER_NOTCAP: 405 printf("mu%d: blank tape\n", MUUNIT(bp->b_dev)); 406 407 case MTER_TM: 408 case MTER_EOT: 409 case MTER_LEOT: 410 if (sc->sc_blkno > bdbtofsb(bp->b_blkno)) { 411 sc->sc_nxrec = bdbtofsb(bp->b_blkno) + fc; 412 sc->sc_blkno = sc->sc_nxrec; 413 } else { 414 sc->sc_blkno = bdbtofsb(bp->b_blkno) - fc; 415 sc->sc_nxrec = sc->sc_blkno - 1; 416 } 417 return (MBN_RETRY); 418 419 case MTER_FPT: 420 printf("mu%d: no write ring\n", MUUNIT(bp->b_dev)); 421 bp->b_flags |= B_ERROR; 422 return (MBN_DONE); 423 424 case MTER_OFFLINE: 425 if (sc->sc_openf > 0) { 426 sc->sc_openf = -1; 427 printf("mu%d: offline\n", MUUNIT(bp->b_dev)); 428 } 429 bp->b_flags |= B_ERROR; 430 return (MBN_DONE); 431 432 case MTER_BOT: 433 if (bp == &cmtbuf[MTUNIT(bp->b_dev)]) 434 goto done; 435 /* FALL THROUGH */ 436 437 default: 438 printf("mu%d: hard error bn%d er=%o ds=%b\n", 439 MUUNIT(bp->b_dev), bp->b_blkno, 440 sc->sc_erreg, sc->sc_dsreg, mtds_bits); 441 mtaddr->mtid = MTID_CLR; /* reset the TM78 */ 442 DELAY(250); 443 while ((mtaddr->mtid & MTID_RDY) == 0) /* wait for it */ 444 ; 445 bp->b_flags |= B_ERROR; 446 return (MBN_DONE); 447 } 448 /* NOTREACHED */ 449 } 450 451 mtread(dev, uio) 452 dev_t dev; 453 struct uio *uio; 454 { 455 int errno; 456 457 errno = mtphys(dev, uio); 458 if (errno) 459 return (errno); 460 return (physio(mtstrategy, &rmtbuf[MTUNIT(dev)], dev, B_READ, minphys, uio)); 461 } 462 463 mtwrite(dev, uio) 464 dev_t dev; 465 struct uio *uio; 466 { 467 int errno; 468 469 errno = mtphys(dev, uio); 470 if (errno) 471 return (errno); 472 return (physio(mtstrategy, &rmtbuf[MTUNIT(dev)], dev, B_WRITE, minphys, uio)); 473 } 474 475 mtphys(dev, uio) 476 dev_t dev; 477 struct uio *uio; 478 { 479 register int mtunit; 480 register struct mu_softc *sc; 481 register struct mba_device *mi; 482 daddr_t a; 483 484 mtunit = MTUNIT(dev); 485 if (mtunit >= NMT || (mi = mtinfo[mtunit]) == 0 || mi->mi_alive == 0) 486 return (ENXIO); 487 a = uio->uio_offset >> 9; 488 sc = &mu_softc[MUUNIT(dev)]; 489 sc->sc_blkno = bdbtofsb(a); 490 sc->sc_nxrec = bdbtofsb(a)+1; 491 return (0); 492 } 493 494 /*ARGSUSED*/ 495 mtioctl(dev, cmd, data, flag) 496 dev_t dev; 497 int cmd; 498 caddr_t data; 499 int flag; 500 { 501 register struct mu_softc *sc = &mu_softc[MUUNIT(dev)]; 502 register struct buf *bp = &cmtbuf[MTUNIT(dev)]; 503 register callcount; 504 register int op; 505 int fcount; 506 struct mtop *mtop; 507 struct mtget *mtget; 508 /* we depend of the values and order of the MT codes here */ 509 static mtops[] = 510 {MT_WTM,MT_SFORWF,MT_SREVF,MT_SFORW,MT_SREV,MT_REW,MT_UNLOAD,MT_SENSE}; 511 512 switch (cmd) { 513 514 case MTIOCTOP: /* tape operation */ 515 mtop = (struct mtop *)data; 516 switch (mtop->mt_op) { 517 518 case MTWEOF: 519 callcount = mtop->mt_count; 520 fcount = 1; 521 break; 522 523 case MTFSF: case MTBSF: 524 callcount = mtop->mt_count; 525 fcount = 1; 526 break; 527 528 case MTFSR: case MTBSR: 529 callcount = 1; 530 fcount = mtop->mt_count; 531 break; 532 533 case MTREW: case MTOFFL: 534 callcount = 1; 535 fcount = 1; 536 break; 537 538 default: 539 return (ENXIO); 540 } 541 if (callcount <= 0 || fcount <= 0) 542 return (EINVAL); 543 op = mtops[mtop->mt_op]; 544 if (op == MT_WTM) 545 op |= sc->sc_dens; 546 while (--callcount >= 0) { 547 register int n; 548 549 do { 550 n = MIN(fcount, 0xff); 551 mtcommand(dev, op, n); 552 fcount -= n; 553 } while (fcount); 554 if ((mtop->mt_op == MTFSR || mtop->mt_op == MTBSR) && 555 bp->b_resid) 556 return (EIO); 557 if (bp->b_flags&B_ERROR) 558 break; 559 } 560 return (geterror(bp)); 561 562 case MTIOCGET: 563 mtget = (struct mtget *)data; 564 mtget->mt_erreg = sc->sc_erreg; 565 mtget->mt_resid = sc->sc_resid; 566 mtcommand(dev, MT_SENSE, 1); /* update drive status */ 567 mtget->mt_dsreg = sc->sc_dsreg; 568 mtget->mt_type = MT_ISMT; 569 break; 570 571 default: 572 return (ENXIO); 573 } 574 return (0); 575 } 576 577 #define DBSIZE 20 578 579 mtdump() 580 { 581 register struct mba_device *mi; 582 register struct mba_regs *mp; 583 int blk, num; 584 int start; 585 586 start = 0; 587 num = maxfree; 588 #define phys(a,b) ((b)((int)(a)&0x7fffffff)) 589 if (mtinfo[0] == 0) 590 return (ENXIO); 591 mi = phys(mtinfo[0], struct mba_device *); 592 mp = phys(mi->mi_hd, struct mba_hd *)->mh_physmba; 593 mp->mba_cr = MBCR_IE; 594 #if lint 595 blk = 0; num = blk; start = num; blk = start; 596 return (0); 597 #endif 598 #ifdef notyet 599 mtaddr = (struct mtdevice *)&mp->mba_drv[mi->mi_drive]; 600 mtaddr->mttc = MTTC_PDP11|MTTC_1600BPI; 601 mtaddr->mtcs1 = MT_DCLR|MT_GO; 602 while (num > 0) { 603 blk = num > DBSIZE ? DBSIZE : num; 604 mtdwrite(start, blk, mtaddr, mp); 605 start += blk; 606 num -= blk; 607 } 608 mteof(mtaddr); 609 mteof(mtaddr); 610 mtwait(mtaddr); 611 if (mtaddr->mtds&MTDS_ERR) 612 return (EIO); 613 mtaddr->mtcs1 = MT_REW|MT_GO; 614 return (0); 615 } 616 617 mtdwrite(dbuf, num, mtaddr, mp) 618 register dbuf, num; 619 register struct mtdevice *mtaddr; 620 struct mba_regs *mp; 621 { 622 register struct pte *io; 623 register int i; 624 625 mtwait(mtaddr); 626 io = mp->mba_map; 627 for (i = 0; i < num; i++) 628 *(int *)io++ = dbuf++ | PG_V; 629 mtaddr->mtfc = -(num*NBPG); 630 mp->mba_sr = -1; 631 mp->mba_bcr = -(num*NBPG); 632 mp->mba_var = 0; 633 mtaddr->mtcs1 = MT_WCOM|MT_GO; 634 } 635 636 mtwait(mtaddr) 637 struct mtdevice *mtaddr; 638 { 639 register s; 640 641 do 642 s = mtaddr->mtds; 643 while ((s & MTDS_DRY) == 0); 644 } 645 646 mteof(mtaddr) 647 struct mtdevice *mtaddr; 648 { 649 650 mtwait(mtaddr); 651 mtaddr->mtcs1 = MT_WEOF|MT_GO; 652 #endif notyet 653 } 654 #endif 655