1 /* mt.c 4.2 82/01/17 */ 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 81 } 82 83 mtslave(mi, ms) 84 struct mba_device *mi; 85 struct mba_slave *ms; 86 { 87 register struct mu_softc *sc = &mu_softc[ms->ms_unit]; 88 register struct mtdevice *mtaddr = (struct mtdevice *)mi->mi_drv; 89 int s = spl7(), rtn = 0; 90 91 mtaddr->mtas = -1; 92 mtaddr->mtncs[ms->ms_slave] = MT_SENSE|MT_GO; 93 while (mtaddr->mtas == 0) 94 ; 95 if ((mtaddr->mtner & MTER_INTCODE) == MTER_DONE && 96 (mtaddr->mtds & MTDS_PRES)) { 97 sc->sc_mi = mi; 98 sc->sc_slave = ms->ms_slave; 99 mutomt[ms->ms_unit] = mi->mi_unit; 100 rtn = 1; 101 } 102 mtaddr->mtas = mtaddr->mtas; 103 splx(s); 104 return (rtn); 105 } 106 107 mtopen(dev, flag) 108 dev_t dev; 109 int flag; 110 { 111 register int muunit; 112 register struct mba_device *mi; 113 register struct mu_softc *sc; 114 int olddens, dens; 115 116 muunit = MUUNIT(dev); 117 if (muunit >= NMU || (sc = &mu_softc[muunit])->sc_openf || 118 (mi = mtinfo[MTUNIT(dev)]) == 0 || mi->mi_alive == 0) { 119 u.u_error = ENXIO; 120 return; 121 } 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 u.u_error = EIO; 129 return; 130 } 131 if ((flag&FWRITE) && (sc->sc_dsreg&MTDS_FPT)) { 132 uprintf("mu%d: no write ring\n", muunit); 133 u.u_error = EIO; 134 return; 135 } 136 if ((sc->sc_dsreg & MTDS_BOT) == 0 && (flag&FWRITE) && 137 dens != sc->sc_dens) { 138 uprintf("mu%d: can't change density in mid-tape\n", muunit); 139 u.u_error = EIO; 140 return; 141 } 142 sc->sc_openf = 1; 143 sc->sc_blkno = (daddr_t)0; 144 sc->sc_nxrec = INF; 145 sc->sc_flags = 0; 146 sc->sc_dens = dens; 147 } 148 149 mtclose(dev, flag) 150 register dev_t dev; 151 register flag; 152 { 153 register struct mu_softc *sc = &mu_softc[MUUNIT(dev)]; 154 155 if (flag == FWRITE || ((flag&FWRITE) && (sc->sc_flags&H_WRITTEN))) 156 mtcommand(dev, MT_CLS|sc->sc_dens, 1); 157 if ((minor(dev)&H_NOREWIND) == 0) 158 mtcommand(dev, MT_REW, 0); 159 sc->sc_openf = 0; 160 } 161 162 mtcommand(dev, com, count) 163 dev_t dev; 164 int com, count; 165 { 166 register struct buf *bp; 167 register int s; 168 169 bp = &cmtbuf[MTUNIT(dev)]; 170 s = spl5(); 171 while (bp->b_flags&B_BUSY) { 172 if(bp->b_repcnt == 0 && (bp->b_flags&B_DONE)) 173 break; 174 bp->b_flags |= B_WANTED; 175 sleep((caddr_t)bp, PRIBIO); 176 } 177 bp->b_flags = B_BUSY|B_READ; 178 splx(s); 179 bp->b_dev = dev; 180 bp->b_command = com; 181 bp->b_repcnt = count; 182 bp->b_blkno = 0; 183 mtstrategy(bp); 184 if (count == 0) 185 return; 186 iowait(bp); 187 if (bp->b_flags&B_WANTED) 188 wakeup((caddr_t)bp); 189 bp->b_flags &= B_ERROR; 190 } 191 192 mtstrategy(bp) 193 register struct buf *bp; 194 { 195 register struct mba_device *mi = mtinfo[MTUNIT(bp->b_dev)]; 196 register struct buf *dp; 197 register int s; 198 199 bp->av_forw = NULL; 200 dp = &mi->mi_tab; 201 s = spl5(); 202 if (dp->b_actf == NULL) 203 dp->b_actf = bp; 204 else 205 dp->b_actl->av_forw = bp; 206 dp->b_actl = bp; 207 if (dp->b_active == 0) 208 mbustart(mi); 209 splx(s); 210 } 211 212 mtustart(mi) 213 register struct mba_device *mi; 214 { 215 register struct mtdevice *mtaddr = 216 (struct mtdevice *)mi->mi_drv; 217 register struct buf *bp = mi->mi_tab.b_actf; 218 register struct mu_softc *sc = &mu_softc[MUUNIT(bp->b_dev)]; 219 daddr_t blkno; 220 221 sc->sc_flags &= ~H_WRITTEN; 222 if (sc->sc_openf < 0) { 223 bp->b_flags |= B_ERROR; 224 return (MBU_NEXT); 225 } 226 if (bp != &cmtbuf[MTUNIT(bp->b_dev)]) { 227 if (dbtofsb(bp->b_blkno) > sc->sc_nxrec) { 228 bp->b_flags |= B_ERROR; 229 bp->b_error = ENXIO; 230 return (MBU_NEXT); 231 } 232 if (dbtofsb(bp->b_blkno) == sc->sc_nxrec && 233 bp->b_flags&B_READ) { 234 bp->b_resid = bp->b_bcount; 235 clrbuf(bp); 236 return (MBU_NEXT); 237 } 238 if ((bp->b_flags&B_READ)==0) 239 sc->sc_nxrec = dbtofsb(bp->b_blkno) + 1; 240 } else { 241 mtaddr->mtncs[MUUNIT(bp->b_dev)] = 242 (bp->b_repcnt<<8)|bp->b_command|MT_GO; 243 return (MBU_STARTED); 244 } 245 if ((blkno = sc->sc_blkno) == dbtofsb(bp->b_blkno)) { 246 if (mi->mi_tab.b_errcnt == 2) { 247 mtaddr->mtca = MUUNIT(bp->b_dev); 248 } else { 249 mtaddr->mtbc = bp->b_bcount; 250 mtaddr->mtca = (1<<2)|MUUNIT(bp->b_dev); 251 } 252 return (MBU_DODATA); 253 } 254 if (blkno < dbtofsb(bp->b_blkno)) 255 mtaddr->mtncs[MUUNIT(bp->b_dev)] = 256 (min(dbtofsb(bp->b_blkno) - blkno, 0377)<<8)| MT_SFORW|MT_GO; 257 else 258 mtaddr->mtncs[MUUNIT(bp->b_dev)] = 259 (min(blkno - dbtofsb(bp->b_blkno), 0377)<<8)| 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 = dbtofsb(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 = dbtofsb(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 > dbtofsb(bp->b_blkno)) { 411 sc->sc_nxrec = dbtofsb(bp->b_blkno) + fc; 412 sc->sc_blkno = sc->sc_nxrec; 413 } else { 414 sc->sc_blkno = dbtofsb(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) 452 dev_t dev; 453 { 454 455 mtphys(dev); 456 if (u.u_error) 457 return; 458 physio(mtstrategy, &rmtbuf[MTUNIT(dev)], dev, B_READ, minphys); 459 } 460 461 mtwrite(dev) 462 { 463 464 mtphys(dev); 465 if (u.u_error) 466 return; 467 physio(mtstrategy, &rmtbuf[MTUNIT(dev)], dev, B_WRITE, minphys); 468 } 469 470 mtphys(dev) 471 dev_t dev; 472 { 473 register int mtunit; 474 register struct mu_softc *sc; 475 register struct mba_device *mi; 476 daddr_t a; 477 478 mtunit = MTUNIT(dev); 479 if (mtunit >= NMT || (mi = mtinfo[mtunit]) == 0 || mi->mi_alive == 0) { 480 u.u_error = ENXIO; 481 return; 482 } 483 a = u.u_offset >> 9; 484 sc = &mu_softc[MUUNIT(dev)]; 485 sc->sc_blkno = dbtofsb(a); 486 sc->sc_nxrec = dbtofsb(a)+1; 487 } 488 489 /*ARGSUSED*/ 490 mtioctl(dev, cmd, addr, flag) 491 dev_t dev; 492 int cmd; 493 caddr_t addr; 494 int flag; 495 { 496 register struct mu_softc *sc = &mu_softc[MUUNIT(dev)]; 497 register struct buf *bp = &cmtbuf[MTUNIT(dev)]; 498 register callcount; 499 register int n, op; 500 int fcount; 501 struct mtop mtop; 502 struct mtget mtget; 503 /* we depend of the values and order of the MT codes here */ 504 static mtops[] = 505 {MT_WTM,MT_SFORWF,MT_SREVF,MT_SFORW,MT_SREV,MT_REW,MT_UNLOAD,MT_SENSE}; 506 507 switch (cmd) { 508 case MTIOCTOP: /* tape operation */ 509 if (copyin((caddr_t)addr, (caddr_t)&mtop, sizeof(mtop))) { 510 u.u_error = EFAULT; 511 return; 512 } 513 switch(mtop.mt_op) { 514 case MTWEOF: 515 callcount = mtop.mt_count; 516 fcount = 1; 517 break; 518 case MTFSF: case MTBSF: 519 callcount = mtop.mt_count; 520 fcount = 1; 521 break; 522 case MTFSR: case MTBSR: 523 callcount = 1; 524 fcount = mtop.mt_count; 525 break; 526 case MTREW: case MTOFFL: 527 callcount = 1; 528 fcount = 1; 529 break; 530 default: 531 u.u_error = ENXIO; 532 return; 533 } 534 if (callcount <= 0 || fcount <= 0) { 535 u.u_error = ENXIO; 536 return; 537 } 538 op = mtops[mtop.mt_op]; 539 if (op == MT_WTM) 540 op |= sc->sc_dens; 541 while (--callcount >= 0) { 542 register int n; 543 544 do { 545 n = min(fcount, 0xff); 546 mtcommand(dev, op, n); 547 fcount -= n; 548 } while (fcount); 549 if ((mtop.mt_op == MTFSR || mtop.mt_op == MTBSR) && 550 bp->b_resid) { 551 u.u_error = EIO; 552 break; 553 } 554 if (bp->b_flags&B_ERROR) 555 break; 556 } 557 geterror(bp); 558 return; 559 case MTIOCGET: 560 mtget.mt_erreg = sc->sc_erreg; 561 mtget.mt_resid = sc->sc_resid; 562 mtcommand(dev, MT_SENSE, 1); /* update drive status */ 563 mtget.mt_dsreg = sc->sc_dsreg; 564 mtget.mt_type = MT_ISMT; 565 if (copyout((caddr_t)&mtget, addr, sizeof(mtget))) 566 u.u_error = EFAULT; 567 return; 568 default: 569 u.u_error = ENXIO; 570 } 571 } 572 573 #define DBSIZE 20 574 575 mtdump() 576 { 577 register struct mba_device *mi; 578 register struct mba_regs *mp; 579 register struct mtdevice *mtaddr; 580 int blk, num; 581 int start; 582 583 start = 0; 584 num = maxfree; 585 #define phys(a,b) ((b)((int)(a)&0x7fffffff)) 586 if (mtinfo[0] == 0) 587 return (ENXIO); 588 mi = phys(mtinfo[0], struct mba_device *); 589 mp = phys(mi->mi_hd, struct mba_hd *)->mh_physmba; 590 mp->mba_cr = MBCR_IE; 591 mtaddr = (struct mtdevice *)&mp->mba_drv[mi->mi_drive]; 592 #ifdef notyet 593 mtaddr->mttc = MTTC_PDP11|MTTC_1600BPI; 594 mtaddr->mtcs1 = MT_DCLR|MT_GO; 595 while (num > 0) { 596 blk = num > DBSIZE ? DBSIZE : num; 597 mtdwrite(start, blk, mtaddr, mp); 598 start += blk; 599 num -= blk; 600 } 601 mteof(mtaddr); 602 mteof(mtaddr); 603 mtwait(mtaddr); 604 if (mtaddr->mtds&MTDS_ERR) 605 return (EIO); 606 mtaddr->mtcs1 = MT_REW|MT_GO; 607 return (0); 608 } 609 610 mtdwrite(dbuf, num, mtaddr, mp) 611 register dbuf, num; 612 register struct mtdevice *mtaddr; 613 struct mba_regs *mp; 614 { 615 register struct pte *io; 616 register int i; 617 618 mtwait(mtaddr); 619 io = mp->mba_map; 620 for (i = 0; i < num; i++) 621 *(int *)io++ = dbuf++ | PG_V; 622 mtaddr->mtfc = -(num*NBPG); 623 mp->mba_sr = -1; 624 mp->mba_bcr = -(num*NBPG); 625 mp->mba_var = 0; 626 mtaddr->mtcs1 = MT_WCOM|MT_GO; 627 } 628 629 mtwait(mtaddr) 630 struct mtdevice *mtaddr; 631 { 632 register s; 633 634 do 635 s = mtaddr->mtds; 636 while ((s & MTDS_DRY) == 0); 637 } 638 639 mteof(mtaddr) 640 struct mtdevice *mtaddr; 641 { 642 643 mtwait(mtaddr); 644 mtaddr->mtcs1 = MT_WEOF|MT_GO; 645 #endif notyet 646 } 647 #endif 648