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