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