1*7380Ssam /* mt.c 4.4 82/07/13 */ 24736Swnj 34736Swnj #include "mu.h" 44736Swnj #if NMT > 0 54736Swnj /* 64736Swnj * TM78/TU78 tape driver 74736Swnj * 84736Swnj * Behavior in complex error situations is uncertain... 94736Swnj * 104736Swnj * TODO: 114736Swnj * test error recovery 124736Swnj * add odd byte count kludge from VMS driver 134736Swnj * write dump routine 144736Swnj */ 154736Swnj #include "../h/param.h" 164736Swnj #include "../h/systm.h" 174736Swnj #include "../h/buf.h" 184736Swnj #include "../h/conf.h" 194736Swnj #include "../h/dir.h" 204736Swnj #include "../h/file.h" 214736Swnj #include "../h/user.h" 224736Swnj #include "../h/map.h" 234736Swnj #include "../h/pte.h" 244736Swnj #include "../h/mbareg.h" 254736Swnj #include "../h/mbavar.h" 264736Swnj #include "../h/mtio.h" 274736Swnj #include "../h/ioctl.h" 284736Swnj #include "../h/cmap.h" 294736Swnj #include "../h/cpu.h" 304736Swnj 314736Swnj #include "../h/mtreg.h" 324736Swnj 334736Swnj struct buf rmtbuf[NMT]; 344736Swnj struct buf cmtbuf[NMT]; 354736Swnj 364736Swnj short mttypes[] = 374736Swnj { MBDT_TU78, 0 }; 384736Swnj struct mba_device *mtinfo[NMT]; 394736Swnj int mtattach(), mtslave(), mtustart(), mtstart(), mtndtint(), mtdtint(); 404736Swnj struct mba_driver mtdriver = 414736Swnj { mtattach, mtslave, mtustart, mtstart, mtdtint, mtndtint, 424736Swnj mttypes, "mt", "mu", mtinfo }; 434736Swnj 444736Swnj #define MASKREG(r) ((r) & 0xffff) 454736Swnj 464736Swnj /* bits in minor device */ 474736Swnj #define MUUNIT(dev) (minor(dev)&03) 484736Swnj #define H_NOREWIND 04 494736Swnj #define H_6250BPI 08 504736Swnj 514736Swnj #define MTUNIT(dev) (mutomt[MUUNIT(dev)]) 524736Swnj 534736Swnj #define INF (daddr_t)1000000L /* a block number that wont exist */ 544736Swnj 554736Swnj struct mu_softc { 564736Swnj char sc_openf; 574736Swnj char sc_flags; 584736Swnj daddr_t sc_blkno; 594736Swnj daddr_t sc_nxrec; 604736Swnj u_short sc_erreg; 614736Swnj u_short sc_dsreg; 624736Swnj short sc_resid; 634736Swnj short sc_dens; 644736Swnj struct mba_device *sc_mi; 654736Swnj int sc_slave; 664736Swnj } mu_softc[NMU]; 674736Swnj short mutomt[NMU]; 684736Swnj 694736Swnj /* 704736Swnj * Bits for sc_flags. 714736Swnj */ 724736Swnj #define H_WRITTEN 1 /* last operation was a write */ 734736Swnj 744736Swnj char mtds_bits[] = MTDS_BITS; 754736Swnj 764736Swnj /*ARGSUSED*/ 774736Swnj mtattach(mi) 784736Swnj struct mba_device *mi; 794736Swnj { 806186Ssam #ifdef lint 816186Ssam mtread(0); mtwrite(0); mtioctl(0, 0, 0, 0); 826186Ssam #endif 834736Swnj } 844736Swnj 854736Swnj mtslave(mi, ms) 864736Swnj struct mba_device *mi; 874736Swnj struct mba_slave *ms; 884736Swnj { 894736Swnj register struct mu_softc *sc = &mu_softc[ms->ms_unit]; 904736Swnj register struct mtdevice *mtaddr = (struct mtdevice *)mi->mi_drv; 914736Swnj int s = spl7(), rtn = 0; 924736Swnj 934736Swnj mtaddr->mtas = -1; 944736Swnj mtaddr->mtncs[ms->ms_slave] = MT_SENSE|MT_GO; 954736Swnj while (mtaddr->mtas == 0) 964736Swnj ; 974736Swnj if ((mtaddr->mtner & MTER_INTCODE) == MTER_DONE && 984736Swnj (mtaddr->mtds & MTDS_PRES)) { 994736Swnj sc->sc_mi = mi; 1004736Swnj sc->sc_slave = ms->ms_slave; 1014736Swnj mutomt[ms->ms_unit] = mi->mi_unit; 1024736Swnj rtn = 1; 1034736Swnj } 1044736Swnj mtaddr->mtas = mtaddr->mtas; 1054736Swnj splx(s); 1064736Swnj return (rtn); 1074736Swnj } 1084736Swnj 1094736Swnj mtopen(dev, flag) 1104736Swnj dev_t dev; 1114736Swnj int flag; 1124736Swnj { 1134736Swnj register int muunit; 1144736Swnj register struct mba_device *mi; 1154736Swnj register struct mu_softc *sc; 1164736Swnj int olddens, dens; 1174736Swnj 1184736Swnj muunit = MUUNIT(dev); 1194736Swnj if (muunit >= NMU || (sc = &mu_softc[muunit])->sc_openf || 1204736Swnj (mi = mtinfo[MTUNIT(dev)]) == 0 || mi->mi_alive == 0) { 1214736Swnj u.u_error = ENXIO; 1224736Swnj return; 1234736Swnj } 1244736Swnj olddens = sc->sc_dens; 1254736Swnj dens = sc->sc_dens = (minor(dev)&H_6250BPI) ? MT_GCR : 0; 1264736Swnj mtcommand(dev, MT_SENSE, 1); 1274736Swnj sc->sc_dens = olddens; 1284736Swnj if ((sc->sc_dsreg & MTDS_ONL) == 0) { 1294736Swnj uprintf("mu%d: not online\n", muunit); 1304736Swnj u.u_error = EIO; 1314736Swnj return; 1324736Swnj } 1334736Swnj if ((flag&FWRITE) && (sc->sc_dsreg&MTDS_FPT)) { 1344736Swnj uprintf("mu%d: no write ring\n", muunit); 1354736Swnj u.u_error = EIO; 1364736Swnj return; 1374736Swnj } 1384736Swnj if ((sc->sc_dsreg & MTDS_BOT) == 0 && (flag&FWRITE) && 1394736Swnj dens != sc->sc_dens) { 1404736Swnj uprintf("mu%d: can't change density in mid-tape\n", muunit); 1414736Swnj u.u_error = EIO; 1424736Swnj return; 1434736Swnj } 1444736Swnj sc->sc_openf = 1; 1454736Swnj sc->sc_blkno = (daddr_t)0; 1464736Swnj sc->sc_nxrec = INF; 1474736Swnj sc->sc_flags = 0; 1484736Swnj sc->sc_dens = dens; 1494736Swnj } 1504736Swnj 1514736Swnj mtclose(dev, flag) 1524736Swnj register dev_t dev; 1534736Swnj register flag; 1544736Swnj { 1554736Swnj register struct mu_softc *sc = &mu_softc[MUUNIT(dev)]; 1564736Swnj 1574736Swnj if (flag == FWRITE || ((flag&FWRITE) && (sc->sc_flags&H_WRITTEN))) 1584736Swnj mtcommand(dev, MT_CLS|sc->sc_dens, 1); 1594736Swnj if ((minor(dev)&H_NOREWIND) == 0) 1604736Swnj mtcommand(dev, MT_REW, 0); 1614736Swnj sc->sc_openf = 0; 1624736Swnj } 1634736Swnj 1644736Swnj mtcommand(dev, com, count) 1654736Swnj dev_t dev; 1664736Swnj int com, count; 1674736Swnj { 1684736Swnj register struct buf *bp; 1695437Sroot register int s; 1704736Swnj 1714736Swnj bp = &cmtbuf[MTUNIT(dev)]; 1725437Sroot s = spl5(); 1734736Swnj while (bp->b_flags&B_BUSY) { 1744736Swnj if(bp->b_repcnt == 0 && (bp->b_flags&B_DONE)) 1754736Swnj break; 1764736Swnj bp->b_flags |= B_WANTED; 1774736Swnj sleep((caddr_t)bp, PRIBIO); 1784736Swnj } 1794736Swnj bp->b_flags = B_BUSY|B_READ; 1805437Sroot splx(s); 1814736Swnj bp->b_dev = dev; 1824736Swnj bp->b_command = com; 1834736Swnj bp->b_repcnt = count; 1844736Swnj bp->b_blkno = 0; 1854736Swnj mtstrategy(bp); 1864736Swnj if (count == 0) 1874736Swnj return; 1884736Swnj iowait(bp); 1894736Swnj if (bp->b_flags&B_WANTED) 1904736Swnj wakeup((caddr_t)bp); 1914736Swnj bp->b_flags &= B_ERROR; 1924736Swnj } 1934736Swnj 1944736Swnj mtstrategy(bp) 1954736Swnj register struct buf *bp; 1964736Swnj { 1974736Swnj register struct mba_device *mi = mtinfo[MTUNIT(bp->b_dev)]; 1984736Swnj register struct buf *dp; 1995437Sroot register int s; 2004736Swnj 2014736Swnj bp->av_forw = NULL; 2024736Swnj dp = &mi->mi_tab; 2035437Sroot s = spl5(); 2044736Swnj if (dp->b_actf == NULL) 2054736Swnj dp->b_actf = bp; 2064736Swnj else 2074736Swnj dp->b_actl->av_forw = bp; 2084736Swnj dp->b_actl = bp; 2094736Swnj if (dp->b_active == 0) 2104736Swnj mbustart(mi); 2115437Sroot splx(s); 2124736Swnj } 2134736Swnj 2144736Swnj mtustart(mi) 2154736Swnj register struct mba_device *mi; 2164736Swnj { 2174736Swnj register struct mtdevice *mtaddr = 2184736Swnj (struct mtdevice *)mi->mi_drv; 2194736Swnj register struct buf *bp = mi->mi_tab.b_actf; 2204736Swnj register struct mu_softc *sc = &mu_softc[MUUNIT(bp->b_dev)]; 2214736Swnj daddr_t blkno; 2224736Swnj 2234736Swnj sc->sc_flags &= ~H_WRITTEN; 2244736Swnj if (sc->sc_openf < 0) { 2254736Swnj bp->b_flags |= B_ERROR; 2264736Swnj return (MBU_NEXT); 2274736Swnj } 2284736Swnj if (bp != &cmtbuf[MTUNIT(bp->b_dev)]) { 229*7380Ssam if (bdbtofsb(bp->b_blkno) > sc->sc_nxrec) { 2304736Swnj bp->b_flags |= B_ERROR; 2314736Swnj bp->b_error = ENXIO; 2324736Swnj return (MBU_NEXT); 2334736Swnj } 234*7380Ssam if (bdbtofsb(bp->b_blkno) == sc->sc_nxrec && 2354736Swnj bp->b_flags&B_READ) { 2364736Swnj bp->b_resid = bp->b_bcount; 2374736Swnj clrbuf(bp); 2384736Swnj return (MBU_NEXT); 2394736Swnj } 2404736Swnj if ((bp->b_flags&B_READ)==0) 241*7380Ssam sc->sc_nxrec = bdbtofsb(bp->b_blkno) + 1; 2424736Swnj } else { 2434736Swnj mtaddr->mtncs[MUUNIT(bp->b_dev)] = 2444736Swnj (bp->b_repcnt<<8)|bp->b_command|MT_GO; 2454736Swnj return (MBU_STARTED); 2464736Swnj } 247*7380Ssam if ((blkno = sc->sc_blkno) == bdbtofsb(bp->b_blkno)) { 2484736Swnj if (mi->mi_tab.b_errcnt == 2) { 2494736Swnj mtaddr->mtca = MUUNIT(bp->b_dev); 2504736Swnj } else { 2514736Swnj mtaddr->mtbc = bp->b_bcount; 2524736Swnj mtaddr->mtca = (1<<2)|MUUNIT(bp->b_dev); 2534736Swnj } 2544736Swnj return (MBU_DODATA); 2554736Swnj } 256*7380Ssam if (blkno < bdbtofsb(bp->b_blkno)) 2574736Swnj mtaddr->mtncs[MUUNIT(bp->b_dev)] = 258*7380Ssam (min((unsigned)(bdbtofsb(bp->b_blkno) - blkno), 0377) << 8) | 2596186Ssam MT_SFORW|MT_GO; 2604736Swnj else 2614736Swnj mtaddr->mtncs[MUUNIT(bp->b_dev)] = 262*7380Ssam (min((unsigned)(blkno - bdbtofsb(bp->b_blkno)), 0377) << 8) | 2636186Ssam MT_SREV|MT_GO; 2644736Swnj return (MBU_STARTED); 2654736Swnj } 2664736Swnj 2674736Swnj mtstart(mi) 2684736Swnj register struct mba_device *mi; 2694736Swnj { 2704736Swnj register struct buf *bp = mi->mi_tab.b_actf; 2714736Swnj register struct mu_softc *sc = &mu_softc[MUUNIT(bp->b_dev)]; 2724736Swnj 2734736Swnj if (bp->b_flags & B_READ) 2744736Swnj if (mi->mi_tab.b_errcnt == 2) 2754736Swnj return(MT_READREV|MT_GO); 2764736Swnj else 2774736Swnj return(MT_READ|MT_GO); 2784736Swnj else 2794736Swnj return(MT_WRITE|sc->sc_dens|MT_GO); 2804736Swnj } 2814736Swnj 2824736Swnj mtdtint(mi, mbsr) 2834736Swnj register struct mba_device *mi; 2844736Swnj int mbsr; 2854736Swnj { 2864736Swnj register struct mtdevice *mtaddr = (struct mtdevice *)mi->mi_drv; 2874736Swnj register struct buf *bp = mi->mi_tab.b_actf; 2884736Swnj register struct mu_softc *sc; 2894736Swnj 2904736Swnj /* I'M NOT SURE IF THIS SHOULD ALWAYS BE THE CASE SO FOR NOW... */ 2914736Swnj if ((mtaddr->mtca&3) != MUUNIT(bp->b_dev)) { 2924736Swnj printf("mt: wrong unit!\n"); 2934736Swnj mtaddr->mtca = MUUNIT(bp->b_dev); 2944736Swnj } 2954736Swnj sc = &mu_softc[MUUNIT(bp->b_dev)]; 2964736Swnj sc->sc_erreg = mtaddr->mter; 2974736Swnj if((bp->b_flags & B_READ) == 0) 2984736Swnj sc->sc_flags |= H_WRITTEN; 2994736Swnj switch (sc->sc_erreg & MTER_INTCODE) { 3004736Swnj case MTER_DONE: 3014736Swnj case MTER_LONGREC: 3024736Swnj if (mi->mi_tab.b_errcnt != 2) 3034736Swnj sc->sc_blkno++; 3044736Swnj bp->b_resid = 0; 3054736Swnj break; 3064736Swnj 3074736Swnj case MTER_NOTCAP: 3084736Swnj printf("mu%d: blank tape\n", MUUNIT(bp->b_dev)); 3094736Swnj goto err; 3104736Swnj 3114736Swnj case MTER_TM: 3124736Swnj case MTER_EOT: 3134736Swnj sc->sc_blkno++; 3144736Swnj err: 3154736Swnj bp->b_resid = bp->b_bcount; 316*7380Ssam sc->sc_nxrec = bdbtofsb(bp->b_blkno); 3174736Swnj break; 3184736Swnj 3194736Swnj case MTER_SHRTREC: 3204736Swnj sc->sc_blkno++; 3214736Swnj if (bp != &rmtbuf[MTUNIT(bp->b_dev)]) 3224736Swnj bp->b_flags |= B_ERROR; 3234736Swnj if (mi->mi_tab.b_errcnt == 2) 3244736Swnj bp->b_bcount = bp->b_resid; /* restore saved value */ 3254736Swnj bp->b_resid = bp->b_bcount - mtaddr->mtbc; 3264736Swnj break; 3274736Swnj 3284736Swnj case MTER_RDOPP: 3294736Swnj mi->mi_tab.b_errcnt = 2; /* indicate "read opposite" */ 3304736Swnj bp->b_resid = bp->b_bcount; /* save it */ 3314736Swnj bp->b_bcount = mtaddr->mtbc; /* use this instead */ 3324736Swnj return(MBD_RETRY); 3334736Swnj 3344736Swnj case MTER_RETRY: 3354736Swnj mi->mi_tab.b_errcnt = 1; /* indicate simple retry */ 3364736Swnj return(MBD_RETRY); 3374736Swnj 3384736Swnj case MTER_OFFLINE: 3394736Swnj if (sc->sc_openf > 0) { 3404736Swnj sc->sc_openf = -1; 3414736Swnj printf("mu%d: offline\n", MUUNIT(bp->b_dev)); 3424736Swnj } 3434736Swnj bp->b_flags |= B_ERROR; 3444736Swnj break; 3454736Swnj 3464736Swnj case MTER_FPT: 3474736Swnj printf("mu%d: no write ring\n", MUUNIT(bp->b_dev)); 3484736Swnj bp->b_flags |= B_ERROR; 3494736Swnj break; 3504736Swnj 3514736Swnj default: 3524736Swnj printf("mu%d: hard error bn%d mbsr=%b er=%x ds=%b\n", 3534736Swnj MUUNIT(bp->b_dev), bp->b_blkno, 3544736Swnj mbsr, mbsr_bits, sc->sc_erreg, 3554736Swnj sc->sc_dsreg, mtds_bits); 3564736Swnj bp->b_flags |= B_ERROR; 3574736Swnj mtaddr->mtid = MTID_CLR; /* reset the TM78 */ 3584736Swnj DELAY(250); 3594736Swnj while ((mtaddr->mtid & MTID_RDY) == 0) /* wait for it */ 3604736Swnj ; 3614736Swnj return (MBD_DONE); 3624736Swnj } 3634736Swnj /* CHECK FOR MBA ERROR WHEN NO OTHER ERROR INDICATED? */ 3644736Swnj return (MBD_DONE); 3654736Swnj } 3664736Swnj 3674736Swnj mtndtint(mi) 3684736Swnj register struct mba_device *mi; 3694736Swnj { 3704736Swnj register struct mtdevice *mtaddr = (struct mtdevice *)mi->mi_drv; 3714736Swnj register struct buf *bp = mi->mi_tab.b_actf; 3724736Swnj register struct mu_softc *sc; 3734736Swnj int er, fc, unit; 3744736Swnj 3754736Swnj unit = (mtaddr->mtner >> 8) & 3; 3764736Swnj er = MASKREG(mtaddr->mtner); 3774736Swnj /* WILL THIS OCCUR IF ANOTHER DRIVE COMES ONLINE? */ 3784736Swnj if (bp == 0 || unit != MUUNIT(bp->b_dev)) { /* consistency check */ 3794736Swnj if ((er & MTER_INTCODE) != MTER_ONLINE) 3804736Swnj printf("mt: unit %d random interrupt\n", unit); 3814736Swnj return (MBN_SKIP); 3824736Swnj } 3834736Swnj if (bp == 0) 3844736Swnj return (MBN_SKIP); 3854736Swnj fc = (mtaddr->mtncs[unit] >> 8) & 0xff; 3864736Swnj sc = &mu_softc[unit]; 3874736Swnj sc->sc_erreg = er; 3884736Swnj sc->sc_resid = fc; 3894736Swnj switch (er & MTER_INTCODE) { 3904736Swnj case MTER_DONE: 3914736Swnj if (bp == &cmtbuf[MTUNIT(bp->b_dev)]) { 3924736Swnj done: 3934736Swnj if (bp->b_command == MT_SENSE) 3944736Swnj sc->sc_dsreg = MASKREG(mtaddr->mtds); 3954736Swnj bp->b_resid = fc; 3964736Swnj return (MBN_DONE); 3974736Swnj } 3984736Swnj /* this is UGLY! (but is it correct?) */ 399*7380Ssam if ((fc = bdbtofsb(bp->b_blkno) - sc->sc_blkno) < 0) 4006186Ssam sc->sc_blkno -= MIN(0377, -fc); 4014736Swnj else 4026186Ssam sc->sc_blkno += MIN(0377, fc); 4034736Swnj return (MBN_RETRY); 4044736Swnj 4054736Swnj case MTER_RWDING: 4064736Swnj return (MBN_SKIP); /* ignore "rewind started" interrupt */ 4074736Swnj 4084736Swnj case MTER_NOTCAP: 4094736Swnj printf("mu%d: blank tape\n", MUUNIT(bp->b_dev)); 4104736Swnj 4114736Swnj case MTER_TM: 4124736Swnj case MTER_EOT: 4134736Swnj case MTER_LEOT: 414*7380Ssam if (sc->sc_blkno > bdbtofsb(bp->b_blkno)) { 415*7380Ssam sc->sc_nxrec = bdbtofsb(bp->b_blkno) + fc; 4164736Swnj sc->sc_blkno = sc->sc_nxrec; 4174736Swnj } else { 418*7380Ssam sc->sc_blkno = bdbtofsb(bp->b_blkno) - fc; 4194736Swnj sc->sc_nxrec = sc->sc_blkno - 1; 4204736Swnj } 4214736Swnj return (MBN_RETRY); 4224736Swnj 4234736Swnj case MTER_FPT: 4244736Swnj printf("mu%d: no write ring\n", MUUNIT(bp->b_dev)); 4254736Swnj bp->b_flags |= B_ERROR; 4264736Swnj return (MBN_DONE); 4274736Swnj 4284736Swnj case MTER_OFFLINE: 4294736Swnj if (sc->sc_openf > 0) { 4304736Swnj sc->sc_openf = -1; 4314736Swnj printf("mu%d: offline\n", MUUNIT(bp->b_dev)); 4324736Swnj } 4334736Swnj bp->b_flags |= B_ERROR; 4344736Swnj return (MBN_DONE); 4354736Swnj 4364736Swnj case MTER_BOT: 4374736Swnj if (bp == &cmtbuf[MTUNIT(bp->b_dev)]) 4384736Swnj goto done; 4394736Swnj /* FALL THROUGH */ 4404736Swnj 4414736Swnj default: 4424736Swnj printf("mu%d: hard error bn%d er=%o ds=%b\n", 4434736Swnj MUUNIT(bp->b_dev), bp->b_blkno, 4444736Swnj sc->sc_erreg, sc->sc_dsreg, mtds_bits); 4454736Swnj mtaddr->mtid = MTID_CLR; /* reset the TM78 */ 4464736Swnj DELAY(250); 4474736Swnj while ((mtaddr->mtid & MTID_RDY) == 0) /* wait for it */ 4484736Swnj ; 4494736Swnj bp->b_flags |= B_ERROR; 4504736Swnj return (MBN_DONE); 4514736Swnj } 4524736Swnj /* NOTREACHED */ 4534736Swnj } 4544736Swnj 4554736Swnj mtread(dev) 4564736Swnj dev_t dev; 4574736Swnj { 4584736Swnj 4594736Swnj mtphys(dev); 4604736Swnj if (u.u_error) 4614736Swnj return; 4624736Swnj physio(mtstrategy, &rmtbuf[MTUNIT(dev)], dev, B_READ, minphys); 4634736Swnj } 4644736Swnj 4654736Swnj mtwrite(dev) 4664736Swnj { 4674736Swnj 4684736Swnj mtphys(dev); 4694736Swnj if (u.u_error) 4704736Swnj return; 4714736Swnj physio(mtstrategy, &rmtbuf[MTUNIT(dev)], dev, B_WRITE, minphys); 4724736Swnj } 4734736Swnj 4744736Swnj mtphys(dev) 4754736Swnj dev_t dev; 4764736Swnj { 4774736Swnj register int mtunit; 4784736Swnj register struct mu_softc *sc; 4794736Swnj register struct mba_device *mi; 4804736Swnj daddr_t a; 4814736Swnj 4824736Swnj mtunit = MTUNIT(dev); 4834736Swnj if (mtunit >= NMT || (mi = mtinfo[mtunit]) == 0 || mi->mi_alive == 0) { 4844736Swnj u.u_error = ENXIO; 4854736Swnj return; 4864736Swnj } 4874736Swnj a = u.u_offset >> 9; 4884736Swnj sc = &mu_softc[MUUNIT(dev)]; 489*7380Ssam sc->sc_blkno = bdbtofsb(a); 490*7380Ssam sc->sc_nxrec = bdbtofsb(a)+1; 4914736Swnj } 4924736Swnj 4934736Swnj /*ARGSUSED*/ 4944736Swnj mtioctl(dev, cmd, addr, flag) 4954736Swnj dev_t dev; 4964736Swnj int cmd; 4974736Swnj caddr_t addr; 4984736Swnj int flag; 4994736Swnj { 5004736Swnj register struct mu_softc *sc = &mu_softc[MUUNIT(dev)]; 5014736Swnj register struct buf *bp = &cmtbuf[MTUNIT(dev)]; 5024736Swnj register callcount; 5036186Ssam register int op; 5044736Swnj int fcount; 5054736Swnj struct mtop mtop; 5064736Swnj struct mtget mtget; 5074736Swnj /* we depend of the values and order of the MT codes here */ 5084736Swnj static mtops[] = 5094736Swnj {MT_WTM,MT_SFORWF,MT_SREVF,MT_SFORW,MT_SREV,MT_REW,MT_UNLOAD,MT_SENSE}; 5104736Swnj 5114736Swnj switch (cmd) { 5124736Swnj case MTIOCTOP: /* tape operation */ 5134736Swnj if (copyin((caddr_t)addr, (caddr_t)&mtop, sizeof(mtop))) { 5144736Swnj u.u_error = EFAULT; 5154736Swnj return; 5164736Swnj } 5174736Swnj switch(mtop.mt_op) { 5184736Swnj case MTWEOF: 5194736Swnj callcount = mtop.mt_count; 5204736Swnj fcount = 1; 5214736Swnj break; 5224736Swnj case MTFSF: case MTBSF: 5234736Swnj callcount = mtop.mt_count; 5244736Swnj fcount = 1; 5254736Swnj break; 5264736Swnj case MTFSR: case MTBSR: 5274736Swnj callcount = 1; 5284736Swnj fcount = mtop.mt_count; 5294736Swnj break; 5304736Swnj case MTREW: case MTOFFL: 5314736Swnj callcount = 1; 5324736Swnj fcount = 1; 5334736Swnj break; 5344736Swnj default: 5354736Swnj u.u_error = ENXIO; 5364736Swnj return; 5374736Swnj } 5384736Swnj if (callcount <= 0 || fcount <= 0) { 5394736Swnj u.u_error = ENXIO; 5404736Swnj return; 5414736Swnj } 5424736Swnj op = mtops[mtop.mt_op]; 5434736Swnj if (op == MT_WTM) 5444736Swnj op |= sc->sc_dens; 5454736Swnj while (--callcount >= 0) { 5464736Swnj register int n; 5474736Swnj 5484736Swnj do { 5496186Ssam n = MIN(fcount, 0xff); 5504736Swnj mtcommand(dev, op, n); 5514736Swnj fcount -= n; 5524736Swnj } while (fcount); 5534736Swnj if ((mtop.mt_op == MTFSR || mtop.mt_op == MTBSR) && 5544736Swnj bp->b_resid) { 5554736Swnj u.u_error = EIO; 5564736Swnj break; 5574736Swnj } 5584736Swnj if (bp->b_flags&B_ERROR) 5594736Swnj break; 5604736Swnj } 5614736Swnj geterror(bp); 5624736Swnj return; 5634736Swnj case MTIOCGET: 5644736Swnj mtget.mt_erreg = sc->sc_erreg; 5654736Swnj mtget.mt_resid = sc->sc_resid; 5664736Swnj mtcommand(dev, MT_SENSE, 1); /* update drive status */ 5674736Swnj mtget.mt_dsreg = sc->sc_dsreg; 5684736Swnj mtget.mt_type = MT_ISMT; 5694736Swnj if (copyout((caddr_t)&mtget, addr, sizeof(mtget))) 5704736Swnj u.u_error = EFAULT; 5714736Swnj return; 5724736Swnj default: 5734736Swnj u.u_error = ENXIO; 5744736Swnj } 5754736Swnj } 5764736Swnj 5774736Swnj #define DBSIZE 20 5784736Swnj 5794736Swnj mtdump() 5804736Swnj { 5814736Swnj register struct mba_device *mi; 5824736Swnj register struct mba_regs *mp; 5834736Swnj register struct mtdevice *mtaddr; 5844736Swnj int blk, num; 5854736Swnj int start; 5864736Swnj 5874736Swnj start = 0; 5884736Swnj num = maxfree; 5894736Swnj #define phys(a,b) ((b)((int)(a)&0x7fffffff)) 5904736Swnj if (mtinfo[0] == 0) 5914736Swnj return (ENXIO); 5924736Swnj mi = phys(mtinfo[0], struct mba_device *); 5934736Swnj mp = phys(mi->mi_hd, struct mba_hd *)->mh_physmba; 5944736Swnj mp->mba_cr = MBCR_IE; 5956186Ssam #if lint 5966186Ssam blk = blk; num = num; start = start; 5976186Ssam return (0); 5986186Ssam #endif 5996186Ssam #ifdef notyet 6004736Swnj mtaddr = (struct mtdevice *)&mp->mba_drv[mi->mi_drive]; 6014736Swnj mtaddr->mttc = MTTC_PDP11|MTTC_1600BPI; 6024736Swnj mtaddr->mtcs1 = MT_DCLR|MT_GO; 6034736Swnj while (num > 0) { 6044736Swnj blk = num > DBSIZE ? DBSIZE : num; 6054736Swnj mtdwrite(start, blk, mtaddr, mp); 6064736Swnj start += blk; 6074736Swnj num -= blk; 6084736Swnj } 6094736Swnj mteof(mtaddr); 6104736Swnj mteof(mtaddr); 6114736Swnj mtwait(mtaddr); 6124736Swnj if (mtaddr->mtds&MTDS_ERR) 6134736Swnj return (EIO); 6144736Swnj mtaddr->mtcs1 = MT_REW|MT_GO; 6154736Swnj return (0); 6164736Swnj } 6174736Swnj 6184736Swnj mtdwrite(dbuf, num, mtaddr, mp) 6194736Swnj register dbuf, num; 6204736Swnj register struct mtdevice *mtaddr; 6214736Swnj struct mba_regs *mp; 6224736Swnj { 6234736Swnj register struct pte *io; 6244736Swnj register int i; 6254736Swnj 6264736Swnj mtwait(mtaddr); 6274736Swnj io = mp->mba_map; 6284736Swnj for (i = 0; i < num; i++) 6294736Swnj *(int *)io++ = dbuf++ | PG_V; 6304736Swnj mtaddr->mtfc = -(num*NBPG); 6314736Swnj mp->mba_sr = -1; 6324736Swnj mp->mba_bcr = -(num*NBPG); 6334736Swnj mp->mba_var = 0; 6344736Swnj mtaddr->mtcs1 = MT_WCOM|MT_GO; 6354736Swnj } 6364736Swnj 6374736Swnj mtwait(mtaddr) 6384736Swnj struct mtdevice *mtaddr; 6394736Swnj { 6404736Swnj register s; 6414736Swnj 6424736Swnj do 6434736Swnj s = mtaddr->mtds; 6444736Swnj while ((s & MTDS_DRY) == 0); 6454736Swnj } 6464736Swnj 6474736Swnj mteof(mtaddr) 6484736Swnj struct mtdevice *mtaddr; 6494736Swnj { 6504736Swnj 6514736Swnj mtwait(mtaddr); 6524736Swnj mtaddr->mtcs1 = MT_WEOF|MT_GO; 6534736Swnj #endif notyet 6544736Swnj } 6554736Swnj #endif 656