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