xref: /csrg-svn/sys/vax/mba/mt.c (revision 26377)
123315Smckusick /*
223315Smckusick  * Copyright (c) 1982 Regents of the University of California.
323315Smckusick  * All rights reserved.  The Berkeley software License Agreement
423315Smckusick  * specifies the terms and conditions for redistribution.
523315Smckusick  *
6*26377Skarels  *	@(#)mt.c	6.6 (Berkeley) 02/23/86
723315Smckusick  */
84736Swnj 
94736Swnj #include "mu.h"
104736Swnj #if NMT > 0
114736Swnj /*
124736Swnj  * TM78/TU78 tape driver
134736Swnj  *
1417214Smckusick  *	Original author - ?
1517214Smckusick  *	Most error recovery bug fixes - ggs (ulysses!ggs)
164736Swnj  *
1717214Smckusick  * OPTIONS:
1817214Smckusick  *	MTLERRM - Long error message text - twd, Brown University
1917214Smckusick  *	MTRDREV - `read reverse' error recovery - ggs (ulysses!ggs)
2017214Smckusick  *
214736Swnj  * TODO:
2217214Smckusick  *	Add odd byte count kludge from VMS driver (?)
2317214Smckusick  *	Write dump routine
244736Swnj  */
2517214Smckusick 
269789Ssam #include "../machine/pte.h"
279789Ssam 
2817119Sbloom #include "param.h"
2917119Sbloom #include "systm.h"
3017119Sbloom #include "buf.h"
3117119Sbloom #include "conf.h"
3217119Sbloom #include "dir.h"
3317119Sbloom #include "file.h"
3417119Sbloom #include "user.h"
3517119Sbloom #include "map.h"
3617119Sbloom #include "ioctl.h"
3717119Sbloom #include "mtio.h"
3817119Sbloom #include "cmap.h"
3917119Sbloom #include "uio.h"
4018324Sralph #include "tty.h"
414736Swnj 
428471Sroot #include "../vax/cpu.h"
4317119Sbloom #include "mbareg.h"
4417119Sbloom #include "mbavar.h"
4517119Sbloom #include "mtreg.h"
464736Swnj 
4717214Smckusick #define MTTIMEOUT	10000		/* loop limit for controller test */
4817214Smckusick #define	INF		1000000L	/* a block number that won't exist */
4917214Smckusick #define MASKREG(r)	((r) & 0xffff)	/* the control registers have 16 bits */
504736Swnj 
5117214Smckusick /* Bits for sc_flags */
524736Swnj 
5317214Smckusick #define	H_WRITTEN	01		/* last operation was a write */
5417214Smckusick #define H_EOT		02		/* end of tape encountered */
5517214Smckusick #define H_IEOT		04		/* ignore EOT condition */
564736Swnj 
5717214Smckusick /* Bits in minor device */
5817214Smckusick 
594736Swnj #define	MUUNIT(dev)	(minor(dev)&03)
604736Swnj #define	H_NOREWIND	04
6117214Smckusick #define	H_6250BPI	010
624736Swnj 
634736Swnj #define MTUNIT(dev)	(mutomt[MUUNIT(dev)])
644736Swnj 
6517214Smckusick #ifdef MTRDREV
6617214Smckusick 	int mt_do_readrev = 1;
6717214Smckusick #else
6817214Smckusick 	int mt_do_readrev = 0;
6917214Smckusick #endif
704736Swnj 
7117214Smckusick /* Per unit status information */
7217214Smckusick 
734736Swnj struct	mu_softc {
7417214Smckusick 	char	sc_openf;		/* unit is open if != 0 */
7517214Smckusick 	char	sc_flags;		/* state flags */
7617214Smckusick 	daddr_t	sc_blkno;		/* current physical block number */
7717214Smckusick 	daddr_t	sc_nxrec;		/* firewall input block number */
7817214Smckusick 	u_short	sc_erreg;		/* copy of mter or mtner */
7917214Smckusick 	u_short	sc_dsreg;		/* copy of mtds */
8017214Smckusick 	short	sc_resid;		/* residual function count for ioctl */
8117214Smckusick 	short	sc_dens;		/* density code - MT_GCR or zero */
8217214Smckusick 	struct	mba_device *sc_mi;	/* massbus structure for unit */
8317214Smckusick 	int	sc_slave;		/* slave number for unit */
8417214Smckusick 	int	sc_i_mtas;		/* mtas at slave attach time */
8517214Smckusick 	int	sc_i_mtner;		/* mtner at slave attach time */
8617214Smckusick 	int	sc_i_mtds;		/* mtds at slave attach time */
8717214Smckusick #ifdef MTLERRM
8817214Smckusick 	char	*sc_mesg;		/* text for interrupt type code */
8917214Smckusick 	char	*sc_fmesg;		/* text for tape error code */
9017214Smckusick #endif
9118324Sralph 	struct	tty *sc_ttyp;		/* record user's tty for errors */
924736Swnj } mu_softc[NMU];
934736Swnj 
9417214Smckusick struct	buf	rmtbuf[NMT];		/* data transfer buffer structures */
9517214Smckusick struct	buf	cmtbuf[NMT];		/* tape command buffer structures */
964736Swnj 
9717214Smckusick struct	mba_device *mtinfo[NMT];	/* unit massbus structure pointers */
9817214Smckusick short	mutomt[NMU];			/* tape unit to controller number map */
9917214Smckusick char	mtds_bits[] = MTDS_BITS;	/* mtds bit names for error messages */
10017214Smckusick short	mttypes[] = { MBDT_TU78, 0 };
1014736Swnj 
10217214Smckusick int	mtattach(), mtslave(), mtustart(), mtstart(), mtndtint(), mtdtint();
10317214Smckusick struct	mba_driver mtdriver =
10417214Smckusick 	{ mtattach, mtslave, mtustart, mtstart, mtdtint, mtndtint,
10517214Smckusick 	  mttypes, "mt", "mu", mtinfo };
10617214Smckusick 
10717214Smckusick void mtcreset();
10817214Smckusick 
1094736Swnj /*ARGSUSED*/
1104736Swnj mtattach(mi)
1114736Swnj 	struct mba_device *mi;
1124736Swnj {
1134736Swnj }
1144736Swnj 
1157431Skre mtslave(mi, ms, sn)
1164736Swnj 	struct mba_device *mi;
1174736Swnj 	struct mba_slave *ms;
1187431Skre 	int sn;
1194736Swnj {
1204736Swnj 	register struct mu_softc *sc = &mu_softc[ms->ms_unit];
1214736Swnj 	register struct mtdevice *mtaddr = (struct mtdevice *)mi->mi_drv;
122*26377Skarels 	int s = spl5(), rtn = 0, i;
1234736Swnj 
12417214Smckusick 	/* Just in case the controller is ill, reset it.  Then issue	*/
12517214Smckusick 	/* a sense operation and wait about a second for it to respond.	*/
12617214Smckusick 
12717214Smckusick 	mtcreset(mtaddr);
1284736Swnj 	mtaddr->mtas = -1;
1297431Skre 	mtaddr->mtncs[sn] = MT_SENSE|MT_GO;
13017214Smckusick 	for (i = MTTIMEOUT; i> 0; i--) {
13117214Smckusick 		DELAY(50);
13217214Smckusick 		if (MASKREG(mtaddr->mtas) != 0)
13317214Smckusick 			break;
13417214Smckusick 	}
13517214Smckusick 	sc->sc_i_mtas = mtaddr->mtas;
13617214Smckusick 	sc->sc_i_mtner = mtaddr->mtner;
13717214Smckusick 	sc->sc_i_mtds = mtaddr->mtds;
13817214Smckusick 
13917214Smckusick 	/* If no response, whimper.  If wrong response, call it an	*/
14017214Smckusick 	/* unsolicited interrupt and use mtndtint to log and correct.	*/
14117214Smckusick 	/* Otherwise, note whether this slave exists.			*/
14217214Smckusick 
14317214Smckusick 	if (i <= 0) {
14417214Smckusick 		printf("mt: controller hung\n");
14517214Smckusick 	} else if ((mtaddr->mtner & MTER_INTCODE) != MTER_DONE) {
14617214Smckusick 		(void) mtndtint(mi);
14717214Smckusick 	} else if (mtaddr->mtds & MTDS_PRES) {
1484736Swnj 		sc->sc_mi = mi;
1497431Skre 		sc->sc_slave = sn;
1504736Swnj 		mutomt[ms->ms_unit] = mi->mi_unit;
1514736Swnj 		rtn = 1;
1524736Swnj 	}
15317214Smckusick 
15417214Smckusick 	/* Cancel the interrupt, then wait a little while for it to go away. */
15517214Smckusick 
1564736Swnj 	mtaddr->mtas = mtaddr->mtas;
15717214Smckusick 	DELAY(10);
1584736Swnj 	splx(s);
1594736Swnj 	return (rtn);
1604736Swnj }
1614736Swnj 
1624736Swnj mtopen(dev, flag)
1634736Swnj 	dev_t dev;
1644736Swnj 	int flag;
1654736Swnj {
1664736Swnj 	register int muunit;
1674736Swnj 	register struct mba_device *mi;
1684736Swnj 	register struct mu_softc *sc;
1694736Swnj 
1704736Swnj 	muunit = MUUNIT(dev);
17117214Smckusick 	if (   (muunit >= NMU)
17217214Smckusick 	    || ((mi = mtinfo[MTUNIT(dev)]) == 0)
17317214Smckusick 	    || (mi->mi_alive == 0) )
1748581Sroot 		return (ENXIO);
17517214Smckusick 	if ((sc = &mu_softc[muunit])->sc_openf)
17617214Smckusick 		return (EBUSY);
17717214Smckusick 	sc->sc_dens = (minor(dev) & H_6250BPI) ? MT_GCR : 0;
1784736Swnj 	mtcommand(dev, MT_SENSE, 1);
1794736Swnj 	if ((sc->sc_dsreg & MTDS_ONL) == 0) {
1804736Swnj 		uprintf("mu%d: not online\n", muunit);
1818581Sroot 		return (EIO);
1824736Swnj 	}
18317214Smckusick 	if ((sc->sc_dsreg & MTDS_AVAIL) == 0) {
18417214Smckusick 		uprintf("mu%d: not online (port selector)\n", muunit);
18517214Smckusick 		return (EIO);
18617214Smckusick 	}
18717214Smckusick 	if ((flag & FWRITE) && (sc->sc_dsreg & MTDS_FPT)) {
1884736Swnj 		uprintf("mu%d: no write ring\n", muunit);
1898581Sroot 		return (EIO);
1904736Swnj 	}
19117214Smckusick 	if (   ((sc->sc_dsreg & MTDS_BOT) == 0)
19217214Smckusick 	    && (flag & FWRITE)
19317214Smckusick 	    && (   (   (sc->sc_dens == MT_GCR)
19417214Smckusick 		    && (sc->sc_dsreg & MTDS_PE) )
19517214Smckusick 		|| (   (sc->sc_dens != MT_GCR)
19617214Smckusick 		    && ((sc->sc_dsreg & MTDS_PE) == 0)))) {
1974736Swnj 		uprintf("mu%d: can't change density in mid-tape\n", muunit);
1988581Sroot 		return (EIO);
1994736Swnj 	}
2004736Swnj 	sc->sc_openf = 1;
2014736Swnj 	sc->sc_blkno = (daddr_t)0;
20217214Smckusick 
20317214Smckusick 	/* Since cooked I/O may do a read-ahead before a write, trash	*/
20417214Smckusick 	/* on a tape can make the first write fail.  Suppress the first	*/
20517214Smckusick 	/* read-ahead unless definitely doing read-write		*/
20617214Smckusick 
20717214Smckusick 	sc->sc_nxrec =  ((flag & (FTRUNC | FWRITE)) == (FTRUNC | FWRITE))
20817214Smckusick 		      ? (daddr_t)0
20917214Smckusick 		      : (daddr_t)INF;
2104736Swnj 	sc->sc_flags = 0;
21118324Sralph 	sc->sc_ttyp = u.u_ttyp;
2128581Sroot 	return (0);
2134736Swnj }
2144736Swnj 
2154736Swnj mtclose(dev, flag)
2164736Swnj 	register dev_t dev;
21717214Smckusick 	register int flag;
2184736Swnj {
2194736Swnj 	register struct mu_softc *sc = &mu_softc[MUUNIT(dev)];
2204736Swnj 
22117214Smckusick 	if (   ((flag & (FREAD | FWRITE)) == FWRITE)
22217214Smckusick 	    || (   (flag & FWRITE)
22317214Smckusick 		&& (sc->sc_flags & H_WRITTEN) ))
2244736Swnj 		mtcommand(dev, MT_CLS|sc->sc_dens, 1);
22517214Smckusick 	if ((minor(dev) & H_NOREWIND) == 0)
2264736Swnj 		mtcommand(dev, MT_REW, 0);
2274736Swnj 	sc->sc_openf = 0;
2284736Swnj }
2294736Swnj 
2304736Swnj mtcommand(dev, com, count)
2314736Swnj 	dev_t dev;
2324736Swnj 	int com, count;
2334736Swnj {
2344736Swnj 	register struct buf *bp;
2355437Sroot 	register int s;
2364736Swnj 
2374736Swnj 	bp = &cmtbuf[MTUNIT(dev)];
2385437Sroot 	s = spl5();
23917214Smckusick 	while (bp->b_flags & B_BUSY) {
24017214Smckusick 		if((bp->b_repcnt == 0) && (bp->b_flags & B_DONE))
2414736Swnj 			break;
2424736Swnj 		bp->b_flags |= B_WANTED;
2434736Swnj 		sleep((caddr_t)bp, PRIBIO);
2444736Swnj 	}
2454736Swnj 	bp->b_flags = B_BUSY|B_READ;
2465437Sroot 	splx(s);
2474736Swnj 	bp->b_dev = dev;
2484736Swnj 	bp->b_command = com;
2494736Swnj 	bp->b_repcnt = count;
2504736Swnj 	bp->b_blkno = 0;
25117214Smckusick 	bp->b_error = 0;
2524736Swnj 	mtstrategy(bp);
2534736Swnj 	if (count == 0)
2544736Swnj 		return;
2554736Swnj 	iowait(bp);
25617214Smckusick 	if (bp->b_flags & B_WANTED)
2574736Swnj 		wakeup((caddr_t)bp);
2584736Swnj 	bp->b_flags &= B_ERROR;
2594736Swnj }
2604736Swnj 
2614736Swnj mtstrategy(bp)
2624736Swnj 	register struct buf *bp;
2634736Swnj {
2644736Swnj 	register struct mba_device *mi = mtinfo[MTUNIT(bp->b_dev)];
2654736Swnj 	register struct buf *dp;
2665437Sroot 	register int s;
2674736Swnj 
26817214Smckusick 	/* If this is a data transfer operation, set the resid to a	*/
26917214Smckusick 	/* default value (EOF) to simplify getting it right during	*/
27017214Smckusick 	/* error recovery or bail out.					*/
27117214Smckusick 
27217214Smckusick 	if (bp != &cmtbuf[MTUNIT(bp->b_dev)])
27317214Smckusick 		bp->b_resid = bp->b_bcount;
27417214Smckusick 
27517214Smckusick 	/* Link this request onto the end of the queue for this		*/
27617214Smckusick 	/* controller, then start I/O if not already active.		*/
27717214Smckusick 
2784736Swnj 	bp->av_forw = NULL;
2794736Swnj 	dp = &mi->mi_tab;
2805437Sroot 	s = spl5();
2814736Swnj 	if (dp->b_actf == NULL)
2824736Swnj 		dp->b_actf = bp;
2834736Swnj 	else
2844736Swnj 		dp->b_actl->av_forw = bp;
2854736Swnj 	dp->b_actl = bp;
2864736Swnj 	if (dp->b_active == 0)
2874736Swnj 		mbustart(mi);
2885437Sroot 	splx(s);
2894736Swnj }
2904736Swnj 
2914736Swnj mtustart(mi)
2924736Swnj 	register struct mba_device *mi;
2934736Swnj {
29417214Smckusick 	register struct mtdevice *mtaddr = (struct mtdevice *)mi->mi_drv;
2954736Swnj 	register struct buf *bp = mi->mi_tab.b_actf;
2964736Swnj 	register struct mu_softc *sc = &mu_softc[MUUNIT(bp->b_dev)];
2974736Swnj 	daddr_t blkno;
298*26377Skarels 	int count;
2994736Swnj 
3004736Swnj 	if (sc->sc_openf < 0) {
3014736Swnj 		bp->b_flags |= B_ERROR;
3024736Swnj 		return (MBU_NEXT);
3034736Swnj 	}
3044736Swnj 	if (bp != &cmtbuf[MTUNIT(bp->b_dev)]) {
30517214Smckusick 
30617214Smckusick 		/* Signal "no space" if out of tape unless suppressed	*/
30717214Smckusick 		/* by MTIOCIEOT.					*/
30817214Smckusick 
30917214Smckusick 		if (   ((sc->sc_flags & (H_EOT | H_IEOT)) == H_EOT)
31017214Smckusick 		    && ((bp->b_flags & B_READ) == 0) ) {
3114736Swnj 			bp->b_flags |= B_ERROR;
31217214Smckusick 			bp->b_error = ENOSPC;
3134736Swnj 			return (MBU_NEXT);
3144736Swnj 		}
31517214Smckusick 
31617214Smckusick 		/* special case tests for cooked mode */
31717214Smckusick 
31817214Smckusick 		if (bp != &rmtbuf[MTUNIT(bp->b_dev)]) {
31917214Smckusick 
32017214Smckusick 			/* seek beyond end of file */
32117214Smckusick 
32217214Smckusick 			if (bdbtofsb(bp->b_blkno) > sc->sc_nxrec) {
32317214Smckusick 				bp->b_flags |= B_ERROR;
32417214Smckusick 				bp->b_error = ENXIO;
32517214Smckusick 				return (MBU_NEXT);
32617214Smckusick 			}
32717214Smckusick 
32817214Smckusick 			/* This should be end of file, but the buffer	   */
32917214Smckusick 			/* system wants a one-block look-ahead.  Humor it. */
33017214Smckusick 
33117214Smckusick 			if (   (bdbtofsb(bp->b_blkno) == sc->sc_nxrec)
33217214Smckusick 			    && (bp->b_flags & B_READ) ) {
33317214Smckusick 				clrbuf(bp);
33417214Smckusick 				return (MBU_NEXT);
33517214Smckusick 			}
33617214Smckusick 
33717214Smckusick 			/* If writing, mark the next block invalid. */
33817214Smckusick 
33917214Smckusick 			if ((bp->b_flags & B_READ) == 0)
34017214Smckusick 				sc->sc_nxrec = bdbtofsb(bp->b_blkno) + 1;
3414736Swnj 		}
3424736Swnj 	} else {
34317214Smckusick 
34417214Smckusick 		/* It's a command, do it now. */
34517214Smckusick 
3464736Swnj 		mtaddr->mtncs[MUUNIT(bp->b_dev)] =
3474736Swnj 			(bp->b_repcnt<<8)|bp->b_command|MT_GO;
3484736Swnj 		return (MBU_STARTED);
3494736Swnj 	}
35017214Smckusick 
35117214Smckusick 	/* If raw I/O, or if the tape is positioned correctly for	*/
35217214Smckusick 	/* cooked I/O, set the byte count, unit number and repeat count	*/
35317214Smckusick 	/* then tell the MASSBUS to proceed.  Note that a negative	*/
35417214Smckusick 	/* bcount tells mbstart to map the buffer for "read backwards".	*/
35517214Smckusick 
35617214Smckusick 	if (   (bp == &rmtbuf[MTUNIT(bp->b_dev)])
35717214Smckusick 	    || ((blkno = sc->sc_blkno) == bdbtofsb(bp->b_blkno)) ) {
3584736Swnj 		if (mi->mi_tab.b_errcnt == 2) {
35917214Smckusick 			mtaddr->mtbc = -(bp->b_bcount);
3604736Swnj 			mtaddr->mtca = MUUNIT(bp->b_dev);
3614736Swnj 		} else {
3624736Swnj 			mtaddr->mtbc = bp->b_bcount;
3634736Swnj 			mtaddr->mtca = (1<<2)|MUUNIT(bp->b_dev);
3644736Swnj 		}
3654736Swnj 		return (MBU_DODATA);
3664736Swnj 	}
36717214Smckusick 
36817214Smckusick 	/* Issue skip operations to position the next block for cooked I/O. */
36917214Smckusick 
3707380Ssam 	if (blkno < bdbtofsb(bp->b_blkno))
371*26377Skarels 		count = (unsigned)(bdbtofsb(bp->b_blkno) - blkno);
3724736Swnj 	else
373*26377Skarels 		count = (unsigned)(blkno - bdbtofsb(bp->b_blkno));
374*26377Skarels 	if (count > 0377)
375*26377Skarels 		count = 0377;
376*26377Skarels 	mtaddr->mtncs[MUUNIT(bp->b_dev)] = count | MT_SFORW|MT_GO;
3774736Swnj 	return (MBU_STARTED);
3784736Swnj }
3794736Swnj 
3804736Swnj mtstart(mi)
3814736Swnj 	register struct mba_device *mi;
3824736Swnj {
3834736Swnj 	register struct buf *bp = mi->mi_tab.b_actf;
3844736Swnj 	register struct mu_softc *sc = &mu_softc[MUUNIT(bp->b_dev)];
3854736Swnj 
3864736Swnj 	if (bp->b_flags & B_READ)
3874736Swnj 		if (mi->mi_tab.b_errcnt == 2)
3884736Swnj 			return(MT_READREV|MT_GO);
3894736Swnj 		else
3904736Swnj 			return(MT_READ|MT_GO);
3914736Swnj 	else
3924736Swnj 		return(MT_WRITE|sc->sc_dens|MT_GO);
3934736Swnj }
3944736Swnj 
3954736Swnj mtdtint(mi, mbsr)
3964736Swnj 	register struct mba_device *mi;
3974736Swnj 	int mbsr;
3984736Swnj {
3994736Swnj 	register struct mtdevice *mtaddr = (struct mtdevice *)mi->mi_drv;
4004736Swnj 	register struct buf *bp = mi->mi_tab.b_actf;
4014736Swnj 	register struct mu_softc *sc;
40217214Smckusick 	register int er;
4034736Swnj 
40417214Smckusick 	/* I'M still NOT SURE IF THIS SHOULD ALWAYS BE THE CASE SO FOR NOW... */
40517214Smckusick 
40617214Smckusick 	if ((mtaddr->mtca & 3) != MUUNIT(bp->b_dev)) {
4074736Swnj 		printf("mt: wrong unit!\n");
4084736Swnj 		mtaddr->mtca = MUUNIT(bp->b_dev);
4094736Swnj 	}
41017214Smckusick 
41117214Smckusick 	er = MASKREG(mtaddr->mter);
4124736Swnj 	sc = &mu_softc[MUUNIT(bp->b_dev)];
41317214Smckusick 	sc->sc_erreg = er;
41417214Smckusick 	if (bp->b_flags & B_READ)
41517214Smckusick 		sc->sc_flags &= ~H_WRITTEN;
41617214Smckusick 	else
4174736Swnj 		sc->sc_flags |= H_WRITTEN;
41817214Smckusick 	switch (er & MTER_INTCODE) {
41917214Smckusick 
42017214Smckusick 	case MTER_EOT:
42117214Smckusick 		sc->sc_flags |= H_EOT;
42217214Smckusick 
42317214Smckusick 		/* fall into MTER_DONE */
42417214Smckusick 
4254736Swnj 	case MTER_DONE:
42617214Smckusick 		sc->sc_blkno++;
42717214Smckusick 		if (mi->mi_tab.b_errcnt == 2) {
42817214Smckusick 			bp->b_bcount = bp->b_resid;
42917214Smckusick 			bp->b_resid -= MASKREG(mtaddr->mtbc);
43017214Smckusick 			if (   (bp->b_resid > 0)
43117214Smckusick 			    && (bp != &rmtbuf[MTUNIT(bp->b_dev)]) )
43217214Smckusick 				bp->b_flags |= B_ERROR;
43317214Smckusick 		} else {
43417214Smckusick 			bp->b_resid = 0;
43517214Smckusick 		}
43617214Smckusick 		break;
43717214Smckusick 
43817214Smckusick 	case MTER_SHRTREC:
43917214Smckusick 		sc->sc_blkno++;
44017214Smckusick 		bp->b_bcount = bp->b_resid;
44117214Smckusick 		bp->b_resid -= MASKREG(mtaddr->mtbc);
44217214Smckusick 		if (bp != &rmtbuf[MTUNIT(bp->b_dev)])
44317214Smckusick 			bp->b_flags |= B_ERROR;
44417214Smckusick 		break;
44517214Smckusick 
44617214Smckusick 	case MTER_RETRY:
44717214Smckusick 
44817214Smckusick 		/* Simple re-try.  Since resid is always a copy of the	*/
44917214Smckusick 		/* original byte count, use it to restore the count.	*/
45017214Smckusick 
45117214Smckusick 		mi->mi_tab.b_errcnt = 1;
45217214Smckusick 		bp->b_bcount = bp->b_resid;
45317214Smckusick 		return(MBD_RETRY);
45417214Smckusick 
45517214Smckusick 	case MTER_RDOPP:
45617214Smckusick 
45717214Smckusick 		/* The controller just decided to read it backwards.	*/
45817214Smckusick 		/* If the controller returns a byte count of zero,	*/
45917214Smckusick 		/* change it to 1, since zero encodes 65536, which	*/
46017214Smckusick 		/* isn't quite what we had in mind.  The byte count	*/
46117214Smckusick 		/* may be larger than the size of the input buffer, so	*/
46217214Smckusick 		/* limit the count to the buffer size.  After		*/
46317214Smckusick 		/* making the byte count reasonable, set bcount to the	*/
46417214Smckusick 		/* negative of the controller's version of the byte	*/
46517214Smckusick 		/* count so that the start address for the transfer is	*/
46617214Smckusick 		/* set up correctly.					*/
46717214Smckusick 
46817214Smckusick 		if (mt_do_readrev) {
46917214Smckusick 			mi->mi_tab.b_errcnt = 2;
47017214Smckusick 			if ((bp->b_bcount = MASKREG(mtaddr->mtbc)) == 0)
47117214Smckusick 				bp->b_bcount = 1;
47217214Smckusick 			if (bp->b_bcount > bp->b_resid)
47317214Smckusick 				bp->b_bcount = bp->b_resid;
47417214Smckusick 			bp->b_bcount = -(bp->b_bcount);
47517214Smckusick 			return(MBD_RETRY);
47617214Smckusick 		} else if (MASKREG(mtaddr->mtbc) <= bp->b_resid) {
47717214Smckusick 			sc->sc_blkno++;
47817214Smckusick 			bp->b_bcount = bp->b_resid;
47917214Smckusick 			bp->b_resid -= MASKREG(mtaddr->mtbc);
48017214Smckusick 			bp->b_flags |= B_ERROR;
48117214Smckusick 			break;
48217214Smckusick 		}
48317214Smckusick 		bp->b_flags |= B_ERROR;
48417214Smckusick 
48517214Smckusick 		/* fall into MTER_LONGREC */
48617214Smckusick 
4874736Swnj 	case MTER_LONGREC:
48817214Smckusick 		sc->sc_blkno++;
48917214Smckusick 		bp->b_bcount = bp->b_resid;
4904736Swnj 		bp->b_resid = 0;
49117214Smckusick 		bp->b_error = ENOMEM;
49217214Smckusick 		bp->b_flags |= B_ERROR;
4934736Swnj 		break;
4944736Swnj 
4954736Swnj 	case MTER_NOTCAP:
4964736Swnj 		printf("mu%d: blank tape\n", MUUNIT(bp->b_dev));
4974736Swnj 		goto err;
4984736Swnj 
4994736Swnj 	case MTER_TM:
50017214Smckusick 
50117214Smckusick 		/* End of file.  Since the default byte count has	*/
50217214Smckusick 		/* already been set, just count the block and proceed.	*/
50317214Smckusick 
5044736Swnj 		sc->sc_blkno++;
5054736Swnj 	err:
5064736Swnj 		if (bp != &rmtbuf[MTUNIT(bp->b_dev)])
50717214Smckusick 			sc->sc_nxrec = bdbtofsb(bp->b_blkno);
5084736Swnj 		break;
5094736Swnj 
5104736Swnj 	case MTER_OFFLINE:
5114736Swnj 		if (sc->sc_openf > 0) {
5124736Swnj 			sc->sc_openf = -1;
51318324Sralph 			tprintf(sc->sc_ttyp, "mu%d: offline\n", MUUNIT(bp->b_dev));
5144736Swnj 		}
5154736Swnj 		bp->b_flags |= B_ERROR;
5164736Swnj 		break;
5174736Swnj 
51817214Smckusick 	case MTER_NOTAVL:
51917214Smckusick 		if (sc->sc_openf > 0) {
52017214Smckusick 			sc->sc_openf = -1;
52118324Sralph 			tprintf(sc->sc_ttyp, "mu%d: offline (port selector)\n",
52218324Sralph 			    MUUNIT(bp->b_dev));
52317214Smckusick 		}
52417214Smckusick 		bp->b_flags |= B_ERROR;
52517214Smckusick 		break;
52617214Smckusick 
5274736Swnj 	case MTER_FPT:
52818324Sralph 		tprintf(sc->sc_ttyp, "mu%d: no write ring\n", MUUNIT(bp->b_dev));
5294736Swnj 		bp->b_flags |= B_ERROR;
5304736Swnj 		break;
5314736Swnj 
53217214Smckusick 	case MTER_UNREAD:
53317214Smckusick 		sc->sc_blkno++;
53417214Smckusick 		bp->b_bcount = bp->b_resid;
53517214Smckusick 		bp->b_resid -= MIN(MASKREG(mtaddr->mtbc), bp->b_bcount);
53617214Smckusick 
53717214Smckusick 		/* Code 010 means a garbage record, nothing serious. */
53817214Smckusick 
53917214Smckusick 		if (((er & MTER_FAILCODE) >> 10) == 010) {
54018324Sralph 			tprintf(sc->sc_ttyp, "mu%d: rn=%d bn=%d unreadable record\n",
54117214Smckusick 			    MUUNIT(bp->b_dev), sc->sc_blkno, bp->b_blkno);
54217214Smckusick 			bp->b_flags |= B_ERROR;
54317214Smckusick 			break;
54417214Smckusick 		}
54517214Smckusick 
54617214Smckusick 		/* Anything else might be a hardware problem,	*/
54717214Smckusick 		/* fall into the error report.			*/
54817214Smckusick 
5494736Swnj 	default:
55017214Smckusick 
55117214Smckusick 		/* The bits in sc->sc_dsreg are from the last sense	*/
55217214Smckusick 		/* command.  To get the most recent copy, you have to	*/
55317214Smckusick 		/* do a sense at interrupt level, which requires nested	*/
55417214Smckusick 		/* error processing.  This is a bit messy, so leave	*/
55517214Smckusick 		/* well enough alone.					*/
55617214Smckusick 
55718324Sralph 		tprintf(sc->sc_ttyp, "mu%d: hard error (data transfer) rn=%d bn=%d mbsr=%b er=%o (octal) ds=%b\n",
55817214Smckusick 		    MUUNIT(bp->b_dev), sc->sc_blkno, bp->b_blkno,
55917214Smckusick 		    mbsr, mbsr_bits, er,
56017214Smckusick 		    MASKREG(sc->sc_dsreg), mtds_bits);
56117214Smckusick #ifdef MTLERRM
56217214Smckusick 		mtintfail(sc);
56317214Smckusick 		printf("     interrupt code = %o (octal) <%s>\n     failure code = %o (octal) <%s>\n",
56417214Smckusick 		    er & MTER_INTCODE, sc->sc_mesg,
56517214Smckusick 		    (er & MTER_FAILCODE) >> 10, sc->sc_fmesg);
56617214Smckusick #endif
5674736Swnj 		bp->b_flags |= B_ERROR;
56817214Smckusick 
56917214Smckusick 		/* The TM78 manual says to reset the controller after	*/
57017214Smckusick 		/* TM fault B or MASSBUS fault.				*/
57117214Smckusick 
57217214Smckusick 		if (   ((er & MTER_INTCODE) == MTER_TMFLTB)
57317214Smckusick 		    || ((er & MTER_INTCODE) == MTER_MBFLT) ) {
57417214Smckusick 			mtcreset(mtaddr);
57517214Smckusick 		}
5764736Swnj 	}
57717214Smckusick 
57817214Smckusick 	/* Just in case some strange error slipped through, (drive off	*/
57917214Smckusick 	/* line during read-reverse error recovery comes to mind) make	*/
58017214Smckusick 	/* sure the byte count is reasonable.				*/
58117214Smckusick 
58217214Smckusick 	if (bp->b_bcount < 0)
58317214Smckusick 		bp->b_bcount = bp->b_resid;
5844736Swnj 	return (MBD_DONE);
5854736Swnj }
5864736Swnj 
5874736Swnj mtndtint(mi)
5884736Swnj 	register struct mba_device *mi;
5894736Swnj {
5904736Swnj 	register struct mtdevice *mtaddr = (struct mtdevice *)mi->mi_drv;
5914736Swnj 	register struct buf *bp = mi->mi_tab.b_actf;
5924736Swnj 	register struct mu_softc *sc;
59317214Smckusick 	register int er, fc;
59417214Smckusick 	int unit;
5954736Swnj 
5964736Swnj 	unit = (mtaddr->mtner >> 8) & 3;
5974736Swnj 	er = MASKREG(mtaddr->mtner);
59817214Smckusick 	sc = &mu_softc[unit];
59917214Smckusick 	sc->sc_erreg = er;
60017214Smckusick 
60117214Smckusick 	/* Check for unsolicited interrupts. */
60217214Smckusick 
6034736Swnj 	if (bp == 0 || unit != MUUNIT(bp->b_dev)) {	/* consistency check */
60417214Smckusick 		if ((er & MTER_INTCODE) != MTER_ONLINE) {
60517214Smckusick 			printf("mt: unit %d unexpected interrupt (non data transfer) er=%o (octal) ds=%b\n",
60617214Smckusick 			    unit, er, MASKREG(sc->sc_dsreg), mtds_bits);
60717214Smckusick #ifdef MTLERRM
60817214Smckusick 			mtintfail(sc);
60917214Smckusick 			printf("    interrupt code = %o (octal) <%s>\n    failure code = %o (octal) <%s>\n",
61017214Smckusick 			    er & MTER_INTCODE, sc->sc_mesg,
61117214Smckusick 			    (er & MTER_FAILCODE) >> 10, sc->sc_fmesg);
61217214Smckusick #endif
61317214Smckusick 			if (   ((er & MTER_INTCODE) == MTER_TMFLTB)
61417214Smckusick 			    || ((er & MTER_INTCODE) == MTER_MBFLT) ) {
61517214Smckusick 
61617214Smckusick 				/* Reset the controller, then set error	*/
61717214Smckusick 				/* status if there was anything active	*/
61817214Smckusick 				/* when the fault occurred.  This may	*/
61917214Smckusick 				/* shoot an innocent bystander, but	*/
62017214Smckusick 				/* it's better than letting an error	*/
62117214Smckusick 				/* slip through.			*/
62217214Smckusick 
62317214Smckusick 				mtcreset(mtaddr);
62417214Smckusick 				if (bp != 0) {
62517214Smckusick 					bp->b_flags |= B_ERROR;
62617214Smckusick 					return (MBN_DONE);
62717214Smckusick 				}
62817214Smckusick 			}
62917214Smckusick 		}
6304736Swnj 		return (MBN_SKIP);
6314736Swnj 	}
6324736Swnj 	if (bp == 0)
6334736Swnj 		return (MBN_SKIP);
63417214Smckusick 
6354736Swnj 	fc = (mtaddr->mtncs[unit] >> 8) & 0xff;
6364736Swnj 	sc->sc_resid = fc;
63717214Smckusick 
63817214Smckusick 	/* Clear the "written" flag after any operation that changes	*/
63917214Smckusick 	/* the position of the tape.					*/
64017214Smckusick 
64117214Smckusick 	if (   (bp != &cmtbuf[MTUNIT(bp->b_dev)])
64217214Smckusick 	    || (bp->b_command != MT_SENSE) )
64317214Smckusick 		sc->sc_flags &= ~H_WRITTEN;
64417214Smckusick 
6454736Swnj 	switch (er & MTER_INTCODE) {
64617214Smckusick 
64717214Smckusick 	case MTER_EOT:
64817214Smckusick 		sc->sc_flags |= H_EOT;
64917214Smckusick 
65017214Smckusick 		/* fall into MTER_DONE */
65117214Smckusick 
6524736Swnj 	case MTER_DONE:
65317214Smckusick 
65417214Smckusick 		/* If this is a command buffer, just update the status.	*/
65517214Smckusick 
6564736Swnj 		if (bp == &cmtbuf[MTUNIT(bp->b_dev)]) {
6574736Swnj 	done:
6584736Swnj 			if (bp->b_command == MT_SENSE)
6594736Swnj 				sc->sc_dsreg = MASKREG(mtaddr->mtds);
6604736Swnj 			return (MBN_DONE);
6614736Swnj 		}
66217214Smckusick 
66317214Smckusick 		/* It's not a command buffer, must be a cooked I/O	*/
66417214Smckusick 		/* skip operation (perhaps a shaky assumption, but it	*/
66517214Smckusick 		/* wasn't my idea).					*/
66617214Smckusick 
6677380Ssam 		if ((fc = bdbtofsb(bp->b_blkno) - sc->sc_blkno) < 0)
6686186Ssam 			sc->sc_blkno -= MIN(0377, -fc);
6694736Swnj 		else
6706186Ssam 			sc->sc_blkno += MIN(0377, fc);
6714736Swnj 		return (MBN_RETRY);
6724736Swnj 
67317214Smckusick 	case MTER_ONLINE:		/* ddj -- shouldn't happen but did */
6744736Swnj 	case MTER_RWDING:
6754736Swnj 		return (MBN_SKIP);	/* ignore "rewind started" interrupt */
6764736Swnj 
6774736Swnj 	case MTER_NOTCAP:
67818324Sralph 		tprintf(sc->sc_ttyp, "mu%d: blank tape\n", MUUNIT(bp->b_dev));
67917214Smckusick 		bp->b_flags |= B_ERROR;
68017214Smckusick 		return (MBN_DONE);
6814736Swnj 
6824736Swnj 	case MTER_TM:
6834736Swnj 	case MTER_LEOT:
68417214Smckusick 
68517214Smckusick 		/* For an ioctl skip operation, count a tape mark as	*/
68617214Smckusick 		/* a record.  If there's anything left to do, update	*/
68717214Smckusick 		/* the repeat count and re-start the command.		*/
68817214Smckusick 
68917214Smckusick 		if (bp == &cmtbuf[MTUNIT(bp->b_dev)]) {
69017214Smckusick 			if ((sc->sc_resid = bp->b_repcnt = fc - 1) == 0)
69117214Smckusick 				return (MBN_DONE);
69217214Smckusick 			else
69317214Smckusick 				return (MBN_RETRY);
69417214Smckusick 
69517214Smckusick 		/* Cooked I/O again.  Just update the books and wait	*/
69617214Smckusick 		/* for someone else to return end of file or complain	*/
69717214Smckusick 		/* about a bad seek.					*/
69817214Smckusick 
69917214Smckusick 		} else if (sc->sc_blkno > bdbtofsb(bp->b_blkno)) {
70017214Smckusick 			sc->sc_nxrec = bdbtofsb(bp->b_blkno) + fc - 1;
7014736Swnj 			sc->sc_blkno = sc->sc_nxrec;
7024736Swnj 		} else {
70317214Smckusick 			sc->sc_nxrec = bdbtofsb(bp->b_blkno) - fc;
70417214Smckusick 			sc->sc_blkno = sc->sc_nxrec + 1;
7054736Swnj 		}
7064736Swnj 		return (MBN_RETRY);
7074736Swnj 
7084736Swnj 	case MTER_FPT:
70918324Sralph 		tprintf(sc->sc_ttyp, "mu%d: no write ring\n", MUUNIT(bp->b_dev));
7104736Swnj 		bp->b_flags |= B_ERROR;
7114736Swnj 		return (MBN_DONE);
7124736Swnj 
7134736Swnj 	case MTER_OFFLINE:
71417214Smckusick 
71517214Smckusick 		/* If `off line' was intentional, don't complain. */
71617214Smckusick 
71717214Smckusick 		if (   (bp == &cmtbuf[MTUNIT(bp->b_dev)])
71817214Smckusick 		    && (bp->b_command == MT_UNLOAD) )
71917214Smckusick 			return(MBN_DONE);
7204736Swnj 		if (sc->sc_openf > 0) {
7214736Swnj 			sc->sc_openf = -1;
72218324Sralph 			tprintf(sc->sc_ttyp, "mu%d: offline\n", MUUNIT(bp->b_dev));
7234736Swnj 		}
7244736Swnj 		bp->b_flags |= B_ERROR;
7254736Swnj 		return (MBN_DONE);
7264736Swnj 
72717214Smckusick 	case MTER_NOTAVL:
72817214Smckusick 		if (sc->sc_openf > 0) {
72917214Smckusick 			sc->sc_openf = -1;
73018324Sralph 			tprintf(sc->sc_ttyp, "mu%d: offline (port selector)\n", MUUNIT(bp->b_dev));
73117214Smckusick 		}
73217214Smckusick 		bp->b_flags |= B_ERROR;
73317214Smckusick 		return (MBN_DONE);
73417214Smckusick 
7354736Swnj 	case MTER_BOT:
7364736Swnj 		if (bp == &cmtbuf[MTUNIT(bp->b_dev)])
7374736Swnj 			goto done;
7384736Swnj 
73917214Smckusick 		/* fall through */
74017214Smckusick 
7414736Swnj 	default:
74218324Sralph 		tprintf(sc->sc_ttyp, "mu%d: hard error (non data transfer) rn=%d bn=%d er=%o (octal) ds=%b\n",
74317214Smckusick 		    MUUNIT(bp->b_dev), sc->sc_blkno, bp->b_blkno,
74417214Smckusick 		    er, MASKREG(sc->sc_dsreg), mtds_bits);
74517214Smckusick #ifdef MTLERRM
74617214Smckusick 		mtintfail(sc);
74717214Smckusick 		printf("     interrupt code = %o (octal) <%s>\n     failure code = %o (octal) <%s>\n",
74817214Smckusick 		    (er & MTER_INTCODE), sc->sc_mesg,
74917214Smckusick 		    (er & MTER_FAILCODE) >> 10, sc->sc_fmesg);
75017214Smckusick #endif
75117214Smckusick 		if (   ((er & MTER_INTCODE) == MTER_TMFLTB)
75217214Smckusick 		    || ((er & MTER_INTCODE) == MTER_MBFLT) ) {
75317214Smckusick 			mtcreset(mtaddr);	/* reset the controller */
75417214Smckusick 		}
7554736Swnj 		bp->b_flags |= B_ERROR;
7564736Swnj 		return (MBN_DONE);
7574736Swnj 	}
7584736Swnj 	/* NOTREACHED */
7594736Swnj }
7604736Swnj 
76117214Smckusick void mtcreset(mtaddr)
76217214Smckusick 	register struct mtdevice *mtaddr;
76317214Smckusick {
76417214Smckusick 	register int i;
76517214Smckusick 
76617214Smckusick 	mtaddr->mtid = MTID_CLR;		/* reset the TM78 */
76717214Smckusick 	DELAY(200);
76817214Smckusick 	for (i = MTTIMEOUT; i > 0; i--) {
76917214Smckusick 		DELAY(50);			/* don't nag */
77017214Smckusick 		if ((mtaddr->mtid & MTID_RDY) != 0)
77117214Smckusick 			return;			/* exit when ready */
77217214Smckusick 	}
77317214Smckusick 	printf("mt: controller hung\n");
77417214Smckusick }
77517214Smckusick 
7767740Sroot mtread(dev, uio)
7774736Swnj 	dev_t dev;
7787740Sroot 	struct uio *uio;
7794736Swnj {
7808158Sroot 	int errno;
7814736Swnj 
7828158Sroot 	errno = mtphys(dev, uio);
7838158Sroot 	if (errno)
7848158Sroot 		return (errno);
7858158Sroot 	return (physio(mtstrategy, &rmtbuf[MTUNIT(dev)], dev, B_READ, minphys, uio));
7864736Swnj }
7874736Swnj 
78817214Smckusick 
7897833Sroot mtwrite(dev, uio)
7907833Sroot 	dev_t dev;
7917833Sroot 	struct uio *uio;
7924736Swnj {
7938158Sroot 	int errno;
7944736Swnj 
7958158Sroot 	errno = mtphys(dev, uio);
7968158Sroot 	if (errno)
7978158Sroot 		return (errno);
7988158Sroot 	return (physio(mtstrategy, &rmtbuf[MTUNIT(dev)], dev, B_WRITE, minphys, uio));
7994736Swnj }
8004736Swnj 
8017740Sroot mtphys(dev, uio)
8024736Swnj 	dev_t dev;
8037740Sroot 	struct uio *uio;
8044736Swnj {
8054736Swnj 	register int mtunit;
80617214Smckusick 	struct mba_device *mi;
80717214Smckusick 	register int bsize = uio->uio_iov->iov_len;
8084736Swnj 
8094736Swnj 	mtunit = MTUNIT(dev);
81017214Smckusick 	if (   (mtunit >= NMT)
81117214Smckusick 	    || ((mi = mtinfo[mtunit]) == 0)
81217214Smckusick 	    || (mi->mi_alive == 0) )
8137740Sroot 		return (ENXIO);
81417214Smckusick 	if (   (bsize > 0xffff)	/* controller limit */
81517214Smckusick 	    || (bsize <= 0) )	/* ambiguous */
81617214Smckusick 		return (EINVAL);
8177740Sroot 	return (0);
8184736Swnj }
8194736Swnj 
8204736Swnj /*ARGSUSED*/
8217637Ssam mtioctl(dev, cmd, data, flag)
8224736Swnj 	dev_t dev;
8234736Swnj 	int cmd;
8247637Ssam 	caddr_t data;
8254736Swnj 	int flag;
8264736Swnj {
8274736Swnj 	register struct mu_softc *sc = &mu_softc[MUUNIT(dev)];
8284736Swnj 	register struct buf *bp = &cmtbuf[MTUNIT(dev)];
82917214Smckusick 	register struct mtop *mtop;
83017214Smckusick 	register struct mtget *mtget;
83117214Smckusick 	int callcount, fcount;
83217214Smckusick 	int op;
83317214Smckusick 
83417214Smckusick 	/* We depend on the values and order of the MT codes here. */
83517214Smckusick 
8364736Swnj 	static mtops[] =
8374736Swnj 	{MT_WTM,MT_SFORWF,MT_SREVF,MT_SFORW,MT_SREV,MT_REW,MT_UNLOAD,MT_SENSE};
8384736Swnj 
8394736Swnj 	switch (cmd) {
8407637Ssam 
84117214Smckusick 	/* tape operation */
84217214Smckusick 
84317214Smckusick 	case MTIOCTOP:
8448606Sroot 		mtop = (struct mtop *)data;
8458606Sroot 		switch (mtop->mt_op) {
8467637Ssam 
8474736Swnj 		case MTWEOF:
8487637Ssam 			callcount = mtop->mt_count;
8494736Swnj 			fcount = 1;
8504736Swnj 			break;
8517637Ssam 
8524736Swnj 		case MTFSF: case MTBSF:
8537637Ssam 			callcount = mtop->mt_count;
8544736Swnj 			fcount = 1;
8554736Swnj 			break;
8567637Ssam 
8574736Swnj 		case MTFSR: case MTBSR:
8584736Swnj 			callcount = 1;
8597637Ssam 			fcount = mtop->mt_count;
8604736Swnj 			break;
8617637Ssam 
8624736Swnj 		case MTREW: case MTOFFL:
8634736Swnj 			callcount = 1;
8644736Swnj 			fcount = 1;
8654736Swnj 			break;
8667637Ssam 
8674736Swnj 		default:
8688581Sroot 			return (ENXIO);
8694736Swnj 		}
87017214Smckusick 		if ((callcount <= 0) || (fcount <= 0))
8718581Sroot 			return (EINVAL);
8727637Ssam 		op = mtops[mtop->mt_op];
8734736Swnj 		if (op == MT_WTM)
8744736Swnj 			op |= sc->sc_dens;
8754736Swnj 		while (--callcount >= 0) {
87617214Smckusick 			register int n, fc = fcount;
8774736Swnj 
8784736Swnj 			do {
87917214Smckusick 				n = MIN(fc, 0xff);
8804736Swnj 				mtcommand(dev, op, n);
88117214Smckusick 				n -= sc->sc_resid;
88217214Smckusick 				fc -= n;
88317214Smckusick 				switch (mtop->mt_op) {
88417214Smckusick 
88517214Smckusick 				case MTWEOF:
88617214Smckusick 					sc->sc_blkno += (daddr_t)n;
88717214Smckusick 					sc->sc_nxrec = sc->sc_blkno - 1;
88817214Smckusick 					break;
88917214Smckusick 
89017214Smckusick 				case MTOFFL:
89117214Smckusick 				case MTREW:
89217214Smckusick 				case MTFSF:
89317214Smckusick 					sc->sc_blkno = (daddr_t)0;
89417214Smckusick 					sc->sc_nxrec = (daddr_t)INF;
89517214Smckusick 					break;
89617214Smckusick 
89717214Smckusick 				case MTBSF:
89817214Smckusick 					if (sc->sc_resid) {
89917214Smckusick 						sc->sc_blkno = (daddr_t)0;
90017214Smckusick 						sc->sc_nxrec = (daddr_t)INF;
90117214Smckusick 					} else {
90217214Smckusick 						sc->sc_blkno = (daddr_t)(-1);
90317214Smckusick 						sc->sc_nxrec = (daddr_t)(-1);
90417214Smckusick 					}
90517214Smckusick 					break;
90617214Smckusick 
90717214Smckusick 				case MTFSR:
90817214Smckusick 					sc->sc_blkno += (daddr_t)n;
90917214Smckusick 					break;
91017214Smckusick 
91117214Smckusick 				case MTBSR:
91217214Smckusick 					sc->sc_blkno -= (daddr_t)n;
91317214Smckusick 					break;
91417214Smckusick 				}
91517214Smckusick 				if (sc->sc_resid)
91617214Smckusick 					break;
91717214Smckusick 			} while (fc);
91817214Smckusick 			if (fc) {
91917214Smckusick 				sc->sc_resid = callcount + fc;
92017214Smckusick 				if (   (mtop->mt_op == MTFSR)
92117214Smckusick 				    || (mtop->mt_op == MTBSR) )
92217214Smckusick 					return (EIO);
92317214Smckusick 				else
92417214Smckusick 					break;
92517214Smckusick 			}
92617214Smckusick 			if (bp->b_flags & B_ERROR)
9274736Swnj 				break;
9284736Swnj 		}
9298712Sroot 		return (geterror(bp));
9307637Ssam 
93117214Smckusick 	/* tape status */
93217214Smckusick 
9334736Swnj 	case MTIOCGET:
9347637Ssam 		mtget = (struct mtget *)data;
9357637Ssam 		mtget->mt_erreg = sc->sc_erreg;
9367637Ssam 		mtget->mt_resid = sc->sc_resid;
9374736Swnj 		mtcommand(dev, MT_SENSE, 1);	/* update drive status */
9387637Ssam 		mtget->mt_dsreg = sc->sc_dsreg;
9397637Ssam 		mtget->mt_type = MT_ISMT;
9408581Sroot 		break;
9417637Ssam 
94217214Smckusick 	/* ignore EOT condition */
94317214Smckusick 
94417214Smckusick 	case MTIOCIEOT:
94517214Smckusick 		sc->sc_flags |= H_IEOT;
94617214Smckusick 		break;
94717214Smckusick 
94817214Smckusick 	/* enable EOT condition */
94917214Smckusick 
95017214Smckusick 	case MTIOCEEOT:
95117214Smckusick 		sc->sc_flags &= ~H_IEOT;
95217214Smckusick 		break;
95317214Smckusick 
9544736Swnj 	default:
9558581Sroot 		return (ENXIO);
9564736Swnj 	}
9578581Sroot 	return (0);
9584736Swnj }
9594736Swnj 
9604736Swnj #define	DBSIZE	20
9614736Swnj 
9624736Swnj mtdump()
9634736Swnj {
9644736Swnj 	register struct mba_device *mi;
9654736Swnj 	register struct mba_regs *mp;
9664736Swnj 	int blk, num;
9674736Swnj 	int start;
9684736Swnj 
9694736Swnj 	start = 0;
9704736Swnj 	num = maxfree;
9714736Swnj #define	phys(a,b)		((b)((int)(a)&0x7fffffff))
9724736Swnj 	if (mtinfo[0] == 0)
9734736Swnj 		return (ENXIO);
9744736Swnj 	mi = phys(mtinfo[0], struct mba_device *);
9754736Swnj 	mp = phys(mi->mi_hd, struct mba_hd *)->mh_physmba;
9764736Swnj 	mp->mba_cr = MBCR_IE;
9776186Ssam #if lint
9788606Sroot 	blk = 0; num = blk; start = num; blk = start;
9796186Ssam 	return (0);
9806186Ssam #endif
9816186Ssam #ifdef notyet
9824736Swnj 	mtaddr = (struct mtdevice *)&mp->mba_drv[mi->mi_drive];
9834736Swnj 	mtaddr->mttc = MTTC_PDP11|MTTC_1600BPI;
9844736Swnj 	mtaddr->mtcs1 = MT_DCLR|MT_GO;
9854736Swnj 	while (num > 0) {
9864736Swnj 		blk = num > DBSIZE ? DBSIZE : num;
9874736Swnj 		mtdwrite(start, blk, mtaddr, mp);
9884736Swnj 		start += blk;
9894736Swnj 		num -= blk;
9904736Swnj 	}
9914736Swnj 	mteof(mtaddr);
9924736Swnj 	mteof(mtaddr);
9934736Swnj 	mtwait(mtaddr);
9944736Swnj 	if (mtaddr->mtds&MTDS_ERR)
9954736Swnj 		return (EIO);
9964736Swnj 	mtaddr->mtcs1 = MT_REW|MT_GO;
9974736Swnj 	return (0);
9984736Swnj }
9994736Swnj 
10004736Swnj mtdwrite(dbuf, num, mtaddr, mp)
10014736Swnj 	register dbuf, num;
10024736Swnj 	register struct mtdevice *mtaddr;
10034736Swnj 	struct mba_regs *mp;
10044736Swnj {
10054736Swnj 	register struct pte *io;
10064736Swnj 	register int i;
10074736Swnj 
10084736Swnj 	mtwait(mtaddr);
10094736Swnj 	io = mp->mba_map;
10104736Swnj 	for (i = 0; i < num; i++)
10114736Swnj 		*(int *)io++ = dbuf++ | PG_V;
10124736Swnj 	mtaddr->mtfc = -(num*NBPG);
10134736Swnj 	mp->mba_sr = -1;
10144736Swnj 	mp->mba_bcr = -(num*NBPG);
10154736Swnj 	mp->mba_var = 0;
10164736Swnj 	mtaddr->mtcs1 = MT_WCOM|MT_GO;
10174736Swnj }
10184736Swnj 
10194736Swnj mtwait(mtaddr)
10204736Swnj 	struct mtdevice *mtaddr;
10214736Swnj {
10224736Swnj 	register s;
10234736Swnj 
10244736Swnj 	do
10254736Swnj 		s = mtaddr->mtds;
10264736Swnj 	while ((s & MTDS_DRY) == 0);
10274736Swnj }
10284736Swnj 
10294736Swnj mteof(mtaddr)
10304736Swnj 	struct mtdevice *mtaddr;
10314736Swnj {
10324736Swnj 
10334736Swnj 	mtwait(mtaddr);
10344736Swnj 	mtaddr->mtcs1 = MT_WEOF|MT_GO;
10354736Swnj #endif notyet
10364736Swnj }
103717214Smckusick 
103817214Smckusick #ifdef MTLERRM
103917214Smckusick mtintfail(sc)
104017214Smckusick 	register struct mu_softc *sc;
104117214Smckusick {
104217214Smckusick 	switch (sc->sc_erreg & MTER_INTCODE) {
104317214Smckusick 
104417214Smckusick 	/* unexpected BOT detected */
104517214Smckusick 
104617214Smckusick 	case MTER_BOT:
104717214Smckusick 		sc->sc_mesg = "unexpected BOT";
104817214Smckusick 		switch ((sc->sc_erreg & MTER_FAILCODE) >> 10) {
104917214Smckusick 		case 01:
105017214Smckusick 			sc->sc_fmesg = "tape was at BOT";
105117214Smckusick 			break;
105217214Smckusick 		case 02:
105317214Smckusick 			sc->sc_fmesg = "BOT seen after tape started";
105417214Smckusick 			break;
105517214Smckusick 		case 03:
105617214Smckusick 			sc->sc_fmesg = "ARA ID detected";
105717214Smckusick 			break;
105817214Smckusick 		default:
105917214Smckusick 			sc->sc_fmesg = "unclassified failure code";
106017214Smckusick 		}
106117214Smckusick 		break;
106217214Smckusick 
106317214Smckusick 	/* unexpected LEOT detected */
106417214Smckusick 
106517214Smckusick 	case MTER_LEOT:
106617214Smckusick 		sc->sc_mesg = "unexpected LEOT";
106717214Smckusick 		sc->sc_fmesg = "";
106817214Smckusick 		break;
106917214Smckusick 
107017214Smckusick 	/* rewinding */
107117214Smckusick 
107217214Smckusick 	case MTER_RWDING:
107317214Smckusick 		sc->sc_mesg = "tape rewinding";
107417214Smckusick 		sc->sc_fmesg = "";
107517214Smckusick 		break;
107617214Smckusick 
107717214Smckusick 	/* not ready */
107817214Smckusick 
107917214Smckusick 	case MTER_NOTRDY:
108017214Smckusick 		sc->sc_mesg = "drive not ready";
108117214Smckusick 		switch ((sc->sc_erreg & MTER_FAILCODE) >> 10) {
108217214Smckusick 		case 01:
108317214Smckusick 			sc->sc_fmesg = "TU on-line but not ready";
108417214Smckusick 			break;
108517214Smckusick 		case 02:
108617214Smckusick 			sc->sc_fmesg = "fatal error has occurred";
108717214Smckusick 			break;
108817214Smckusick 		case 03:
108917214Smckusick 			sc->sc_fmesg = "access allowed but not really";
109017214Smckusick 			break;
109117214Smckusick 		default:
109217214Smckusick 			sc->sc_fmesg = "unclassified failure code";
109317214Smckusick 		}
109417214Smckusick 		break;
109517214Smckusick 
109617214Smckusick 	/* not available */
109717214Smckusick 
109817214Smckusick 	case MTER_NOTAVL:
109917214Smckusick 		sc->sc_mesg = "drive not available";
110017214Smckusick 		sc->sc_fmesg = "";
110117214Smckusick 		break;
110217214Smckusick 
110317214Smckusick 	/* unit does not exist */
110417214Smckusick 
110517214Smckusick 	case MTER_NONEX:
110617214Smckusick 		sc->sc_mesg = "unit does not exist";
110717214Smckusick 		sc->sc_fmesg = "";
110817214Smckusick 		break;
110917214Smckusick 
111017214Smckusick 	/* not capable */
111117214Smckusick 
111217214Smckusick 	case MTER_NOTCAP:
111317214Smckusick 		sc->sc_mesg = "not capable";
111417214Smckusick 		switch ((sc->sc_erreg & MTER_FAILCODE) >> 10) {
111517214Smckusick 		case 01:
111617214Smckusick 			sc->sc_fmesg = "no record found within 25 feet";
111717214Smckusick 			break;
111817214Smckusick 		case 02:
111917214Smckusick 			sc->sc_fmesg = "ID burst neither PE nor GCR";
112017214Smckusick 			break;
112117214Smckusick 		case 03:
112217214Smckusick 			sc->sc_fmesg = "ARA ID not found";
112317214Smckusick 			break;
112417214Smckusick 		case 04:
112517214Smckusick 			sc->sc_fmesg = "no gap found after ID burst";
112617214Smckusick 			break;
112717214Smckusick 		default:
112817214Smckusick 			sc->sc_fmesg = "unclassified failure code";
112917214Smckusick 		}
113017214Smckusick 		break;
113117214Smckusick 
113217214Smckusick 	/* long tape record */
113317214Smckusick 
113417214Smckusick 	case MTER_LONGREC:
113517214Smckusick 		sc->sc_mesg = "long record";
113617214Smckusick 		switch ((sc->sc_erreg & MTER_FAILCODE) >> 10) {
113717214Smckusick 		case 00:
113817214Smckusick 			sc->sc_fmesg = "extended sense data not found";
113917214Smckusick 			break;
114017214Smckusick 		case 01:
114117214Smckusick 			sc->sc_fmesg = "extended sense data updated";
114217214Smckusick 			break;
114317214Smckusick 		default:
114417214Smckusick 			sc->sc_fmesg = "unclassified failure code";
114517214Smckusick 		}
114617214Smckusick 		break;
114717214Smckusick 
114817214Smckusick 	/* unreadable */
114917214Smckusick 
115017214Smckusick 	case MTER_UNREAD:
115117214Smckusick 		sc->sc_mesg = "unreadable record";
115217214Smckusick 		goto code22;
115317214Smckusick 
115417214Smckusick 	/* error */
115517214Smckusick 
115617214Smckusick 	case MTER_ERROR:
115717214Smckusick 		sc->sc_mesg = "error";
115817214Smckusick 		goto code22;
115917214Smckusick 
116017214Smckusick 	/* EOT error */
116117214Smckusick 
116217214Smckusick 	case MTER_EOTERR:
116317214Smckusick 		sc->sc_mesg = "EOT error";
116417214Smckusick 		goto code22;
116517214Smckusick 
116617214Smckusick 	/* tape position lost */
116717214Smckusick 
116817214Smckusick 	case MTER_BADTAPE:
116917214Smckusick 		sc->sc_mesg = "bad tape";
117017214Smckusick 	code22:
117117214Smckusick 		switch ((sc->sc_erreg & MTER_FAILCODE) >> 10) {
117217214Smckusick 		case 01:
117317214Smckusick 			sc->sc_fmesg = "GCR write error";
117417214Smckusick 			break;
117517214Smckusick 		case 02:
117617214Smckusick 			sc->sc_fmesg = "GCR read error";
117717214Smckusick 			break;
117817214Smckusick 		case 03:
117917214Smckusick 			sc->sc_fmesg = "PE read error";
118017214Smckusick 			break;
118117214Smckusick 		case 04:
118217214Smckusick 			sc->sc_fmesg = "PE write error";
118317214Smckusick 			break;
118417214Smckusick 		case 05:
118517214Smckusick 			sc->sc_fmesg = "at least 1 bit set in ECCSTA";
118617214Smckusick 			break;
118717214Smckusick 		case 06:
118817214Smckusick 			sc->sc_fmesg = "PE write error";
118917214Smckusick 			break;
119017214Smckusick 		case 07:
119117214Smckusick 			sc->sc_fmesg = "GCR write error";
119217214Smckusick 			break;
119317214Smckusick 		case 010:
119417214Smckusick 			sc->sc_fmesg = "RSTAT contains bad code";
119517214Smckusick 			break;
119617214Smckusick 		case 011:
119717214Smckusick 			sc->sc_fmesg = "PE write error";
119817214Smckusick 			break;
119917214Smckusick 		case 012:
120017214Smckusick 			sc->sc_fmesg = "MASSBUS parity error";
120117214Smckusick 			break;
120217214Smckusick 		case 013:
120317214Smckusick 			sc->sc_fmesg = "invalid data transferred";
120417214Smckusick 			break;
120517214Smckusick 		default:
120617214Smckusick 			sc->sc_fmesg = "unclassified failure code";
120717214Smckusick 		}
120817214Smckusick 		break;
120917214Smckusick 
121017214Smckusick 	/* TM fault A */
121117214Smckusick 
121217214Smckusick 	case MTER_TMFLTA:
121317214Smckusick 		sc->sc_mesg = "TM fault A";
121417214Smckusick 		switch ((sc->sc_erreg & MTER_FAILCODE) >> 10) {
121517214Smckusick 		case 01:
121617214Smckusick 			sc->sc_fmesg = "illegal command code";
121717214Smckusick 			break;
121817214Smckusick 		case 02:
121917214Smckusick 			sc->sc_fmesg = "DT command issued when NDT command active";
122017214Smckusick 			break;
122117214Smckusick 		case 03:
122217214Smckusick 			sc->sc_fmesg = "WMC error";
122317214Smckusick 			break;
122417214Smckusick 		case 04:
122517214Smckusick 			sc->sc_fmesg = "RUN not received from MASSBUS controller";
122617214Smckusick 			break;
122717214Smckusick 		case 05:
122817214Smckusick 			sc->sc_fmesg = "mismatch in command read - function routine";
122917214Smckusick 			break;
123017214Smckusick 		case 06:
123117214Smckusick 			sc->sc_fmesg = "ECC ROM parity error";
123217214Smckusick 			break;
123317214Smckusick 		case 07:
123417214Smckusick 			sc->sc_fmesg = "XMC ROM parity error";
123517214Smckusick 			break;
123617214Smckusick 		case 010:
123717214Smckusick 			sc->sc_fmesg = "mismatch in command read - ID burst command";
123817214Smckusick 			break;
123917214Smckusick 		case 011:
124017214Smckusick 			sc->sc_fmesg = "mismatch in command read - verify ARA burst command";
124117214Smckusick 			break;
124217214Smckusick 		case 012:
124317214Smckusick 			sc->sc_fmesg = "mismatch in command read - verify ARA ID command";
124417214Smckusick 			break;
124517214Smckusick 		case 013:
124617214Smckusick 			sc->sc_fmesg = "mismatch in command read - verify gap command";
124717214Smckusick 			break;
124817214Smckusick 		case 014:
124917214Smckusick 			sc->sc_fmesg = "mismatch in command read - read id burst command";
125017214Smckusick 			break;
125117214Smckusick 		case 015:
125217214Smckusick 			sc->sc_fmesg = "mismatch in command read - verify ARA ID command";
125317214Smckusick 			break;
125417214Smckusick 		case 016:
125517214Smckusick 			sc->sc_fmesg = "mismatch in command read - verify gap command";
125617214Smckusick 			break;
125717214Smckusick 		case 017:
125817214Smckusick 			sc->sc_fmesg = "mismatch in command read - find gap command";
125917214Smckusick 			break;
126017214Smckusick 		case 020:
126117214Smckusick 			sc->sc_fmesg = "WMC LEFT failed to set";
126217214Smckusick 			break;
126317214Smckusick 		case 021:
126417214Smckusick 			sc->sc_fmesg = "XL PE set in INTSTA register";
126517214Smckusick 			break;
126617214Smckusick 		case 022:
126717214Smckusick 			sc->sc_fmesg = "XMC DONE did not set";
126817214Smckusick 			break;
126917214Smckusick 		case 023:
127017214Smckusick 			sc->sc_fmesg = "WMC ROM PE or RD PE set in WMCERR register";
127117214Smckusick 			break;
127217214Smckusick 		default:
127317214Smckusick 			sc->sc_fmesg = "unclassified failure code";
127417214Smckusick 		}
127517214Smckusick 		break;
127617214Smckusick 
127717214Smckusick 	/* TU fault A */
127817214Smckusick 
127917214Smckusick 	case MTER_TUFLTA:
128017214Smckusick 		sc->sc_mesg = "TU fault A";
128117214Smckusick 		switch ((sc->sc_erreg & MTER_FAILCODE) >> 10) {
128217214Smckusick 		case 01:
128317214Smckusick 			sc->sc_fmesg = "TU status parity error";
128417214Smckusick 			break;
128517214Smckusick 		case 02:
128617214Smckusick 			sc->sc_fmesg = "TU command parity error";
128717214Smckusick 			break;
128817214Smckusick 		case 03:
128917214Smckusick 			sc->sc_fmesg = "rewinding tape went offline";
129017214Smckusick 			break;
129117214Smckusick 		case 04:
129217214Smckusick 			sc->sc_fmesg = "tape went not ready during DSE";
129317214Smckusick 			break;
129417214Smckusick 		case 05:
129517214Smckusick 			sc->sc_fmesg = "TU CMD status changed during DSE";
129617214Smckusick 			break;
129717214Smckusick 		case 06:
129817214Smckusick 			sc->sc_fmesg = "TU never came up to speed";
129917214Smckusick 			break;
130017214Smckusick 		case 07:
130117214Smckusick 			sc->sc_fmesg = "TU velocity changed";
130217214Smckusick 			break;
130317214Smckusick 		case 010:
130417214Smckusick 			sc->sc_fmesg = "TU CMD did not load correctly to start tape motion";
130517214Smckusick 			break;
130617214Smckusick 		case 011:
130717214Smckusick 			sc->sc_fmesg = "TU CMD did not load correctly to set drive density";
130817214Smckusick 			break;
130917214Smckusick 		case 012:
131017214Smckusick 			sc->sc_fmesg = "TU CMD did not load correctly to start tape motion to write BOT ID";
131117214Smckusick 			break;
131217214Smckusick 		case 013:
131317214Smckusick 			sc->sc_fmesg = "TU CMD did not load correctly to backup tape to BOT after failing to write BOT ID";
131417214Smckusick 			break;
131517214Smckusick 		case 014:
131617214Smckusick 			sc->sc_fmesg = "failed to write density ID burst";
131717214Smckusick 			break;
131817214Smckusick 		case 015:
131917214Smckusick 			sc->sc_fmesg = "failed to write ARA burst";
132017214Smckusick 			break;
132117214Smckusick 		case 016:
132217214Smckusick 			sc->sc_fmesg = "failed to write ARA ID";
132317214Smckusick 			break;
132417214Smckusick 		case 017:
132517214Smckusick 			sc->sc_fmesg = "ARA error bit set in MTA status B register";
132617214Smckusick 			break;
132717214Smckusick 		case 021:
132817214Smckusick 			sc->sc_fmesg = "could not find a gap after ID code was written correctly";
132917214Smckusick 			break;
133017214Smckusick 		case 022:
133117214Smckusick 			sc->sc_fmesg = "TU CMD did not load correctly to start tape motion to read ID burst";
133217214Smckusick 			break;
133317214Smckusick 		case 023:
133417214Smckusick 			sc->sc_fmesg = "timeout looking for BOT after detecting ARA ID burst";
133517214Smckusick 			break;
133617214Smckusick 		case 024:
133717214Smckusick 			sc->sc_fmesg = "failed to write tape mark";
133817214Smckusick 			break;
133917214Smckusick 		case 025:
134017214Smckusick 			sc->sc_fmesg = "tape never came up to speed while trying to reposition for retry of writing tape mark";
134117214Smckusick 			break;
134217214Smckusick 		case 026:
134317214Smckusick 			sc->sc_fmesg = "TU CMD did not load correctly to start tape motion in erase gap routine";
134417214Smckusick 			break;
134517214Smckusick 		case 027:
134617214Smckusick 			sc->sc_fmesg = "could not detect a gap in in erase gap routine";
134717214Smckusick 			break;
134817214Smckusick 		case 030:
134917214Smckusick 			sc->sc_fmesg = "could not detect a gap after writing record";
135017214Smckusick 			break;
135117214Smckusick 		case 031:
135217214Smckusick 			sc->sc_fmesg = "read path terminated before entire record was written";
135317214Smckusick 			break;
135417214Smckusick 		case 032:
135517214Smckusick 			sc->sc_fmesg = "could not find a gap after writing record and read path terminated early";
135617214Smckusick 			break;
135717214Smckusick 		case 033:
135817214Smckusick 			sc->sc_fmesg = "TU CMD did not load correctly to backup for retry of write tape mark";
135917214Smckusick 			break;
136017214Smckusick 		case 034:
136117214Smckusick 			sc->sc_fmesg = "TU velocity changed after up to speed while trying to reposition for retry of writing tape mark";
136217214Smckusick 			break;
136317214Smckusick 		case 035:
136417214Smckusick 			sc->sc_fmesg = "TU CMD did not load correctly to backup to retry a load of BOT ID";
136517214Smckusick 			break;
136617214Smckusick 		case 036:
136717214Smckusick 			sc->sc_fmesg = "timeout looking for BOT after failing to write BOT ID";
136817214Smckusick 			break;
136917214Smckusick 		case 037:
137017214Smckusick 			sc->sc_fmesg = "TU velocity changed while writing PE gap before starting to write record";
137117214Smckusick 			break;
137217214Smckusick 		case 040:
137317214Smckusick 			sc->sc_fmesg = "TU CMD did not load correctly to set PE tape density at start of write BOT ID burst";
137417214Smckusick 			break;
137517214Smckusick 		case 041:
137617214Smckusick 			sc->sc_fmesg = "TU CMD did not load correctly to set GCR tape density after writing Density ID";
137717214Smckusick 			break;
137817214Smckusick 		case 042:
137917214Smckusick 			sc->sc_fmesg = "TU CMD did not load correctly to set PE tape density at start of read from BOT";
138017214Smckusick 			break;
138117214Smckusick 		case 043:
138217214Smckusick 			sc->sc_fmesg = "TU CMD did not load correctly to set GCR tape density after reading a GCR Density ID burst";
138317214Smckusick 			break;
138417214Smckusick 		default:
138517214Smckusick 			sc->sc_fmesg = "unclassified failure code";
138617214Smckusick 		}
138717214Smckusick 		break;
138817214Smckusick 
138917214Smckusick 	/* TM fault B */
139017214Smckusick 
139117214Smckusick 	case MTER_TMFLTB:
139217214Smckusick 		sc->sc_mesg = "TM fault B";
139317214Smckusick 		switch ((sc->sc_erreg & MTER_FAILCODE) >> 10) {
139417214Smckusick 		case 00:
139517214Smckusick 			sc->sc_fmesg = "RST0 interrupt occurred with TM RDY set";
139617214Smckusick 			break;
139717214Smckusick 		case 01:
139817214Smckusick 			sc->sc_fmesg = "power failed to interrupt";
139917214Smckusick 			break;
140017214Smckusick 		case 02:
140117214Smckusick 			sc->sc_fmesg = "unknown interrupt on channel 5.5";
140217214Smckusick 			break;
140317214Smckusick 		case 03:
140417214Smckusick 			sc->sc_fmesg = "unknown interrupt on channel 6.5";
140517214Smckusick 			break;
140617214Smckusick 		case 04:
140717214Smckusick 			sc->sc_fmesg = "unknown interrupt on channel 7";
140817214Smckusick 			break;
140917214Smckusick 		case 05:
141017214Smckusick 			sc->sc_fmesg = "unknown interrupt on channel 7.5";
141117214Smckusick 			break;
141217214Smckusick 		case 06:
141317214Smckusick 			sc->sc_fmesg = "CAS contention retry count expired";
141417214Smckusick 			break;
141517214Smckusick 		case 07:
141617214Smckusick 			sc->sc_fmesg = "CAS contention error not retryable";
141717214Smckusick 			break;
141817214Smckusick 		case 010:
141917214Smckusick 			sc->sc_fmesg = "queue error, could not find queue entry";
142017214Smckusick 			break;
142117214Smckusick 		case 011:
142217214Smckusick 			sc->sc_fmesg = "queue entry already full";
142317214Smckusick 			break;
142417214Smckusick 		case 012:
142517214Smckusick 			sc->sc_fmesg = "8085 ROM parity error";
142617214Smckusick 			break;
142717214Smckusick 		case 013:
142817214Smckusick 		case 014:
142917214Smckusick 		case 015:
143017214Smckusick 		case 016:
143117214Smckusick 		case 017:
143217214Smckusick 		case 020:
143317214Smckusick 		case 021:
143417214Smckusick 		case 022:
143517214Smckusick 		case 023:
143617214Smckusick 		case 024:
143717214Smckusick 		case 025:
143817214Smckusick 		case 026:
143917214Smckusick 		case 027:
144017214Smckusick 		case 030:
144117214Smckusick 		case 031:
144217214Smckusick 		case 032:
144317214Smckusick 		case 033:
144417214Smckusick 		case 034:
144517214Smckusick 		case 035:
144617214Smckusick 		case 036:
144717214Smckusick 		case 037:
144817214Smckusick 		case 040:
144917214Smckusick 		case 041:
145017214Smckusick 		case 042:
145117214Smckusick 		case 043:
145217214Smckusick 		case 044:
145317214Smckusick 		case 045:
145417214Smckusick 		case 046:
145517214Smckusick 		case 047:
145617214Smckusick 		case 050:
145717214Smckusick 		case 051:
145817214Smckusick 		case 052:
145917214Smckusick 		case 053:
146017214Smckusick 		case 054:
146117214Smckusick 		case 055:
146217214Smckusick 		case 056:
146317214Smckusick 		case 057:
146417214Smckusick 			sc->sc_fmesg = "inline test failed";
146517214Smckusick 			break;
146617214Smckusick 		default:
146717214Smckusick 			sc->sc_fmesg = "unclassified failure code";
146817214Smckusick 		}
146917214Smckusick 		break;
147017214Smckusick 
147117214Smckusick 	/* MASSBUS fault */
147217214Smckusick 
147317214Smckusick 	case MTER_MBFLT:
147417214Smckusick 		sc->sc_mesg = "MB fault";
147517214Smckusick 		switch ((sc->sc_erreg & MTER_FAILCODE) >> 10) {
147617214Smckusick 		case 01:
147717214Smckusick 			sc->sc_fmesg = "control bus parity error";
147817214Smckusick 			break;
147917214Smckusick 		case 02:
148017214Smckusick 			sc->sc_fmesg = "illegal register referenced";
148117214Smckusick 			break;
148217214Smckusick 		default:
148317214Smckusick 			sc->sc_fmesg = "unclassified failure code";
148417214Smckusick 		}
148517214Smckusick 		break;
148617214Smckusick 
148717214Smckusick 	/* keypad entry error */
148817214Smckusick 
148917214Smckusick 	case MTER_KEYFAIL:
149017214Smckusick 		sc->sc_mesg = "keypad entry error";
149117214Smckusick 		sc->sc_fmesg = "";
149217214Smckusick 		break;
149317214Smckusick 	default:
149417214Smckusick 		sc->sc_mesg = "unclassified error";
149517214Smckusick 		sc->sc_fmesg = "";
149617214Smckusick 		break;
149717214Smckusick 	}
149817214Smckusick }
149917214Smckusick #endif MTLERRM
15004736Swnj #endif
1501