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