xref: /csrg-svn/sys/vax/mba/ht.c (revision 2980)
1*2980Swnj /*	ht.c	4.8	81/03/07	*/
22961Swnj 
3*2980Swnj #include "tu.h"
41563Sbill #if NHT > 0
522Sbill /*
62926Swnj  * TM03/TU?? tape driver
722Sbill  */
822Sbill #include "../h/param.h"
922Sbill #include "../h/systm.h"
1022Sbill #include "../h/buf.h"
1122Sbill #include "../h/conf.h"
1222Sbill #include "../h/dir.h"
1322Sbill #include "../h/file.h"
1422Sbill #include "../h/user.h"
1522Sbill #include "../h/map.h"
16420Sbill #include "../h/pte.h"
17*2980Swnj #include "../h/mbareg.h"
18*2980Swnj #include "../h/mbavar.h"
192926Swnj #include "../h/mtio.h"
202926Swnj #include "../h/ioctl.h"
211917Swnj #include "../h/cmap.h"
222961Swnj #include "../h/cpu.h"
2322Sbill 
242926Swnj #include "../h/htreg.h"
2522Sbill 
262926Swnj struct	buf	rhtbuf[NHT];
272926Swnj struct	buf	chtbuf[NHT];
2822Sbill 
292926Swnj short	httypes[] =
302926Swnj 	{ MBDT_TE16, MBDT_TU45, MBDT_TU77, 0 };
31*2980Swnj struct	mba_device *htinfo[NHT];
32*2980Swnj int	htdkinit(), htattach(), htslave(), htustart(), htndtint(), htdtint();
332926Swnj struct	mba_driver htdriver =
34*2980Swnj     { htattach, htslave, htustart, 0, htdtint, htndtint,
35*2980Swnj       httypes, "ht", "tu", htinfo };
3622Sbill 
372926Swnj #define MASKREG(r)	((r) & 0xffff)
3822Sbill 
392926Swnj /* bits in minor device */
40*2980Swnj #define	TUUNIT(dev)	(minor(dev)&03)
412926Swnj #define	H_NOREWIND	04
422926Swnj #define	H_1600BPI	08
4322Sbill 
44*2980Swnj #define HTUNIT(dev)	(htunit[TUUNIT(dev)])
45*2980Swnj 
462926Swnj #define	INF	(daddr_t)1000000L	/* a block number that wont exist */
472926Swnj 
482926Swnj struct	ht_softc {
492926Swnj 	char	sc_openf;
502926Swnj 	char	sc_flags;
512926Swnj 	daddr_t	sc_blkno;
522926Swnj 	daddr_t	sc_nxrec;
532926Swnj 	u_short	sc_erreg;
542926Swnj 	u_short	sc_dsreg;
552926Swnj 	short	sc_resid;
562926Swnj 	short	sc_dens;
57*2980Swnj 	struct	mba_device *sc_mi;
58*2980Swnj 	int	sc_slave;
59*2980Swnj } ht_softc[NTU];
60*2980Swnj short	htunit[NTU];
612926Swnj 
622926Swnj /*
632926Swnj  * Bits for sc_flags.
642926Swnj  */
652926Swnj #define	H_WRITTEN 1	/* last operation was a write */
662926Swnj #define H_ERASED  2	/* last write retry was an erase gap */
672926Swnj #define H_REWIND  4	/* last unit start was a rewind */
6822Sbill 
692926Swnj /*ARGSUSED*/
70*2980Swnj htattach(mi)
71*2980Swnj 	struct mba_device *mi;
722926Swnj {
732926Swnj 
742926Swnj }
752926Swnj 
76*2980Swnj htslave(mi, ms)
77*2980Swnj 	struct mba_device *mi;
78*2980Swnj 	struct mba_slave *ms;
79*2980Swnj {
80*2980Swnj 	register struct ht_softc *sc = &ht_softc[ms->ms_unit];
81*2980Swnj 
82*2980Swnj 	sc->sc_mi = mi;
83*2980Swnj 	sc->sc_slave = ms->ms_slave;
84*2980Swnj 	htunit[ms->ms_unit] = mi->mi_unit;
85*2980Swnj }
86*2980Swnj 
8722Sbill htopen(dev, flag)
882926Swnj 	dev_t dev;
892926Swnj 	int flag;
9022Sbill {
912926Swnj 	register int unit;
92*2980Swnj 	register struct mba_device *mi;
932926Swnj 	register struct ht_softc *sc;
9422Sbill 
95*2980Swnj 	unit = TUUNIT(dev);
96*2980Swnj 	if (unit >= NTU || (sc = &ht_softc[unit])->sc_openf ||
97*2980Swnj 	    (mi = htinfo[HTUNIT(dev)]) == 0 || mi->mi_alive == 0) {
9822Sbill 		u.u_error = ENXIO;
9922Sbill 		return;
10022Sbill 	}
1012926Swnj 	/*
1022926Swnj 	 * The NOP below serves two purposes:
1032926Swnj 	 * 1. To get a recent copy of the status registers.
1042926Swnj 	 * 2. To ensure that any outstanding rewinds are truly finished
1052926Swnj 	 */
1062926Swnj 	htcommand(dev, HT_SENSE, 1);
1072926Swnj 	if ((sc->sc_dsreg & HTDS_MOL) == 0 ||
1082926Swnj 	   (flag & (FREAD|FWRITE)) == FWRITE && sc->sc_dsreg&HTDS_WRL) {
1092926Swnj 		u.u_error = EIO;
1102926Swnj 		return;
1112926Swnj 	}
1122926Swnj 	sc->sc_dens =
1132961Swnj 	    ((minor(dev)&H_1600BPI)?HTTC_1600BPI:HTTC_800BPI)|
114*2980Swnj 		HTTC_PDP11|sc->sc_slave;
1152926Swnj 	sc->sc_openf = 1;
1162926Swnj 	sc->sc_blkno = (daddr_t)0;
1172926Swnj 	sc->sc_nxrec = INF;
1182926Swnj 	sc->sc_flags = 0;
11922Sbill }
12022Sbill 
12122Sbill htclose(dev, flag)
1222926Swnj 	register dev_t dev;
1232926Swnj 	register flag;
12422Sbill {
125*2980Swnj 	register struct ht_softc *sc = &ht_softc[TUUNIT(dev)];
12622Sbill 
1272926Swnj 	if (flag == FWRITE || ((flag&FWRITE) && (sc->sc_flags&H_WRITTEN))) {
1282926Swnj 		htcommand(dev, HT_WEOF, 1);
1292926Swnj 		htcommand(dev, HT_WEOF, 1);
1302926Swnj 		htcommand(dev, HT_SREV, 1);
13122Sbill 	}
1322926Swnj 	if ((minor(dev)&H_NOREWIND) == 0)
1332926Swnj 		/* 0 as third arg means don't wait */
1342926Swnj 		htcommand(dev, HT_REW, 0);
1352926Swnj 	sc->sc_openf = 0;
13622Sbill }
13722Sbill 
1382926Swnj /*
1392926Swnj  * Do a non-data-transfer command.
1402926Swnj  *
1412926Swnj  * N.B.: Count should be zero ONLY for rewind during close.
1422926Swnj  */
1432926Swnj htcommand(dev, com, count)
1442926Swnj 	dev_t dev;
1452926Swnj 	int com, count;
14622Sbill {
14722Sbill 	register struct buf *bp;
14822Sbill 
1492926Swnj 	bp = &chtbuf[HTUNIT(dev)];
150128Sbill 	(void) spl5();
1512926Swnj 	while (bp->b_flags&B_BUSY) {
152*2980Swnj 		if (bp->b_command == H_REWIND && bp->b_repcnt == 0 &&
153*2980Swnj 		    (bp->b_flags&B_DONE))
154*2980Swnj 			break;
15522Sbill 		bp->b_flags |= B_WANTED;
15622Sbill 		sleep((caddr_t)bp, PRIBIO);
15722Sbill 	}
1582943Swnj 	bp->b_flags = B_BUSY|B_READ;
159128Sbill 	(void) spl0();
16022Sbill 	bp->b_dev = dev;
1612926Swnj 	bp->b_command = com;
1622926Swnj 	bp->b_repcnt = count;
16322Sbill 	bp->b_blkno = 0;
16422Sbill 	htstrategy(bp);
1652926Swnj 	if (count == 0)
1662926Swnj 		return;
16722Sbill 	iowait(bp);
1682926Swnj 	if (bp->b_flags&B_WANTED)
16922Sbill 		wakeup((caddr_t)bp);
1702926Swnj 	bp->b_flags &= B_ERROR;
17122Sbill }
17222Sbill 
17322Sbill htstrategy(bp)
1742926Swnj 	register struct buf *bp;
17522Sbill {
1762926Swnj 	register int unit = HTUNIT(bp->b_dev);
177*2980Swnj 	register struct mba_device *mi = htinfo[unit];
1782926Swnj 	register struct buf *dp;
17922Sbill 
18022Sbill 	bp->av_forw = NULL;
1812926Swnj 	dp = &mi->mi_tab;
182128Sbill 	(void) spl5();
1832926Swnj 	if (dp->b_actf == NULL)
1842926Swnj 		dp->b_actf = bp;
18522Sbill 	else
1862926Swnj 		dp->b_actl->av_forw = bp;
1872926Swnj 	dp->b_actl = bp;
1882926Swnj 	if (dp->b_active == 0)
1892926Swnj 		mbustart(mi);
190128Sbill 	(void) spl0();
19122Sbill }
19222Sbill 
1932926Swnj htustart(mi)
194*2980Swnj 	register struct mba_device *mi;
19522Sbill {
1962926Swnj 	register struct htdevice *htaddr =
1972926Swnj 	    (struct htdevice *)mi->mi_drv;
1982926Swnj 	register struct buf *bp = mi->mi_tab.b_actf;
199*2980Swnj 	int unit = TUUNIT(bp->b_dev);
2002926Swnj 	register struct ht_softc *sc = &ht_softc[unit];
20122Sbill 	daddr_t blkno;
20222Sbill 
2032926Swnj 	htaddr->httc = sc->sc_dens;
2042926Swnj 	sc->sc_dsreg = htaddr->htds;
2052926Swnj 	sc->sc_erreg = htaddr->hter;
2062926Swnj 	sc->sc_resid = htaddr->htfc;
2072926Swnj 	sc->sc_flags &= ~(H_WRITTEN|H_REWIND);
2082926Swnj 	if ((htaddr->htdt & HTDT_SPR) == 0 || (htaddr->htds & HTDS_MOL) == 0)
2092926Swnj 		if (sc->sc_openf > 0)
2102926Swnj 			sc->sc_openf = -1;
2112926Swnj 	if (sc->sc_openf < 0) {
2122926Swnj 		bp->b_flags |= B_ERROR;
2132926Swnj 		return (MBU_NEXT);
2142926Swnj 	}
2152926Swnj 	if (bp != &chtbuf[unit]) {
2162926Swnj 		if (dbtofsb(bp->b_blkno) > sc->sc_nxrec) {
2172926Swnj 			bp->b_flags |= B_ERROR;
2182926Swnj 			bp->b_error = ENXIO;
2192961Swnj 			return (MBU_NEXT);
2202926Swnj 		} else if (dbtofsb(bp->b_blkno) == sc->sc_nxrec &&
2212926Swnj 		    bp->b_flags&B_READ) {
2222926Swnj 			bp->b_resid = bp->b_bcount;
2232926Swnj 			clrbuf(bp);
2242961Swnj 			return (MBU_NEXT);
2252926Swnj 		} else if ((bp->b_flags&B_READ)==0)
2262926Swnj 			sc->sc_nxrec = dbtofsb(bp->b_blkno) + 1;
2272926Swnj 	} else {
2282961Swnj 		if (bp->b_command == HT_SENSE)
2292926Swnj 			return (MBU_NEXT);
2302926Swnj 		if (bp->b_command == HT_REW)
2312926Swnj 			sc->sc_flags |= H_REWIND;
2322926Swnj 		else
2332926Swnj 			htaddr->htfc = -bp->b_bcount;
2342926Swnj 		htaddr->htcs1 = bp->b_command|HT_GO;
2352926Swnj 		return (MBU_STARTED);
2362926Swnj 	}
2372926Swnj 	if ((blkno = sc->sc_blkno) == dbtofsb(bp->b_blkno)) {
2382926Swnj 		htaddr->htfc = -bp->b_bcount;
2392926Swnj 		if ((bp->b_flags&B_READ) == 0) {
2402926Swnj 			if (mi->mi_tab.b_errcnt)
2412926Swnj 				if (sc->sc_flags & H_ERASED)
2422926Swnj 					sc->sc_flags &= ~H_ERASED;
2432926Swnj 				else {
2442926Swnj 					sc->sc_flags |= H_ERASED;
2452926Swnj 					htaddr->htcs1 = HT_ERASE | HT_GO;
2462926Swnj 					return (MBU_STARTED);
2472926Swnj 				}
2482926Swnj 			if (htaddr->htds & HTDS_EOT) {
2492926Swnj 				bp->b_resid = bp->b_bcount;
2502926Swnj 				return (MBU_NEXT);
2512926Swnj 			}
25222Sbill 		}
2532926Swnj 		return (MBU_DODATA);
25422Sbill 	}
2552926Swnj 	if (blkno < dbtofsb(bp->b_blkno)) {
2562926Swnj 		htaddr->htfc = blkno - dbtofsb(bp->b_blkno);
2572926Swnj 		htaddr->htcs1 = HT_SFORW|HT_GO;
25822Sbill 	} else {
2592926Swnj 		htaddr->htfc = dbtofsb(bp->b_blkno) - blkno;
2602926Swnj 		htaddr->htcs1 = HT_SREV|HT_GO;
26122Sbill 	}
2622926Swnj 	return (MBU_STARTED);
26322Sbill }
26422Sbill 
2652926Swnj /*
2662926Swnj  * data transfer interrupt - must be read or write
2672926Swnj  */
26822Sbill /*ARGSUSED*/
2692926Swnj htdtint(mi, mbasr)
270*2980Swnj 	register struct mba_device *mi;
2712926Swnj 	int mbasr;
27222Sbill {
2732926Swnj 	register struct htdevice *htaddr = (struct htdevice *)mi->mi_drv;
2742926Swnj 	register struct buf *bp = mi->mi_tab.b_actf;
2752926Swnj 	register struct ht_softc *sc;
2762961Swnj 	int ds, er, mbs;
27722Sbill 
278*2980Swnj 	sc = &ht_softc[TUUNIT(bp->b_dev)];
2792926Swnj 	ds = sc->sc_dsreg = MASKREG(htaddr->htds);
2802926Swnj 	er = sc->sc_erreg = MASKREG(htaddr->hter);
2812926Swnj 	sc->sc_resid = MASKREG(htaddr->htfc);
2822961Swnj 	mbs = mbasr;
2832926Swnj 	sc->sc_blkno++;
2842926Swnj 	if((bp->b_flags & B_READ) == 0)
2852926Swnj 		sc->sc_flags |= H_WRITTEN;
2862926Swnj 	if ((ds&(HTDS_ERR|HTDS_MOL)) != HTDS_MOL ||
2872961Swnj 	    mbs & MBAEBITS) {
2882926Swnj 		htaddr->htcs1 = HT_DCLR|HT_GO;
2892961Swnj 		mbclrattn(mi);
2902961Swnj 		if (bp == &rhtbuf[HTUNIT(bp->b_dev)]) {
2912926Swnj 			er &= ~HTER_FCE;
2922961Swnj 			mbs &= ~(MBS_DTABT|MBS_MBEXC);
2932961Swnj 		}
2942926Swnj 		if (bp->b_flags & B_READ && ds & HTDS_PES)
2952926Swnj 			er &= ~(HTER_CSITM|HTER_CORCRC);
2962926Swnj 		if (er&HTER_HARD ||
2972961Swnj 		    mbs&MBAEBITS || (ds&HTDS_MOL) == 0 ||
2982961Swnj 		    er && ++mi->mi_tab.b_errcnt >= 7) {
2992926Swnj 			if ((ds & HTDS_MOL) == 0 && sc->sc_openf > 0)
3002926Swnj 				sc->sc_openf = -1;
301*2980Swnj 			printf("tu%d: hard error bn%d mbasr=%b er=%b\n",
302*2980Swnj 			    TUUNIT(bp->b_dev), bp->b_blkno,
3032926Swnj 			    mbasr, mbasr_bits,
3042926Swnj 			    MASKREG(htaddr->hter), HTER_BITS);
30522Sbill 			bp->b_flags |= B_ERROR;
3062926Swnj 			return (MBD_DONE);
30722Sbill 		}
3082926Swnj 		if (er)
3092926Swnj 			return (MBD_RETRY);
31022Sbill 	}
3112926Swnj 	bp->b_resid = 0;
3122926Swnj 	if (bp->b_flags & B_READ)
3132926Swnj 		if (ds&HTDS_TM) {		/* must be a read, right? */
3142926Swnj 			bp->b_resid = bp->b_bcount;
3152926Swnj 			sc->sc_nxrec = dbtofsb(bp->b_blkno);
3162926Swnj 		} else if(bp->b_bcount > MASKREG(htaddr->htfc))
3172926Swnj 			bp->b_resid = bp->b_bcount - MASKREG(htaddr->htfc);
3182926Swnj 	return (MBD_DONE);
3192926Swnj }
32022Sbill 
3212926Swnj /*
3222926Swnj  * non-data-transfer interrupt
3232926Swnj  */
3242926Swnj htndtint(mi)
325*2980Swnj 	register struct mba_device *mi;
3262926Swnj {
3272926Swnj 	register struct htdevice *htaddr = (struct htdevice *)mi->mi_drv;
3282926Swnj 	register struct buf *bp = mi->mi_tab.b_actf;
3292926Swnj 	register struct ht_softc *sc;
3302926Swnj 	int er, ds, fc;
33122Sbill 
332*2980Swnj 	if (bp == 0)
333*2980Swnj 		return (MBN_SKIP);
334*2980Swnj 	sc = &ht_softc[TUUNIT(bp->b_dev)];
3352926Swnj 	ds = sc->sc_dsreg = MASKREG(htaddr->htds);
3362926Swnj 	er = sc->sc_erreg = MASKREG(htaddr->hter);
3372961Swnj 	fc = sc->sc_resid = MASKREG(htaddr->htfc);
3382961Swnj 	if (sc->sc_erreg) {
3392926Swnj 		htaddr->htcs1 = HT_DCLR|HT_GO;
3402961Swnj 		mbclrattn(mi);
3412961Swnj 	}
342*2980Swnj 	if (sc->sc_flags&H_REWIND) {
343*2980Swnj 		sc->sc_flags &= ~H_REWIND;
344*2980Swnj 		return (MBN_CONT);
345*2980Swnj 	}
346*2980Swnj 	if (bp == &chtbuf[TUUNIT(bp->b_dev)]) {
3472926Swnj 		if (bp->b_command == HT_REWOFFL)
3482926Swnj 			/* offline is on purpose; don't do anything special */
3492926Swnj 			ds |= HTDS_MOL;
3502926Swnj 		else if (bp->b_resid == HT_SREV &&
3512926Swnj 		    er == (HTER_NEF|HTER_FCE) &&
3522926Swnj 		    ds&HTDS_BOT && bp->b_bcount == INF)
3532926Swnj 			er &= ~HTER_NEF;
3542926Swnj 		er &= ~HTER_FCE;
3552926Swnj 		if (er == 0)
3562926Swnj 			ds &= ~HTDS_ERR;
35722Sbill 	}
3582926Swnj 	if ((ds & (HTDS_ERR|HTDS_MOL)) != HTDS_MOL) {
3592926Swnj 		if ((ds & HTDS_MOL) == 0 && sc->sc_openf > 0)
3602926Swnj 			sc->sc_openf = -1;
361*2980Swnj 		printf("tu%d: hard error bn%d er=%b ds=%b\n",
362*2980Swnj 		    TUUNIT(bp->b_dev), bp->b_blkno,
3632926Swnj 		    sc->sc_erreg, HTER_BITS, sc->sc_dsreg, HTDS_BITS);
3642926Swnj 		bp->b_flags |= B_ERROR;
3652926Swnj 		return (MBN_DONE);
3662926Swnj 	}
367*2980Swnj 	if (bp == &chtbuf[TUUNIT(bp->b_dev)]) {
3682926Swnj 		if (sc->sc_flags & H_REWIND)
3692926Swnj 			return (ds & HTDS_BOT ? MBN_DONE : MBN_RETRY);
3702926Swnj 		bp->b_resid = -sc->sc_resid;
3712926Swnj 		return (MBN_DONE);
3722926Swnj 	}
3732926Swnj 	if (ds & HTDS_TM)
3742926Swnj 		if (sc->sc_blkno > dbtofsb(bp->b_blkno)) {/* reversing */
3752926Swnj 			sc->sc_nxrec = dbtofsb(bp->b_blkno) - fc;
3762926Swnj 			sc->sc_blkno = sc->sc_nxrec;
3772926Swnj 		} else {			/* spacing forward */
3782926Swnj 			sc->sc_blkno = dbtofsb(bp->b_blkno) + fc;
3792926Swnj 			sc->sc_nxrec = sc->sc_blkno - 1;
3802926Swnj 		}
3812926Swnj 	else
3822926Swnj 		sc->sc_blkno = dbtofsb(bp->b_blkno);
3832926Swnj 	return (MBN_RETRY);
38422Sbill }
38522Sbill 
38622Sbill htread(dev)
3872926Swnj 	dev_t dev;
38822Sbill {
3892926Swnj 
39022Sbill 	htphys(dev);
3912926Swnj 	if (u.u_error)
3922926Swnj 		return;
3932926Swnj 	physio(htstrategy, &rhtbuf[HTUNIT(dev)], dev, B_READ, minphys);
39422Sbill }
39522Sbill 
39622Sbill htwrite(dev)
39722Sbill {
3982926Swnj 
39922Sbill 	htphys(dev);
4002926Swnj 	if (u.u_error)
4012926Swnj 		return;
4022926Swnj 	physio(htstrategy, &rhtbuf[HTUNIT(dev)], dev, B_WRITE, minphys);
40322Sbill }
40422Sbill 
40522Sbill htphys(dev)
4062926Swnj 	dev_t dev;
40722Sbill {
4082926Swnj 	register int unit;
4092926Swnj 	register struct ht_softc *sc;
41022Sbill 	daddr_t a;
41122Sbill 
4122926Swnj 	unit = HTUNIT(dev);
4132926Swnj 	if (unit >= NHT) {
4142926Swnj 		u.u_error = ENXIO;
4152926Swnj 		return;
41622Sbill 	}
4172926Swnj 	a = u.u_offset >> 9;
4182926Swnj 	sc = &ht_softc[unit];
4192926Swnj 	sc->sc_blkno = dbtofsb(a);
4202926Swnj 	sc->sc_nxrec = dbtofsb(a)+1;
42122Sbill }
4221917Swnj 
4232926Swnj /*ARGSUSED*/
4242926Swnj htioctl(dev, cmd, addr, flag)
4252926Swnj 	dev_t dev;
4262926Swnj 	int cmd;
4272926Swnj 	caddr_t addr;
4282926Swnj 	int flag;
4292926Swnj {
4302926Swnj 	register unit = HTUNIT(dev);
4312926Swnj 	register struct ht_softc *sc = &ht_softc[unit];
4322926Swnj 	register struct buf *bp = &chtbuf[unit];
4332926Swnj 	register callcount;
4342926Swnj 	int fcount;
4352926Swnj 	struct mtop mtop;
4362926Swnj 	struct mtget mtget;
4372926Swnj 	/* we depend of the values and order of the MT codes here */
4382926Swnj 	static htops[] =
4392926Swnj    {HT_WEOF,HT_SFORW,HT_SREV,HT_SFORW,HT_SREV,HT_REW,HT_REWOFFL,HT_SENSE};
4401917Swnj 
4412926Swnj 	switch (cmd) {
4422926Swnj 		case MTIOCTOP:	/* tape operation */
4432926Swnj 		if (copyin((caddr_t)addr, (caddr_t)&mtop, sizeof(mtop))) {
4442926Swnj 			u.u_error = EFAULT;
4452926Swnj 			return;
4462926Swnj 		}
4472926Swnj 		switch(mtop.mt_op) {
4482926Swnj 		case MTWEOF:
4492926Swnj 			callcount = mtop.mt_count;
4502926Swnj 			fcount = 1;
4512926Swnj 			break;
4522926Swnj 		case MTFSF: case MTBSF:
4532926Swnj 			callcount = mtop.mt_count;
4542926Swnj 			fcount = INF;
4552926Swnj 			break;
4562926Swnj 		case MTFSR: case MTBSR:
4572926Swnj 			callcount = 1;
4582926Swnj 			fcount = mtop.mt_count;
4592926Swnj 			break;
4602926Swnj 		case MTREW: case MTOFFL:
4612926Swnj 			callcount = 1;
4622926Swnj 			fcount = 1;
4632926Swnj 			break;
4642926Swnj 		default:
4652926Swnj 			u.u_error = ENXIO;
4662926Swnj 			return;
4672926Swnj 		}
4682926Swnj 		if (callcount <= 0 || fcount <= 0) {
4692926Swnj 			u.u_error = ENXIO;
4702926Swnj 			return;
4712926Swnj 		}
4722926Swnj 		while (--callcount >= 0) {
4732926Swnj 			htcommand(dev, htops[mtop.mt_op], fcount);
4742926Swnj 			if ((mtop.mt_op == MTFSR || mtop.mt_op == MTBSR) &&
4752926Swnj 			    bp->b_resid) {
4762926Swnj 				u.u_error = EIO;
4772926Swnj 				break;
4782926Swnj 			}
4792926Swnj 			if ((chtbuf[HTUNIT(bp->b_dev)].b_flags&B_ERROR) ||
4802926Swnj 			    sc->sc_dsreg&HTDS_BOT)
4812926Swnj 				break;
4822926Swnj 		}
4832926Swnj 		geterror(bp);
4842926Swnj 		return;
4852926Swnj 	case MTIOCGET:
4862926Swnj 		mtget.mt_dsreg = sc->sc_dsreg;
4872926Swnj 		mtget.mt_erreg = sc->sc_erreg;
4882926Swnj 		mtget.mt_resid = sc->sc_resid;
4892926Swnj 		if (copyout((caddr_t)&mtget, addr, sizeof(mtget)))
4902926Swnj 			u.u_error = EFAULT;
4912926Swnj 		return;
4922926Swnj 	default:
4932926Swnj 		u.u_error = ENXIO;
4942926Swnj 	}
4952926Swnj }
4962926Swnj 
4971917Swnj #define	DBSIZE	20
4981917Swnj 
4992926Swnj htdump()
5001917Swnj {
501*2980Swnj 	register struct mba_device *mi;
5022926Swnj 	register struct mba_regs *mp;
5032926Swnj 	register struct htdevice *htaddr;
5042926Swnj 	int blk, num;
5052926Swnj 	int start;
5061917Swnj 
5072926Swnj 	start = 0;
5082926Swnj 	num = maxfree;
5092926Swnj #define	phys(a,b)		((b)((int)(a)&0x7fffffff))
5102926Swnj 	if (htinfo[0] == 0)
5112926Swnj 		return (ENXIO);
512*2980Swnj 	mi = phys(htinfo[0], struct mba_device *);
5132926Swnj 	mp = phys(mi->mi_hd, struct mba_hd *)->mh_physmba;
5142926Swnj #if VAX780
5152961Swnj 	if (cpu == VAX780)
5162961Swnj 		mbainit(mp);
5172961Swnj #endif
5182926Swnj 	htaddr = (struct htdevice *)&mp->mba_drv[mi->mi_drive];
5192926Swnj 	htaddr->httc = HTTC_PDP11|HTTC_1600BPI;
5202926Swnj 	htaddr->htcs1 = HT_DCLR|HT_GO;
5211917Swnj 	while (num > 0) {
5221917Swnj 		blk = num > DBSIZE ? DBSIZE : num;
5232926Swnj 		htdwrite(start, blk, htaddr, mp);
5242926Swnj 		start += blk;
5251917Swnj 		num -= blk;
5261917Swnj 	}
5272926Swnj 	htwait(htaddr);
5282926Swnj 	htaddr->htcs1 = HT_REW|HT_GO;
5292926Swnj 	hteof(htaddr);
5302926Swnj 	hteof(htaddr);
5311917Swnj }
5321917Swnj 
5332926Swnj htdwrite(dbuf, num, htaddr, mp)
5342926Swnj 	register dbuf, num;
5352926Swnj 	register struct htdevice *htaddr;
5362926Swnj 	struct mba_regs *mp;
5371917Swnj {
5382926Swnj 	register struct pte *io;
5391917Swnj 	register int i;
5401917Swnj 
5412926Swnj 	htwait(htaddr);
5422926Swnj 	io = mp->mba_map;
5431917Swnj 	for (i = 0; i < num; i++)
5442926Swnj 		*(int *)io++ = dbuf++ | PG_V;
5452926Swnj 	htaddr->htfc = -(num*NBPG);
5462926Swnj 	mp->mba_sr = -1;
5472926Swnj 	mp->mba_bcr = -(num*NBPG);
5482926Swnj 	mp->mba_var = 0;
5492926Swnj 	htaddr->htcs1 = HT_WCOM|HT_GO;
5501917Swnj }
5511917Swnj 
5522926Swnj htwait(htaddr)
5532926Swnj 	struct htdevice *htaddr;
5541917Swnj {
5551917Swnj 	register s;
5561917Swnj 
5571917Swnj 	do
5582926Swnj 		s = htaddr->htds;
5592926Swnj 	while ((s & HTDS_DRY) == 0);
5601917Swnj }
5611917Swnj 
5622926Swnj hteof(htaddr)
5632926Swnj 	struct htdevice *htaddr;
5641917Swnj {
5651917Swnj 
5662926Swnj 	htwait(htaddr);
5672926Swnj 	htaddr->htcs1 = HT_WEOF|HT_GO;
5681917Swnj }
5691563Sbill #endif
570