xref: /csrg-svn/sys/vax/mba/mt.c (revision 23315)
1*23315Smckusick /*
2*23315Smckusick  * Copyright (c) 1982 Regents of the University of California.
3*23315Smckusick  * All rights reserved.  The Berkeley software License Agreement
4*23315Smckusick  * specifies the terms and conditions for redistribution.
5*23315Smckusick  *
6*23315Smckusick  *	@(#)mt.c	6.5 (Berkeley) 06/08/85
7*23315Smckusick  */
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 {
11317214Smckusick #ifdef lint
11417214Smckusick 	mtread(0); mtwrite(0); mtioctl(0, 0, 0, 0);
11517214Smckusick #endif
1164736Swnj }
1174736Swnj 
1187431Skre mtslave(mi, ms, sn)
1194736Swnj 	struct mba_device *mi;
1204736Swnj 	struct mba_slave *ms;
1217431Skre 	int sn;
1224736Swnj {
1234736Swnj 	register struct mu_softc *sc = &mu_softc[ms->ms_unit];
1244736Swnj 	register struct mtdevice *mtaddr = (struct mtdevice *)mi->mi_drv;
12517214Smckusick 	int s = spl7(), rtn = 0, i;
1264736Swnj 
12717214Smckusick 	/* Just in case the controller is ill, reset it.  Then issue	*/
12817214Smckusick 	/* a sense operation and wait about a second for it to respond.	*/
12917214Smckusick 
13017214Smckusick 	mtcreset(mtaddr);
1314736Swnj 	mtaddr->mtas = -1;
1327431Skre 	mtaddr->mtncs[sn] = MT_SENSE|MT_GO;
13317214Smckusick 	for (i = MTTIMEOUT; i> 0; i--) {
13417214Smckusick 		DELAY(50);
13517214Smckusick 		if (MASKREG(mtaddr->mtas) != 0)
13617214Smckusick 			break;
13717214Smckusick 	}
13817214Smckusick 	sc->sc_i_mtas = mtaddr->mtas;
13917214Smckusick 	sc->sc_i_mtner = mtaddr->mtner;
14017214Smckusick 	sc->sc_i_mtds = mtaddr->mtds;
14117214Smckusick 
14217214Smckusick 	/* If no response, whimper.  If wrong response, call it an	*/
14317214Smckusick 	/* unsolicited interrupt and use mtndtint to log and correct.	*/
14417214Smckusick 	/* Otherwise, note whether this slave exists.			*/
14517214Smckusick 
14617214Smckusick 	if (i <= 0) {
14717214Smckusick 		printf("mt: controller hung\n");
14817214Smckusick 	} else if ((mtaddr->mtner & MTER_INTCODE) != MTER_DONE) {
14917214Smckusick 		(void) mtndtint(mi);
15017214Smckusick 	} else if (mtaddr->mtds & MTDS_PRES) {
1514736Swnj 		sc->sc_mi = mi;
1527431Skre 		sc->sc_slave = sn;
1534736Swnj 		mutomt[ms->ms_unit] = mi->mi_unit;
1544736Swnj 		rtn = 1;
1554736Swnj 	}
15617214Smckusick 
15717214Smckusick 	/* Cancel the interrupt, then wait a little while for it to go away. */
15817214Smckusick 
1594736Swnj 	mtaddr->mtas = mtaddr->mtas;
16017214Smckusick 	DELAY(10);
1614736Swnj 	splx(s);
1624736Swnj 	return (rtn);
1634736Swnj }
1644736Swnj 
1654736Swnj mtopen(dev, flag)
1664736Swnj 	dev_t dev;
1674736Swnj 	int flag;
1684736Swnj {
1694736Swnj 	register int muunit;
1704736Swnj 	register struct mba_device *mi;
1714736Swnj 	register struct mu_softc *sc;
1724736Swnj 
1734736Swnj 	muunit = MUUNIT(dev);
17417214Smckusick 	if (   (muunit >= NMU)
17517214Smckusick 	    || ((mi = mtinfo[MTUNIT(dev)]) == 0)
17617214Smckusick 	    || (mi->mi_alive == 0) )
1778581Sroot 		return (ENXIO);
17817214Smckusick 	if ((sc = &mu_softc[muunit])->sc_openf)
17917214Smckusick 		return (EBUSY);
18017214Smckusick 	sc->sc_dens = (minor(dev) & H_6250BPI) ? MT_GCR : 0;
1814736Swnj 	mtcommand(dev, MT_SENSE, 1);
1824736Swnj 	if ((sc->sc_dsreg & MTDS_ONL) == 0) {
1834736Swnj 		uprintf("mu%d: not online\n", muunit);
1848581Sroot 		return (EIO);
1854736Swnj 	}
18617214Smckusick 	if ((sc->sc_dsreg & MTDS_AVAIL) == 0) {
18717214Smckusick 		uprintf("mu%d: not online (port selector)\n", muunit);
18817214Smckusick 		return (EIO);
18917214Smckusick 	}
19017214Smckusick 	if ((flag & FWRITE) && (sc->sc_dsreg & MTDS_FPT)) {
1914736Swnj 		uprintf("mu%d: no write ring\n", muunit);
1928581Sroot 		return (EIO);
1934736Swnj 	}
19417214Smckusick 	if (   ((sc->sc_dsreg & MTDS_BOT) == 0)
19517214Smckusick 	    && (flag & FWRITE)
19617214Smckusick 	    && (   (   (sc->sc_dens == MT_GCR)
19717214Smckusick 		    && (sc->sc_dsreg & MTDS_PE) )
19817214Smckusick 		|| (   (sc->sc_dens != MT_GCR)
19917214Smckusick 		    && ((sc->sc_dsreg & MTDS_PE) == 0)))) {
2004736Swnj 		uprintf("mu%d: can't change density in mid-tape\n", muunit);
2018581Sroot 		return (EIO);
2024736Swnj 	}
2034736Swnj 	sc->sc_openf = 1;
2044736Swnj 	sc->sc_blkno = (daddr_t)0;
20517214Smckusick 
20617214Smckusick 	/* Since cooked I/O may do a read-ahead before a write, trash	*/
20717214Smckusick 	/* on a tape can make the first write fail.  Suppress the first	*/
20817214Smckusick 	/* read-ahead unless definitely doing read-write		*/
20917214Smckusick 
21017214Smckusick 	sc->sc_nxrec =  ((flag & (FTRUNC | FWRITE)) == (FTRUNC | FWRITE))
21117214Smckusick 		      ? (daddr_t)0
21217214Smckusick 		      : (daddr_t)INF;
2134736Swnj 	sc->sc_flags = 0;
21418324Sralph 	sc->sc_ttyp = u.u_ttyp;
2158581Sroot 	return (0);
2164736Swnj }
2174736Swnj 
2184736Swnj mtclose(dev, flag)
2194736Swnj 	register dev_t dev;
22017214Smckusick 	register int flag;
2214736Swnj {
2224736Swnj 	register struct mu_softc *sc = &mu_softc[MUUNIT(dev)];
2234736Swnj 
22417214Smckusick 	if (   ((flag & (FREAD | FWRITE)) == FWRITE)
22517214Smckusick 	    || (   (flag & FWRITE)
22617214Smckusick 		&& (sc->sc_flags & H_WRITTEN) ))
2274736Swnj 		mtcommand(dev, MT_CLS|sc->sc_dens, 1);
22817214Smckusick 	if ((minor(dev) & H_NOREWIND) == 0)
2294736Swnj 		mtcommand(dev, MT_REW, 0);
2304736Swnj 	sc->sc_openf = 0;
2314736Swnj }
2324736Swnj 
2334736Swnj mtcommand(dev, com, count)
2344736Swnj 	dev_t dev;
2354736Swnj 	int com, count;
2364736Swnj {
2374736Swnj 	register struct buf *bp;
2385437Sroot 	register int s;
2394736Swnj 
2404736Swnj 	bp = &cmtbuf[MTUNIT(dev)];
2415437Sroot 	s = spl5();
24217214Smckusick 	while (bp->b_flags & B_BUSY) {
24317214Smckusick 		if((bp->b_repcnt == 0) && (bp->b_flags & B_DONE))
2444736Swnj 			break;
2454736Swnj 		bp->b_flags |= B_WANTED;
2464736Swnj 		sleep((caddr_t)bp, PRIBIO);
2474736Swnj 	}
2484736Swnj 	bp->b_flags = B_BUSY|B_READ;
2495437Sroot 	splx(s);
2504736Swnj 	bp->b_dev = dev;
2514736Swnj 	bp->b_command = com;
2524736Swnj 	bp->b_repcnt = count;
2534736Swnj 	bp->b_blkno = 0;
25417214Smckusick 	bp->b_error = 0;
2554736Swnj 	mtstrategy(bp);
2564736Swnj 	if (count == 0)
2574736Swnj 		return;
2584736Swnj 	iowait(bp);
25917214Smckusick 	if (bp->b_flags & B_WANTED)
2604736Swnj 		wakeup((caddr_t)bp);
2614736Swnj 	bp->b_flags &= B_ERROR;
2624736Swnj }
2634736Swnj 
2644736Swnj mtstrategy(bp)
2654736Swnj 	register struct buf *bp;
2664736Swnj {
2674736Swnj 	register struct mba_device *mi = mtinfo[MTUNIT(bp->b_dev)];
2684736Swnj 	register struct buf *dp;
2695437Sroot 	register int s;
2704736Swnj 
27117214Smckusick 	/* If this is a data transfer operation, set the resid to a	*/
27217214Smckusick 	/* default value (EOF) to simplify getting it right during	*/
27317214Smckusick 	/* error recovery or bail out.					*/
27417214Smckusick 
27517214Smckusick 	if (bp != &cmtbuf[MTUNIT(bp->b_dev)])
27617214Smckusick 		bp->b_resid = bp->b_bcount;
27717214Smckusick 
27817214Smckusick 	/* Link this request onto the end of the queue for this		*/
27917214Smckusick 	/* controller, then start I/O if not already active.		*/
28017214Smckusick 
2814736Swnj 	bp->av_forw = NULL;
2824736Swnj 	dp = &mi->mi_tab;
2835437Sroot 	s = spl5();
2844736Swnj 	if (dp->b_actf == NULL)
2854736Swnj 		dp->b_actf = bp;
2864736Swnj 	else
2874736Swnj 		dp->b_actl->av_forw = bp;
2884736Swnj 	dp->b_actl = bp;
2894736Swnj 	if (dp->b_active == 0)
2904736Swnj 		mbustart(mi);
2915437Sroot 	splx(s);
2924736Swnj }
2934736Swnj 
2944736Swnj mtustart(mi)
2954736Swnj 	register struct mba_device *mi;
2964736Swnj {
29717214Smckusick 	register struct mtdevice *mtaddr = (struct mtdevice *)mi->mi_drv;
2984736Swnj 	register struct buf *bp = mi->mi_tab.b_actf;
2994736Swnj 	register struct mu_softc *sc = &mu_softc[MUUNIT(bp->b_dev)];
3004736Swnj 	daddr_t blkno;
3014736Swnj 
3024736Swnj 	if (sc->sc_openf < 0) {
3034736Swnj 		bp->b_flags |= B_ERROR;
3044736Swnj 		return (MBU_NEXT);
3054736Swnj 	}
3064736Swnj 	if (bp != &cmtbuf[MTUNIT(bp->b_dev)]) {
30717214Smckusick 
30817214Smckusick 		/* Signal "no space" if out of tape unless suppressed	*/
30917214Smckusick 		/* by MTIOCIEOT.					*/
31017214Smckusick 
31117214Smckusick 		if (   ((sc->sc_flags & (H_EOT | H_IEOT)) == H_EOT)
31217214Smckusick 		    && ((bp->b_flags & B_READ) == 0) ) {
3134736Swnj 			bp->b_flags |= B_ERROR;
31417214Smckusick 			bp->b_error = ENOSPC;
3154736Swnj 			return (MBU_NEXT);
3164736Swnj 		}
31717214Smckusick 
31817214Smckusick 		/* special case tests for cooked mode */
31917214Smckusick 
32017214Smckusick 		if (bp != &rmtbuf[MTUNIT(bp->b_dev)]) {
32117214Smckusick 
32217214Smckusick 			/* seek beyond end of file */
32317214Smckusick 
32417214Smckusick 			if (bdbtofsb(bp->b_blkno) > sc->sc_nxrec) {
32517214Smckusick 				bp->b_flags |= B_ERROR;
32617214Smckusick 				bp->b_error = ENXIO;
32717214Smckusick 				return (MBU_NEXT);
32817214Smckusick 			}
32917214Smckusick 
33017214Smckusick 			/* This should be end of file, but the buffer	   */
33117214Smckusick 			/* system wants a one-block look-ahead.  Humor it. */
33217214Smckusick 
33317214Smckusick 			if (   (bdbtofsb(bp->b_blkno) == sc->sc_nxrec)
33417214Smckusick 			    && (bp->b_flags & B_READ) ) {
33517214Smckusick 				clrbuf(bp);
33617214Smckusick 				return (MBU_NEXT);
33717214Smckusick 			}
33817214Smckusick 
33917214Smckusick 			/* If writing, mark the next block invalid. */
34017214Smckusick 
34117214Smckusick 			if ((bp->b_flags & B_READ) == 0)
34217214Smckusick 				sc->sc_nxrec = bdbtofsb(bp->b_blkno) + 1;
3434736Swnj 		}
3444736Swnj 	} else {
34517214Smckusick 
34617214Smckusick 		/* It's a command, do it now. */
34717214Smckusick 
3484736Swnj 		mtaddr->mtncs[MUUNIT(bp->b_dev)] =
3494736Swnj 			(bp->b_repcnt<<8)|bp->b_command|MT_GO;
3504736Swnj 		return (MBU_STARTED);
3514736Swnj 	}
35217214Smckusick 
35317214Smckusick 	/* If raw I/O, or if the tape is positioned correctly for	*/
35417214Smckusick 	/* cooked I/O, set the byte count, unit number and repeat count	*/
35517214Smckusick 	/* then tell the MASSBUS to proceed.  Note that a negative	*/
35617214Smckusick 	/* bcount tells mbstart to map the buffer for "read backwards".	*/
35717214Smckusick 
35817214Smckusick 	if (   (bp == &rmtbuf[MTUNIT(bp->b_dev)])
35917214Smckusick 	    || ((blkno = sc->sc_blkno) == bdbtofsb(bp->b_blkno)) ) {
3604736Swnj 		if (mi->mi_tab.b_errcnt == 2) {
36117214Smckusick 			mtaddr->mtbc = -(bp->b_bcount);
3624736Swnj 			mtaddr->mtca = MUUNIT(bp->b_dev);
3634736Swnj 		} else {
3644736Swnj 			mtaddr->mtbc = bp->b_bcount;
3654736Swnj 			mtaddr->mtca = (1<<2)|MUUNIT(bp->b_dev);
3664736Swnj 		}
3674736Swnj 		return (MBU_DODATA);
3684736Swnj 	}
36917214Smckusick 
37017214Smckusick 	/* Issue skip operations to position the next block for cooked I/O. */
37117214Smckusick 
3727380Ssam 	if (blkno < bdbtofsb(bp->b_blkno))
3734736Swnj 		mtaddr->mtncs[MUUNIT(bp->b_dev)] =
3747380Ssam 		  (min((unsigned)(bdbtofsb(bp->b_blkno) - blkno), 0377) << 8) |
3756186Ssam 			MT_SFORW|MT_GO;
3764736Swnj 	else
3774736Swnj 		mtaddr->mtncs[MUUNIT(bp->b_dev)] =
3787380Ssam 		  (min((unsigned)(blkno - bdbtofsb(bp->b_blkno)), 0377) << 8) |
3796186Ssam 			MT_SREV|MT_GO;
3804736Swnj 	return (MBU_STARTED);
3814736Swnj }
3824736Swnj 
3834736Swnj mtstart(mi)
3844736Swnj 	register struct mba_device *mi;
3854736Swnj {
3864736Swnj 	register struct buf *bp = mi->mi_tab.b_actf;
3874736Swnj 	register struct mu_softc *sc = &mu_softc[MUUNIT(bp->b_dev)];
3884736Swnj 
3894736Swnj 	if (bp->b_flags & B_READ)
3904736Swnj 		if (mi->mi_tab.b_errcnt == 2)
3914736Swnj 			return(MT_READREV|MT_GO);
3924736Swnj 		else
3934736Swnj 			return(MT_READ|MT_GO);
3944736Swnj 	else
3954736Swnj 		return(MT_WRITE|sc->sc_dens|MT_GO);
3964736Swnj }
3974736Swnj 
3984736Swnj mtdtint(mi, mbsr)
3994736Swnj 	register struct mba_device *mi;
4004736Swnj 	int mbsr;
4014736Swnj {
4024736Swnj 	register struct mtdevice *mtaddr = (struct mtdevice *)mi->mi_drv;
4034736Swnj 	register struct buf *bp = mi->mi_tab.b_actf;
4044736Swnj 	register struct mu_softc *sc;
40517214Smckusick 	register int er;
4064736Swnj 
40717214Smckusick 	/* I'M still NOT SURE IF THIS SHOULD ALWAYS BE THE CASE SO FOR NOW... */
40817214Smckusick 
40917214Smckusick 	if ((mtaddr->mtca & 3) != MUUNIT(bp->b_dev)) {
4104736Swnj 		printf("mt: wrong unit!\n");
4114736Swnj 		mtaddr->mtca = MUUNIT(bp->b_dev);
4124736Swnj 	}
41317214Smckusick 
41417214Smckusick 	er = MASKREG(mtaddr->mter);
4154736Swnj 	sc = &mu_softc[MUUNIT(bp->b_dev)];
41617214Smckusick 	sc->sc_erreg = er;
41717214Smckusick 	if (bp->b_flags & B_READ)
41817214Smckusick 		sc->sc_flags &= ~H_WRITTEN;
41917214Smckusick 	else
4204736Swnj 		sc->sc_flags |= H_WRITTEN;
42117214Smckusick 	switch (er & MTER_INTCODE) {
42217214Smckusick 
42317214Smckusick 	case MTER_EOT:
42417214Smckusick 		sc->sc_flags |= H_EOT;
42517214Smckusick 
42617214Smckusick 		/* fall into MTER_DONE */
42717214Smckusick 
4284736Swnj 	case MTER_DONE:
42917214Smckusick 		sc->sc_blkno++;
43017214Smckusick 		if (mi->mi_tab.b_errcnt == 2) {
43117214Smckusick 			bp->b_bcount = bp->b_resid;
43217214Smckusick 			bp->b_resid -= MASKREG(mtaddr->mtbc);
43317214Smckusick 			if (   (bp->b_resid > 0)
43417214Smckusick 			    && (bp != &rmtbuf[MTUNIT(bp->b_dev)]) )
43517214Smckusick 				bp->b_flags |= B_ERROR;
43617214Smckusick 		} else {
43717214Smckusick 			bp->b_resid = 0;
43817214Smckusick 		}
43917214Smckusick 		break;
44017214Smckusick 
44117214Smckusick 	case MTER_SHRTREC:
44217214Smckusick 		sc->sc_blkno++;
44317214Smckusick 		bp->b_bcount = bp->b_resid;
44417214Smckusick 		bp->b_resid -= MASKREG(mtaddr->mtbc);
44517214Smckusick 		if (bp != &rmtbuf[MTUNIT(bp->b_dev)])
44617214Smckusick 			bp->b_flags |= B_ERROR;
44717214Smckusick 		break;
44817214Smckusick 
44917214Smckusick 	case MTER_RETRY:
45017214Smckusick 
45117214Smckusick 		/* Simple re-try.  Since resid is always a copy of the	*/
45217214Smckusick 		/* original byte count, use it to restore the count.	*/
45317214Smckusick 
45417214Smckusick 		mi->mi_tab.b_errcnt = 1;
45517214Smckusick 		bp->b_bcount = bp->b_resid;
45617214Smckusick 		return(MBD_RETRY);
45717214Smckusick 
45817214Smckusick 	case MTER_RDOPP:
45917214Smckusick 
46017214Smckusick 		/* The controller just decided to read it backwards.	*/
46117214Smckusick 		/* If the controller returns a byte count of zero,	*/
46217214Smckusick 		/* change it to 1, since zero encodes 65536, which	*/
46317214Smckusick 		/* isn't quite what we had in mind.  The byte count	*/
46417214Smckusick 		/* may be larger than the size of the input buffer, so	*/
46517214Smckusick 		/* limit the count to the buffer size.  After		*/
46617214Smckusick 		/* making the byte count reasonable, set bcount to the	*/
46717214Smckusick 		/* negative of the controller's version of the byte	*/
46817214Smckusick 		/* count so that the start address for the transfer is	*/
46917214Smckusick 		/* set up correctly.					*/
47017214Smckusick 
47117214Smckusick 		if (mt_do_readrev) {
47217214Smckusick 			mi->mi_tab.b_errcnt = 2;
47317214Smckusick 			if ((bp->b_bcount = MASKREG(mtaddr->mtbc)) == 0)
47417214Smckusick 				bp->b_bcount = 1;
47517214Smckusick 			if (bp->b_bcount > bp->b_resid)
47617214Smckusick 				bp->b_bcount = bp->b_resid;
47717214Smckusick 			bp->b_bcount = -(bp->b_bcount);
47817214Smckusick 			return(MBD_RETRY);
47917214Smckusick 		} else if (MASKREG(mtaddr->mtbc) <= bp->b_resid) {
48017214Smckusick 			sc->sc_blkno++;
48117214Smckusick 			bp->b_bcount = bp->b_resid;
48217214Smckusick 			bp->b_resid -= MASKREG(mtaddr->mtbc);
48317214Smckusick 			bp->b_flags |= B_ERROR;
48417214Smckusick 			break;
48517214Smckusick 		}
48617214Smckusick 		bp->b_flags |= B_ERROR;
48717214Smckusick 
48817214Smckusick 		/* fall into MTER_LONGREC */
48917214Smckusick 
4904736Swnj 	case MTER_LONGREC:
49117214Smckusick 		sc->sc_blkno++;
49217214Smckusick 		bp->b_bcount = bp->b_resid;
4934736Swnj 		bp->b_resid = 0;
49417214Smckusick 		bp->b_error = ENOMEM;
49517214Smckusick 		bp->b_flags |= B_ERROR;
4964736Swnj 		break;
4974736Swnj 
4984736Swnj 	case MTER_NOTCAP:
4994736Swnj 		printf("mu%d: blank tape\n", MUUNIT(bp->b_dev));
5004736Swnj 		goto err;
5014736Swnj 
5024736Swnj 	case MTER_TM:
50317214Smckusick 
50417214Smckusick 		/* End of file.  Since the default byte count has	*/
50517214Smckusick 		/* already been set, just count the block and proceed.	*/
50617214Smckusick 
5074736Swnj 		sc->sc_blkno++;
5084736Swnj 	err:
5094736Swnj 		if (bp != &rmtbuf[MTUNIT(bp->b_dev)])
51017214Smckusick 			sc->sc_nxrec = bdbtofsb(bp->b_blkno);
5114736Swnj 		break;
5124736Swnj 
5134736Swnj 	case MTER_OFFLINE:
5144736Swnj 		if (sc->sc_openf > 0) {
5154736Swnj 			sc->sc_openf = -1;
51618324Sralph 			tprintf(sc->sc_ttyp, "mu%d: offline\n", MUUNIT(bp->b_dev));
5174736Swnj 		}
5184736Swnj 		bp->b_flags |= B_ERROR;
5194736Swnj 		break;
5204736Swnj 
52117214Smckusick 	case MTER_NOTAVL:
52217214Smckusick 		if (sc->sc_openf > 0) {
52317214Smckusick 			sc->sc_openf = -1;
52418324Sralph 			tprintf(sc->sc_ttyp, "mu%d: offline (port selector)\n",
52518324Sralph 			    MUUNIT(bp->b_dev));
52617214Smckusick 		}
52717214Smckusick 		bp->b_flags |= B_ERROR;
52817214Smckusick 		break;
52917214Smckusick 
5304736Swnj 	case MTER_FPT:
53118324Sralph 		tprintf(sc->sc_ttyp, "mu%d: no write ring\n", MUUNIT(bp->b_dev));
5324736Swnj 		bp->b_flags |= B_ERROR;
5334736Swnj 		break;
5344736Swnj 
53517214Smckusick 	case MTER_UNREAD:
53617214Smckusick 		sc->sc_blkno++;
53717214Smckusick 		bp->b_bcount = bp->b_resid;
53817214Smckusick 		bp->b_resid -= MIN(MASKREG(mtaddr->mtbc), bp->b_bcount);
53917214Smckusick 
54017214Smckusick 		/* Code 010 means a garbage record, nothing serious. */
54117214Smckusick 
54217214Smckusick 		if (((er & MTER_FAILCODE) >> 10) == 010) {
54318324Sralph 			tprintf(sc->sc_ttyp, "mu%d: rn=%d bn=%d unreadable record\n",
54417214Smckusick 			    MUUNIT(bp->b_dev), sc->sc_blkno, bp->b_blkno);
54517214Smckusick 			bp->b_flags |= B_ERROR;
54617214Smckusick 			break;
54717214Smckusick 		}
54817214Smckusick 
54917214Smckusick 		/* Anything else might be a hardware problem,	*/
55017214Smckusick 		/* fall into the error report.			*/
55117214Smckusick 
5524736Swnj 	default:
55317214Smckusick 
55417214Smckusick 		/* The bits in sc->sc_dsreg are from the last sense	*/
55517214Smckusick 		/* command.  To get the most recent copy, you have to	*/
55617214Smckusick 		/* do a sense at interrupt level, which requires nested	*/
55717214Smckusick 		/* error processing.  This is a bit messy, so leave	*/
55817214Smckusick 		/* well enough alone.					*/
55917214Smckusick 
56018324Sralph 		tprintf(sc->sc_ttyp, "mu%d: hard error (data transfer) rn=%d bn=%d mbsr=%b er=%o (octal) ds=%b\n",
56117214Smckusick 		    MUUNIT(bp->b_dev), sc->sc_blkno, bp->b_blkno,
56217214Smckusick 		    mbsr, mbsr_bits, er,
56317214Smckusick 		    MASKREG(sc->sc_dsreg), mtds_bits);
56417214Smckusick #ifdef MTLERRM
56517214Smckusick 		mtintfail(sc);
56617214Smckusick 		printf("     interrupt code = %o (octal) <%s>\n     failure code = %o (octal) <%s>\n",
56717214Smckusick 		    er & MTER_INTCODE, sc->sc_mesg,
56817214Smckusick 		    (er & MTER_FAILCODE) >> 10, sc->sc_fmesg);
56917214Smckusick #endif
5704736Swnj 		bp->b_flags |= B_ERROR;
57117214Smckusick 
57217214Smckusick 		/* The TM78 manual says to reset the controller after	*/
57317214Smckusick 		/* TM fault B or MASSBUS fault.				*/
57417214Smckusick 
57517214Smckusick 		if (   ((er & MTER_INTCODE) == MTER_TMFLTB)
57617214Smckusick 		    || ((er & MTER_INTCODE) == MTER_MBFLT) ) {
57717214Smckusick 			mtcreset(mtaddr);
57817214Smckusick 		}
5794736Swnj 	}
58017214Smckusick 
58117214Smckusick 	/* Just in case some strange error slipped through, (drive off	*/
58217214Smckusick 	/* line during read-reverse error recovery comes to mind) make	*/
58317214Smckusick 	/* sure the byte count is reasonable.				*/
58417214Smckusick 
58517214Smckusick 	if (bp->b_bcount < 0)
58617214Smckusick 		bp->b_bcount = bp->b_resid;
5874736Swnj 	return (MBD_DONE);
5884736Swnj }
5894736Swnj 
5904736Swnj mtndtint(mi)
5914736Swnj 	register struct mba_device *mi;
5924736Swnj {
5934736Swnj 	register struct mtdevice *mtaddr = (struct mtdevice *)mi->mi_drv;
5944736Swnj 	register struct buf *bp = mi->mi_tab.b_actf;
5954736Swnj 	register struct mu_softc *sc;
59617214Smckusick 	register int er, fc;
59717214Smckusick 	int unit;
5984736Swnj 
5994736Swnj 	unit = (mtaddr->mtner >> 8) & 3;
6004736Swnj 	er = MASKREG(mtaddr->mtner);
60117214Smckusick 	sc = &mu_softc[unit];
60217214Smckusick 	sc->sc_erreg = er;
60317214Smckusick 
60417214Smckusick 	/* Check for unsolicited interrupts. */
60517214Smckusick 
6064736Swnj 	if (bp == 0 || unit != MUUNIT(bp->b_dev)) {	/* consistency check */
60717214Smckusick 		if ((er & MTER_INTCODE) != MTER_ONLINE) {
60817214Smckusick 			printf("mt: unit %d unexpected interrupt (non data transfer) er=%o (octal) ds=%b\n",
60917214Smckusick 			    unit, er, MASKREG(sc->sc_dsreg), mtds_bits);
61017214Smckusick #ifdef MTLERRM
61117214Smckusick 			mtintfail(sc);
61217214Smckusick 			printf("    interrupt code = %o (octal) <%s>\n    failure code = %o (octal) <%s>\n",
61317214Smckusick 			    er & MTER_INTCODE, sc->sc_mesg,
61417214Smckusick 			    (er & MTER_FAILCODE) >> 10, sc->sc_fmesg);
61517214Smckusick #endif
61617214Smckusick 			if (   ((er & MTER_INTCODE) == MTER_TMFLTB)
61717214Smckusick 			    || ((er & MTER_INTCODE) == MTER_MBFLT) ) {
61817214Smckusick 
61917214Smckusick 				/* Reset the controller, then set error	*/
62017214Smckusick 				/* status if there was anything active	*/
62117214Smckusick 				/* when the fault occurred.  This may	*/
62217214Smckusick 				/* shoot an innocent bystander, but	*/
62317214Smckusick 				/* it's better than letting an error	*/
62417214Smckusick 				/* slip through.			*/
62517214Smckusick 
62617214Smckusick 				mtcreset(mtaddr);
62717214Smckusick 				if (bp != 0) {
62817214Smckusick 					bp->b_flags |= B_ERROR;
62917214Smckusick 					return (MBN_DONE);
63017214Smckusick 				}
63117214Smckusick 			}
63217214Smckusick 		}
6334736Swnj 		return (MBN_SKIP);
6344736Swnj 	}
6354736Swnj 	if (bp == 0)
6364736Swnj 		return (MBN_SKIP);
63717214Smckusick 
6384736Swnj 	fc = (mtaddr->mtncs[unit] >> 8) & 0xff;
6394736Swnj 	sc->sc_resid = fc;
64017214Smckusick 
64117214Smckusick 	/* Clear the "written" flag after any operation that changes	*/
64217214Smckusick 	/* the position of the tape.					*/
64317214Smckusick 
64417214Smckusick 	if (   (bp != &cmtbuf[MTUNIT(bp->b_dev)])
64517214Smckusick 	    || (bp->b_command != MT_SENSE) )
64617214Smckusick 		sc->sc_flags &= ~H_WRITTEN;
64717214Smckusick 
6484736Swnj 	switch (er & MTER_INTCODE) {
64917214Smckusick 
65017214Smckusick 	case MTER_EOT:
65117214Smckusick 		sc->sc_flags |= H_EOT;
65217214Smckusick 
65317214Smckusick 		/* fall into MTER_DONE */
65417214Smckusick 
6554736Swnj 	case MTER_DONE:
65617214Smckusick 
65717214Smckusick 		/* If this is a command buffer, just update the status.	*/
65817214Smckusick 
6594736Swnj 		if (bp == &cmtbuf[MTUNIT(bp->b_dev)]) {
6604736Swnj 	done:
6614736Swnj 			if (bp->b_command == MT_SENSE)
6624736Swnj 				sc->sc_dsreg = MASKREG(mtaddr->mtds);
6634736Swnj 			return (MBN_DONE);
6644736Swnj 		}
66517214Smckusick 
66617214Smckusick 		/* It's not a command buffer, must be a cooked I/O	*/
66717214Smckusick 		/* skip operation (perhaps a shaky assumption, but it	*/
66817214Smckusick 		/* wasn't my idea).					*/
66917214Smckusick 
6707380Ssam 		if ((fc = bdbtofsb(bp->b_blkno) - sc->sc_blkno) < 0)
6716186Ssam 			sc->sc_blkno -= MIN(0377, -fc);
6724736Swnj 		else
6736186Ssam 			sc->sc_blkno += MIN(0377, fc);
6744736Swnj 		return (MBN_RETRY);
6754736Swnj 
67617214Smckusick 	case MTER_ONLINE:		/* ddj -- shouldn't happen but did */
6774736Swnj 	case MTER_RWDING:
6784736Swnj 		return (MBN_SKIP);	/* ignore "rewind started" interrupt */
6794736Swnj 
6804736Swnj 	case MTER_NOTCAP:
68118324Sralph 		tprintf(sc->sc_ttyp, "mu%d: blank tape\n", MUUNIT(bp->b_dev));
68217214Smckusick 		bp->b_flags |= B_ERROR;
68317214Smckusick 		return (MBN_DONE);
6844736Swnj 
6854736Swnj 	case MTER_TM:
6864736Swnj 	case MTER_LEOT:
68717214Smckusick 
68817214Smckusick 		/* For an ioctl skip operation, count a tape mark as	*/
68917214Smckusick 		/* a record.  If there's anything left to do, update	*/
69017214Smckusick 		/* the repeat count and re-start the command.		*/
69117214Smckusick 
69217214Smckusick 		if (bp == &cmtbuf[MTUNIT(bp->b_dev)]) {
69317214Smckusick 			if ((sc->sc_resid = bp->b_repcnt = fc - 1) == 0)
69417214Smckusick 				return (MBN_DONE);
69517214Smckusick 			else
69617214Smckusick 				return (MBN_RETRY);
69717214Smckusick 
69817214Smckusick 		/* Cooked I/O again.  Just update the books and wait	*/
69917214Smckusick 		/* for someone else to return end of file or complain	*/
70017214Smckusick 		/* about a bad seek.					*/
70117214Smckusick 
70217214Smckusick 		} else if (sc->sc_blkno > bdbtofsb(bp->b_blkno)) {
70317214Smckusick 			sc->sc_nxrec = bdbtofsb(bp->b_blkno) + fc - 1;
7044736Swnj 			sc->sc_blkno = sc->sc_nxrec;
7054736Swnj 		} else {
70617214Smckusick 			sc->sc_nxrec = bdbtofsb(bp->b_blkno) - fc;
70717214Smckusick 			sc->sc_blkno = sc->sc_nxrec + 1;
7084736Swnj 		}
7094736Swnj 		return (MBN_RETRY);
7104736Swnj 
7114736Swnj 	case MTER_FPT:
71218324Sralph 		tprintf(sc->sc_ttyp, "mu%d: no write ring\n", MUUNIT(bp->b_dev));
7134736Swnj 		bp->b_flags |= B_ERROR;
7144736Swnj 		return (MBN_DONE);
7154736Swnj 
7164736Swnj 	case MTER_OFFLINE:
71717214Smckusick 
71817214Smckusick 		/* If `off line' was intentional, don't complain. */
71917214Smckusick 
72017214Smckusick 		if (   (bp == &cmtbuf[MTUNIT(bp->b_dev)])
72117214Smckusick 		    && (bp->b_command == MT_UNLOAD) )
72217214Smckusick 			return(MBN_DONE);
7234736Swnj 		if (sc->sc_openf > 0) {
7244736Swnj 			sc->sc_openf = -1;
72518324Sralph 			tprintf(sc->sc_ttyp, "mu%d: offline\n", MUUNIT(bp->b_dev));
7264736Swnj 		}
7274736Swnj 		bp->b_flags |= B_ERROR;
7284736Swnj 		return (MBN_DONE);
7294736Swnj 
73017214Smckusick 	case MTER_NOTAVL:
73117214Smckusick 		if (sc->sc_openf > 0) {
73217214Smckusick 			sc->sc_openf = -1;
73318324Sralph 			tprintf(sc->sc_ttyp, "mu%d: offline (port selector)\n", MUUNIT(bp->b_dev));
73417214Smckusick 		}
73517214Smckusick 		bp->b_flags |= B_ERROR;
73617214Smckusick 		return (MBN_DONE);
73717214Smckusick 
7384736Swnj 	case MTER_BOT:
7394736Swnj 		if (bp == &cmtbuf[MTUNIT(bp->b_dev)])
7404736Swnj 			goto done;
7414736Swnj 
74217214Smckusick 		/* fall through */
74317214Smckusick 
7444736Swnj 	default:
74518324Sralph 		tprintf(sc->sc_ttyp, "mu%d: hard error (non data transfer) rn=%d bn=%d er=%o (octal) ds=%b\n",
74617214Smckusick 		    MUUNIT(bp->b_dev), sc->sc_blkno, bp->b_blkno,
74717214Smckusick 		    er, MASKREG(sc->sc_dsreg), mtds_bits);
74817214Smckusick #ifdef MTLERRM
74917214Smckusick 		mtintfail(sc);
75017214Smckusick 		printf("     interrupt code = %o (octal) <%s>\n     failure code = %o (octal) <%s>\n",
75117214Smckusick 		    (er & MTER_INTCODE), sc->sc_mesg,
75217214Smckusick 		    (er & MTER_FAILCODE) >> 10, sc->sc_fmesg);
75317214Smckusick #endif
75417214Smckusick 		if (   ((er & MTER_INTCODE) == MTER_TMFLTB)
75517214Smckusick 		    || ((er & MTER_INTCODE) == MTER_MBFLT) ) {
75617214Smckusick 			mtcreset(mtaddr);	/* reset the controller */
75717214Smckusick 		}
7584736Swnj 		bp->b_flags |= B_ERROR;
7594736Swnj 		return (MBN_DONE);
7604736Swnj 	}
7614736Swnj 	/* NOTREACHED */
7624736Swnj }
7634736Swnj 
76417214Smckusick void mtcreset(mtaddr)
76517214Smckusick 	register struct mtdevice *mtaddr;
76617214Smckusick {
76717214Smckusick 	register int i;
76817214Smckusick 
76917214Smckusick 	mtaddr->mtid = MTID_CLR;		/* reset the TM78 */
77017214Smckusick 	DELAY(200);
77117214Smckusick 	for (i = MTTIMEOUT; i > 0; i--) {
77217214Smckusick 		DELAY(50);			/* don't nag */
77317214Smckusick 		if ((mtaddr->mtid & MTID_RDY) != 0)
77417214Smckusick 			return;			/* exit when ready */
77517214Smckusick 	}
77617214Smckusick 	printf("mt: controller hung\n");
77717214Smckusick }
77817214Smckusick 
7797740Sroot mtread(dev, uio)
7804736Swnj 	dev_t dev;
7817740Sroot 	struct uio *uio;
7824736Swnj {
7838158Sroot 	int errno;
7844736Swnj 
7858158Sroot 	errno = mtphys(dev, uio);
7868158Sroot 	if (errno)
7878158Sroot 		return (errno);
7888158Sroot 	return (physio(mtstrategy, &rmtbuf[MTUNIT(dev)], dev, B_READ, minphys, uio));
7894736Swnj }
7904736Swnj 
79117214Smckusick 
7927833Sroot mtwrite(dev, uio)
7937833Sroot 	dev_t dev;
7947833Sroot 	struct uio *uio;
7954736Swnj {
7968158Sroot 	int errno;
7974736Swnj 
7988158Sroot 	errno = mtphys(dev, uio);
7998158Sroot 	if (errno)
8008158Sroot 		return (errno);
8018158Sroot 	return (physio(mtstrategy, &rmtbuf[MTUNIT(dev)], dev, B_WRITE, minphys, uio));
8024736Swnj }
8034736Swnj 
8047740Sroot mtphys(dev, uio)
8054736Swnj 	dev_t dev;
8067740Sroot 	struct uio *uio;
8074736Swnj {
8084736Swnj 	register int mtunit;
80917214Smckusick 	struct mba_device *mi;
81017214Smckusick 	register int bsize = uio->uio_iov->iov_len;
8114736Swnj 
8124736Swnj 	mtunit = MTUNIT(dev);
81317214Smckusick 	if (   (mtunit >= NMT)
81417214Smckusick 	    || ((mi = mtinfo[mtunit]) == 0)
81517214Smckusick 	    || (mi->mi_alive == 0) )
8167740Sroot 		return (ENXIO);
81717214Smckusick 	if (   (bsize > 0xffff)	/* controller limit */
81817214Smckusick 	    || (bsize <= 0) )	/* ambiguous */
81917214Smckusick 		return (EINVAL);
8207740Sroot 	return (0);
8214736Swnj }
8224736Swnj 
8234736Swnj /*ARGSUSED*/
8247637Ssam mtioctl(dev, cmd, data, flag)
8254736Swnj 	dev_t dev;
8264736Swnj 	int cmd;
8277637Ssam 	caddr_t data;
8284736Swnj 	int flag;
8294736Swnj {
8304736Swnj 	register struct mu_softc *sc = &mu_softc[MUUNIT(dev)];
8314736Swnj 	register struct buf *bp = &cmtbuf[MTUNIT(dev)];
83217214Smckusick 	register struct mtop *mtop;
83317214Smckusick 	register struct mtget *mtget;
83417214Smckusick 	int callcount, fcount;
83517214Smckusick 	int op;
83617214Smckusick 
83717214Smckusick 	/* We depend on the values and order of the MT codes here. */
83817214Smckusick 
8394736Swnj 	static mtops[] =
8404736Swnj 	{MT_WTM,MT_SFORWF,MT_SREVF,MT_SFORW,MT_SREV,MT_REW,MT_UNLOAD,MT_SENSE};
8414736Swnj 
8424736Swnj 	switch (cmd) {
8437637Ssam 
84417214Smckusick 	/* tape operation */
84517214Smckusick 
84617214Smckusick 	case MTIOCTOP:
8478606Sroot 		mtop = (struct mtop *)data;
8488606Sroot 		switch (mtop->mt_op) {
8497637Ssam 
8504736Swnj 		case MTWEOF:
8517637Ssam 			callcount = mtop->mt_count;
8524736Swnj 			fcount = 1;
8534736Swnj 			break;
8547637Ssam 
8554736Swnj 		case MTFSF: case MTBSF:
8567637Ssam 			callcount = mtop->mt_count;
8574736Swnj 			fcount = 1;
8584736Swnj 			break;
8597637Ssam 
8604736Swnj 		case MTFSR: case MTBSR:
8614736Swnj 			callcount = 1;
8627637Ssam 			fcount = mtop->mt_count;
8634736Swnj 			break;
8647637Ssam 
8654736Swnj 		case MTREW: case MTOFFL:
8664736Swnj 			callcount = 1;
8674736Swnj 			fcount = 1;
8684736Swnj 			break;
8697637Ssam 
8704736Swnj 		default:
8718581Sroot 			return (ENXIO);
8724736Swnj 		}
87317214Smckusick 		if ((callcount <= 0) || (fcount <= 0))
8748581Sroot 			return (EINVAL);
8757637Ssam 		op = mtops[mtop->mt_op];
8764736Swnj 		if (op == MT_WTM)
8774736Swnj 			op |= sc->sc_dens;
8784736Swnj 		while (--callcount >= 0) {
87917214Smckusick 			register int n, fc = fcount;
8804736Swnj 
8814736Swnj 			do {
88217214Smckusick 				n = MIN(fc, 0xff);
8834736Swnj 				mtcommand(dev, op, n);
88417214Smckusick 				n -= sc->sc_resid;
88517214Smckusick 				fc -= n;
88617214Smckusick 				switch (mtop->mt_op) {
88717214Smckusick 
88817214Smckusick 				case MTWEOF:
88917214Smckusick 					sc->sc_blkno += (daddr_t)n;
89017214Smckusick 					sc->sc_nxrec = sc->sc_blkno - 1;
89117214Smckusick 					break;
89217214Smckusick 
89317214Smckusick 				case MTOFFL:
89417214Smckusick 				case MTREW:
89517214Smckusick 				case MTFSF:
89617214Smckusick 					sc->sc_blkno = (daddr_t)0;
89717214Smckusick 					sc->sc_nxrec = (daddr_t)INF;
89817214Smckusick 					break;
89917214Smckusick 
90017214Smckusick 				case MTBSF:
90117214Smckusick 					if (sc->sc_resid) {
90217214Smckusick 						sc->sc_blkno = (daddr_t)0;
90317214Smckusick 						sc->sc_nxrec = (daddr_t)INF;
90417214Smckusick 					} else {
90517214Smckusick 						sc->sc_blkno = (daddr_t)(-1);
90617214Smckusick 						sc->sc_nxrec = (daddr_t)(-1);
90717214Smckusick 					}
90817214Smckusick 					break;
90917214Smckusick 
91017214Smckusick 				case MTFSR:
91117214Smckusick 					sc->sc_blkno += (daddr_t)n;
91217214Smckusick 					break;
91317214Smckusick 
91417214Smckusick 				case MTBSR:
91517214Smckusick 					sc->sc_blkno -= (daddr_t)n;
91617214Smckusick 					break;
91717214Smckusick 				}
91817214Smckusick 				if (sc->sc_resid)
91917214Smckusick 					break;
92017214Smckusick 			} while (fc);
92117214Smckusick 			if (fc) {
92217214Smckusick 				sc->sc_resid = callcount + fc;
92317214Smckusick 				if (   (mtop->mt_op == MTFSR)
92417214Smckusick 				    || (mtop->mt_op == MTBSR) )
92517214Smckusick 					return (EIO);
92617214Smckusick 				else
92717214Smckusick 					break;
92817214Smckusick 			}
92917214Smckusick 			if (bp->b_flags & B_ERROR)
9304736Swnj 				break;
9314736Swnj 		}
9328712Sroot 		return (geterror(bp));
9337637Ssam 
93417214Smckusick 	/* tape status */
93517214Smckusick 
9364736Swnj 	case MTIOCGET:
9377637Ssam 		mtget = (struct mtget *)data;
9387637Ssam 		mtget->mt_erreg = sc->sc_erreg;
9397637Ssam 		mtget->mt_resid = sc->sc_resid;
9404736Swnj 		mtcommand(dev, MT_SENSE, 1);	/* update drive status */
9417637Ssam 		mtget->mt_dsreg = sc->sc_dsreg;
9427637Ssam 		mtget->mt_type = MT_ISMT;
9438581Sroot 		break;
9447637Ssam 
94517214Smckusick 	/* ignore EOT condition */
94617214Smckusick 
94717214Smckusick 	case MTIOCIEOT:
94817214Smckusick 		sc->sc_flags |= H_IEOT;
94917214Smckusick 		break;
95017214Smckusick 
95117214Smckusick 	/* enable EOT condition */
95217214Smckusick 
95317214Smckusick 	case MTIOCEEOT:
95417214Smckusick 		sc->sc_flags &= ~H_IEOT;
95517214Smckusick 		break;
95617214Smckusick 
9574736Swnj 	default:
9588581Sroot 		return (ENXIO);
9594736Swnj 	}
9608581Sroot 	return (0);
9614736Swnj }
9624736Swnj 
9634736Swnj #define	DBSIZE	20
9644736Swnj 
9654736Swnj mtdump()
9664736Swnj {
9674736Swnj 	register struct mba_device *mi;
9684736Swnj 	register struct mba_regs *mp;
9694736Swnj 	int blk, num;
9704736Swnj 	int start;
9714736Swnj 
9724736Swnj 	start = 0;
9734736Swnj 	num = maxfree;
9744736Swnj #define	phys(a,b)		((b)((int)(a)&0x7fffffff))
9754736Swnj 	if (mtinfo[0] == 0)
9764736Swnj 		return (ENXIO);
9774736Swnj 	mi = phys(mtinfo[0], struct mba_device *);
9784736Swnj 	mp = phys(mi->mi_hd, struct mba_hd *)->mh_physmba;
9794736Swnj 	mp->mba_cr = MBCR_IE;
9806186Ssam #if lint
9818606Sroot 	blk = 0; num = blk; start = num; blk = start;
9826186Ssam 	return (0);
9836186Ssam #endif
9846186Ssam #ifdef notyet
9854736Swnj 	mtaddr = (struct mtdevice *)&mp->mba_drv[mi->mi_drive];
9864736Swnj 	mtaddr->mttc = MTTC_PDP11|MTTC_1600BPI;
9874736Swnj 	mtaddr->mtcs1 = MT_DCLR|MT_GO;
9884736Swnj 	while (num > 0) {
9894736Swnj 		blk = num > DBSIZE ? DBSIZE : num;
9904736Swnj 		mtdwrite(start, blk, mtaddr, mp);
9914736Swnj 		start += blk;
9924736Swnj 		num -= blk;
9934736Swnj 	}
9944736Swnj 	mteof(mtaddr);
9954736Swnj 	mteof(mtaddr);
9964736Swnj 	mtwait(mtaddr);
9974736Swnj 	if (mtaddr->mtds&MTDS_ERR)
9984736Swnj 		return (EIO);
9994736Swnj 	mtaddr->mtcs1 = MT_REW|MT_GO;
10004736Swnj 	return (0);
10014736Swnj }
10024736Swnj 
10034736Swnj mtdwrite(dbuf, num, mtaddr, mp)
10044736Swnj 	register dbuf, num;
10054736Swnj 	register struct mtdevice *mtaddr;
10064736Swnj 	struct mba_regs *mp;
10074736Swnj {
10084736Swnj 	register struct pte *io;
10094736Swnj 	register int i;
10104736Swnj 
10114736Swnj 	mtwait(mtaddr);
10124736Swnj 	io = mp->mba_map;
10134736Swnj 	for (i = 0; i < num; i++)
10144736Swnj 		*(int *)io++ = dbuf++ | PG_V;
10154736Swnj 	mtaddr->mtfc = -(num*NBPG);
10164736Swnj 	mp->mba_sr = -1;
10174736Swnj 	mp->mba_bcr = -(num*NBPG);
10184736Swnj 	mp->mba_var = 0;
10194736Swnj 	mtaddr->mtcs1 = MT_WCOM|MT_GO;
10204736Swnj }
10214736Swnj 
10224736Swnj mtwait(mtaddr)
10234736Swnj 	struct mtdevice *mtaddr;
10244736Swnj {
10254736Swnj 	register s;
10264736Swnj 
10274736Swnj 	do
10284736Swnj 		s = mtaddr->mtds;
10294736Swnj 	while ((s & MTDS_DRY) == 0);
10304736Swnj }
10314736Swnj 
10324736Swnj mteof(mtaddr)
10334736Swnj 	struct mtdevice *mtaddr;
10344736Swnj {
10354736Swnj 
10364736Swnj 	mtwait(mtaddr);
10374736Swnj 	mtaddr->mtcs1 = MT_WEOF|MT_GO;
10384736Swnj #endif notyet
10394736Swnj }
104017214Smckusick 
104117214Smckusick #ifdef MTLERRM
104217214Smckusick mtintfail(sc)
104317214Smckusick 	register struct mu_softc *sc;
104417214Smckusick {
104517214Smckusick 	switch (sc->sc_erreg & MTER_INTCODE) {
104617214Smckusick 
104717214Smckusick 	/* unexpected BOT detected */
104817214Smckusick 
104917214Smckusick 	case MTER_BOT:
105017214Smckusick 		sc->sc_mesg = "unexpected BOT";
105117214Smckusick 		switch ((sc->sc_erreg & MTER_FAILCODE) >> 10) {
105217214Smckusick 		case 01:
105317214Smckusick 			sc->sc_fmesg = "tape was at BOT";
105417214Smckusick 			break;
105517214Smckusick 		case 02:
105617214Smckusick 			sc->sc_fmesg = "BOT seen after tape started";
105717214Smckusick 			break;
105817214Smckusick 		case 03:
105917214Smckusick 			sc->sc_fmesg = "ARA ID detected";
106017214Smckusick 			break;
106117214Smckusick 		default:
106217214Smckusick 			sc->sc_fmesg = "unclassified failure code";
106317214Smckusick 		}
106417214Smckusick 		break;
106517214Smckusick 
106617214Smckusick 	/* unexpected LEOT detected */
106717214Smckusick 
106817214Smckusick 	case MTER_LEOT:
106917214Smckusick 		sc->sc_mesg = "unexpected LEOT";
107017214Smckusick 		sc->sc_fmesg = "";
107117214Smckusick 		break;
107217214Smckusick 
107317214Smckusick 	/* rewinding */
107417214Smckusick 
107517214Smckusick 	case MTER_RWDING:
107617214Smckusick 		sc->sc_mesg = "tape rewinding";
107717214Smckusick 		sc->sc_fmesg = "";
107817214Smckusick 		break;
107917214Smckusick 
108017214Smckusick 	/* not ready */
108117214Smckusick 
108217214Smckusick 	case MTER_NOTRDY:
108317214Smckusick 		sc->sc_mesg = "drive not ready";
108417214Smckusick 		switch ((sc->sc_erreg & MTER_FAILCODE) >> 10) {
108517214Smckusick 		case 01:
108617214Smckusick 			sc->sc_fmesg = "TU on-line but not ready";
108717214Smckusick 			break;
108817214Smckusick 		case 02:
108917214Smckusick 			sc->sc_fmesg = "fatal error has occurred";
109017214Smckusick 			break;
109117214Smckusick 		case 03:
109217214Smckusick 			sc->sc_fmesg = "access allowed but not really";
109317214Smckusick 			break;
109417214Smckusick 		default:
109517214Smckusick 			sc->sc_fmesg = "unclassified failure code";
109617214Smckusick 		}
109717214Smckusick 		break;
109817214Smckusick 
109917214Smckusick 	/* not available */
110017214Smckusick 
110117214Smckusick 	case MTER_NOTAVL:
110217214Smckusick 		sc->sc_mesg = "drive not available";
110317214Smckusick 		sc->sc_fmesg = "";
110417214Smckusick 		break;
110517214Smckusick 
110617214Smckusick 	/* unit does not exist */
110717214Smckusick 
110817214Smckusick 	case MTER_NONEX:
110917214Smckusick 		sc->sc_mesg = "unit does not exist";
111017214Smckusick 		sc->sc_fmesg = "";
111117214Smckusick 		break;
111217214Smckusick 
111317214Smckusick 	/* not capable */
111417214Smckusick 
111517214Smckusick 	case MTER_NOTCAP:
111617214Smckusick 		sc->sc_mesg = "not capable";
111717214Smckusick 		switch ((sc->sc_erreg & MTER_FAILCODE) >> 10) {
111817214Smckusick 		case 01:
111917214Smckusick 			sc->sc_fmesg = "no record found within 25 feet";
112017214Smckusick 			break;
112117214Smckusick 		case 02:
112217214Smckusick 			sc->sc_fmesg = "ID burst neither PE nor GCR";
112317214Smckusick 			break;
112417214Smckusick 		case 03:
112517214Smckusick 			sc->sc_fmesg = "ARA ID not found";
112617214Smckusick 			break;
112717214Smckusick 		case 04:
112817214Smckusick 			sc->sc_fmesg = "no gap found after ID burst";
112917214Smckusick 			break;
113017214Smckusick 		default:
113117214Smckusick 			sc->sc_fmesg = "unclassified failure code";
113217214Smckusick 		}
113317214Smckusick 		break;
113417214Smckusick 
113517214Smckusick 	/* long tape record */
113617214Smckusick 
113717214Smckusick 	case MTER_LONGREC:
113817214Smckusick 		sc->sc_mesg = "long record";
113917214Smckusick 		switch ((sc->sc_erreg & MTER_FAILCODE) >> 10) {
114017214Smckusick 		case 00:
114117214Smckusick 			sc->sc_fmesg = "extended sense data not found";
114217214Smckusick 			break;
114317214Smckusick 		case 01:
114417214Smckusick 			sc->sc_fmesg = "extended sense data updated";
114517214Smckusick 			break;
114617214Smckusick 		default:
114717214Smckusick 			sc->sc_fmesg = "unclassified failure code";
114817214Smckusick 		}
114917214Smckusick 		break;
115017214Smckusick 
115117214Smckusick 	/* unreadable */
115217214Smckusick 
115317214Smckusick 	case MTER_UNREAD:
115417214Smckusick 		sc->sc_mesg = "unreadable record";
115517214Smckusick 		goto code22;
115617214Smckusick 
115717214Smckusick 	/* error */
115817214Smckusick 
115917214Smckusick 	case MTER_ERROR:
116017214Smckusick 		sc->sc_mesg = "error";
116117214Smckusick 		goto code22;
116217214Smckusick 
116317214Smckusick 	/* EOT error */
116417214Smckusick 
116517214Smckusick 	case MTER_EOTERR:
116617214Smckusick 		sc->sc_mesg = "EOT error";
116717214Smckusick 		goto code22;
116817214Smckusick 
116917214Smckusick 	/* tape position lost */
117017214Smckusick 
117117214Smckusick 	case MTER_BADTAPE:
117217214Smckusick 		sc->sc_mesg = "bad tape";
117317214Smckusick 	code22:
117417214Smckusick 		switch ((sc->sc_erreg & MTER_FAILCODE) >> 10) {
117517214Smckusick 		case 01:
117617214Smckusick 			sc->sc_fmesg = "GCR write error";
117717214Smckusick 			break;
117817214Smckusick 		case 02:
117917214Smckusick 			sc->sc_fmesg = "GCR read error";
118017214Smckusick 			break;
118117214Smckusick 		case 03:
118217214Smckusick 			sc->sc_fmesg = "PE read error";
118317214Smckusick 			break;
118417214Smckusick 		case 04:
118517214Smckusick 			sc->sc_fmesg = "PE write error";
118617214Smckusick 			break;
118717214Smckusick 		case 05:
118817214Smckusick 			sc->sc_fmesg = "at least 1 bit set in ECCSTA";
118917214Smckusick 			break;
119017214Smckusick 		case 06:
119117214Smckusick 			sc->sc_fmesg = "PE write error";
119217214Smckusick 			break;
119317214Smckusick 		case 07:
119417214Smckusick 			sc->sc_fmesg = "GCR write error";
119517214Smckusick 			break;
119617214Smckusick 		case 010:
119717214Smckusick 			sc->sc_fmesg = "RSTAT contains bad code";
119817214Smckusick 			break;
119917214Smckusick 		case 011:
120017214Smckusick 			sc->sc_fmesg = "PE write error";
120117214Smckusick 			break;
120217214Smckusick 		case 012:
120317214Smckusick 			sc->sc_fmesg = "MASSBUS parity error";
120417214Smckusick 			break;
120517214Smckusick 		case 013:
120617214Smckusick 			sc->sc_fmesg = "invalid data transferred";
120717214Smckusick 			break;
120817214Smckusick 		default:
120917214Smckusick 			sc->sc_fmesg = "unclassified failure code";
121017214Smckusick 		}
121117214Smckusick 		break;
121217214Smckusick 
121317214Smckusick 	/* TM fault A */
121417214Smckusick 
121517214Smckusick 	case MTER_TMFLTA:
121617214Smckusick 		sc->sc_mesg = "TM fault A";
121717214Smckusick 		switch ((sc->sc_erreg & MTER_FAILCODE) >> 10) {
121817214Smckusick 		case 01:
121917214Smckusick 			sc->sc_fmesg = "illegal command code";
122017214Smckusick 			break;
122117214Smckusick 		case 02:
122217214Smckusick 			sc->sc_fmesg = "DT command issued when NDT command active";
122317214Smckusick 			break;
122417214Smckusick 		case 03:
122517214Smckusick 			sc->sc_fmesg = "WMC error";
122617214Smckusick 			break;
122717214Smckusick 		case 04:
122817214Smckusick 			sc->sc_fmesg = "RUN not received from MASSBUS controller";
122917214Smckusick 			break;
123017214Smckusick 		case 05:
123117214Smckusick 			sc->sc_fmesg = "mismatch in command read - function routine";
123217214Smckusick 			break;
123317214Smckusick 		case 06:
123417214Smckusick 			sc->sc_fmesg = "ECC ROM parity error";
123517214Smckusick 			break;
123617214Smckusick 		case 07:
123717214Smckusick 			sc->sc_fmesg = "XMC ROM parity error";
123817214Smckusick 			break;
123917214Smckusick 		case 010:
124017214Smckusick 			sc->sc_fmesg = "mismatch in command read - ID burst command";
124117214Smckusick 			break;
124217214Smckusick 		case 011:
124317214Smckusick 			sc->sc_fmesg = "mismatch in command read - verify ARA burst command";
124417214Smckusick 			break;
124517214Smckusick 		case 012:
124617214Smckusick 			sc->sc_fmesg = "mismatch in command read - verify ARA ID command";
124717214Smckusick 			break;
124817214Smckusick 		case 013:
124917214Smckusick 			sc->sc_fmesg = "mismatch in command read - verify gap command";
125017214Smckusick 			break;
125117214Smckusick 		case 014:
125217214Smckusick 			sc->sc_fmesg = "mismatch in command read - read id burst command";
125317214Smckusick 			break;
125417214Smckusick 		case 015:
125517214Smckusick 			sc->sc_fmesg = "mismatch in command read - verify ARA ID command";
125617214Smckusick 			break;
125717214Smckusick 		case 016:
125817214Smckusick 			sc->sc_fmesg = "mismatch in command read - verify gap command";
125917214Smckusick 			break;
126017214Smckusick 		case 017:
126117214Smckusick 			sc->sc_fmesg = "mismatch in command read - find gap command";
126217214Smckusick 			break;
126317214Smckusick 		case 020:
126417214Smckusick 			sc->sc_fmesg = "WMC LEFT failed to set";
126517214Smckusick 			break;
126617214Smckusick 		case 021:
126717214Smckusick 			sc->sc_fmesg = "XL PE set in INTSTA register";
126817214Smckusick 			break;
126917214Smckusick 		case 022:
127017214Smckusick 			sc->sc_fmesg = "XMC DONE did not set";
127117214Smckusick 			break;
127217214Smckusick 		case 023:
127317214Smckusick 			sc->sc_fmesg = "WMC ROM PE or RD PE set in WMCERR register";
127417214Smckusick 			break;
127517214Smckusick 		default:
127617214Smckusick 			sc->sc_fmesg = "unclassified failure code";
127717214Smckusick 		}
127817214Smckusick 		break;
127917214Smckusick 
128017214Smckusick 	/* TU fault A */
128117214Smckusick 
128217214Smckusick 	case MTER_TUFLTA:
128317214Smckusick 		sc->sc_mesg = "TU fault A";
128417214Smckusick 		switch ((sc->sc_erreg & MTER_FAILCODE) >> 10) {
128517214Smckusick 		case 01:
128617214Smckusick 			sc->sc_fmesg = "TU status parity error";
128717214Smckusick 			break;
128817214Smckusick 		case 02:
128917214Smckusick 			sc->sc_fmesg = "TU command parity error";
129017214Smckusick 			break;
129117214Smckusick 		case 03:
129217214Smckusick 			sc->sc_fmesg = "rewinding tape went offline";
129317214Smckusick 			break;
129417214Smckusick 		case 04:
129517214Smckusick 			sc->sc_fmesg = "tape went not ready during DSE";
129617214Smckusick 			break;
129717214Smckusick 		case 05:
129817214Smckusick 			sc->sc_fmesg = "TU CMD status changed during DSE";
129917214Smckusick 			break;
130017214Smckusick 		case 06:
130117214Smckusick 			sc->sc_fmesg = "TU never came up to speed";
130217214Smckusick 			break;
130317214Smckusick 		case 07:
130417214Smckusick 			sc->sc_fmesg = "TU velocity changed";
130517214Smckusick 			break;
130617214Smckusick 		case 010:
130717214Smckusick 			sc->sc_fmesg = "TU CMD did not load correctly to start tape motion";
130817214Smckusick 			break;
130917214Smckusick 		case 011:
131017214Smckusick 			sc->sc_fmesg = "TU CMD did not load correctly to set drive density";
131117214Smckusick 			break;
131217214Smckusick 		case 012:
131317214Smckusick 			sc->sc_fmesg = "TU CMD did not load correctly to start tape motion to write BOT ID";
131417214Smckusick 			break;
131517214Smckusick 		case 013:
131617214Smckusick 			sc->sc_fmesg = "TU CMD did not load correctly to backup tape to BOT after failing to write BOT ID";
131717214Smckusick 			break;
131817214Smckusick 		case 014:
131917214Smckusick 			sc->sc_fmesg = "failed to write density ID burst";
132017214Smckusick 			break;
132117214Smckusick 		case 015:
132217214Smckusick 			sc->sc_fmesg = "failed to write ARA burst";
132317214Smckusick 			break;
132417214Smckusick 		case 016:
132517214Smckusick 			sc->sc_fmesg = "failed to write ARA ID";
132617214Smckusick 			break;
132717214Smckusick 		case 017:
132817214Smckusick 			sc->sc_fmesg = "ARA error bit set in MTA status B register";
132917214Smckusick 			break;
133017214Smckusick 		case 021:
133117214Smckusick 			sc->sc_fmesg = "could not find a gap after ID code was written correctly";
133217214Smckusick 			break;
133317214Smckusick 		case 022:
133417214Smckusick 			sc->sc_fmesg = "TU CMD did not load correctly to start tape motion to read ID burst";
133517214Smckusick 			break;
133617214Smckusick 		case 023:
133717214Smckusick 			sc->sc_fmesg = "timeout looking for BOT after detecting ARA ID burst";
133817214Smckusick 			break;
133917214Smckusick 		case 024:
134017214Smckusick 			sc->sc_fmesg = "failed to write tape mark";
134117214Smckusick 			break;
134217214Smckusick 		case 025:
134317214Smckusick 			sc->sc_fmesg = "tape never came up to speed while trying to reposition for retry of writing tape mark";
134417214Smckusick 			break;
134517214Smckusick 		case 026:
134617214Smckusick 			sc->sc_fmesg = "TU CMD did not load correctly to start tape motion in erase gap routine";
134717214Smckusick 			break;
134817214Smckusick 		case 027:
134917214Smckusick 			sc->sc_fmesg = "could not detect a gap in in erase gap routine";
135017214Smckusick 			break;
135117214Smckusick 		case 030:
135217214Smckusick 			sc->sc_fmesg = "could not detect a gap after writing record";
135317214Smckusick 			break;
135417214Smckusick 		case 031:
135517214Smckusick 			sc->sc_fmesg = "read path terminated before entire record was written";
135617214Smckusick 			break;
135717214Smckusick 		case 032:
135817214Smckusick 			sc->sc_fmesg = "could not find a gap after writing record and read path terminated early";
135917214Smckusick 			break;
136017214Smckusick 		case 033:
136117214Smckusick 			sc->sc_fmesg = "TU CMD did not load correctly to backup for retry of write tape mark";
136217214Smckusick 			break;
136317214Smckusick 		case 034:
136417214Smckusick 			sc->sc_fmesg = "TU velocity changed after up to speed while trying to reposition for retry of writing tape mark";
136517214Smckusick 			break;
136617214Smckusick 		case 035:
136717214Smckusick 			sc->sc_fmesg = "TU CMD did not load correctly to backup to retry a load of BOT ID";
136817214Smckusick 			break;
136917214Smckusick 		case 036:
137017214Smckusick 			sc->sc_fmesg = "timeout looking for BOT after failing to write BOT ID";
137117214Smckusick 			break;
137217214Smckusick 		case 037:
137317214Smckusick 			sc->sc_fmesg = "TU velocity changed while writing PE gap before starting to write record";
137417214Smckusick 			break;
137517214Smckusick 		case 040:
137617214Smckusick 			sc->sc_fmesg = "TU CMD did not load correctly to set PE tape density at start of write BOT ID burst";
137717214Smckusick 			break;
137817214Smckusick 		case 041:
137917214Smckusick 			sc->sc_fmesg = "TU CMD did not load correctly to set GCR tape density after writing Density ID";
138017214Smckusick 			break;
138117214Smckusick 		case 042:
138217214Smckusick 			sc->sc_fmesg = "TU CMD did not load correctly to set PE tape density at start of read from BOT";
138317214Smckusick 			break;
138417214Smckusick 		case 043:
138517214Smckusick 			sc->sc_fmesg = "TU CMD did not load correctly to set GCR tape density after reading a GCR Density ID burst";
138617214Smckusick 			break;
138717214Smckusick 		default:
138817214Smckusick 			sc->sc_fmesg = "unclassified failure code";
138917214Smckusick 		}
139017214Smckusick 		break;
139117214Smckusick 
139217214Smckusick 	/* TM fault B */
139317214Smckusick 
139417214Smckusick 	case MTER_TMFLTB:
139517214Smckusick 		sc->sc_mesg = "TM fault B";
139617214Smckusick 		switch ((sc->sc_erreg & MTER_FAILCODE) >> 10) {
139717214Smckusick 		case 00:
139817214Smckusick 			sc->sc_fmesg = "RST0 interrupt occurred with TM RDY set";
139917214Smckusick 			break;
140017214Smckusick 		case 01:
140117214Smckusick 			sc->sc_fmesg = "power failed to interrupt";
140217214Smckusick 			break;
140317214Smckusick 		case 02:
140417214Smckusick 			sc->sc_fmesg = "unknown interrupt on channel 5.5";
140517214Smckusick 			break;
140617214Smckusick 		case 03:
140717214Smckusick 			sc->sc_fmesg = "unknown interrupt on channel 6.5";
140817214Smckusick 			break;
140917214Smckusick 		case 04:
141017214Smckusick 			sc->sc_fmesg = "unknown interrupt on channel 7";
141117214Smckusick 			break;
141217214Smckusick 		case 05:
141317214Smckusick 			sc->sc_fmesg = "unknown interrupt on channel 7.5";
141417214Smckusick 			break;
141517214Smckusick 		case 06:
141617214Smckusick 			sc->sc_fmesg = "CAS contention retry count expired";
141717214Smckusick 			break;
141817214Smckusick 		case 07:
141917214Smckusick 			sc->sc_fmesg = "CAS contention error not retryable";
142017214Smckusick 			break;
142117214Smckusick 		case 010:
142217214Smckusick 			sc->sc_fmesg = "queue error, could not find queue entry";
142317214Smckusick 			break;
142417214Smckusick 		case 011:
142517214Smckusick 			sc->sc_fmesg = "queue entry already full";
142617214Smckusick 			break;
142717214Smckusick 		case 012:
142817214Smckusick 			sc->sc_fmesg = "8085 ROM parity error";
142917214Smckusick 			break;
143017214Smckusick 		case 013:
143117214Smckusick 		case 014:
143217214Smckusick 		case 015:
143317214Smckusick 		case 016:
143417214Smckusick 		case 017:
143517214Smckusick 		case 020:
143617214Smckusick 		case 021:
143717214Smckusick 		case 022:
143817214Smckusick 		case 023:
143917214Smckusick 		case 024:
144017214Smckusick 		case 025:
144117214Smckusick 		case 026:
144217214Smckusick 		case 027:
144317214Smckusick 		case 030:
144417214Smckusick 		case 031:
144517214Smckusick 		case 032:
144617214Smckusick 		case 033:
144717214Smckusick 		case 034:
144817214Smckusick 		case 035:
144917214Smckusick 		case 036:
145017214Smckusick 		case 037:
145117214Smckusick 		case 040:
145217214Smckusick 		case 041:
145317214Smckusick 		case 042:
145417214Smckusick 		case 043:
145517214Smckusick 		case 044:
145617214Smckusick 		case 045:
145717214Smckusick 		case 046:
145817214Smckusick 		case 047:
145917214Smckusick 		case 050:
146017214Smckusick 		case 051:
146117214Smckusick 		case 052:
146217214Smckusick 		case 053:
146317214Smckusick 		case 054:
146417214Smckusick 		case 055:
146517214Smckusick 		case 056:
146617214Smckusick 		case 057:
146717214Smckusick 			sc->sc_fmesg = "inline test failed";
146817214Smckusick 			break;
146917214Smckusick 		default:
147017214Smckusick 			sc->sc_fmesg = "unclassified failure code";
147117214Smckusick 		}
147217214Smckusick 		break;
147317214Smckusick 
147417214Smckusick 	/* MASSBUS fault */
147517214Smckusick 
147617214Smckusick 	case MTER_MBFLT:
147717214Smckusick 		sc->sc_mesg = "MB fault";
147817214Smckusick 		switch ((sc->sc_erreg & MTER_FAILCODE) >> 10) {
147917214Smckusick 		case 01:
148017214Smckusick 			sc->sc_fmesg = "control bus parity error";
148117214Smckusick 			break;
148217214Smckusick 		case 02:
148317214Smckusick 			sc->sc_fmesg = "illegal register referenced";
148417214Smckusick 			break;
148517214Smckusick 		default:
148617214Smckusick 			sc->sc_fmesg = "unclassified failure code";
148717214Smckusick 		}
148817214Smckusick 		break;
148917214Smckusick 
149017214Smckusick 	/* keypad entry error */
149117214Smckusick 
149217214Smckusick 	case MTER_KEYFAIL:
149317214Smckusick 		sc->sc_mesg = "keypad entry error";
149417214Smckusick 		sc->sc_fmesg = "";
149517214Smckusick 		break;
149617214Smckusick 	default:
149717214Smckusick 		sc->sc_mesg = "unclassified error";
149817214Smckusick 		sc->sc_fmesg = "";
149917214Smckusick 		break;
150017214Smckusick 	}
150117214Smckusick }
150217214Smckusick #endif MTLERRM
15034736Swnj #endif
1504