xref: /csrg-svn/sys/vax/mba/mt.c (revision 18324)
1*18324Sralph /*	mt.c	6.4	85/03/13	*/
24736Swnj 
34736Swnj #include "mu.h"
44736Swnj #if NMT > 0
54736Swnj /*
64736Swnj  * TM78/TU78 tape driver
74736Swnj  *
817214Smckusick  *	Original author - ?
917214Smckusick  *	Most error recovery bug fixes - ggs (ulysses!ggs)
104736Swnj  *
1117214Smckusick  * OPTIONS:
1217214Smckusick  *	MTLERRM - Long error message text - twd, Brown University
1317214Smckusick  *	MTRDREV - `read reverse' error recovery - ggs (ulysses!ggs)
1417214Smckusick  *
154736Swnj  * TODO:
1617214Smckusick  *	Add odd byte count kludge from VMS driver (?)
1717214Smckusick  *	Write dump routine
184736Swnj  */
1917214Smckusick 
209789Ssam #include "../machine/pte.h"
219789Ssam 
2217119Sbloom #include "param.h"
2317119Sbloom #include "systm.h"
2417119Sbloom #include "buf.h"
2517119Sbloom #include "conf.h"
2617119Sbloom #include "dir.h"
2717119Sbloom #include "file.h"
2817119Sbloom #include "user.h"
2917119Sbloom #include "map.h"
3017119Sbloom #include "ioctl.h"
3117119Sbloom #include "mtio.h"
3217119Sbloom #include "cmap.h"
3317119Sbloom #include "uio.h"
34*18324Sralph #include "tty.h"
354736Swnj 
368471Sroot #include "../vax/cpu.h"
3717119Sbloom #include "mbareg.h"
3817119Sbloom #include "mbavar.h"
3917119Sbloom #include "mtreg.h"
404736Swnj 
4117214Smckusick #define MTTIMEOUT	10000		/* loop limit for controller test */
4217214Smckusick #define	INF		1000000L	/* a block number that won't exist */
4317214Smckusick #define MASKREG(r)	((r) & 0xffff)	/* the control registers have 16 bits */
444736Swnj 
4517214Smckusick /* Bits for sc_flags */
464736Swnj 
4717214Smckusick #define	H_WRITTEN	01		/* last operation was a write */
4817214Smckusick #define H_EOT		02		/* end of tape encountered */
4917214Smckusick #define H_IEOT		04		/* ignore EOT condition */
504736Swnj 
5117214Smckusick /* Bits in minor device */
5217214Smckusick 
534736Swnj #define	MUUNIT(dev)	(minor(dev)&03)
544736Swnj #define	H_NOREWIND	04
5517214Smckusick #define	H_6250BPI	010
564736Swnj 
574736Swnj #define MTUNIT(dev)	(mutomt[MUUNIT(dev)])
584736Swnj 
5917214Smckusick #ifdef MTRDREV
6017214Smckusick 	int mt_do_readrev = 1;
6117214Smckusick #else
6217214Smckusick 	int mt_do_readrev = 0;
6317214Smckusick #endif
644736Swnj 
6517214Smckusick /* Per unit status information */
6617214Smckusick 
674736Swnj struct	mu_softc {
6817214Smckusick 	char	sc_openf;		/* unit is open if != 0 */
6917214Smckusick 	char	sc_flags;		/* state flags */
7017214Smckusick 	daddr_t	sc_blkno;		/* current physical block number */
7117214Smckusick 	daddr_t	sc_nxrec;		/* firewall input block number */
7217214Smckusick 	u_short	sc_erreg;		/* copy of mter or mtner */
7317214Smckusick 	u_short	sc_dsreg;		/* copy of mtds */
7417214Smckusick 	short	sc_resid;		/* residual function count for ioctl */
7517214Smckusick 	short	sc_dens;		/* density code - MT_GCR or zero */
7617214Smckusick 	struct	mba_device *sc_mi;	/* massbus structure for unit */
7717214Smckusick 	int	sc_slave;		/* slave number for unit */
7817214Smckusick 	int	sc_i_mtas;		/* mtas at slave attach time */
7917214Smckusick 	int	sc_i_mtner;		/* mtner at slave attach time */
8017214Smckusick 	int	sc_i_mtds;		/* mtds at slave attach time */
8117214Smckusick #ifdef MTLERRM
8217214Smckusick 	char	*sc_mesg;		/* text for interrupt type code */
8317214Smckusick 	char	*sc_fmesg;		/* text for tape error code */
8417214Smckusick #endif
85*18324Sralph 	struct	tty *sc_ttyp;		/* record user's tty for errors */
864736Swnj } mu_softc[NMU];
874736Swnj 
8817214Smckusick struct	buf	rmtbuf[NMT];		/* data transfer buffer structures */
8917214Smckusick struct	buf	cmtbuf[NMT];		/* tape command buffer structures */
904736Swnj 
9117214Smckusick struct	mba_device *mtinfo[NMT];	/* unit massbus structure pointers */
9217214Smckusick short	mutomt[NMU];			/* tape unit to controller number map */
9317214Smckusick char	mtds_bits[] = MTDS_BITS;	/* mtds bit names for error messages */
9417214Smckusick short	mttypes[] = { MBDT_TU78, 0 };
954736Swnj 
9617214Smckusick int	mtattach(), mtslave(), mtustart(), mtstart(), mtndtint(), mtdtint();
9717214Smckusick struct	mba_driver mtdriver =
9817214Smckusick 	{ mtattach, mtslave, mtustart, mtstart, mtdtint, mtndtint,
9917214Smckusick 	  mttypes, "mt", "mu", mtinfo };
10017214Smckusick 
10117214Smckusick void mtcreset();
10217214Smckusick 
1034736Swnj /*ARGSUSED*/
1044736Swnj mtattach(mi)
1054736Swnj 	struct mba_device *mi;
1064736Swnj {
10717214Smckusick #ifdef lint
10817214Smckusick 	mtread(0); mtwrite(0); mtioctl(0, 0, 0, 0);
10917214Smckusick #endif
1104736Swnj }
1114736Swnj 
1127431Skre mtslave(mi, ms, sn)
1134736Swnj 	struct mba_device *mi;
1144736Swnj 	struct mba_slave *ms;
1157431Skre 	int sn;
1164736Swnj {
1174736Swnj 	register struct mu_softc *sc = &mu_softc[ms->ms_unit];
1184736Swnj 	register struct mtdevice *mtaddr = (struct mtdevice *)mi->mi_drv;
11917214Smckusick 	int s = spl7(), rtn = 0, i;
1204736Swnj 
12117214Smckusick 	/* Just in case the controller is ill, reset it.  Then issue	*/
12217214Smckusick 	/* a sense operation and wait about a second for it to respond.	*/
12317214Smckusick 
12417214Smckusick 	mtcreset(mtaddr);
1254736Swnj 	mtaddr->mtas = -1;
1267431Skre 	mtaddr->mtncs[sn] = MT_SENSE|MT_GO;
12717214Smckusick 	for (i = MTTIMEOUT; i> 0; i--) {
12817214Smckusick 		DELAY(50);
12917214Smckusick 		if (MASKREG(mtaddr->mtas) != 0)
13017214Smckusick 			break;
13117214Smckusick 	}
13217214Smckusick 	sc->sc_i_mtas = mtaddr->mtas;
13317214Smckusick 	sc->sc_i_mtner = mtaddr->mtner;
13417214Smckusick 	sc->sc_i_mtds = mtaddr->mtds;
13517214Smckusick 
13617214Smckusick 	/* If no response, whimper.  If wrong response, call it an	*/
13717214Smckusick 	/* unsolicited interrupt and use mtndtint to log and correct.	*/
13817214Smckusick 	/* Otherwise, note whether this slave exists.			*/
13917214Smckusick 
14017214Smckusick 	if (i <= 0) {
14117214Smckusick 		printf("mt: controller hung\n");
14217214Smckusick 	} else if ((mtaddr->mtner & MTER_INTCODE) != MTER_DONE) {
14317214Smckusick 		(void) mtndtint(mi);
14417214Smckusick 	} else if (mtaddr->mtds & MTDS_PRES) {
1454736Swnj 		sc->sc_mi = mi;
1467431Skre 		sc->sc_slave = sn;
1474736Swnj 		mutomt[ms->ms_unit] = mi->mi_unit;
1484736Swnj 		rtn = 1;
1494736Swnj 	}
15017214Smckusick 
15117214Smckusick 	/* Cancel the interrupt, then wait a little while for it to go away. */
15217214Smckusick 
1534736Swnj 	mtaddr->mtas = mtaddr->mtas;
15417214Smckusick 	DELAY(10);
1554736Swnj 	splx(s);
1564736Swnj 	return (rtn);
1574736Swnj }
1584736Swnj 
1594736Swnj mtopen(dev, flag)
1604736Swnj 	dev_t dev;
1614736Swnj 	int flag;
1624736Swnj {
1634736Swnj 	register int muunit;
1644736Swnj 	register struct mba_device *mi;
1654736Swnj 	register struct mu_softc *sc;
1664736Swnj 
1674736Swnj 	muunit = MUUNIT(dev);
16817214Smckusick 	if (   (muunit >= NMU)
16917214Smckusick 	    || ((mi = mtinfo[MTUNIT(dev)]) == 0)
17017214Smckusick 	    || (mi->mi_alive == 0) )
1718581Sroot 		return (ENXIO);
17217214Smckusick 	if ((sc = &mu_softc[muunit])->sc_openf)
17317214Smckusick 		return (EBUSY);
17417214Smckusick 	sc->sc_dens = (minor(dev) & H_6250BPI) ? MT_GCR : 0;
1754736Swnj 	mtcommand(dev, MT_SENSE, 1);
1764736Swnj 	if ((sc->sc_dsreg & MTDS_ONL) == 0) {
1774736Swnj 		uprintf("mu%d: not online\n", muunit);
1788581Sroot 		return (EIO);
1794736Swnj 	}
18017214Smckusick 	if ((sc->sc_dsreg & MTDS_AVAIL) == 0) {
18117214Smckusick 		uprintf("mu%d: not online (port selector)\n", muunit);
18217214Smckusick 		return (EIO);
18317214Smckusick 	}
18417214Smckusick 	if ((flag & FWRITE) && (sc->sc_dsreg & MTDS_FPT)) {
1854736Swnj 		uprintf("mu%d: no write ring\n", muunit);
1868581Sroot 		return (EIO);
1874736Swnj 	}
18817214Smckusick 	if (   ((sc->sc_dsreg & MTDS_BOT) == 0)
18917214Smckusick 	    && (flag & FWRITE)
19017214Smckusick 	    && (   (   (sc->sc_dens == MT_GCR)
19117214Smckusick 		    && (sc->sc_dsreg & MTDS_PE) )
19217214Smckusick 		|| (   (sc->sc_dens != MT_GCR)
19317214Smckusick 		    && ((sc->sc_dsreg & MTDS_PE) == 0)))) {
1944736Swnj 		uprintf("mu%d: can't change density in mid-tape\n", muunit);
1958581Sroot 		return (EIO);
1964736Swnj 	}
1974736Swnj 	sc->sc_openf = 1;
1984736Swnj 	sc->sc_blkno = (daddr_t)0;
19917214Smckusick 
20017214Smckusick 	/* Since cooked I/O may do a read-ahead before a write, trash	*/
20117214Smckusick 	/* on a tape can make the first write fail.  Suppress the first	*/
20217214Smckusick 	/* read-ahead unless definitely doing read-write		*/
20317214Smckusick 
20417214Smckusick 	sc->sc_nxrec =  ((flag & (FTRUNC | FWRITE)) == (FTRUNC | FWRITE))
20517214Smckusick 		      ? (daddr_t)0
20617214Smckusick 		      : (daddr_t)INF;
2074736Swnj 	sc->sc_flags = 0;
208*18324Sralph 	sc->sc_ttyp = u.u_ttyp;
2098581Sroot 	return (0);
2104736Swnj }
2114736Swnj 
2124736Swnj mtclose(dev, flag)
2134736Swnj 	register dev_t dev;
21417214Smckusick 	register int flag;
2154736Swnj {
2164736Swnj 	register struct mu_softc *sc = &mu_softc[MUUNIT(dev)];
2174736Swnj 
21817214Smckusick 	if (   ((flag & (FREAD | FWRITE)) == FWRITE)
21917214Smckusick 	    || (   (flag & FWRITE)
22017214Smckusick 		&& (sc->sc_flags & H_WRITTEN) ))
2214736Swnj 		mtcommand(dev, MT_CLS|sc->sc_dens, 1);
22217214Smckusick 	if ((minor(dev) & H_NOREWIND) == 0)
2234736Swnj 		mtcommand(dev, MT_REW, 0);
2244736Swnj 	sc->sc_openf = 0;
2254736Swnj }
2264736Swnj 
2274736Swnj mtcommand(dev, com, count)
2284736Swnj 	dev_t dev;
2294736Swnj 	int com, count;
2304736Swnj {
2314736Swnj 	register struct buf *bp;
2325437Sroot 	register int s;
2334736Swnj 
2344736Swnj 	bp = &cmtbuf[MTUNIT(dev)];
2355437Sroot 	s = spl5();
23617214Smckusick 	while (bp->b_flags & B_BUSY) {
23717214Smckusick 		if((bp->b_repcnt == 0) && (bp->b_flags & B_DONE))
2384736Swnj 			break;
2394736Swnj 		bp->b_flags |= B_WANTED;
2404736Swnj 		sleep((caddr_t)bp, PRIBIO);
2414736Swnj 	}
2424736Swnj 	bp->b_flags = B_BUSY|B_READ;
2435437Sroot 	splx(s);
2444736Swnj 	bp->b_dev = dev;
2454736Swnj 	bp->b_command = com;
2464736Swnj 	bp->b_repcnt = count;
2474736Swnj 	bp->b_blkno = 0;
24817214Smckusick 	bp->b_error = 0;
2494736Swnj 	mtstrategy(bp);
2504736Swnj 	if (count == 0)
2514736Swnj 		return;
2524736Swnj 	iowait(bp);
25317214Smckusick 	if (bp->b_flags & B_WANTED)
2544736Swnj 		wakeup((caddr_t)bp);
2554736Swnj 	bp->b_flags &= B_ERROR;
2564736Swnj }
2574736Swnj 
2584736Swnj mtstrategy(bp)
2594736Swnj 	register struct buf *bp;
2604736Swnj {
2614736Swnj 	register struct mba_device *mi = mtinfo[MTUNIT(bp->b_dev)];
2624736Swnj 	register struct buf *dp;
2635437Sroot 	register int s;
2644736Swnj 
26517214Smckusick 	/* If this is a data transfer operation, set the resid to a	*/
26617214Smckusick 	/* default value (EOF) to simplify getting it right during	*/
26717214Smckusick 	/* error recovery or bail out.					*/
26817214Smckusick 
26917214Smckusick 	if (bp != &cmtbuf[MTUNIT(bp->b_dev)])
27017214Smckusick 		bp->b_resid = bp->b_bcount;
27117214Smckusick 
27217214Smckusick 	/* Link this request onto the end of the queue for this		*/
27317214Smckusick 	/* controller, then start I/O if not already active.		*/
27417214Smckusick 
2754736Swnj 	bp->av_forw = NULL;
2764736Swnj 	dp = &mi->mi_tab;
2775437Sroot 	s = spl5();
2784736Swnj 	if (dp->b_actf == NULL)
2794736Swnj 		dp->b_actf = bp;
2804736Swnj 	else
2814736Swnj 		dp->b_actl->av_forw = bp;
2824736Swnj 	dp->b_actl = bp;
2834736Swnj 	if (dp->b_active == 0)
2844736Swnj 		mbustart(mi);
2855437Sroot 	splx(s);
2864736Swnj }
2874736Swnj 
2884736Swnj mtustart(mi)
2894736Swnj 	register struct mba_device *mi;
2904736Swnj {
29117214Smckusick 	register struct mtdevice *mtaddr = (struct mtdevice *)mi->mi_drv;
2924736Swnj 	register struct buf *bp = mi->mi_tab.b_actf;
2934736Swnj 	register struct mu_softc *sc = &mu_softc[MUUNIT(bp->b_dev)];
2944736Swnj 	daddr_t blkno;
2954736Swnj 
2964736Swnj 	if (sc->sc_openf < 0) {
2974736Swnj 		bp->b_flags |= B_ERROR;
2984736Swnj 		return (MBU_NEXT);
2994736Swnj 	}
3004736Swnj 	if (bp != &cmtbuf[MTUNIT(bp->b_dev)]) {
30117214Smckusick 
30217214Smckusick 		/* Signal "no space" if out of tape unless suppressed	*/
30317214Smckusick 		/* by MTIOCIEOT.					*/
30417214Smckusick 
30517214Smckusick 		if (   ((sc->sc_flags & (H_EOT | H_IEOT)) == H_EOT)
30617214Smckusick 		    && ((bp->b_flags & B_READ) == 0) ) {
3074736Swnj 			bp->b_flags |= B_ERROR;
30817214Smckusick 			bp->b_error = ENOSPC;
3094736Swnj 			return (MBU_NEXT);
3104736Swnj 		}
31117214Smckusick 
31217214Smckusick 		/* special case tests for cooked mode */
31317214Smckusick 
31417214Smckusick 		if (bp != &rmtbuf[MTUNIT(bp->b_dev)]) {
31517214Smckusick 
31617214Smckusick 			/* seek beyond end of file */
31717214Smckusick 
31817214Smckusick 			if (bdbtofsb(bp->b_blkno) > sc->sc_nxrec) {
31917214Smckusick 				bp->b_flags |= B_ERROR;
32017214Smckusick 				bp->b_error = ENXIO;
32117214Smckusick 				return (MBU_NEXT);
32217214Smckusick 			}
32317214Smckusick 
32417214Smckusick 			/* This should be end of file, but the buffer	   */
32517214Smckusick 			/* system wants a one-block look-ahead.  Humor it. */
32617214Smckusick 
32717214Smckusick 			if (   (bdbtofsb(bp->b_blkno) == sc->sc_nxrec)
32817214Smckusick 			    && (bp->b_flags & B_READ) ) {
32917214Smckusick 				clrbuf(bp);
33017214Smckusick 				return (MBU_NEXT);
33117214Smckusick 			}
33217214Smckusick 
33317214Smckusick 			/* If writing, mark the next block invalid. */
33417214Smckusick 
33517214Smckusick 			if ((bp->b_flags & B_READ) == 0)
33617214Smckusick 				sc->sc_nxrec = bdbtofsb(bp->b_blkno) + 1;
3374736Swnj 		}
3384736Swnj 	} else {
33917214Smckusick 
34017214Smckusick 		/* It's a command, do it now. */
34117214Smckusick 
3424736Swnj 		mtaddr->mtncs[MUUNIT(bp->b_dev)] =
3434736Swnj 			(bp->b_repcnt<<8)|bp->b_command|MT_GO;
3444736Swnj 		return (MBU_STARTED);
3454736Swnj 	}
34617214Smckusick 
34717214Smckusick 	/* If raw I/O, or if the tape is positioned correctly for	*/
34817214Smckusick 	/* cooked I/O, set the byte count, unit number and repeat count	*/
34917214Smckusick 	/* then tell the MASSBUS to proceed.  Note that a negative	*/
35017214Smckusick 	/* bcount tells mbstart to map the buffer for "read backwards".	*/
35117214Smckusick 
35217214Smckusick 	if (   (bp == &rmtbuf[MTUNIT(bp->b_dev)])
35317214Smckusick 	    || ((blkno = sc->sc_blkno) == bdbtofsb(bp->b_blkno)) ) {
3544736Swnj 		if (mi->mi_tab.b_errcnt == 2) {
35517214Smckusick 			mtaddr->mtbc = -(bp->b_bcount);
3564736Swnj 			mtaddr->mtca = MUUNIT(bp->b_dev);
3574736Swnj 		} else {
3584736Swnj 			mtaddr->mtbc = bp->b_bcount;
3594736Swnj 			mtaddr->mtca = (1<<2)|MUUNIT(bp->b_dev);
3604736Swnj 		}
3614736Swnj 		return (MBU_DODATA);
3624736Swnj 	}
36317214Smckusick 
36417214Smckusick 	/* Issue skip operations to position the next block for cooked I/O. */
36517214Smckusick 
3667380Ssam 	if (blkno < bdbtofsb(bp->b_blkno))
3674736Swnj 		mtaddr->mtncs[MUUNIT(bp->b_dev)] =
3687380Ssam 		  (min((unsigned)(bdbtofsb(bp->b_blkno) - blkno), 0377) << 8) |
3696186Ssam 			MT_SFORW|MT_GO;
3704736Swnj 	else
3714736Swnj 		mtaddr->mtncs[MUUNIT(bp->b_dev)] =
3727380Ssam 		  (min((unsigned)(blkno - bdbtofsb(bp->b_blkno)), 0377) << 8) |
3736186Ssam 			MT_SREV|MT_GO;
3744736Swnj 	return (MBU_STARTED);
3754736Swnj }
3764736Swnj 
3774736Swnj mtstart(mi)
3784736Swnj 	register struct mba_device *mi;
3794736Swnj {
3804736Swnj 	register struct buf *bp = mi->mi_tab.b_actf;
3814736Swnj 	register struct mu_softc *sc = &mu_softc[MUUNIT(bp->b_dev)];
3824736Swnj 
3834736Swnj 	if (bp->b_flags & B_READ)
3844736Swnj 		if (mi->mi_tab.b_errcnt == 2)
3854736Swnj 			return(MT_READREV|MT_GO);
3864736Swnj 		else
3874736Swnj 			return(MT_READ|MT_GO);
3884736Swnj 	else
3894736Swnj 		return(MT_WRITE|sc->sc_dens|MT_GO);
3904736Swnj }
3914736Swnj 
3924736Swnj mtdtint(mi, mbsr)
3934736Swnj 	register struct mba_device *mi;
3944736Swnj 	int mbsr;
3954736Swnj {
3964736Swnj 	register struct mtdevice *mtaddr = (struct mtdevice *)mi->mi_drv;
3974736Swnj 	register struct buf *bp = mi->mi_tab.b_actf;
3984736Swnj 	register struct mu_softc *sc;
39917214Smckusick 	register int er;
4004736Swnj 
40117214Smckusick 	/* I'M still NOT SURE IF THIS SHOULD ALWAYS BE THE CASE SO FOR NOW... */
40217214Smckusick 
40317214Smckusick 	if ((mtaddr->mtca & 3) != MUUNIT(bp->b_dev)) {
4044736Swnj 		printf("mt: wrong unit!\n");
4054736Swnj 		mtaddr->mtca = MUUNIT(bp->b_dev);
4064736Swnj 	}
40717214Smckusick 
40817214Smckusick 	er = MASKREG(mtaddr->mter);
4094736Swnj 	sc = &mu_softc[MUUNIT(bp->b_dev)];
41017214Smckusick 	sc->sc_erreg = er;
41117214Smckusick 	if (bp->b_flags & B_READ)
41217214Smckusick 		sc->sc_flags &= ~H_WRITTEN;
41317214Smckusick 	else
4144736Swnj 		sc->sc_flags |= H_WRITTEN;
41517214Smckusick 	switch (er & MTER_INTCODE) {
41617214Smckusick 
41717214Smckusick 	case MTER_EOT:
41817214Smckusick 		sc->sc_flags |= H_EOT;
41917214Smckusick 
42017214Smckusick 		/* fall into MTER_DONE */
42117214Smckusick 
4224736Swnj 	case MTER_DONE:
42317214Smckusick 		sc->sc_blkno++;
42417214Smckusick 		if (mi->mi_tab.b_errcnt == 2) {
42517214Smckusick 			bp->b_bcount = bp->b_resid;
42617214Smckusick 			bp->b_resid -= MASKREG(mtaddr->mtbc);
42717214Smckusick 			if (   (bp->b_resid > 0)
42817214Smckusick 			    && (bp != &rmtbuf[MTUNIT(bp->b_dev)]) )
42917214Smckusick 				bp->b_flags |= B_ERROR;
43017214Smckusick 		} else {
43117214Smckusick 			bp->b_resid = 0;
43217214Smckusick 		}
43317214Smckusick 		break;
43417214Smckusick 
43517214Smckusick 	case MTER_SHRTREC:
43617214Smckusick 		sc->sc_blkno++;
43717214Smckusick 		bp->b_bcount = bp->b_resid;
43817214Smckusick 		bp->b_resid -= MASKREG(mtaddr->mtbc);
43917214Smckusick 		if (bp != &rmtbuf[MTUNIT(bp->b_dev)])
44017214Smckusick 			bp->b_flags |= B_ERROR;
44117214Smckusick 		break;
44217214Smckusick 
44317214Smckusick 	case MTER_RETRY:
44417214Smckusick 
44517214Smckusick 		/* Simple re-try.  Since resid is always a copy of the	*/
44617214Smckusick 		/* original byte count, use it to restore the count.	*/
44717214Smckusick 
44817214Smckusick 		mi->mi_tab.b_errcnt = 1;
44917214Smckusick 		bp->b_bcount = bp->b_resid;
45017214Smckusick 		return(MBD_RETRY);
45117214Smckusick 
45217214Smckusick 	case MTER_RDOPP:
45317214Smckusick 
45417214Smckusick 		/* The controller just decided to read it backwards.	*/
45517214Smckusick 		/* If the controller returns a byte count of zero,	*/
45617214Smckusick 		/* change it to 1, since zero encodes 65536, which	*/
45717214Smckusick 		/* isn't quite what we had in mind.  The byte count	*/
45817214Smckusick 		/* may be larger than the size of the input buffer, so	*/
45917214Smckusick 		/* limit the count to the buffer size.  After		*/
46017214Smckusick 		/* making the byte count reasonable, set bcount to the	*/
46117214Smckusick 		/* negative of the controller's version of the byte	*/
46217214Smckusick 		/* count so that the start address for the transfer is	*/
46317214Smckusick 		/* set up correctly.					*/
46417214Smckusick 
46517214Smckusick 		if (mt_do_readrev) {
46617214Smckusick 			mi->mi_tab.b_errcnt = 2;
46717214Smckusick 			if ((bp->b_bcount = MASKREG(mtaddr->mtbc)) == 0)
46817214Smckusick 				bp->b_bcount = 1;
46917214Smckusick 			if (bp->b_bcount > bp->b_resid)
47017214Smckusick 				bp->b_bcount = bp->b_resid;
47117214Smckusick 			bp->b_bcount = -(bp->b_bcount);
47217214Smckusick 			return(MBD_RETRY);
47317214Smckusick 		} else if (MASKREG(mtaddr->mtbc) <= bp->b_resid) {
47417214Smckusick 			sc->sc_blkno++;
47517214Smckusick 			bp->b_bcount = bp->b_resid;
47617214Smckusick 			bp->b_resid -= MASKREG(mtaddr->mtbc);
47717214Smckusick 			bp->b_flags |= B_ERROR;
47817214Smckusick 			break;
47917214Smckusick 		}
48017214Smckusick 		bp->b_flags |= B_ERROR;
48117214Smckusick 
48217214Smckusick 		/* fall into MTER_LONGREC */
48317214Smckusick 
4844736Swnj 	case MTER_LONGREC:
48517214Smckusick 		sc->sc_blkno++;
48617214Smckusick 		bp->b_bcount = bp->b_resid;
4874736Swnj 		bp->b_resid = 0;
48817214Smckusick 		bp->b_error = ENOMEM;
48917214Smckusick 		bp->b_flags |= B_ERROR;
4904736Swnj 		break;
4914736Swnj 
4924736Swnj 	case MTER_NOTCAP:
4934736Swnj 		printf("mu%d: blank tape\n", MUUNIT(bp->b_dev));
4944736Swnj 		goto err;
4954736Swnj 
4964736Swnj 	case MTER_TM:
49717214Smckusick 
49817214Smckusick 		/* End of file.  Since the default byte count has	*/
49917214Smckusick 		/* already been set, just count the block and proceed.	*/
50017214Smckusick 
5014736Swnj 		sc->sc_blkno++;
5024736Swnj 	err:
5034736Swnj 		if (bp != &rmtbuf[MTUNIT(bp->b_dev)])
50417214Smckusick 			sc->sc_nxrec = bdbtofsb(bp->b_blkno);
5054736Swnj 		break;
5064736Swnj 
5074736Swnj 	case MTER_OFFLINE:
5084736Swnj 		if (sc->sc_openf > 0) {
5094736Swnj 			sc->sc_openf = -1;
510*18324Sralph 			tprintf(sc->sc_ttyp, "mu%d: offline\n", MUUNIT(bp->b_dev));
5114736Swnj 		}
5124736Swnj 		bp->b_flags |= B_ERROR;
5134736Swnj 		break;
5144736Swnj 
51517214Smckusick 	case MTER_NOTAVL:
51617214Smckusick 		if (sc->sc_openf > 0) {
51717214Smckusick 			sc->sc_openf = -1;
518*18324Sralph 			tprintf(sc->sc_ttyp, "mu%d: offline (port selector)\n",
519*18324Sralph 			    MUUNIT(bp->b_dev));
52017214Smckusick 		}
52117214Smckusick 		bp->b_flags |= B_ERROR;
52217214Smckusick 		break;
52317214Smckusick 
5244736Swnj 	case MTER_FPT:
525*18324Sralph 		tprintf(sc->sc_ttyp, "mu%d: no write ring\n", MUUNIT(bp->b_dev));
5264736Swnj 		bp->b_flags |= B_ERROR;
5274736Swnj 		break;
5284736Swnj 
52917214Smckusick 	case MTER_UNREAD:
53017214Smckusick 		sc->sc_blkno++;
53117214Smckusick 		bp->b_bcount = bp->b_resid;
53217214Smckusick 		bp->b_resid -= MIN(MASKREG(mtaddr->mtbc), bp->b_bcount);
53317214Smckusick 
53417214Smckusick 		/* Code 010 means a garbage record, nothing serious. */
53517214Smckusick 
53617214Smckusick 		if (((er & MTER_FAILCODE) >> 10) == 010) {
537*18324Sralph 			tprintf(sc->sc_ttyp, "mu%d: rn=%d bn=%d unreadable record\n",
53817214Smckusick 			    MUUNIT(bp->b_dev), sc->sc_blkno, bp->b_blkno);
53917214Smckusick 			bp->b_flags |= B_ERROR;
54017214Smckusick 			break;
54117214Smckusick 		}
54217214Smckusick 
54317214Smckusick 		/* Anything else might be a hardware problem,	*/
54417214Smckusick 		/* fall into the error report.			*/
54517214Smckusick 
5464736Swnj 	default:
54717214Smckusick 
54817214Smckusick 		/* The bits in sc->sc_dsreg are from the last sense	*/
54917214Smckusick 		/* command.  To get the most recent copy, you have to	*/
55017214Smckusick 		/* do a sense at interrupt level, which requires nested	*/
55117214Smckusick 		/* error processing.  This is a bit messy, so leave	*/
55217214Smckusick 		/* well enough alone.					*/
55317214Smckusick 
554*18324Sralph 		tprintf(sc->sc_ttyp, "mu%d: hard error (data transfer) rn=%d bn=%d mbsr=%b er=%o (octal) ds=%b\n",
55517214Smckusick 		    MUUNIT(bp->b_dev), sc->sc_blkno, bp->b_blkno,
55617214Smckusick 		    mbsr, mbsr_bits, er,
55717214Smckusick 		    MASKREG(sc->sc_dsreg), mtds_bits);
55817214Smckusick #ifdef MTLERRM
55917214Smckusick 		mtintfail(sc);
56017214Smckusick 		printf("     interrupt code = %o (octal) <%s>\n     failure code = %o (octal) <%s>\n",
56117214Smckusick 		    er & MTER_INTCODE, sc->sc_mesg,
56217214Smckusick 		    (er & MTER_FAILCODE) >> 10, sc->sc_fmesg);
56317214Smckusick #endif
5644736Swnj 		bp->b_flags |= B_ERROR;
56517214Smckusick 
56617214Smckusick 		/* The TM78 manual says to reset the controller after	*/
56717214Smckusick 		/* TM fault B or MASSBUS fault.				*/
56817214Smckusick 
56917214Smckusick 		if (   ((er & MTER_INTCODE) == MTER_TMFLTB)
57017214Smckusick 		    || ((er & MTER_INTCODE) == MTER_MBFLT) ) {
57117214Smckusick 			mtcreset(mtaddr);
57217214Smckusick 		}
5734736Swnj 	}
57417214Smckusick 
57517214Smckusick 	/* Just in case some strange error slipped through, (drive off	*/
57617214Smckusick 	/* line during read-reverse error recovery comes to mind) make	*/
57717214Smckusick 	/* sure the byte count is reasonable.				*/
57817214Smckusick 
57917214Smckusick 	if (bp->b_bcount < 0)
58017214Smckusick 		bp->b_bcount = bp->b_resid;
5814736Swnj 	return (MBD_DONE);
5824736Swnj }
5834736Swnj 
5844736Swnj mtndtint(mi)
5854736Swnj 	register struct mba_device *mi;
5864736Swnj {
5874736Swnj 	register struct mtdevice *mtaddr = (struct mtdevice *)mi->mi_drv;
5884736Swnj 	register struct buf *bp = mi->mi_tab.b_actf;
5894736Swnj 	register struct mu_softc *sc;
59017214Smckusick 	register int er, fc;
59117214Smckusick 	int unit;
5924736Swnj 
5934736Swnj 	unit = (mtaddr->mtner >> 8) & 3;
5944736Swnj 	er = MASKREG(mtaddr->mtner);
59517214Smckusick 	sc = &mu_softc[unit];
59617214Smckusick 	sc->sc_erreg = er;
59717214Smckusick 
59817214Smckusick 	/* Check for unsolicited interrupts. */
59917214Smckusick 
6004736Swnj 	if (bp == 0 || unit != MUUNIT(bp->b_dev)) {	/* consistency check */
60117214Smckusick 		if ((er & MTER_INTCODE) != MTER_ONLINE) {
60217214Smckusick 			printf("mt: unit %d unexpected interrupt (non data transfer) er=%o (octal) ds=%b\n",
60317214Smckusick 			    unit, er, MASKREG(sc->sc_dsreg), mtds_bits);
60417214Smckusick #ifdef MTLERRM
60517214Smckusick 			mtintfail(sc);
60617214Smckusick 			printf("    interrupt code = %o (octal) <%s>\n    failure code = %o (octal) <%s>\n",
60717214Smckusick 			    er & MTER_INTCODE, sc->sc_mesg,
60817214Smckusick 			    (er & MTER_FAILCODE) >> 10, sc->sc_fmesg);
60917214Smckusick #endif
61017214Smckusick 			if (   ((er & MTER_INTCODE) == MTER_TMFLTB)
61117214Smckusick 			    || ((er & MTER_INTCODE) == MTER_MBFLT) ) {
61217214Smckusick 
61317214Smckusick 				/* Reset the controller, then set error	*/
61417214Smckusick 				/* status if there was anything active	*/
61517214Smckusick 				/* when the fault occurred.  This may	*/
61617214Smckusick 				/* shoot an innocent bystander, but	*/
61717214Smckusick 				/* it's better than letting an error	*/
61817214Smckusick 				/* slip through.			*/
61917214Smckusick 
62017214Smckusick 				mtcreset(mtaddr);
62117214Smckusick 				if (bp != 0) {
62217214Smckusick 					bp->b_flags |= B_ERROR;
62317214Smckusick 					return (MBN_DONE);
62417214Smckusick 				}
62517214Smckusick 			}
62617214Smckusick 		}
6274736Swnj 		return (MBN_SKIP);
6284736Swnj 	}
6294736Swnj 	if (bp == 0)
6304736Swnj 		return (MBN_SKIP);
63117214Smckusick 
6324736Swnj 	fc = (mtaddr->mtncs[unit] >> 8) & 0xff;
6334736Swnj 	sc->sc_resid = fc;
63417214Smckusick 
63517214Smckusick 	/* Clear the "written" flag after any operation that changes	*/
63617214Smckusick 	/* the position of the tape.					*/
63717214Smckusick 
63817214Smckusick 	if (   (bp != &cmtbuf[MTUNIT(bp->b_dev)])
63917214Smckusick 	    || (bp->b_command != MT_SENSE) )
64017214Smckusick 		sc->sc_flags &= ~H_WRITTEN;
64117214Smckusick 
6424736Swnj 	switch (er & MTER_INTCODE) {
64317214Smckusick 
64417214Smckusick 	case MTER_EOT:
64517214Smckusick 		sc->sc_flags |= H_EOT;
64617214Smckusick 
64717214Smckusick 		/* fall into MTER_DONE */
64817214Smckusick 
6494736Swnj 	case MTER_DONE:
65017214Smckusick 
65117214Smckusick 		/* If this is a command buffer, just update the status.	*/
65217214Smckusick 
6534736Swnj 		if (bp == &cmtbuf[MTUNIT(bp->b_dev)]) {
6544736Swnj 	done:
6554736Swnj 			if (bp->b_command == MT_SENSE)
6564736Swnj 				sc->sc_dsreg = MASKREG(mtaddr->mtds);
6574736Swnj 			return (MBN_DONE);
6584736Swnj 		}
65917214Smckusick 
66017214Smckusick 		/* It's not a command buffer, must be a cooked I/O	*/
66117214Smckusick 		/* skip operation (perhaps a shaky assumption, but it	*/
66217214Smckusick 		/* wasn't my idea).					*/
66317214Smckusick 
6647380Ssam 		if ((fc = bdbtofsb(bp->b_blkno) - sc->sc_blkno) < 0)
6656186Ssam 			sc->sc_blkno -= MIN(0377, -fc);
6664736Swnj 		else
6676186Ssam 			sc->sc_blkno += MIN(0377, fc);
6684736Swnj 		return (MBN_RETRY);
6694736Swnj 
67017214Smckusick 	case MTER_ONLINE:		/* ddj -- shouldn't happen but did */
6714736Swnj 	case MTER_RWDING:
6724736Swnj 		return (MBN_SKIP);	/* ignore "rewind started" interrupt */
6734736Swnj 
6744736Swnj 	case MTER_NOTCAP:
675*18324Sralph 		tprintf(sc->sc_ttyp, "mu%d: blank tape\n", MUUNIT(bp->b_dev));
67617214Smckusick 		bp->b_flags |= B_ERROR;
67717214Smckusick 		return (MBN_DONE);
6784736Swnj 
6794736Swnj 	case MTER_TM:
6804736Swnj 	case MTER_LEOT:
68117214Smckusick 
68217214Smckusick 		/* For an ioctl skip operation, count a tape mark as	*/
68317214Smckusick 		/* a record.  If there's anything left to do, update	*/
68417214Smckusick 		/* the repeat count and re-start the command.		*/
68517214Smckusick 
68617214Smckusick 		if (bp == &cmtbuf[MTUNIT(bp->b_dev)]) {
68717214Smckusick 			if ((sc->sc_resid = bp->b_repcnt = fc - 1) == 0)
68817214Smckusick 				return (MBN_DONE);
68917214Smckusick 			else
69017214Smckusick 				return (MBN_RETRY);
69117214Smckusick 
69217214Smckusick 		/* Cooked I/O again.  Just update the books and wait	*/
69317214Smckusick 		/* for someone else to return end of file or complain	*/
69417214Smckusick 		/* about a bad seek.					*/
69517214Smckusick 
69617214Smckusick 		} else if (sc->sc_blkno > bdbtofsb(bp->b_blkno)) {
69717214Smckusick 			sc->sc_nxrec = bdbtofsb(bp->b_blkno) + fc - 1;
6984736Swnj 			sc->sc_blkno = sc->sc_nxrec;
6994736Swnj 		} else {
70017214Smckusick 			sc->sc_nxrec = bdbtofsb(bp->b_blkno) - fc;
70117214Smckusick 			sc->sc_blkno = sc->sc_nxrec + 1;
7024736Swnj 		}
7034736Swnj 		return (MBN_RETRY);
7044736Swnj 
7054736Swnj 	case MTER_FPT:
706*18324Sralph 		tprintf(sc->sc_ttyp, "mu%d: no write ring\n", MUUNIT(bp->b_dev));
7074736Swnj 		bp->b_flags |= B_ERROR;
7084736Swnj 		return (MBN_DONE);
7094736Swnj 
7104736Swnj 	case MTER_OFFLINE:
71117214Smckusick 
71217214Smckusick 		/* If `off line' was intentional, don't complain. */
71317214Smckusick 
71417214Smckusick 		if (   (bp == &cmtbuf[MTUNIT(bp->b_dev)])
71517214Smckusick 		    && (bp->b_command == MT_UNLOAD) )
71617214Smckusick 			return(MBN_DONE);
7174736Swnj 		if (sc->sc_openf > 0) {
7184736Swnj 			sc->sc_openf = -1;
719*18324Sralph 			tprintf(sc->sc_ttyp, "mu%d: offline\n", MUUNIT(bp->b_dev));
7204736Swnj 		}
7214736Swnj 		bp->b_flags |= B_ERROR;
7224736Swnj 		return (MBN_DONE);
7234736Swnj 
72417214Smckusick 	case MTER_NOTAVL:
72517214Smckusick 		if (sc->sc_openf > 0) {
72617214Smckusick 			sc->sc_openf = -1;
727*18324Sralph 			tprintf(sc->sc_ttyp, "mu%d: offline (port selector)\n", MUUNIT(bp->b_dev));
72817214Smckusick 		}
72917214Smckusick 		bp->b_flags |= B_ERROR;
73017214Smckusick 		return (MBN_DONE);
73117214Smckusick 
7324736Swnj 	case MTER_BOT:
7334736Swnj 		if (bp == &cmtbuf[MTUNIT(bp->b_dev)])
7344736Swnj 			goto done;
7354736Swnj 
73617214Smckusick 		/* fall through */
73717214Smckusick 
7384736Swnj 	default:
739*18324Sralph 		tprintf(sc->sc_ttyp, "mu%d: hard error (non data transfer) rn=%d bn=%d er=%o (octal) ds=%b\n",
74017214Smckusick 		    MUUNIT(bp->b_dev), sc->sc_blkno, bp->b_blkno,
74117214Smckusick 		    er, MASKREG(sc->sc_dsreg), mtds_bits);
74217214Smckusick #ifdef MTLERRM
74317214Smckusick 		mtintfail(sc);
74417214Smckusick 		printf("     interrupt code = %o (octal) <%s>\n     failure code = %o (octal) <%s>\n",
74517214Smckusick 		    (er & MTER_INTCODE), sc->sc_mesg,
74617214Smckusick 		    (er & MTER_FAILCODE) >> 10, sc->sc_fmesg);
74717214Smckusick #endif
74817214Smckusick 		if (   ((er & MTER_INTCODE) == MTER_TMFLTB)
74917214Smckusick 		    || ((er & MTER_INTCODE) == MTER_MBFLT) ) {
75017214Smckusick 			mtcreset(mtaddr);	/* reset the controller */
75117214Smckusick 		}
7524736Swnj 		bp->b_flags |= B_ERROR;
7534736Swnj 		return (MBN_DONE);
7544736Swnj 	}
7554736Swnj 	/* NOTREACHED */
7564736Swnj }
7574736Swnj 
75817214Smckusick void mtcreset(mtaddr)
75917214Smckusick 	register struct mtdevice *mtaddr;
76017214Smckusick {
76117214Smckusick 	register int i;
76217214Smckusick 
76317214Smckusick 	mtaddr->mtid = MTID_CLR;		/* reset the TM78 */
76417214Smckusick 	DELAY(200);
76517214Smckusick 	for (i = MTTIMEOUT; i > 0; i--) {
76617214Smckusick 		DELAY(50);			/* don't nag */
76717214Smckusick 		if ((mtaddr->mtid & MTID_RDY) != 0)
76817214Smckusick 			return;			/* exit when ready */
76917214Smckusick 	}
77017214Smckusick 	printf("mt: controller hung\n");
77117214Smckusick }
77217214Smckusick 
7737740Sroot mtread(dev, uio)
7744736Swnj 	dev_t dev;
7757740Sroot 	struct uio *uio;
7764736Swnj {
7778158Sroot 	int errno;
7784736Swnj 
7798158Sroot 	errno = mtphys(dev, uio);
7808158Sroot 	if (errno)
7818158Sroot 		return (errno);
7828158Sroot 	return (physio(mtstrategy, &rmtbuf[MTUNIT(dev)], dev, B_READ, minphys, uio));
7834736Swnj }
7844736Swnj 
78517214Smckusick 
7867833Sroot mtwrite(dev, uio)
7877833Sroot 	dev_t dev;
7887833Sroot 	struct uio *uio;
7894736Swnj {
7908158Sroot 	int errno;
7914736Swnj 
7928158Sroot 	errno = mtphys(dev, uio);
7938158Sroot 	if (errno)
7948158Sroot 		return (errno);
7958158Sroot 	return (physio(mtstrategy, &rmtbuf[MTUNIT(dev)], dev, B_WRITE, minphys, uio));
7964736Swnj }
7974736Swnj 
7987740Sroot mtphys(dev, uio)
7994736Swnj 	dev_t dev;
8007740Sroot 	struct uio *uio;
8014736Swnj {
8024736Swnj 	register int mtunit;
80317214Smckusick 	struct mba_device *mi;
80417214Smckusick 	register int bsize = uio->uio_iov->iov_len;
8054736Swnj 
8064736Swnj 	mtunit = MTUNIT(dev);
80717214Smckusick 	if (   (mtunit >= NMT)
80817214Smckusick 	    || ((mi = mtinfo[mtunit]) == 0)
80917214Smckusick 	    || (mi->mi_alive == 0) )
8107740Sroot 		return (ENXIO);
81117214Smckusick 	if (   (bsize > 0xffff)	/* controller limit */
81217214Smckusick 	    || (bsize <= 0) )	/* ambiguous */
81317214Smckusick 		return (EINVAL);
8147740Sroot 	return (0);
8154736Swnj }
8164736Swnj 
8174736Swnj /*ARGSUSED*/
8187637Ssam mtioctl(dev, cmd, data, flag)
8194736Swnj 	dev_t dev;
8204736Swnj 	int cmd;
8217637Ssam 	caddr_t data;
8224736Swnj 	int flag;
8234736Swnj {
8244736Swnj 	register struct mu_softc *sc = &mu_softc[MUUNIT(dev)];
8254736Swnj 	register struct buf *bp = &cmtbuf[MTUNIT(dev)];
82617214Smckusick 	register struct mtop *mtop;
82717214Smckusick 	register struct mtget *mtget;
82817214Smckusick 	int callcount, fcount;
82917214Smckusick 	int op;
83017214Smckusick 
83117214Smckusick 	/* We depend on the values and order of the MT codes here. */
83217214Smckusick 
8334736Swnj 	static mtops[] =
8344736Swnj 	{MT_WTM,MT_SFORWF,MT_SREVF,MT_SFORW,MT_SREV,MT_REW,MT_UNLOAD,MT_SENSE};
8354736Swnj 
8364736Swnj 	switch (cmd) {
8377637Ssam 
83817214Smckusick 	/* tape operation */
83917214Smckusick 
84017214Smckusick 	case MTIOCTOP:
8418606Sroot 		mtop = (struct mtop *)data;
8428606Sroot 		switch (mtop->mt_op) {
8437637Ssam 
8444736Swnj 		case MTWEOF:
8457637Ssam 			callcount = mtop->mt_count;
8464736Swnj 			fcount = 1;
8474736Swnj 			break;
8487637Ssam 
8494736Swnj 		case MTFSF: case MTBSF:
8507637Ssam 			callcount = mtop->mt_count;
8514736Swnj 			fcount = 1;
8524736Swnj 			break;
8537637Ssam 
8544736Swnj 		case MTFSR: case MTBSR:
8554736Swnj 			callcount = 1;
8567637Ssam 			fcount = mtop->mt_count;
8574736Swnj 			break;
8587637Ssam 
8594736Swnj 		case MTREW: case MTOFFL:
8604736Swnj 			callcount = 1;
8614736Swnj 			fcount = 1;
8624736Swnj 			break;
8637637Ssam 
8644736Swnj 		default:
8658581Sroot 			return (ENXIO);
8664736Swnj 		}
86717214Smckusick 		if ((callcount <= 0) || (fcount <= 0))
8688581Sroot 			return (EINVAL);
8697637Ssam 		op = mtops[mtop->mt_op];
8704736Swnj 		if (op == MT_WTM)
8714736Swnj 			op |= sc->sc_dens;
8724736Swnj 		while (--callcount >= 0) {
87317214Smckusick 			register int n, fc = fcount;
8744736Swnj 
8754736Swnj 			do {
87617214Smckusick 				n = MIN(fc, 0xff);
8774736Swnj 				mtcommand(dev, op, n);
87817214Smckusick 				n -= sc->sc_resid;
87917214Smckusick 				fc -= n;
88017214Smckusick 				switch (mtop->mt_op) {
88117214Smckusick 
88217214Smckusick 				case MTWEOF:
88317214Smckusick 					sc->sc_blkno += (daddr_t)n;
88417214Smckusick 					sc->sc_nxrec = sc->sc_blkno - 1;
88517214Smckusick 					break;
88617214Smckusick 
88717214Smckusick 				case MTOFFL:
88817214Smckusick 				case MTREW:
88917214Smckusick 				case MTFSF:
89017214Smckusick 					sc->sc_blkno = (daddr_t)0;
89117214Smckusick 					sc->sc_nxrec = (daddr_t)INF;
89217214Smckusick 					break;
89317214Smckusick 
89417214Smckusick 				case MTBSF:
89517214Smckusick 					if (sc->sc_resid) {
89617214Smckusick 						sc->sc_blkno = (daddr_t)0;
89717214Smckusick 						sc->sc_nxrec = (daddr_t)INF;
89817214Smckusick 					} else {
89917214Smckusick 						sc->sc_blkno = (daddr_t)(-1);
90017214Smckusick 						sc->sc_nxrec = (daddr_t)(-1);
90117214Smckusick 					}
90217214Smckusick 					break;
90317214Smckusick 
90417214Smckusick 				case MTFSR:
90517214Smckusick 					sc->sc_blkno += (daddr_t)n;
90617214Smckusick 					break;
90717214Smckusick 
90817214Smckusick 				case MTBSR:
90917214Smckusick 					sc->sc_blkno -= (daddr_t)n;
91017214Smckusick 					break;
91117214Smckusick 				}
91217214Smckusick 				if (sc->sc_resid)
91317214Smckusick 					break;
91417214Smckusick 			} while (fc);
91517214Smckusick 			if (fc) {
91617214Smckusick 				sc->sc_resid = callcount + fc;
91717214Smckusick 				if (   (mtop->mt_op == MTFSR)
91817214Smckusick 				    || (mtop->mt_op == MTBSR) )
91917214Smckusick 					return (EIO);
92017214Smckusick 				else
92117214Smckusick 					break;
92217214Smckusick 			}
92317214Smckusick 			if (bp->b_flags & B_ERROR)
9244736Swnj 				break;
9254736Swnj 		}
9268712Sroot 		return (geterror(bp));
9277637Ssam 
92817214Smckusick 	/* tape status */
92917214Smckusick 
9304736Swnj 	case MTIOCGET:
9317637Ssam 		mtget = (struct mtget *)data;
9327637Ssam 		mtget->mt_erreg = sc->sc_erreg;
9337637Ssam 		mtget->mt_resid = sc->sc_resid;
9344736Swnj 		mtcommand(dev, MT_SENSE, 1);	/* update drive status */
9357637Ssam 		mtget->mt_dsreg = sc->sc_dsreg;
9367637Ssam 		mtget->mt_type = MT_ISMT;
9378581Sroot 		break;
9387637Ssam 
93917214Smckusick 	/* ignore EOT condition */
94017214Smckusick 
94117214Smckusick 	case MTIOCIEOT:
94217214Smckusick 		sc->sc_flags |= H_IEOT;
94317214Smckusick 		break;
94417214Smckusick 
94517214Smckusick 	/* enable EOT condition */
94617214Smckusick 
94717214Smckusick 	case MTIOCEEOT:
94817214Smckusick 		sc->sc_flags &= ~H_IEOT;
94917214Smckusick 		break;
95017214Smckusick 
9514736Swnj 	default:
9528581Sroot 		return (ENXIO);
9534736Swnj 	}
9548581Sroot 	return (0);
9554736Swnj }
9564736Swnj 
9574736Swnj #define	DBSIZE	20
9584736Swnj 
9594736Swnj mtdump()
9604736Swnj {
9614736Swnj 	register struct mba_device *mi;
9624736Swnj 	register struct mba_regs *mp;
9634736Swnj 	int blk, num;
9644736Swnj 	int start;
9654736Swnj 
9664736Swnj 	start = 0;
9674736Swnj 	num = maxfree;
9684736Swnj #define	phys(a,b)		((b)((int)(a)&0x7fffffff))
9694736Swnj 	if (mtinfo[0] == 0)
9704736Swnj 		return (ENXIO);
9714736Swnj 	mi = phys(mtinfo[0], struct mba_device *);
9724736Swnj 	mp = phys(mi->mi_hd, struct mba_hd *)->mh_physmba;
9734736Swnj 	mp->mba_cr = MBCR_IE;
9746186Ssam #if lint
9758606Sroot 	blk = 0; num = blk; start = num; blk = start;
9766186Ssam 	return (0);
9776186Ssam #endif
9786186Ssam #ifdef notyet
9794736Swnj 	mtaddr = (struct mtdevice *)&mp->mba_drv[mi->mi_drive];
9804736Swnj 	mtaddr->mttc = MTTC_PDP11|MTTC_1600BPI;
9814736Swnj 	mtaddr->mtcs1 = MT_DCLR|MT_GO;
9824736Swnj 	while (num > 0) {
9834736Swnj 		blk = num > DBSIZE ? DBSIZE : num;
9844736Swnj 		mtdwrite(start, blk, mtaddr, mp);
9854736Swnj 		start += blk;
9864736Swnj 		num -= blk;
9874736Swnj 	}
9884736Swnj 	mteof(mtaddr);
9894736Swnj 	mteof(mtaddr);
9904736Swnj 	mtwait(mtaddr);
9914736Swnj 	if (mtaddr->mtds&MTDS_ERR)
9924736Swnj 		return (EIO);
9934736Swnj 	mtaddr->mtcs1 = MT_REW|MT_GO;
9944736Swnj 	return (0);
9954736Swnj }
9964736Swnj 
9974736Swnj mtdwrite(dbuf, num, mtaddr, mp)
9984736Swnj 	register dbuf, num;
9994736Swnj 	register struct mtdevice *mtaddr;
10004736Swnj 	struct mba_regs *mp;
10014736Swnj {
10024736Swnj 	register struct pte *io;
10034736Swnj 	register int i;
10044736Swnj 
10054736Swnj 	mtwait(mtaddr);
10064736Swnj 	io = mp->mba_map;
10074736Swnj 	for (i = 0; i < num; i++)
10084736Swnj 		*(int *)io++ = dbuf++ | PG_V;
10094736Swnj 	mtaddr->mtfc = -(num*NBPG);
10104736Swnj 	mp->mba_sr = -1;
10114736Swnj 	mp->mba_bcr = -(num*NBPG);
10124736Swnj 	mp->mba_var = 0;
10134736Swnj 	mtaddr->mtcs1 = MT_WCOM|MT_GO;
10144736Swnj }
10154736Swnj 
10164736Swnj mtwait(mtaddr)
10174736Swnj 	struct mtdevice *mtaddr;
10184736Swnj {
10194736Swnj 	register s;
10204736Swnj 
10214736Swnj 	do
10224736Swnj 		s = mtaddr->mtds;
10234736Swnj 	while ((s & MTDS_DRY) == 0);
10244736Swnj }
10254736Swnj 
10264736Swnj mteof(mtaddr)
10274736Swnj 	struct mtdevice *mtaddr;
10284736Swnj {
10294736Swnj 
10304736Swnj 	mtwait(mtaddr);
10314736Swnj 	mtaddr->mtcs1 = MT_WEOF|MT_GO;
10324736Swnj #endif notyet
10334736Swnj }
103417214Smckusick 
103517214Smckusick #ifdef MTLERRM
103617214Smckusick mtintfail(sc)
103717214Smckusick 	register struct mu_softc *sc;
103817214Smckusick {
103917214Smckusick 	switch (sc->sc_erreg & MTER_INTCODE) {
104017214Smckusick 
104117214Smckusick 	/* unexpected BOT detected */
104217214Smckusick 
104317214Smckusick 	case MTER_BOT:
104417214Smckusick 		sc->sc_mesg = "unexpected BOT";
104517214Smckusick 		switch ((sc->sc_erreg & MTER_FAILCODE) >> 10) {
104617214Smckusick 		case 01:
104717214Smckusick 			sc->sc_fmesg = "tape was at BOT";
104817214Smckusick 			break;
104917214Smckusick 		case 02:
105017214Smckusick 			sc->sc_fmesg = "BOT seen after tape started";
105117214Smckusick 			break;
105217214Smckusick 		case 03:
105317214Smckusick 			sc->sc_fmesg = "ARA ID detected";
105417214Smckusick 			break;
105517214Smckusick 		default:
105617214Smckusick 			sc->sc_fmesg = "unclassified failure code";
105717214Smckusick 		}
105817214Smckusick 		break;
105917214Smckusick 
106017214Smckusick 	/* unexpected LEOT detected */
106117214Smckusick 
106217214Smckusick 	case MTER_LEOT:
106317214Smckusick 		sc->sc_mesg = "unexpected LEOT";
106417214Smckusick 		sc->sc_fmesg = "";
106517214Smckusick 		break;
106617214Smckusick 
106717214Smckusick 	/* rewinding */
106817214Smckusick 
106917214Smckusick 	case MTER_RWDING:
107017214Smckusick 		sc->sc_mesg = "tape rewinding";
107117214Smckusick 		sc->sc_fmesg = "";
107217214Smckusick 		break;
107317214Smckusick 
107417214Smckusick 	/* not ready */
107517214Smckusick 
107617214Smckusick 	case MTER_NOTRDY:
107717214Smckusick 		sc->sc_mesg = "drive not ready";
107817214Smckusick 		switch ((sc->sc_erreg & MTER_FAILCODE) >> 10) {
107917214Smckusick 		case 01:
108017214Smckusick 			sc->sc_fmesg = "TU on-line but not ready";
108117214Smckusick 			break;
108217214Smckusick 		case 02:
108317214Smckusick 			sc->sc_fmesg = "fatal error has occurred";
108417214Smckusick 			break;
108517214Smckusick 		case 03:
108617214Smckusick 			sc->sc_fmesg = "access allowed but not really";
108717214Smckusick 			break;
108817214Smckusick 		default:
108917214Smckusick 			sc->sc_fmesg = "unclassified failure code";
109017214Smckusick 		}
109117214Smckusick 		break;
109217214Smckusick 
109317214Smckusick 	/* not available */
109417214Smckusick 
109517214Smckusick 	case MTER_NOTAVL:
109617214Smckusick 		sc->sc_mesg = "drive not available";
109717214Smckusick 		sc->sc_fmesg = "";
109817214Smckusick 		break;
109917214Smckusick 
110017214Smckusick 	/* unit does not exist */
110117214Smckusick 
110217214Smckusick 	case MTER_NONEX:
110317214Smckusick 		sc->sc_mesg = "unit does not exist";
110417214Smckusick 		sc->sc_fmesg = "";
110517214Smckusick 		break;
110617214Smckusick 
110717214Smckusick 	/* not capable */
110817214Smckusick 
110917214Smckusick 	case MTER_NOTCAP:
111017214Smckusick 		sc->sc_mesg = "not capable";
111117214Smckusick 		switch ((sc->sc_erreg & MTER_FAILCODE) >> 10) {
111217214Smckusick 		case 01:
111317214Smckusick 			sc->sc_fmesg = "no record found within 25 feet";
111417214Smckusick 			break;
111517214Smckusick 		case 02:
111617214Smckusick 			sc->sc_fmesg = "ID burst neither PE nor GCR";
111717214Smckusick 			break;
111817214Smckusick 		case 03:
111917214Smckusick 			sc->sc_fmesg = "ARA ID not found";
112017214Smckusick 			break;
112117214Smckusick 		case 04:
112217214Smckusick 			sc->sc_fmesg = "no gap found after ID burst";
112317214Smckusick 			break;
112417214Smckusick 		default:
112517214Smckusick 			sc->sc_fmesg = "unclassified failure code";
112617214Smckusick 		}
112717214Smckusick 		break;
112817214Smckusick 
112917214Smckusick 	/* long tape record */
113017214Smckusick 
113117214Smckusick 	case MTER_LONGREC:
113217214Smckusick 		sc->sc_mesg = "long record";
113317214Smckusick 		switch ((sc->sc_erreg & MTER_FAILCODE) >> 10) {
113417214Smckusick 		case 00:
113517214Smckusick 			sc->sc_fmesg = "extended sense data not found";
113617214Smckusick 			break;
113717214Smckusick 		case 01:
113817214Smckusick 			sc->sc_fmesg = "extended sense data updated";
113917214Smckusick 			break;
114017214Smckusick 		default:
114117214Smckusick 			sc->sc_fmesg = "unclassified failure code";
114217214Smckusick 		}
114317214Smckusick 		break;
114417214Smckusick 
114517214Smckusick 	/* unreadable */
114617214Smckusick 
114717214Smckusick 	case MTER_UNREAD:
114817214Smckusick 		sc->sc_mesg = "unreadable record";
114917214Smckusick 		goto code22;
115017214Smckusick 
115117214Smckusick 	/* error */
115217214Smckusick 
115317214Smckusick 	case MTER_ERROR:
115417214Smckusick 		sc->sc_mesg = "error";
115517214Smckusick 		goto code22;
115617214Smckusick 
115717214Smckusick 	/* EOT error */
115817214Smckusick 
115917214Smckusick 	case MTER_EOTERR:
116017214Smckusick 		sc->sc_mesg = "EOT error";
116117214Smckusick 		goto code22;
116217214Smckusick 
116317214Smckusick 	/* tape position lost */
116417214Smckusick 
116517214Smckusick 	case MTER_BADTAPE:
116617214Smckusick 		sc->sc_mesg = "bad tape";
116717214Smckusick 	code22:
116817214Smckusick 		switch ((sc->sc_erreg & MTER_FAILCODE) >> 10) {
116917214Smckusick 		case 01:
117017214Smckusick 			sc->sc_fmesg = "GCR write error";
117117214Smckusick 			break;
117217214Smckusick 		case 02:
117317214Smckusick 			sc->sc_fmesg = "GCR read error";
117417214Smckusick 			break;
117517214Smckusick 		case 03:
117617214Smckusick 			sc->sc_fmesg = "PE read error";
117717214Smckusick 			break;
117817214Smckusick 		case 04:
117917214Smckusick 			sc->sc_fmesg = "PE write error";
118017214Smckusick 			break;
118117214Smckusick 		case 05:
118217214Smckusick 			sc->sc_fmesg = "at least 1 bit set in ECCSTA";
118317214Smckusick 			break;
118417214Smckusick 		case 06:
118517214Smckusick 			sc->sc_fmesg = "PE write error";
118617214Smckusick 			break;
118717214Smckusick 		case 07:
118817214Smckusick 			sc->sc_fmesg = "GCR write error";
118917214Smckusick 			break;
119017214Smckusick 		case 010:
119117214Smckusick 			sc->sc_fmesg = "RSTAT contains bad code";
119217214Smckusick 			break;
119317214Smckusick 		case 011:
119417214Smckusick 			sc->sc_fmesg = "PE write error";
119517214Smckusick 			break;
119617214Smckusick 		case 012:
119717214Smckusick 			sc->sc_fmesg = "MASSBUS parity error";
119817214Smckusick 			break;
119917214Smckusick 		case 013:
120017214Smckusick 			sc->sc_fmesg = "invalid data transferred";
120117214Smckusick 			break;
120217214Smckusick 		default:
120317214Smckusick 			sc->sc_fmesg = "unclassified failure code";
120417214Smckusick 		}
120517214Smckusick 		break;
120617214Smckusick 
120717214Smckusick 	/* TM fault A */
120817214Smckusick 
120917214Smckusick 	case MTER_TMFLTA:
121017214Smckusick 		sc->sc_mesg = "TM fault A";
121117214Smckusick 		switch ((sc->sc_erreg & MTER_FAILCODE) >> 10) {
121217214Smckusick 		case 01:
121317214Smckusick 			sc->sc_fmesg = "illegal command code";
121417214Smckusick 			break;
121517214Smckusick 		case 02:
121617214Smckusick 			sc->sc_fmesg = "DT command issued when NDT command active";
121717214Smckusick 			break;
121817214Smckusick 		case 03:
121917214Smckusick 			sc->sc_fmesg = "WMC error";
122017214Smckusick 			break;
122117214Smckusick 		case 04:
122217214Smckusick 			sc->sc_fmesg = "RUN not received from MASSBUS controller";
122317214Smckusick 			break;
122417214Smckusick 		case 05:
122517214Smckusick 			sc->sc_fmesg = "mismatch in command read - function routine";
122617214Smckusick 			break;
122717214Smckusick 		case 06:
122817214Smckusick 			sc->sc_fmesg = "ECC ROM parity error";
122917214Smckusick 			break;
123017214Smckusick 		case 07:
123117214Smckusick 			sc->sc_fmesg = "XMC ROM parity error";
123217214Smckusick 			break;
123317214Smckusick 		case 010:
123417214Smckusick 			sc->sc_fmesg = "mismatch in command read - ID burst command";
123517214Smckusick 			break;
123617214Smckusick 		case 011:
123717214Smckusick 			sc->sc_fmesg = "mismatch in command read - verify ARA burst command";
123817214Smckusick 			break;
123917214Smckusick 		case 012:
124017214Smckusick 			sc->sc_fmesg = "mismatch in command read - verify ARA ID command";
124117214Smckusick 			break;
124217214Smckusick 		case 013:
124317214Smckusick 			sc->sc_fmesg = "mismatch in command read - verify gap command";
124417214Smckusick 			break;
124517214Smckusick 		case 014:
124617214Smckusick 			sc->sc_fmesg = "mismatch in command read - read id burst command";
124717214Smckusick 			break;
124817214Smckusick 		case 015:
124917214Smckusick 			sc->sc_fmesg = "mismatch in command read - verify ARA ID command";
125017214Smckusick 			break;
125117214Smckusick 		case 016:
125217214Smckusick 			sc->sc_fmesg = "mismatch in command read - verify gap command";
125317214Smckusick 			break;
125417214Smckusick 		case 017:
125517214Smckusick 			sc->sc_fmesg = "mismatch in command read - find gap command";
125617214Smckusick 			break;
125717214Smckusick 		case 020:
125817214Smckusick 			sc->sc_fmesg = "WMC LEFT failed to set";
125917214Smckusick 			break;
126017214Smckusick 		case 021:
126117214Smckusick 			sc->sc_fmesg = "XL PE set in INTSTA register";
126217214Smckusick 			break;
126317214Smckusick 		case 022:
126417214Smckusick 			sc->sc_fmesg = "XMC DONE did not set";
126517214Smckusick 			break;
126617214Smckusick 		case 023:
126717214Smckusick 			sc->sc_fmesg = "WMC ROM PE or RD PE set in WMCERR register";
126817214Smckusick 			break;
126917214Smckusick 		default:
127017214Smckusick 			sc->sc_fmesg = "unclassified failure code";
127117214Smckusick 		}
127217214Smckusick 		break;
127317214Smckusick 
127417214Smckusick 	/* TU fault A */
127517214Smckusick 
127617214Smckusick 	case MTER_TUFLTA:
127717214Smckusick 		sc->sc_mesg = "TU fault A";
127817214Smckusick 		switch ((sc->sc_erreg & MTER_FAILCODE) >> 10) {
127917214Smckusick 		case 01:
128017214Smckusick 			sc->sc_fmesg = "TU status parity error";
128117214Smckusick 			break;
128217214Smckusick 		case 02:
128317214Smckusick 			sc->sc_fmesg = "TU command parity error";
128417214Smckusick 			break;
128517214Smckusick 		case 03:
128617214Smckusick 			sc->sc_fmesg = "rewinding tape went offline";
128717214Smckusick 			break;
128817214Smckusick 		case 04:
128917214Smckusick 			sc->sc_fmesg = "tape went not ready during DSE";
129017214Smckusick 			break;
129117214Smckusick 		case 05:
129217214Smckusick 			sc->sc_fmesg = "TU CMD status changed during DSE";
129317214Smckusick 			break;
129417214Smckusick 		case 06:
129517214Smckusick 			sc->sc_fmesg = "TU never came up to speed";
129617214Smckusick 			break;
129717214Smckusick 		case 07:
129817214Smckusick 			sc->sc_fmesg = "TU velocity changed";
129917214Smckusick 			break;
130017214Smckusick 		case 010:
130117214Smckusick 			sc->sc_fmesg = "TU CMD did not load correctly to start tape motion";
130217214Smckusick 			break;
130317214Smckusick 		case 011:
130417214Smckusick 			sc->sc_fmesg = "TU CMD did not load correctly to set drive density";
130517214Smckusick 			break;
130617214Smckusick 		case 012:
130717214Smckusick 			sc->sc_fmesg = "TU CMD did not load correctly to start tape motion to write BOT ID";
130817214Smckusick 			break;
130917214Smckusick 		case 013:
131017214Smckusick 			sc->sc_fmesg = "TU CMD did not load correctly to backup tape to BOT after failing to write BOT ID";
131117214Smckusick 			break;
131217214Smckusick 		case 014:
131317214Smckusick 			sc->sc_fmesg = "failed to write density ID burst";
131417214Smckusick 			break;
131517214Smckusick 		case 015:
131617214Smckusick 			sc->sc_fmesg = "failed to write ARA burst";
131717214Smckusick 			break;
131817214Smckusick 		case 016:
131917214Smckusick 			sc->sc_fmesg = "failed to write ARA ID";
132017214Smckusick 			break;
132117214Smckusick 		case 017:
132217214Smckusick 			sc->sc_fmesg = "ARA error bit set in MTA status B register";
132317214Smckusick 			break;
132417214Smckusick 		case 021:
132517214Smckusick 			sc->sc_fmesg = "could not find a gap after ID code was written correctly";
132617214Smckusick 			break;
132717214Smckusick 		case 022:
132817214Smckusick 			sc->sc_fmesg = "TU CMD did not load correctly to start tape motion to read ID burst";
132917214Smckusick 			break;
133017214Smckusick 		case 023:
133117214Smckusick 			sc->sc_fmesg = "timeout looking for BOT after detecting ARA ID burst";
133217214Smckusick 			break;
133317214Smckusick 		case 024:
133417214Smckusick 			sc->sc_fmesg = "failed to write tape mark";
133517214Smckusick 			break;
133617214Smckusick 		case 025:
133717214Smckusick 			sc->sc_fmesg = "tape never came up to speed while trying to reposition for retry of writing tape mark";
133817214Smckusick 			break;
133917214Smckusick 		case 026:
134017214Smckusick 			sc->sc_fmesg = "TU CMD did not load correctly to start tape motion in erase gap routine";
134117214Smckusick 			break;
134217214Smckusick 		case 027:
134317214Smckusick 			sc->sc_fmesg = "could not detect a gap in in erase gap routine";
134417214Smckusick 			break;
134517214Smckusick 		case 030:
134617214Smckusick 			sc->sc_fmesg = "could not detect a gap after writing record";
134717214Smckusick 			break;
134817214Smckusick 		case 031:
134917214Smckusick 			sc->sc_fmesg = "read path terminated before entire record was written";
135017214Smckusick 			break;
135117214Smckusick 		case 032:
135217214Smckusick 			sc->sc_fmesg = "could not find a gap after writing record and read path terminated early";
135317214Smckusick 			break;
135417214Smckusick 		case 033:
135517214Smckusick 			sc->sc_fmesg = "TU CMD did not load correctly to backup for retry of write tape mark";
135617214Smckusick 			break;
135717214Smckusick 		case 034:
135817214Smckusick 			sc->sc_fmesg = "TU velocity changed after up to speed while trying to reposition for retry of writing tape mark";
135917214Smckusick 			break;
136017214Smckusick 		case 035:
136117214Smckusick 			sc->sc_fmesg = "TU CMD did not load correctly to backup to retry a load of BOT ID";
136217214Smckusick 			break;
136317214Smckusick 		case 036:
136417214Smckusick 			sc->sc_fmesg = "timeout looking for BOT after failing to write BOT ID";
136517214Smckusick 			break;
136617214Smckusick 		case 037:
136717214Smckusick 			sc->sc_fmesg = "TU velocity changed while writing PE gap before starting to write record";
136817214Smckusick 			break;
136917214Smckusick 		case 040:
137017214Smckusick 			sc->sc_fmesg = "TU CMD did not load correctly to set PE tape density at start of write BOT ID burst";
137117214Smckusick 			break;
137217214Smckusick 		case 041:
137317214Smckusick 			sc->sc_fmesg = "TU CMD did not load correctly to set GCR tape density after writing Density ID";
137417214Smckusick 			break;
137517214Smckusick 		case 042:
137617214Smckusick 			sc->sc_fmesg = "TU CMD did not load correctly to set PE tape density at start of read from BOT";
137717214Smckusick 			break;
137817214Smckusick 		case 043:
137917214Smckusick 			sc->sc_fmesg = "TU CMD did not load correctly to set GCR tape density after reading a GCR Density ID burst";
138017214Smckusick 			break;
138117214Smckusick 		default:
138217214Smckusick 			sc->sc_fmesg = "unclassified failure code";
138317214Smckusick 		}
138417214Smckusick 		break;
138517214Smckusick 
138617214Smckusick 	/* TM fault B */
138717214Smckusick 
138817214Smckusick 	case MTER_TMFLTB:
138917214Smckusick 		sc->sc_mesg = "TM fault B";
139017214Smckusick 		switch ((sc->sc_erreg & MTER_FAILCODE) >> 10) {
139117214Smckusick 		case 00:
139217214Smckusick 			sc->sc_fmesg = "RST0 interrupt occurred with TM RDY set";
139317214Smckusick 			break;
139417214Smckusick 		case 01:
139517214Smckusick 			sc->sc_fmesg = "power failed to interrupt";
139617214Smckusick 			break;
139717214Smckusick 		case 02:
139817214Smckusick 			sc->sc_fmesg = "unknown interrupt on channel 5.5";
139917214Smckusick 			break;
140017214Smckusick 		case 03:
140117214Smckusick 			sc->sc_fmesg = "unknown interrupt on channel 6.5";
140217214Smckusick 			break;
140317214Smckusick 		case 04:
140417214Smckusick 			sc->sc_fmesg = "unknown interrupt on channel 7";
140517214Smckusick 			break;
140617214Smckusick 		case 05:
140717214Smckusick 			sc->sc_fmesg = "unknown interrupt on channel 7.5";
140817214Smckusick 			break;
140917214Smckusick 		case 06:
141017214Smckusick 			sc->sc_fmesg = "CAS contention retry count expired";
141117214Smckusick 			break;
141217214Smckusick 		case 07:
141317214Smckusick 			sc->sc_fmesg = "CAS contention error not retryable";
141417214Smckusick 			break;
141517214Smckusick 		case 010:
141617214Smckusick 			sc->sc_fmesg = "queue error, could not find queue entry";
141717214Smckusick 			break;
141817214Smckusick 		case 011:
141917214Smckusick 			sc->sc_fmesg = "queue entry already full";
142017214Smckusick 			break;
142117214Smckusick 		case 012:
142217214Smckusick 			sc->sc_fmesg = "8085 ROM parity error";
142317214Smckusick 			break;
142417214Smckusick 		case 013:
142517214Smckusick 		case 014:
142617214Smckusick 		case 015:
142717214Smckusick 		case 016:
142817214Smckusick 		case 017:
142917214Smckusick 		case 020:
143017214Smckusick 		case 021:
143117214Smckusick 		case 022:
143217214Smckusick 		case 023:
143317214Smckusick 		case 024:
143417214Smckusick 		case 025:
143517214Smckusick 		case 026:
143617214Smckusick 		case 027:
143717214Smckusick 		case 030:
143817214Smckusick 		case 031:
143917214Smckusick 		case 032:
144017214Smckusick 		case 033:
144117214Smckusick 		case 034:
144217214Smckusick 		case 035:
144317214Smckusick 		case 036:
144417214Smckusick 		case 037:
144517214Smckusick 		case 040:
144617214Smckusick 		case 041:
144717214Smckusick 		case 042:
144817214Smckusick 		case 043:
144917214Smckusick 		case 044:
145017214Smckusick 		case 045:
145117214Smckusick 		case 046:
145217214Smckusick 		case 047:
145317214Smckusick 		case 050:
145417214Smckusick 		case 051:
145517214Smckusick 		case 052:
145617214Smckusick 		case 053:
145717214Smckusick 		case 054:
145817214Smckusick 		case 055:
145917214Smckusick 		case 056:
146017214Smckusick 		case 057:
146117214Smckusick 			sc->sc_fmesg = "inline test failed";
146217214Smckusick 			break;
146317214Smckusick 		default:
146417214Smckusick 			sc->sc_fmesg = "unclassified failure code";
146517214Smckusick 		}
146617214Smckusick 		break;
146717214Smckusick 
146817214Smckusick 	/* MASSBUS fault */
146917214Smckusick 
147017214Smckusick 	case MTER_MBFLT:
147117214Smckusick 		sc->sc_mesg = "MB fault";
147217214Smckusick 		switch ((sc->sc_erreg & MTER_FAILCODE) >> 10) {
147317214Smckusick 		case 01:
147417214Smckusick 			sc->sc_fmesg = "control bus parity error";
147517214Smckusick 			break;
147617214Smckusick 		case 02:
147717214Smckusick 			sc->sc_fmesg = "illegal register referenced";
147817214Smckusick 			break;
147917214Smckusick 		default:
148017214Smckusick 			sc->sc_fmesg = "unclassified failure code";
148117214Smckusick 		}
148217214Smckusick 		break;
148317214Smckusick 
148417214Smckusick 	/* keypad entry error */
148517214Smckusick 
148617214Smckusick 	case MTER_KEYFAIL:
148717214Smckusick 		sc->sc_mesg = "keypad entry error";
148817214Smckusick 		sc->sc_fmesg = "";
148917214Smckusick 		break;
149017214Smckusick 	default:
149117214Smckusick 		sc->sc_mesg = "unclassified error";
149217214Smckusick 		sc->sc_fmesg = "";
149317214Smckusick 		break;
149417214Smckusick 	}
149517214Smckusick }
149617214Smckusick #endif MTLERRM
14974736Swnj #endif
1498