1*7740Sroot /* mt.c 4.7 82/08/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" 267637Ssam #include "../h/ioctl.h" 274736Swnj #include "../h/mtio.h" 284736Swnj #include "../h/cmap.h" 294736Swnj #include "../h/cpu.h" 30*7740Sroot #include "../h/uio.h" 314736Swnj 324736Swnj #include "../h/mtreg.h" 334736Swnj 344736Swnj struct buf rmtbuf[NMT]; 354736Swnj struct buf cmtbuf[NMT]; 364736Swnj 374736Swnj short mttypes[] = 384736Swnj { MBDT_TU78, 0 }; 394736Swnj struct mba_device *mtinfo[NMT]; 404736Swnj int mtattach(), mtslave(), mtustart(), mtstart(), mtndtint(), mtdtint(); 414736Swnj struct mba_driver mtdriver = 424736Swnj { mtattach, mtslave, mtustart, mtstart, mtdtint, mtndtint, 434736Swnj mttypes, "mt", "mu", mtinfo }; 444736Swnj 454736Swnj #define MASKREG(r) ((r) & 0xffff) 464736Swnj 474736Swnj /* bits in minor device */ 484736Swnj #define MUUNIT(dev) (minor(dev)&03) 494736Swnj #define H_NOREWIND 04 504736Swnj #define H_6250BPI 08 514736Swnj 524736Swnj #define MTUNIT(dev) (mutomt[MUUNIT(dev)]) 534736Swnj 544736Swnj #define INF (daddr_t)1000000L /* a block number that wont exist */ 554736Swnj 564736Swnj struct mu_softc { 574736Swnj char sc_openf; 584736Swnj char sc_flags; 594736Swnj daddr_t sc_blkno; 604736Swnj daddr_t sc_nxrec; 614736Swnj u_short sc_erreg; 624736Swnj u_short sc_dsreg; 634736Swnj short sc_resid; 644736Swnj short sc_dens; 654736Swnj struct mba_device *sc_mi; 664736Swnj int sc_slave; 674736Swnj } mu_softc[NMU]; 684736Swnj short mutomt[NMU]; 694736Swnj 704736Swnj /* 714736Swnj * Bits for sc_flags. 724736Swnj */ 734736Swnj #define H_WRITTEN 1 /* last operation was a write */ 744736Swnj 754736Swnj char mtds_bits[] = MTDS_BITS; 764736Swnj 774736Swnj /*ARGSUSED*/ 784736Swnj mtattach(mi) 794736Swnj struct mba_device *mi; 804736Swnj { 816186Ssam #ifdef lint 82*7740Sroot mtread(0, 0); mtwrite(0); mtioctl(0, 0, 0, 0); 836186Ssam #endif 844736Swnj } 854736Swnj 867431Skre mtslave(mi, ms, sn) 874736Swnj struct mba_device *mi; 884736Swnj struct mba_slave *ms; 897431Skre int sn; 904736Swnj { 914736Swnj register struct mu_softc *sc = &mu_softc[ms->ms_unit]; 924736Swnj register struct mtdevice *mtaddr = (struct mtdevice *)mi->mi_drv; 934736Swnj int s = spl7(), rtn = 0; 944736Swnj 954736Swnj mtaddr->mtas = -1; 967431Skre mtaddr->mtncs[sn] = MT_SENSE|MT_GO; 974736Swnj while (mtaddr->mtas == 0) 984736Swnj ; 994736Swnj if ((mtaddr->mtner & MTER_INTCODE) == MTER_DONE && 1004736Swnj (mtaddr->mtds & MTDS_PRES)) { 1014736Swnj sc->sc_mi = mi; 1027431Skre sc->sc_slave = sn; 1034736Swnj mutomt[ms->ms_unit] = mi->mi_unit; 1044736Swnj rtn = 1; 1054736Swnj } 1064736Swnj mtaddr->mtas = mtaddr->mtas; 1074736Swnj splx(s); 1084736Swnj return (rtn); 1094736Swnj } 1104736Swnj 1114736Swnj mtopen(dev, flag) 1124736Swnj dev_t dev; 1134736Swnj int flag; 1144736Swnj { 1154736Swnj register int muunit; 1164736Swnj register struct mba_device *mi; 1174736Swnj register struct mu_softc *sc; 1184736Swnj int olddens, dens; 1194736Swnj 1204736Swnj muunit = MUUNIT(dev); 1214736Swnj if (muunit >= NMU || (sc = &mu_softc[muunit])->sc_openf || 1224736Swnj (mi = mtinfo[MTUNIT(dev)]) == 0 || mi->mi_alive == 0) { 1234736Swnj u.u_error = ENXIO; 1244736Swnj return; 1254736Swnj } 1264736Swnj olddens = sc->sc_dens; 1274736Swnj dens = sc->sc_dens = (minor(dev)&H_6250BPI) ? MT_GCR : 0; 1284736Swnj mtcommand(dev, MT_SENSE, 1); 1294736Swnj sc->sc_dens = olddens; 1304736Swnj if ((sc->sc_dsreg & MTDS_ONL) == 0) { 1314736Swnj uprintf("mu%d: not online\n", muunit); 1324736Swnj u.u_error = EIO; 1334736Swnj return; 1344736Swnj } 1354736Swnj if ((flag&FWRITE) && (sc->sc_dsreg&MTDS_FPT)) { 1364736Swnj uprintf("mu%d: no write ring\n", muunit); 1374736Swnj u.u_error = EIO; 1384736Swnj return; 1394736Swnj } 1404736Swnj if ((sc->sc_dsreg & MTDS_BOT) == 0 && (flag&FWRITE) && 1414736Swnj dens != sc->sc_dens) { 1424736Swnj uprintf("mu%d: can't change density in mid-tape\n", muunit); 1434736Swnj u.u_error = EIO; 1444736Swnj return; 1454736Swnj } 1464736Swnj sc->sc_openf = 1; 1474736Swnj sc->sc_blkno = (daddr_t)0; 1484736Swnj sc->sc_nxrec = INF; 1494736Swnj sc->sc_flags = 0; 1504736Swnj sc->sc_dens = dens; 1514736Swnj } 1524736Swnj 1534736Swnj mtclose(dev, flag) 1544736Swnj register dev_t dev; 1554736Swnj register flag; 1564736Swnj { 1574736Swnj register struct mu_softc *sc = &mu_softc[MUUNIT(dev)]; 1584736Swnj 1594736Swnj if (flag == FWRITE || ((flag&FWRITE) && (sc->sc_flags&H_WRITTEN))) 1604736Swnj mtcommand(dev, MT_CLS|sc->sc_dens, 1); 1614736Swnj if ((minor(dev)&H_NOREWIND) == 0) 1624736Swnj mtcommand(dev, MT_REW, 0); 1634736Swnj sc->sc_openf = 0; 1644736Swnj } 1654736Swnj 1664736Swnj mtcommand(dev, com, count) 1674736Swnj dev_t dev; 1684736Swnj int com, count; 1694736Swnj { 1704736Swnj register struct buf *bp; 1715437Sroot register int s; 1724736Swnj 1734736Swnj bp = &cmtbuf[MTUNIT(dev)]; 1745437Sroot s = spl5(); 1754736Swnj while (bp->b_flags&B_BUSY) { 1764736Swnj if(bp->b_repcnt == 0 && (bp->b_flags&B_DONE)) 1774736Swnj break; 1784736Swnj bp->b_flags |= B_WANTED; 1794736Swnj sleep((caddr_t)bp, PRIBIO); 1804736Swnj } 1814736Swnj bp->b_flags = B_BUSY|B_READ; 1825437Sroot splx(s); 1834736Swnj bp->b_dev = dev; 1844736Swnj bp->b_command = com; 1854736Swnj bp->b_repcnt = count; 1864736Swnj bp->b_blkno = 0; 1874736Swnj mtstrategy(bp); 1884736Swnj if (count == 0) 1894736Swnj return; 1904736Swnj iowait(bp); 1914736Swnj if (bp->b_flags&B_WANTED) 1924736Swnj wakeup((caddr_t)bp); 1934736Swnj bp->b_flags &= B_ERROR; 1944736Swnj } 1954736Swnj 1964736Swnj mtstrategy(bp) 1974736Swnj register struct buf *bp; 1984736Swnj { 1994736Swnj register struct mba_device *mi = mtinfo[MTUNIT(bp->b_dev)]; 2004736Swnj register struct buf *dp; 2015437Sroot register int s; 2024736Swnj 2034736Swnj bp->av_forw = NULL; 2044736Swnj dp = &mi->mi_tab; 2055437Sroot s = spl5(); 2064736Swnj if (dp->b_actf == NULL) 2074736Swnj dp->b_actf = bp; 2084736Swnj else 2094736Swnj dp->b_actl->av_forw = bp; 2104736Swnj dp->b_actl = bp; 2114736Swnj if (dp->b_active == 0) 2124736Swnj mbustart(mi); 2135437Sroot splx(s); 2144736Swnj } 2154736Swnj 2164736Swnj mtustart(mi) 2174736Swnj register struct mba_device *mi; 2184736Swnj { 2194736Swnj register struct mtdevice *mtaddr = 2204736Swnj (struct mtdevice *)mi->mi_drv; 2214736Swnj register struct buf *bp = mi->mi_tab.b_actf; 2224736Swnj register struct mu_softc *sc = &mu_softc[MUUNIT(bp->b_dev)]; 2234736Swnj daddr_t blkno; 2244736Swnj 2254736Swnj sc->sc_flags &= ~H_WRITTEN; 2264736Swnj if (sc->sc_openf < 0) { 2274736Swnj bp->b_flags |= B_ERROR; 2284736Swnj return (MBU_NEXT); 2294736Swnj } 2304736Swnj if (bp != &cmtbuf[MTUNIT(bp->b_dev)]) { 2317380Ssam if (bdbtofsb(bp->b_blkno) > sc->sc_nxrec) { 2324736Swnj bp->b_flags |= B_ERROR; 2334736Swnj bp->b_error = ENXIO; 2344736Swnj return (MBU_NEXT); 2354736Swnj } 2367380Ssam if (bdbtofsb(bp->b_blkno) == sc->sc_nxrec && 2374736Swnj bp->b_flags&B_READ) { 2384736Swnj bp->b_resid = bp->b_bcount; 2394736Swnj clrbuf(bp); 2404736Swnj return (MBU_NEXT); 2414736Swnj } 2424736Swnj if ((bp->b_flags&B_READ)==0) 2437380Ssam sc->sc_nxrec = bdbtofsb(bp->b_blkno) + 1; 2444736Swnj } else { 2454736Swnj mtaddr->mtncs[MUUNIT(bp->b_dev)] = 2464736Swnj (bp->b_repcnt<<8)|bp->b_command|MT_GO; 2474736Swnj return (MBU_STARTED); 2484736Swnj } 2497380Ssam if ((blkno = sc->sc_blkno) == bdbtofsb(bp->b_blkno)) { 2504736Swnj if (mi->mi_tab.b_errcnt == 2) { 2514736Swnj mtaddr->mtca = MUUNIT(bp->b_dev); 2524736Swnj } else { 2534736Swnj mtaddr->mtbc = bp->b_bcount; 2544736Swnj mtaddr->mtca = (1<<2)|MUUNIT(bp->b_dev); 2554736Swnj } 2564736Swnj return (MBU_DODATA); 2574736Swnj } 2587380Ssam if (blkno < bdbtofsb(bp->b_blkno)) 2594736Swnj mtaddr->mtncs[MUUNIT(bp->b_dev)] = 2607380Ssam (min((unsigned)(bdbtofsb(bp->b_blkno) - blkno), 0377) << 8) | 2616186Ssam MT_SFORW|MT_GO; 2624736Swnj else 2634736Swnj mtaddr->mtncs[MUUNIT(bp->b_dev)] = 2647380Ssam (min((unsigned)(blkno - bdbtofsb(bp->b_blkno)), 0377) << 8) | 2656186Ssam MT_SREV|MT_GO; 2664736Swnj return (MBU_STARTED); 2674736Swnj } 2684736Swnj 2694736Swnj mtstart(mi) 2704736Swnj register struct mba_device *mi; 2714736Swnj { 2724736Swnj register struct buf *bp = mi->mi_tab.b_actf; 2734736Swnj register struct mu_softc *sc = &mu_softc[MUUNIT(bp->b_dev)]; 2744736Swnj 2754736Swnj if (bp->b_flags & B_READ) 2764736Swnj if (mi->mi_tab.b_errcnt == 2) 2774736Swnj return(MT_READREV|MT_GO); 2784736Swnj else 2794736Swnj return(MT_READ|MT_GO); 2804736Swnj else 2814736Swnj return(MT_WRITE|sc->sc_dens|MT_GO); 2824736Swnj } 2834736Swnj 2844736Swnj mtdtint(mi, mbsr) 2854736Swnj register struct mba_device *mi; 2864736Swnj int mbsr; 2874736Swnj { 2884736Swnj register struct mtdevice *mtaddr = (struct mtdevice *)mi->mi_drv; 2894736Swnj register struct buf *bp = mi->mi_tab.b_actf; 2904736Swnj register struct mu_softc *sc; 2914736Swnj 2924736Swnj /* I'M NOT SURE IF THIS SHOULD ALWAYS BE THE CASE SO FOR NOW... */ 2934736Swnj if ((mtaddr->mtca&3) != MUUNIT(bp->b_dev)) { 2944736Swnj printf("mt: wrong unit!\n"); 2954736Swnj mtaddr->mtca = MUUNIT(bp->b_dev); 2964736Swnj } 2974736Swnj sc = &mu_softc[MUUNIT(bp->b_dev)]; 2984736Swnj sc->sc_erreg = mtaddr->mter; 2994736Swnj if((bp->b_flags & B_READ) == 0) 3004736Swnj sc->sc_flags |= H_WRITTEN; 3014736Swnj switch (sc->sc_erreg & MTER_INTCODE) { 3024736Swnj case MTER_DONE: 3034736Swnj case MTER_LONGREC: 3044736Swnj if (mi->mi_tab.b_errcnt != 2) 3054736Swnj sc->sc_blkno++; 3064736Swnj bp->b_resid = 0; 3074736Swnj break; 3084736Swnj 3094736Swnj case MTER_NOTCAP: 3104736Swnj printf("mu%d: blank tape\n", MUUNIT(bp->b_dev)); 3114736Swnj goto err; 3124736Swnj 3134736Swnj case MTER_TM: 3144736Swnj case MTER_EOT: 3154736Swnj sc->sc_blkno++; 3164736Swnj err: 3174736Swnj bp->b_resid = bp->b_bcount; 3187380Ssam sc->sc_nxrec = bdbtofsb(bp->b_blkno); 3194736Swnj break; 3204736Swnj 3214736Swnj case MTER_SHRTREC: 3224736Swnj sc->sc_blkno++; 3234736Swnj if (bp != &rmtbuf[MTUNIT(bp->b_dev)]) 3244736Swnj bp->b_flags |= B_ERROR; 3254736Swnj if (mi->mi_tab.b_errcnt == 2) 3264736Swnj bp->b_bcount = bp->b_resid; /* restore saved value */ 3274736Swnj bp->b_resid = bp->b_bcount - mtaddr->mtbc; 3284736Swnj break; 3294736Swnj 3304736Swnj case MTER_RDOPP: 3314736Swnj mi->mi_tab.b_errcnt = 2; /* indicate "read opposite" */ 3324736Swnj bp->b_resid = bp->b_bcount; /* save it */ 3334736Swnj bp->b_bcount = mtaddr->mtbc; /* use this instead */ 3344736Swnj return(MBD_RETRY); 3354736Swnj 3364736Swnj case MTER_RETRY: 3374736Swnj mi->mi_tab.b_errcnt = 1; /* indicate simple retry */ 3384736Swnj return(MBD_RETRY); 3394736Swnj 3404736Swnj case MTER_OFFLINE: 3414736Swnj if (sc->sc_openf > 0) { 3424736Swnj sc->sc_openf = -1; 3434736Swnj printf("mu%d: offline\n", MUUNIT(bp->b_dev)); 3444736Swnj } 3454736Swnj bp->b_flags |= B_ERROR; 3464736Swnj break; 3474736Swnj 3484736Swnj case MTER_FPT: 3494736Swnj printf("mu%d: no write ring\n", MUUNIT(bp->b_dev)); 3504736Swnj bp->b_flags |= B_ERROR; 3514736Swnj break; 3524736Swnj 3534736Swnj default: 3544736Swnj printf("mu%d: hard error bn%d mbsr=%b er=%x ds=%b\n", 3554736Swnj MUUNIT(bp->b_dev), bp->b_blkno, 3564736Swnj mbsr, mbsr_bits, sc->sc_erreg, 3574736Swnj sc->sc_dsreg, mtds_bits); 3584736Swnj bp->b_flags |= B_ERROR; 3594736Swnj mtaddr->mtid = MTID_CLR; /* reset the TM78 */ 3604736Swnj DELAY(250); 3614736Swnj while ((mtaddr->mtid & MTID_RDY) == 0) /* wait for it */ 3624736Swnj ; 3634736Swnj return (MBD_DONE); 3644736Swnj } 3654736Swnj /* CHECK FOR MBA ERROR WHEN NO OTHER ERROR INDICATED? */ 3664736Swnj return (MBD_DONE); 3674736Swnj } 3684736Swnj 3694736Swnj mtndtint(mi) 3704736Swnj register struct mba_device *mi; 3714736Swnj { 3724736Swnj register struct mtdevice *mtaddr = (struct mtdevice *)mi->mi_drv; 3734736Swnj register struct buf *bp = mi->mi_tab.b_actf; 3744736Swnj register struct mu_softc *sc; 3754736Swnj int er, fc, unit; 3764736Swnj 3774736Swnj unit = (mtaddr->mtner >> 8) & 3; 3784736Swnj er = MASKREG(mtaddr->mtner); 3794736Swnj /* WILL THIS OCCUR IF ANOTHER DRIVE COMES ONLINE? */ 3804736Swnj if (bp == 0 || unit != MUUNIT(bp->b_dev)) { /* consistency check */ 3814736Swnj if ((er & MTER_INTCODE) != MTER_ONLINE) 3824736Swnj printf("mt: unit %d random interrupt\n", unit); 3834736Swnj return (MBN_SKIP); 3844736Swnj } 3854736Swnj if (bp == 0) 3864736Swnj return (MBN_SKIP); 3874736Swnj fc = (mtaddr->mtncs[unit] >> 8) & 0xff; 3884736Swnj sc = &mu_softc[unit]; 3894736Swnj sc->sc_erreg = er; 3904736Swnj sc->sc_resid = fc; 3914736Swnj switch (er & MTER_INTCODE) { 3924736Swnj case MTER_DONE: 3934736Swnj if (bp == &cmtbuf[MTUNIT(bp->b_dev)]) { 3944736Swnj done: 3954736Swnj if (bp->b_command == MT_SENSE) 3964736Swnj sc->sc_dsreg = MASKREG(mtaddr->mtds); 3974736Swnj bp->b_resid = fc; 3984736Swnj return (MBN_DONE); 3994736Swnj } 4004736Swnj /* this is UGLY! (but is it correct?) */ 4017380Ssam if ((fc = bdbtofsb(bp->b_blkno) - sc->sc_blkno) < 0) 4026186Ssam sc->sc_blkno -= MIN(0377, -fc); 4034736Swnj else 4046186Ssam sc->sc_blkno += MIN(0377, fc); 4054736Swnj return (MBN_RETRY); 4064736Swnj 4074736Swnj case MTER_RWDING: 4084736Swnj return (MBN_SKIP); /* ignore "rewind started" interrupt */ 4094736Swnj 4104736Swnj case MTER_NOTCAP: 4114736Swnj printf("mu%d: blank tape\n", MUUNIT(bp->b_dev)); 4124736Swnj 4134736Swnj case MTER_TM: 4144736Swnj case MTER_EOT: 4154736Swnj case MTER_LEOT: 4167380Ssam if (sc->sc_blkno > bdbtofsb(bp->b_blkno)) { 4177380Ssam sc->sc_nxrec = bdbtofsb(bp->b_blkno) + fc; 4184736Swnj sc->sc_blkno = sc->sc_nxrec; 4194736Swnj } else { 4207380Ssam sc->sc_blkno = bdbtofsb(bp->b_blkno) - fc; 4214736Swnj sc->sc_nxrec = sc->sc_blkno - 1; 4224736Swnj } 4234736Swnj return (MBN_RETRY); 4244736Swnj 4254736Swnj case MTER_FPT: 4264736Swnj printf("mu%d: no write ring\n", MUUNIT(bp->b_dev)); 4274736Swnj bp->b_flags |= B_ERROR; 4284736Swnj return (MBN_DONE); 4294736Swnj 4304736Swnj case MTER_OFFLINE: 4314736Swnj if (sc->sc_openf > 0) { 4324736Swnj sc->sc_openf = -1; 4334736Swnj printf("mu%d: offline\n", MUUNIT(bp->b_dev)); 4344736Swnj } 4354736Swnj bp->b_flags |= B_ERROR; 4364736Swnj return (MBN_DONE); 4374736Swnj 4384736Swnj case MTER_BOT: 4394736Swnj if (bp == &cmtbuf[MTUNIT(bp->b_dev)]) 4404736Swnj goto done; 4414736Swnj /* FALL THROUGH */ 4424736Swnj 4434736Swnj default: 4444736Swnj printf("mu%d: hard error bn%d er=%o ds=%b\n", 4454736Swnj MUUNIT(bp->b_dev), bp->b_blkno, 4464736Swnj sc->sc_erreg, sc->sc_dsreg, mtds_bits); 4474736Swnj mtaddr->mtid = MTID_CLR; /* reset the TM78 */ 4484736Swnj DELAY(250); 4494736Swnj while ((mtaddr->mtid & MTID_RDY) == 0) /* wait for it */ 4504736Swnj ; 4514736Swnj bp->b_flags |= B_ERROR; 4524736Swnj return (MBN_DONE); 4534736Swnj } 4544736Swnj /* NOTREACHED */ 4554736Swnj } 4564736Swnj 457*7740Sroot mtread(dev, uio) 4584736Swnj dev_t dev; 459*7740Sroot struct uio *uio; 4604736Swnj { 4614736Swnj 462*7740Sroot u.u_error = mtphys(dev, uio); 4634736Swnj if (u.u_error) 4644736Swnj return; 465*7740Sroot physio(mtstrategy, &rmtbuf[MTUNIT(dev)], dev, B_READ, minphys, uio); 4664736Swnj } 4674736Swnj 4684736Swnj mtwrite(dev) 4694736Swnj { 4704736Swnj 471*7740Sroot mtphys(dev, 0); 4724736Swnj if (u.u_error) 4734736Swnj return; 474*7740Sroot physio(mtstrategy, &rmtbuf[MTUNIT(dev)], dev, B_WRITE, minphys, 0); 4754736Swnj } 4764736Swnj 477*7740Sroot mtphys(dev, uio) 4784736Swnj dev_t dev; 479*7740Sroot struct uio *uio; 4804736Swnj { 4814736Swnj register int mtunit; 4824736Swnj register struct mu_softc *sc; 4834736Swnj register struct mba_device *mi; 4844736Swnj daddr_t a; 4854736Swnj 4864736Swnj mtunit = MTUNIT(dev); 4874736Swnj if (mtunit >= NMT || (mi = mtinfo[mtunit]) == 0 || mi->mi_alive == 0) { 4884736Swnj u.u_error = ENXIO; 489*7740Sroot return (ENXIO); 4904736Swnj } 491*7740Sroot if (uio) 492*7740Sroot a = uio->uio_offset >> 9; 493*7740Sroot else 494*7740Sroot a = u.u_offset >> 9; 4954736Swnj sc = &mu_softc[MUUNIT(dev)]; 4967380Ssam sc->sc_blkno = bdbtofsb(a); 4977380Ssam sc->sc_nxrec = bdbtofsb(a)+1; 498*7740Sroot return (0); 4994736Swnj } 5004736Swnj 5014736Swnj /*ARGSUSED*/ 5027637Ssam mtioctl(dev, cmd, data, flag) 5034736Swnj dev_t dev; 5044736Swnj int cmd; 5057637Ssam caddr_t data; 5064736Swnj int flag; 5074736Swnj { 5084736Swnj register struct mu_softc *sc = &mu_softc[MUUNIT(dev)]; 5094736Swnj register struct buf *bp = &cmtbuf[MTUNIT(dev)]; 5104736Swnj register callcount; 5116186Ssam register int op; 5124736Swnj int fcount; 5137637Ssam struct mtop *mtop; 5147637Ssam struct mtget *mtget; 5154736Swnj /* we depend of the values and order of the MT codes here */ 5164736Swnj static mtops[] = 5174736Swnj {MT_WTM,MT_SFORWF,MT_SREVF,MT_SFORW,MT_SREV,MT_REW,MT_UNLOAD,MT_SENSE}; 5184736Swnj 5194736Swnj switch (cmd) { 5207637Ssam 5217637Ssam case MTIOCTOP: /* tape operation */ 5227637Ssam mtop = (struct mtop *)mtop; 5237637Ssam switch(mtop->mt_op) { 5247637Ssam 5254736Swnj case MTWEOF: 5267637Ssam callcount = mtop->mt_count; 5274736Swnj fcount = 1; 5284736Swnj break; 5297637Ssam 5304736Swnj case MTFSF: case MTBSF: 5317637Ssam callcount = mtop->mt_count; 5324736Swnj fcount = 1; 5334736Swnj break; 5347637Ssam 5354736Swnj case MTFSR: case MTBSR: 5364736Swnj callcount = 1; 5377637Ssam fcount = mtop->mt_count; 5384736Swnj break; 5397637Ssam 5404736Swnj case MTREW: case MTOFFL: 5414736Swnj callcount = 1; 5424736Swnj fcount = 1; 5434736Swnj break; 5447637Ssam 5454736Swnj default: 5464736Swnj u.u_error = ENXIO; 5474736Swnj return; 5484736Swnj } 5494736Swnj if (callcount <= 0 || fcount <= 0) { 5504736Swnj u.u_error = ENXIO; 5514736Swnj return; 5524736Swnj } 5537637Ssam op = mtops[mtop->mt_op]; 5544736Swnj if (op == MT_WTM) 5554736Swnj op |= sc->sc_dens; 5564736Swnj while (--callcount >= 0) { 5574736Swnj register int n; 5584736Swnj 5594736Swnj do { 5606186Ssam n = MIN(fcount, 0xff); 5614736Swnj mtcommand(dev, op, n); 5624736Swnj fcount -= n; 5634736Swnj } while (fcount); 5647637Ssam if ((mtop->mt_op == MTFSR || mtop->mt_op == MTBSR) && 5654736Swnj bp->b_resid) { 5664736Swnj u.u_error = EIO; 5674736Swnj break; 5684736Swnj } 5694736Swnj if (bp->b_flags&B_ERROR) 5704736Swnj break; 5714736Swnj } 5724736Swnj geterror(bp); 5734736Swnj return; 5747637Ssam 5754736Swnj case MTIOCGET: 5767637Ssam mtget = (struct mtget *)data; 5777637Ssam mtget->mt_erreg = sc->sc_erreg; 5787637Ssam mtget->mt_resid = sc->sc_resid; 5794736Swnj mtcommand(dev, MT_SENSE, 1); /* update drive status */ 5807637Ssam mtget->mt_dsreg = sc->sc_dsreg; 5817637Ssam mtget->mt_type = MT_ISMT; 5824736Swnj return; 5837637Ssam 5844736Swnj default: 5854736Swnj u.u_error = ENXIO; 5864736Swnj } 5874736Swnj } 5884736Swnj 5894736Swnj #define DBSIZE 20 5904736Swnj 5914736Swnj mtdump() 5924736Swnj { 5934736Swnj register struct mba_device *mi; 5944736Swnj register struct mba_regs *mp; 5954736Swnj register struct mtdevice *mtaddr; 5964736Swnj int blk, num; 5974736Swnj int start; 5984736Swnj 5994736Swnj start = 0; 6004736Swnj num = maxfree; 6014736Swnj #define phys(a,b) ((b)((int)(a)&0x7fffffff)) 6024736Swnj if (mtinfo[0] == 0) 6034736Swnj return (ENXIO); 6044736Swnj mi = phys(mtinfo[0], struct mba_device *); 6054736Swnj mp = phys(mi->mi_hd, struct mba_hd *)->mh_physmba; 6064736Swnj mp->mba_cr = MBCR_IE; 6076186Ssam #if lint 6086186Ssam blk = blk; num = num; start = start; 6096186Ssam return (0); 6106186Ssam #endif 6116186Ssam #ifdef notyet 6124736Swnj mtaddr = (struct mtdevice *)&mp->mba_drv[mi->mi_drive]; 6134736Swnj mtaddr->mttc = MTTC_PDP11|MTTC_1600BPI; 6144736Swnj mtaddr->mtcs1 = MT_DCLR|MT_GO; 6154736Swnj while (num > 0) { 6164736Swnj blk = num > DBSIZE ? DBSIZE : num; 6174736Swnj mtdwrite(start, blk, mtaddr, mp); 6184736Swnj start += blk; 6194736Swnj num -= blk; 6204736Swnj } 6214736Swnj mteof(mtaddr); 6224736Swnj mteof(mtaddr); 6234736Swnj mtwait(mtaddr); 6244736Swnj if (mtaddr->mtds&MTDS_ERR) 6254736Swnj return (EIO); 6264736Swnj mtaddr->mtcs1 = MT_REW|MT_GO; 6274736Swnj return (0); 6284736Swnj } 6294736Swnj 6304736Swnj mtdwrite(dbuf, num, mtaddr, mp) 6314736Swnj register dbuf, num; 6324736Swnj register struct mtdevice *mtaddr; 6334736Swnj struct mba_regs *mp; 6344736Swnj { 6354736Swnj register struct pte *io; 6364736Swnj register int i; 6374736Swnj 6384736Swnj mtwait(mtaddr); 6394736Swnj io = mp->mba_map; 6404736Swnj for (i = 0; i < num; i++) 6414736Swnj *(int *)io++ = dbuf++ | PG_V; 6424736Swnj mtaddr->mtfc = -(num*NBPG); 6434736Swnj mp->mba_sr = -1; 6444736Swnj mp->mba_bcr = -(num*NBPG); 6454736Swnj mp->mba_var = 0; 6464736Swnj mtaddr->mtcs1 = MT_WCOM|MT_GO; 6474736Swnj } 6484736Swnj 6494736Swnj mtwait(mtaddr) 6504736Swnj struct mtdevice *mtaddr; 6514736Swnj { 6524736Swnj register s; 6534736Swnj 6544736Swnj do 6554736Swnj s = mtaddr->mtds; 6564736Swnj while ((s & MTDS_DRY) == 0); 6574736Swnj } 6584736Swnj 6594736Swnj mteof(mtaddr) 6604736Swnj struct mtdevice *mtaddr; 6614736Swnj { 6624736Swnj 6634736Swnj mtwait(mtaddr); 6644736Swnj mtaddr->mtcs1 = MT_WEOF|MT_GO; 6654736Swnj #endif notyet 6664736Swnj } 6674736Swnj #endif 668