xref: /original-bsd/sys/vax/mba/mt.c (revision 95ecee29)
1 /*-
2  * Copyright (c) 1982, 1986 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * %sccs.include.proprietary.c%
6  *
7  *	@(#)mt.c	7.11 (Berkeley) 09/23/93
8  */
9 
10 #include "mu.h"
11 #if NMT > 0
12 /*
13  * TM78/TU78 tape driver
14  *
15  *	Original author - ?
16  *	Most error recovery bug fixes - ggs (ulysses!ggs)
17  *	`read reverse' error recovery - ggs (ulysses!ggs)
18  *
19  * OPTIONS:
20  *	MTLERRM - Long error message text - twd, Brown University
21  *
22  * TODO:
23  *	Add odd byte count kludge from VMS driver (?)
24  *	Write dump routine
25  */
26 
27 #include "sys/param.h"
28 #include "sys/systm.h"
29 #include "sys/buf.h"
30 #include "sys/conf.h"
31 #include "sys/file.h"
32 #include "sys/user.h"
33 #include "sys/proc.h"
34 #include "sys/map.h"
35 #include "sys/ioctl.h"
36 #include "sys/mtio.h"
37 #include "sys/cmap.h"
38 #include "sys/tty.h"
39 #include "sys/syslog.h"
40 
41 #include "../include/pte.h"
42 #include "../include/cpu.h"
43 #include "mbareg.h"
44 #include "mbavar.h"
45 #include "mtreg.h"
46 
47 #define MTTIMEOUT	10000		/* loop limit for controller test */
48 #define	INF		1000000L	/* a block number that won't exist */
49 #define MASKREG(r)	((r) & 0xffff)	/* the control registers have 16 bits */
50 
51 /* Bits for sc_flags */
52 
53 #define	H_WRITTEN	01		/* last operation was a write */
54 #define H_EOT		02		/* end of tape encountered */
55 #define H_IEOT		04		/* ignore EOT condition */
56 
57 int	mt_do_readrev = 1;
58 
59 /* Per unit status information */
60 
61 struct	mu_softc {
62 	char	sc_openf;	/* unit is open if != 0 */
63 	char	sc_flags;	/* state flags */
64 	daddr_t	sc_blkno;	/* current physical block number */
65 	daddr_t	sc_nxrec;	/* firewall input block number */
66 	u_short	sc_erreg;	/* copy of mter or mtner */
67 	u_short	sc_dsreg;	/* copy of mtds */
68 	short	sc_resid;	/* residual function count for ioctl */
69 	short	sc_dens;	/* density code - MT_GCR or zero */
70 	int	sc_i_mtas;	/* mtas at slave attach time */
71 	int	sc_i_mtner;	/* mtner at slave attach time */
72 	int	sc_i_mtds;	/* mtds at slave attach time */
73 	caddr_t	sc_ctty;	/* record user's tty for errors */
74 	int	sc_blks;	/* number of I/O operations since open */
75 	int	sc_softerrs;	/* number of soft I/O errors since open */
76 } mu_softc[NMU];
77 
78 struct	buf	cmtbuf[NMT];		/* tape command buffer structures */
79 
80 struct	mba_device *mtinfo[NMT];	/* unit to ctlr structures */
81 struct	mba_slave *muinfo[NMU];		/* unit to slave structures */
82 
83 char	mtds_bits[] = MTDS_BITS;	/* mtds bit names for error messages */
84 short	mttypes[] = { MBDT_TU78, 0 };
85 
86 int	mtattach(), mtslave(), mtustart(), mtstart(), mtndtint(), mtdtint();
87 struct	mba_driver mtdriver =
88 	{ mtattach, mtslave, mtustart, mtstart, mtdtint, mtndtint,
89 	  mttypes, "mt", "mu", mtinfo };
90 
91 /* Bits in minor device */
92 #define	MUUNIT(dev)	(minor(dev)&03)
93 #define	H_NOREWIND	04
94 #define	H_6250BPI	010
95 
96 #define MTUNIT(dev)	(muinfo[MUUNIT(dev)]->ms_ctlr)
97 
98 void	mtcreset();
99 
100 /*ARGSUSED*/
101 mtattach(mi)
102 	struct mba_device *mi;
103 {
104 
105 	/* void */
106 }
107 
108 mtslave(mi, ms, sn)
109 	struct mba_device *mi;
110 	struct mba_slave *ms;
111 	int sn;
112 {
113 	register struct mu_softc *sc = &mu_softc[ms->ms_unit];
114 	register struct mtdevice *mtaddr = (struct mtdevice *)mi->mi_drv;
115 	int s = spl5(), rtn = 0, i;
116 
117 	/*
118 	 * Just in case the controller is ill, reset it.  Then issue
119 	 * a sense operation and wait about a second for it to respond.
120 	 */
121 	mtcreset(mtaddr);
122 	mtaddr->mtas = -1;
123 	mtaddr->mtncs[sn] = MT_SENSE|MT_GO;
124 	for (i = MTTIMEOUT; i > 0; i--) {
125 		DELAY(50);
126 		if (MASKREG(mtaddr->mtas) != 0)
127 			break;
128 	}
129 	sc->sc_i_mtas = mtaddr->mtas;
130 	sc->sc_i_mtner = mtaddr->mtner;
131 	sc->sc_i_mtds = mtaddr->mtds;
132 
133 	/*
134 	 * If no response, whimper.  If wrong response, call it an
135 	 * unsolicited interrupt and use mtndtint to log and correct.
136 	 * Otherwise, note whether this slave exists.
137 	 */
138 	if (i <= 0)
139 		printf("mt: controller hung\n");
140 	else if ((mtaddr->mtner & MTER_INTCODE) != MTER_DONE)
141 		(void) mtndtint(mi);
142 	else if (mtaddr->mtds & MTDS_PRES) {
143 		muinfo[ms->ms_unit] = ms;
144 		rtn = 1;
145 	}
146 
147 	/* cancel the interrupt, then wait a little while for it to go away */
148 	mtaddr->mtas = mtaddr->mtas;
149 	DELAY(10);
150 	splx(s);
151 	return (rtn);
152 }
153 
154 mtopen(dev, flag)
155 	dev_t dev;
156 	int flag;
157 {
158 	register int muunit;
159 	register struct mu_softc *sc;
160 	register struct mba_slave *ms;
161 
162 	muunit = MUUNIT(dev);
163 	if (muunit >= NMU || (ms = muinfo[muunit]) == NULL ||
164 	    ms->ms_alive == 0 || mtinfo[ms->ms_ctlr]->mi_alive == 0)
165 		return (ENXIO);
166 	if ((sc = &mu_softc[muunit])->sc_openf)
167 		return (EBUSY);
168 	sc->sc_openf = 1;
169 	sc->sc_dens = (minor(dev) & H_6250BPI) ? MT_GCR : 0;
170 	mtcommand(dev, MT_SENSE, 1);
171 	if ((sc->sc_dsreg & MTDS_ONL) == 0) {
172 		uprintf("mu%d: not online\n", muunit);
173 		sc->sc_openf = 0;
174 		return (EIO);
175 	}
176 	if ((sc->sc_dsreg & MTDS_AVAIL) == 0) {
177 		uprintf("mu%d: not online (port selector)\n", muunit);
178 		sc->sc_openf = 0;
179 		return (EIO);
180 	}
181 	if ((flag & FWRITE) && (sc->sc_dsreg & MTDS_FPT)) {
182 		uprintf("mu%d: no write ring\n", muunit);
183 		sc->sc_openf = 0;
184 		return (EIO);
185 	}
186 	if ((sc->sc_dsreg & MTDS_BOT) == 0 && (flag & FWRITE) &&
187 	    (sc->sc_dens == MT_GCR) != ((sc->sc_dsreg & MTDS_PE) == 0)) {
188 		uprintf("mu%d: can't change density in mid-tape\n", muunit);
189 		sc->sc_openf = 0;
190 		return (EIO);
191 	}
192 	sc->sc_blkno = (daddr_t)0;
193 
194 	/*
195 	 * Since cooked I/O may do a read-ahead before a write, trash
196 	 * on a tape can make the first write fail.  Suppress the first
197 	 * read-ahead unless definitely doing read-write.
198 	 */
199 	sc->sc_nxrec = ((flag & (FTRUNC | FWRITE)) == (FTRUNC | FWRITE)) ?
200 	    (daddr_t)0 : (daddr_t)INF;
201 	sc->sc_flags = 0;
202 	sc->sc_blks = 0;
203 	sc->sc_softerrs = 0;
204 	sc->sc_ctty = (caddr_t)(u.u_procp->p_flag & P_CONTROLT ?
205 	    u.u_procp->p_session->s_ttyp : 0);
206 	return (0);
207 }
208 
209 mtclose(dev, flag)
210 	register dev_t dev;
211 	register int flag;
212 {
213 	register struct mu_softc *sc = &mu_softc[MUUNIT(dev)];
214 
215 	if ((flag & (FREAD | FWRITE)) == FWRITE ||
216 	    ((flag & FWRITE) && (sc->sc_flags & H_WRITTEN)))
217 		mtcommand(dev, MT_CLS|sc->sc_dens, 1);
218 	if ((minor(dev) & H_NOREWIND) == 0)
219 		mtcommand(dev, MT_REW, 0);
220 	if (sc->sc_blks > 100 && sc->sc_softerrs > sc->sc_blks / 100)
221 		log(LOG_INFO, "mu%d: %d soft errors in %d blocks\n",
222 		    MUUNIT(dev), sc->sc_softerrs, sc->sc_blks);
223 	sc->sc_openf = 0;
224 	return (0);
225 }
226 
227 mtcommand(dev, com, count)
228 	dev_t dev;
229 	int com, count;
230 {
231 	register struct buf *bp;
232 	int s;
233 
234 	bp = &cmtbuf[MTUNIT(dev)];
235 	s = spl5();
236 	while (bp->b_flags & B_BUSY) {
237 		if (bp->b_repcnt == 0 && (bp->b_flags & B_DONE))
238 			break;
239 		bp->b_flags |= B_WANTED;
240 		sleep((caddr_t)bp, PRIBIO);
241 	}
242 	bp->b_flags = B_BUSY|B_READ;
243 	splx(s);
244 	bp->b_dev = dev;
245 	bp->b_command = com;
246 	bp->b_repcnt = count;
247 	bp->b_blkno = 0;
248 	bp->b_error = 0;
249 	mtstrategy(bp);
250 	if (count == 0)
251 		return;
252 	biowait(bp);
253 	if (bp->b_flags & B_WANTED)
254 		wakeup((caddr_t)bp);
255 	bp->b_flags &= B_ERROR;
256 }
257 
258 mtstrategy(bp)
259 	register struct buf *bp;
260 {
261 	register struct buf *dp;
262 	struct mba_device *mi = mtinfo[MTUNIT(bp->b_dev)];
263 	int s;
264 
265 	/*
266 	 * If this is a data transfer operation, set the resid to a
267 	 * default value (EOF) to simplify getting it right during
268 	 * error recovery or bail out.
269 	 */
270 	if (bp != &cmtbuf[MTUNIT(bp->b_dev)])
271 		bp->b_resid = bp->b_bcount;
272 
273 	/*
274 	 * Link this request onto the end of the queue for this
275 	 * controller, then start I/O if not already active.
276 	 */
277 	bp->av_forw = NULL;
278 	dp = &mi->mi_tab;
279 	s = spl5();
280 	if (dp->b_actf == NULL)
281 		dp->b_actf = bp;
282 	else
283 		dp->b_actl->av_forw = bp;
284 	dp->b_actl = bp;
285 	if (dp->b_active == 0)
286 		mbustart(mi);
287 	splx(s);
288 }
289 
290 mtustart(mi)
291 	register struct mba_device *mi;
292 {
293 	register struct mtdevice *mtaddr = (struct mtdevice *)mi->mi_drv;
294 	register struct buf *bp = mi->mi_tab.b_actf;
295 	register struct mu_softc *sc = &mu_softc[MUUNIT(bp->b_dev)];
296 	daddr_t blkno;
297 	int count;
298 
299 	if (sc->sc_openf < 0) {
300 		bp->b_flags |= B_ERROR;
301 		return (MBU_NEXT);
302 	}
303 	if (bp != &cmtbuf[MTUNIT(bp->b_dev)]) {
304 		/*
305 		 * Data transfer.  If write at end of tape,
306 		 * signal "no space" unless suppressed
307 		 * by MTIOCIEOT.
308 		 */
309 		if ((sc->sc_flags & (H_EOT | H_IEOT)) == H_EOT &&
310 		    (bp->b_flags & B_READ) == 0) {
311 			bp->b_flags |= B_ERROR;
312 			bp->b_error = ENOSPC;
313 			return (MBU_NEXT);
314 		}
315 
316 		if (bp->b_flags & B_RAW) {
317 			/* raw transfer; never seek */
318 			sc->sc_blkno = bdbtofsb(bp->b_blkno);
319 			sc->sc_nxrec = sc->sc_blkno + 1;
320 		} else {
321 			/* seek beyond end of file */
322 			if (bdbtofsb(bp->b_blkno) > sc->sc_nxrec) {
323 				bp->b_flags |= B_ERROR;
324 				bp->b_error = ENXIO;
325 				return (MBU_NEXT);
326 			}
327 
328 			/*
329 			 * This should be end of file, but the buffer
330 			 * system wants a one-block look-ahead.  Humor it.
331 			 */
332 			if (bdbtofsb(bp->b_blkno) == sc->sc_nxrec &&
333 			    bp->b_flags & B_READ) {
334 				bp->b_resid = bp->b_bcount;
335 				clrbuf(bp);
336 				return (MBU_NEXT);
337 			}
338 
339 			/* If writing, mark the next block invalid. */
340 			if ((bp->b_flags & B_READ) == 0)
341 				sc->sc_nxrec = bdbtofsb(bp->b_blkno) + 1;
342 		}
343 	} else {
344 		/* It's a command, do it now. */
345 		mtaddr->mtncs[MUUNIT(bp->b_dev)] =
346 			(bp->b_repcnt<<8)|bp->b_command|MT_GO;
347 		return (MBU_STARTED);
348 	}
349 
350 	/*
351 	 * If raw I/O, or if the tape is positioned correctly for
352 	 * cooked I/O, set the byte count, unit number and repeat count
353 	 * then tell the MASSBUS to proceed.  Note that a negative
354 	 * bcount tells mbstart to map the buffer for "read backwards".
355 	 */
356 	if ((blkno = sc->sc_blkno) == bdbtofsb(bp->b_blkno)) {
357 		if (mi->mi_tab.b_errcnt == 2) {
358 			mtaddr->mtbc = -bp->b_bcount;
359 			mtaddr->mtca = MUUNIT(bp->b_dev);
360 		} else {
361 			mtaddr->mtbc = bp->b_bcount;
362 			mtaddr->mtca = (1<<2)|MUUNIT(bp->b_dev);
363 		}
364 		return (MBU_DODATA);
365 	}
366 
367 	/* Issue skip operations to position the next block for cooked I/O. */
368 
369 	if (blkno < bdbtofsb(bp->b_blkno))
370 		count = bdbtofsb(bp->b_blkno) - blkno;
371 	else
372 		count = blkno - bdbtofsb(bp->b_blkno);
373 	if ((unsigned)count > 0377)
374 		count = 0377;
375 	mtaddr->mtncs[MUUNIT(bp->b_dev)] = count | MT_SFORW|MT_GO;
376 	return (MBU_STARTED);
377 }
378 
379 mtstart(mi)
380 	register struct mba_device *mi;
381 {
382 	register struct buf *bp = mi->mi_tab.b_actf;
383 	register struct mu_softc *sc = &mu_softc[MUUNIT(bp->b_dev)];
384 
385 	if (bp->b_flags & B_READ)
386 		if (mi->mi_tab.b_errcnt == 2)
387 			return (MT_READREV|MT_GO);
388 		else
389 			return (MT_READ|MT_GO);
390 	else
391 		return (MT_WRITE|sc->sc_dens|MT_GO);
392 }
393 
394 mtdtint(mi, mbsr)
395 	register struct mba_device *mi;
396 	int mbsr;
397 {
398 	register struct mtdevice *mtaddr = (struct mtdevice *)mi->mi_drv;
399 	register struct buf *bp = mi->mi_tab.b_actf;
400 	register struct mu_softc *sc;
401 	register int er;
402 
403 	/* I'M still NOT SURE IF THIS SHOULD ALWAYS BE THE CASE SO FOR NOW... */
404 	if ((mtaddr->mtca & 3) != MUUNIT(bp->b_dev)) {
405 		printf("mt: wrong unit!\n");
406 		mtaddr->mtca = MUUNIT(bp->b_dev);
407 	}
408 
409 	er = MASKREG(mtaddr->mter);
410 	sc = &mu_softc[MUUNIT(bp->b_dev)];
411 	sc->sc_erreg = er;
412 	if (bp->b_flags & B_READ)
413 		sc->sc_flags &= ~H_WRITTEN;
414 	else
415 		sc->sc_flags |= H_WRITTEN;
416 	switch (er & MTER_INTCODE) {
417 
418 	case MTER_EOT:
419 		sc->sc_flags |= H_EOT;
420 		/* fall into MTER_DONE */
421 
422 	case MTER_DONE:
423 		sc->sc_blkno++;
424 		if (mi->mi_tab.b_errcnt == 2) {
425 			bp->b_bcount = bp->b_resid;
426 			bp->b_resid -= MASKREG(mtaddr->mtbc);
427 			if (bp->b_resid > 0 && (bp->b_flags & B_RAW) == 0)
428 				bp->b_flags |= B_ERROR;
429 		} else
430 			bp->b_resid = 0;
431 		break;
432 
433 	case MTER_SHRTREC:
434 		sc->sc_blkno++;
435 		bp->b_bcount = bp->b_resid;
436 		bp->b_resid -= MASKREG(mtaddr->mtbc);
437 		if ((bp->b_flags & B_RAW) == 0)
438 			bp->b_flags |= B_ERROR;
439 		break;
440 
441 	case MTER_RETRY:
442 		/*
443 		 * Simple re-try.  Since resid is always a copy of the
444 		 * original byte count, use it to restore the count.
445 		 */
446 		mi->mi_tab.b_errcnt = 1;
447 		bp->b_bcount = bp->b_resid;
448 		return (MBD_RETRY);
449 
450 	case MTER_RDOPP:
451 		/*
452 		 * The controller just decided to read it backwards.
453 		 * If the controller returns a byte count of zero,
454 		 * change it to 1, since zero encodes 65536, which
455 		 * isn't quite what we had in mind.  The byte count
456 		 * may be larger than the size of the input buffer, so
457 		 * limit the count to the buffer size.  After
458 		 * making the byte count reasonable, set bcount to the
459 		 * negative of the controller's version of the byte
460 		 * count so that the start address for the transfer is
461 		 * set up correctly.
462 		 */
463 		if (mt_do_readrev) {
464 			mi->mi_tab.b_errcnt = 2;
465 			if ((bp->b_bcount = MASKREG(mtaddr->mtbc)) == 0)
466 				bp->b_bcount = 1;
467 			if (bp->b_bcount > bp->b_resid)
468 				bp->b_bcount = bp->b_resid;
469 			bp->b_bcount = -(bp->b_bcount);
470 			return(MBD_RETRY);
471 		} else if (MASKREG(mtaddr->mtbc) <= bp->b_resid) {
472 			sc->sc_blkno++;
473 			bp->b_bcount = bp->b_resid;
474 			bp->b_resid -= MASKREG(mtaddr->mtbc);
475 			bp->b_flags |= B_ERROR;
476 			break;
477 		}
478 		bp->b_flags |= B_ERROR;
479 		/* fall into MTER_LONGREC */
480 
481 	case MTER_LONGREC:
482 		sc->sc_blkno++;
483 		bp->b_bcount = bp->b_resid;
484 		bp->b_resid = 0;
485 		bp->b_error = ENOMEM;
486 		bp->b_flags |= B_ERROR;
487 		break;
488 
489 	case MTER_NOTCAP:
490 		printf("mu%d: blank tape\n", MUUNIT(bp->b_dev));
491 		goto err;
492 
493 	case MTER_TM:
494 		/*
495 		 * End of file.  Since the default byte count has
496 		 * already been set, just count the block and proceed.
497 		 */
498 		sc->sc_blkno++;
499 	err:
500 		sc->sc_nxrec = bdbtofsb(bp->b_blkno);
501 		break;
502 
503 	case MTER_OFFLINE:
504 		if (sc->sc_openf > 0) {
505 			sc->sc_openf = -1;
506 			tprintf(sc->sc_ctty, "mu%d: offline\n",
507 			    MUUNIT(bp->b_dev));
508 		}
509 		bp->b_flags |= B_ERROR;
510 		break;
511 
512 	case MTER_NOTAVL:
513 		if (sc->sc_openf > 0) {
514 			sc->sc_openf = -1;
515 			tprintf(sc->sc_ctty, "mu%d: offline (port selector)\n",
516 			    MUUNIT(bp->b_dev));
517 		}
518 		bp->b_flags |= B_ERROR;
519 		break;
520 
521 	case MTER_FPT:
522 		tprintf(sc->sc_ctty, "mu%d: no write ring\n",
523 		    MUUNIT(bp->b_dev));
524 		bp->b_flags |= B_ERROR;
525 		break;
526 
527 	case MTER_UNREAD:
528 		sc->sc_blkno++;
529 		bp->b_bcount = bp->b_resid;
530 		bp->b_resid -= MIN(MASKREG(mtaddr->mtbc), bp->b_bcount);
531 
532 		/* code 010 means a garbage record, nothing serious. */
533 		if ((er & MTER_FAILCODE) == (010 << MTER_FSHIFT)) {
534 			tprintf(sc->sc_ctty,
535 			    "mu%d: rn=%d bn=%d unreadable record\n",
536 			    MUUNIT(bp->b_dev), sc->sc_blkno, bp->b_blkno);
537 			bp->b_flags |= B_ERROR;
538 			break;
539 		}
540 
541 		/*
542 		 * Anything else might be a hardware problem,
543 		 * fall into the error report.
544 		 */
545 
546 	default:
547 		/*
548 		 * The bits in sc->sc_dsreg are from the last sense
549 		 * command.  To get the most recent copy, you have to
550 		 * do a sense at interrupt level, which requires nested
551 		 * error processing.  This is a bit messy, so leave
552 		 * well enough alone.
553 		 */
554 		tprintf(sc->sc_ctty, "\
555 mu%d: hard error (data transfer) rn=%d bn=%d mbsr=%b er=0%o ds=%b\n",
556 		    MUUNIT(bp->b_dev), sc->sc_blkno, bp->b_blkno,
557 		    mbsr, mbsr_bits, er,
558 		    MASKREG(sc->sc_dsreg), mtds_bits);
559 #ifdef MTLERRM
560 		mtintfail(er);
561 #endif
562 		bp->b_flags |= B_ERROR;
563 
564 		/*
565 		 * The TM78 manual says to reset the controller after
566 		 * TM fault B or MASSBUS fault.
567 		 */
568 		if ((er & MTER_INTCODE) == MTER_TMFLTB ||
569 		    (er & MTER_INTCODE) == MTER_MBFLT)
570 			mtcreset(mtaddr);
571 	}
572 
573 	/*
574 	 * Just in case some strange error slipped through (drive off
575 	 * line during read-reverse error recovery comes to mind), make
576 	 * sure the byte count is reasonable.
577 	 */
578 	if (bp->b_bcount < 0)
579 		bp->b_bcount = bp->b_resid;
580 
581 	if ((bp->b_flags & B_ERROR) == 0) {
582 		/* this counts reverse reads as soft errors */
583 		sc->sc_blks++;
584 		if (mi->mi_tab.b_errcnt) /* alternatively, if == 1 */
585 			sc->sc_softerrs++;
586 	}
587 	return (MBD_DONE);
588 }
589 
590 mtndtint(mi)
591 	register struct mba_device *mi;
592 {
593 	register struct mtdevice *mtaddr = (struct mtdevice *)mi->mi_drv;
594 	register struct buf *bp = mi->mi_tab.b_actf;
595 	register struct mu_softc *sc;
596 	register int er, fc;
597 	int unit;
598 
599 	unit = (mtaddr->mtner >> 8) & 3;
600 	er = MASKREG(mtaddr->mtner);
601 	sc = &mu_softc[unit];
602 	sc->sc_erreg = er;
603 
604 	/* Check for unsolicited interrupts. */
605 	if (bp == NULL || unit != MUUNIT(bp->b_dev)) {
606 		if ((er & MTER_INTCODE) == MTER_ONLINE)
607 			return (MBN_SKIP);
608 
609 		printf("mu%d: stray intr (non data transfer) er=0%o ds=%b\n",
610 		    unit, er, MASKREG(sc->sc_dsreg), mtds_bits);
611 #ifdef MTLERRM
612 		mtintfail(er);
613 #endif
614 		if ((er & MTER_INTCODE) == MTER_TMFLTB ||
615 		    (er & MTER_INTCODE) == MTER_MBFLT) {
616 			/*
617 			 * Reset the controller, then set error status
618 			 * if there was anything active when the fault
619 			 * occurred.  This may shoot an innocent
620 			 * bystander, but it's better than letting
621 			 * an error slip through.
622 			 */
623 			mtcreset(mtaddr);
624 			if (bp != NULL) {
625 				bp->b_flags |= B_ERROR;
626 				return (MBN_DONE);
627 			}
628 		}
629 		return (MBN_SKIP);
630 	}
631 
632 	fc = (mtaddr->mtncs[unit] >> 8) & 0xff;
633 	sc->sc_resid = fc;
634 
635 	/*
636 	 * Clear the "written" flag after any operation that changes
637 	 * the position of the tape.
638 	 */
639 	if (bp != &cmtbuf[MTUNIT(bp->b_dev)] || bp->b_command != MT_SENSE)
640 		sc->sc_flags &= ~H_WRITTEN;
641 
642 	switch (er & MTER_INTCODE) {
643 
644 	case MTER_EOT:
645 		sc->sc_flags |= H_EOT;
646 		/* fall into MTER_DONE */
647 
648 	case MTER_DONE:
649 		/* If this is a command buffer, just update the status.	*/
650 		if (bp == &cmtbuf[MTUNIT(bp->b_dev)]) {
651 	done:
652 			if (bp->b_command == MT_SENSE)
653 				sc->sc_dsreg = MASKREG(mtaddr->mtds);
654 			return (MBN_DONE);
655 		}
656 
657 		/*
658 		 * It's not a command buffer, must be a cooked I/O
659 		 * skip operation (perhaps a shaky assumption, but it
660 		 * wasn't my idea).
661 		 */
662 		if ((fc = bdbtofsb(bp->b_blkno) - sc->sc_blkno) < 0)
663 			sc->sc_blkno -= MIN(0377, -fc);
664 		else
665 			sc->sc_blkno += MIN(0377, fc);
666 		return (MBN_RETRY);
667 
668 	case MTER_ONLINE:		/* ddj -- shouldn't happen but did */
669 	case MTER_RWDING:
670 		return (MBN_SKIP);	/* ignore "rewind started" interrupt */
671 
672 	case MTER_NOTCAP:
673 		tprintf(sc->sc_ctty, "mu%d: blank tape\n", MUUNIT(bp->b_dev));
674 		bp->b_flags |= B_ERROR;
675 		return (MBN_DONE);
676 
677 	case MTER_TM:
678 	case MTER_LEOT:
679 		/*
680 		 * For an ioctl skip operation, count a tape mark as
681 		 * a record.  If there's anything left to do, update
682 		 * the repeat count and re-start the command.
683 		 */
684 		if (bp == &cmtbuf[MTUNIT(bp->b_dev)]) {
685 			if ((sc->sc_resid = bp->b_repcnt = fc - 1) == 0)
686 				return (MBN_DONE);
687 			else
688 				return (MBN_RETRY);
689 		} else {
690 			/*
691 			 * Cooked I/O again.  Just update the books and
692 			 * wait for someone else to return end of file or
693 			 * complain about a bad seek.
694 			 */
695 			if (sc->sc_blkno > bdbtofsb(bp->b_blkno)) {
696 				sc->sc_nxrec = bdbtofsb(bp->b_blkno) + fc - 1;
697 				sc->sc_blkno = sc->sc_nxrec;
698 			} else {
699 				sc->sc_nxrec = bdbtofsb(bp->b_blkno) - fc;
700 				sc->sc_blkno = sc->sc_nxrec + 1;
701 			}
702 		}
703 		return (MBN_RETRY);
704 
705 	case MTER_FPT:
706 		tprintf(sc->sc_ctty, "mu%d: no write ring\n",
707 		    MUUNIT(bp->b_dev));
708 		bp->b_flags |= B_ERROR;
709 		return (MBN_DONE);
710 
711 	case MTER_OFFLINE:
712 		/* If `off line' was intentional, don't complain. */
713 		if (bp == &cmtbuf[MTUNIT(bp->b_dev)] &&
714 		    bp->b_command == MT_UNLOAD)
715 			return(MBN_DONE);
716 		if (sc->sc_openf > 0) {
717 			sc->sc_openf = -1;
718 			tprintf(sc->sc_ctty, "mu%d: offline\n",
719 			    MUUNIT(bp->b_dev));
720 		}
721 		bp->b_flags |= B_ERROR;
722 		return (MBN_DONE);
723 
724 	case MTER_NOTAVL:
725 		if (sc->sc_openf > 0) {
726 			sc->sc_openf = -1;
727 			tprintf(sc->sc_ctty, "mu%d: offline (port selector)\n",
728 			    MUUNIT(bp->b_dev));
729 		}
730 		bp->b_flags |= B_ERROR;
731 		return (MBN_DONE);
732 
733 	case MTER_BOT:
734 		if (bp == &cmtbuf[MTUNIT(bp->b_dev)])
735 			goto done;
736 		/* fall through */
737 
738 	default:
739 		tprintf(sc->sc_ctty, "\
740 mu%d: hard error (non data transfer) rn=%d bn=%d er=0%o ds=%b\n",
741 		    MUUNIT(bp->b_dev), sc->sc_blkno, bp->b_blkno,
742 		    er, MASKREG(sc->sc_dsreg), mtds_bits);
743 #ifdef MTLERRM
744 		mtintfail(er);
745 #endif
746 		if ((er & MTER_INTCODE) == MTER_TMFLTB ||
747 		    (er & MTER_INTCODE) == MTER_MBFLT)
748 			mtcreset(mtaddr);	/* reset the controller */
749 		bp->b_flags |= B_ERROR;
750 		return (MBN_DONE);
751 	}
752 	/* NOTREACHED */
753 }
754 
755 void
756 mtcreset(mtaddr)
757 	register struct mtdevice *mtaddr;
758 {
759 	register int i;
760 
761 	mtaddr->mtid = MTID_CLR;		/* reset the TM78 */
762 	DELAY(200);
763 	for (i = MTTIMEOUT; i > 0; i--) {
764 		DELAY(50);			/* don't nag */
765 		if ((mtaddr->mtid & MTID_RDY) != 0)
766 			return;			/* exit when ready */
767 	}
768 	printf("mt: controller hung\n");
769 }
770 
771 /*ARGSUSED*/
772 mtioctl(dev, cmd, data, flag)
773 	dev_t dev;
774 	int cmd;
775 	caddr_t data;
776 	int flag;
777 {
778 	register struct mu_softc *sc = &mu_softc[MUUNIT(dev)];
779 	register struct buf *bp = &cmtbuf[MTUNIT(dev)];
780 	register struct mtop *mtop;
781 	register struct mtget *mtget;
782 	int callcount, fcount, error = 0;
783 	int op;
784 
785 	/* We depend on the values and order of the MT codes here. */
786 
787 	static mtops[] =
788 	{MT_WTM,MT_SFORWF,MT_SREVF,MT_SFORW,MT_SREV,MT_REW,MT_UNLOAD,MT_SENSE};
789 
790 	switch (cmd) {
791 
792 	/* tape operation */
793 
794 	case MTIOCTOP:
795 		mtop = (struct mtop *)data;
796 		switch (mtop->mt_op) {
797 
798 		case MTWEOF:
799 			callcount = mtop->mt_count;
800 			fcount = 1;
801 			break;
802 
803 		case MTFSF: case MTBSF:
804 			callcount = mtop->mt_count;
805 			fcount = 1;
806 			break;
807 
808 		case MTFSR: case MTBSR:
809 			callcount = 1;
810 			fcount = mtop->mt_count;
811 			break;
812 
813 		case MTREW: case MTOFFL:
814 			callcount = 1;
815 			fcount = 1;
816 			break;
817 
818 		default:
819 			return (ENXIO);
820 		}
821 		if (callcount <= 0 || fcount <= 0)
822 			return (EINVAL);
823 		op = mtops[mtop->mt_op];
824 		if (op == MT_WTM)
825 			op |= sc->sc_dens;
826 		while (--callcount >= 0) {
827 			register int n, fc = fcount;
828 
829 			do {
830 				n = MIN(fc, 0xff);
831 				mtcommand(dev, op, n);
832 				n -= sc->sc_resid;
833 				fc -= n;
834 				switch (mtop->mt_op) {
835 
836 				case MTWEOF:
837 					sc->sc_blkno += (daddr_t)n;
838 					sc->sc_nxrec = sc->sc_blkno - 1;
839 					break;
840 
841 				case MTOFFL:
842 				case MTREW:
843 				case MTFSF:
844 					sc->sc_blkno = (daddr_t)0;
845 					sc->sc_nxrec = (daddr_t)INF;
846 					break;
847 
848 				case MTBSF:
849 					if (sc->sc_resid) {
850 						sc->sc_blkno = (daddr_t)0;
851 						sc->sc_nxrec = (daddr_t)INF;
852 					} else {
853 						sc->sc_blkno = (daddr_t)(-1);
854 						sc->sc_nxrec = (daddr_t)(-1);
855 					}
856 					break;
857 
858 				case MTFSR:
859 					sc->sc_blkno += (daddr_t)n;
860 					break;
861 
862 				case MTBSR:
863 					sc->sc_blkno -= (daddr_t)n;
864 					break;
865 				}
866 				if (sc->sc_resid)
867 					break;
868 			} while (fc);
869 			if (fc) {
870 				sc->sc_resid = callcount + fc;
871 				if (mtop->mt_op == MTFSR ||
872 				    mtop->mt_op == MTBSR)
873 					return (EIO);
874 				break;
875 			}
876 			if (bp->b_flags & B_ERROR)
877 				break;
878 		}
879 		if (bp->b_flags&B_ERROR)
880 			if ((error = bp->b_error)==0)
881 				return (EIO);
882 		return (error);
883 
884 	/* tape status */
885 	case MTIOCGET:
886 		mtget = (struct mtget *)data;
887 		mtget->mt_erreg = sc->sc_erreg;
888 		mtget->mt_resid = sc->sc_resid;
889 		mtcommand(dev, MT_SENSE, 1);	/* update drive status */
890 		mtget->mt_dsreg = sc->sc_dsreg;
891 		mtget->mt_type = MT_ISMT;
892 		break;
893 
894 	/* ignore EOT condition */
895 	case MTIOCIEOT:
896 		sc->sc_flags |= H_IEOT;
897 		break;
898 
899 	/* enable EOT condition */
900 	case MTIOCEEOT:
901 		sc->sc_flags &= ~H_IEOT;
902 		break;
903 
904 	default:
905 		return (ENXIO);
906 	}
907 	return (0);
908 }
909 
910 #define	DBSIZE	20
911 
912 mtdump()
913 {
914 	register struct mba_device *mi;
915 	register struct mba_regs *mp;
916 	int blk, num;
917 	int start;
918 
919 	start = 0;
920 	num = maxfree;
921 #define	phys(a,b)		((b)((int)(a)&0x7fffffff))
922 	if (mtinfo[0] == 0)
923 		return (ENXIO);
924 	mi = phys(mtinfo[0], struct mba_device *);
925 	mp = phys(mi->mi_hd, struct mba_hd *)->mh_physmba;
926 	mp->mba_cr = MBCR_IE;
927 #if lint
928 	blk = 0; num = blk; start = num; blk = start;
929 	return (0);
930 #endif
931 #ifdef notyet
932 	mtaddr = (struct mtdevice *)&mp->mba_drv[mi->mi_drive];
933 	mtaddr->mttc = MTTC_PDP11|MTTC_1600BPI;
934 	mtaddr->mtcs1 = MT_DCLR|MT_GO;
935 	while (num > 0) {
936 		blk = num > DBSIZE ? DBSIZE : num;
937 		mtdwrite(start, blk, mtaddr, mp);
938 		start += blk;
939 		num -= blk;
940 	}
941 	mteof(mtaddr);
942 	mteof(mtaddr);
943 	mtwait(mtaddr);
944 	if (mtaddr->mtds&MTDS_ERR)
945 		return (EIO);
946 	mtaddr->mtcs1 = MT_REW|MT_GO;
947 	return (0);
948 }
949 
950 mtdwrite(dbuf, num, mtaddr, mp)
951 	register dbuf, num;
952 	register struct mtdevice *mtaddr;
953 	struct mba_regs *mp;
954 {
955 	register struct pte *io;
956 	register int i;
957 
958 	mtwait(mtaddr);
959 	io = mp->mba_map;
960 	for (i = 0; i < num; i++)
961 		*(int *)io++ = dbuf++ | PG_V;
962 	mtaddr->mtfc = -(num*NBPG);
963 	mp->mba_sr = -1;
964 	mp->mba_bcr = -(num*NBPG);
965 	mp->mba_var = 0;
966 	mtaddr->mtcs1 = MT_WCOM|MT_GO;
967 }
968 
969 mtwait(mtaddr)
970 	struct mtdevice *mtaddr;
971 {
972 	register s;
973 
974 	do
975 		s = mtaddr->mtds;
976 	while ((s & MTDS_DRY) == 0);
977 }
978 
979 mteof(mtaddr)
980 	struct mtdevice *mtaddr;
981 {
982 
983 	mtwait(mtaddr);
984 	mtaddr->mtcs1 = MT_WEOF|MT_GO;
985 #endif notyet
986 }
987 
988 #ifdef MTLERRM
989 /*
990  * Failure messages for each failure code, per interrupt code.
991  * Each table ends with a code of -1 as a default.
992  */
993 struct fmesg {
994 	int	f_code;
995 	char	*f_mesg;
996 };
997 
998 static char unclass[] = "unclassified failure code";
999 
1000 /* MTER_BOT */
1001 static struct fmesg botmsg[] = {
1002 	01,	"tape was at BOT",
1003 	02,	"BOT seen after tape started",
1004 	03,	"ARA ID detected",
1005 	-1,	unclass
1006 };
1007 
1008 /* MTER_NOTRDY */
1009 static struct fmesg notrdymsg[] = {
1010 	01,	"TU on-line but not ready",
1011 	02,	"fatal error has occurred",
1012 	03,	"access allowed but not ready",
1013 	-1,	unclass
1014 };
1015 
1016 /* MTER_NOTCAP */
1017 static struct fmesg notcapmsg[] = {
1018 	01,	"no record found within 25 feet",
1019 	02,	"ID burst neither PE nor GCR",
1020 	03,	"ARA ID not found",
1021 	04,	"no gap found after ID burst",
1022 	-1,	unclass
1023 };
1024 
1025 /* MTER_LONGREC */
1026 static struct fmesg longrecmsg[] = {
1027 	00,	"extended sense data not found",
1028 	01,	"extended sense data updated",
1029 	-1,	unclass
1030 };
1031 
1032 /* MTER_UNREAD, MTER_ERROR, MTER_EOTERR, MTER_BADTAPE */
1033 static struct fmesg code22msg[] = {
1034 	01,	"GCR write error",
1035 	02,	"GCR read error",
1036 	03,	"PE read error",
1037 	04,	"PE write error",
1038 	05,	"at least 1 bit set in ECCSTA",
1039 	06,	"PE write error",
1040 	07,	"GCR write error",
1041 	010,	"RSTAT contains bad code",
1042 	011,	"PE write error",
1043 	012,	"MASSBUS parity error",
1044 	013,	"invalid data transferred",
1045 	-1,	unclass
1046 };
1047 
1048 /* MTER_TMFLTA */
1049 static struct fmesg tmfltamsg[] = {
1050 	01,	"illegal command code",
1051 	02,	"DT command issued when NDT command active",
1052 	03,	"WMC error",
1053 	04,	"RUN not received from MASSBUS controller",
1054 	05,	"mismatch in command read - function routine",
1055 	06,	"ECC ROM parity error",
1056 	07,	"XMC ROM parity error",
1057 	010,	"mismatch in command read - ID burst command",
1058 	011,	"mismatch in command read - verify ARA burst command",
1059 	012,	"mismatch in command read - verify ARA ID command",
1060 	013,	"mismatch in command read - verify gap command",
1061 	014,	"mismatch in command read - read id burst command",
1062 	015,	"mismatch in command read - verify ARA ID command",
1063 	016,	"mismatch in command read - verify gap command",
1064 	017,	"mismatch in command read - find gap command",
1065 	020,	"WMC LEFT failed to set",
1066 	021,	"XL PE set in INTSTA register",
1067 	022,	"XMC DONE did not set",
1068 	023,	"WMC ROM PE or RD PE set in WMCERR register",
1069 	-1,	unclass
1070 };
1071 
1072 /* MTER_TUFLTA */
1073 static struct fmesg tufltamsg[] = {
1074 	01,	"TU status parity error",
1075 	02,	"TU command parity error",
1076 	03,	"rewinding tape went offline",
1077 	04,	"tape went not ready during DSE",
1078 	05,	"TU CMD status changed during DSE",
1079 	06,	"TU never came up to speed",
1080 	07,	"TU velocity changed",
1081 	010,	"TU CMD did not load correctly to start tape motion",
1082 	011,	"TU CMD did not load correctly to set drive density",
1083 	012,	"TU CMD did not load correctly to start tape motion to write BOT ID",
1084 	013,	"TU CMD did not load correctly to backup tape to BOT after failing to write BOT ID",
1085 	014,	"failed to write density ID burst",
1086 	015,	"failed to write ARA burst",
1087 	016,	"failed to write ARA ID",
1088 	017,	"ARA error bit set in MTA status B register",
1089 	021,	"could not find a gap after ID code was written correctly",
1090 	022,	"TU CMD did not load correctly to start tape motion to read ID burst",
1091 	023,	"timeout looking for BOT after detecting ARA ID burst",
1092 	024,	"failed to write tape mark",
1093 	025,	"tape never came up to speed while trying to reposition for retry of writing tape mark",
1094 	026,	"TU CMD did not load correctly to start tape motion in erase gap routine",
1095 	027,	"could not detect a gap in in erase gap routine",
1096 	030,	"could not detect a gap after writing record",
1097 	031,	"read path terminated before entire record was written",
1098 	032,	"could not find a gap after writing record and read path terminated early",
1099 	033,	"TU CMD did not load correctly to backup for retry of write tape mark",
1100 	034,	"TU velocity changed after up to speed while trying to reposition for retry of writing tape mark",
1101 	035,	"TU CMD did not load correctly to backup to retry a load of BOT ID",
1102 	036,	"timeout looking for BOT after failing to write BOT ID",
1103 	037,	"TU velocity changed while writing PE gap before starting to write record",
1104 	040,	"TU CMD did not load correctly to set PE tape density at start of write BOT ID burst",
1105 	041,	"TU CMD did not load correctly to set GCR tape density after writing Density ID",
1106 	042,	"TU CMD did not load correctly to set PE tape density at start of read from BOT",
1107 	043,	"TU CMD did not load correctly to set GCR tape density after reading a GCR Density ID burst",
1108 };
1109 
1110 /* MTER_TMFLTB */
1111 static char inlinetest[] = "inline test failed";
1112 static struct fmesg tmfltbmsg[] = {
1113 	00,	"RST0 interrupt occurred with TM RDY set",
1114 	01,	"power failed to interrupt",
1115 	02,	"unknown interrupt on channel 5.5",
1116 	03,	"unknown interrupt on channel 6.5",
1117 	04,	"unknown interrupt on channel 7",
1118 	05,	"unknown interrupt on channel 7.5",
1119 	06,	"CAS contention retry count expired",
1120 	07,	"CAS contention error not retryable",
1121 	010,	"queue error, could not find queue entry",
1122 	011,	"queue entry already full",
1123 	012,	"8085 ROM parity error",
1124 	013,	inlinetest,
1125 	013,	inlinetest,
1126 	014,	inlinetest,
1127 	015,	inlinetest,
1128 	016,	inlinetest,
1129 	017,	inlinetest,
1130 	020,	inlinetest,
1131 	021,	inlinetest,
1132 	022,	inlinetest,
1133 	023,	inlinetest,
1134 	024,	inlinetest,
1135 	025,	inlinetest,
1136 	026,	inlinetest,
1137 	027,	inlinetest,
1138 	030,	inlinetest,
1139 	031,	inlinetest,
1140 	032,	inlinetest,
1141 	033,	inlinetest,
1142 	034,	inlinetest,
1143 	035,	inlinetest,
1144 	036,	inlinetest,
1145 	037,	inlinetest,
1146 	040,	inlinetest,
1147 	041,	inlinetest,
1148 	042,	inlinetest,
1149 	043,	inlinetest,
1150 	044,	inlinetest,
1151 	045,	inlinetest,
1152 	046,	inlinetest,
1153 	047,	inlinetest,
1154 	050,	inlinetest,
1155 	051,	inlinetest,
1156 	052,	inlinetest,
1157 	053,	inlinetest,
1158 	054,	inlinetest,
1159 	055,	inlinetest,
1160 	056,	inlinetest,
1161 	057,	inlinetest,
1162 	-1,	unclass
1163 };
1164 
1165 /* MTER_MBFLT */
1166 static struct fmesg mbfltmsg[] = {
1167 	01,	"control bus parity error",
1168 	02,	"illegal register referenced",
1169 	-1,	unclass
1170 };
1171 
1172 /*
1173  * MTER_LEOT, MTER_RWDING, NTER_NOTAVL, MTER_NONEX, MTER_KEYFAIL,
1174  * and default: no failure message.
1175  */
1176 static struct fmesg nullmsg[] = {
1177 	-1,	""
1178 };
1179 
1180 /*
1181  * Interrupt code table.
1182  */
1183 static struct errmsg {
1184 	int	e_code;
1185 	char	*e_mesg;
1186 	struct	fmesg *e_fmesg;
1187 } errmsg[] = {
1188 	MTER_BOT,	"unexpected BOT",	botmsg,
1189 	MTER_LEOT,	"unexpected LEOT",	nullmsg,
1190 	MTER_RWDING,	"tape rewinding",	nullmsg,
1191 	MTER_NOTRDY,	"drive not ready",	notrdymsg,
1192 	MTER_NOTAVL,	"drive not available",	nullmsg,
1193 	MTER_NONEX,	"unit does not exist",	nullmsg,
1194 	MTER_NOTCAP,	"not capable",		notcapmsg,
1195 	MTER_LONGREC,	"long record",		longrecmsg,
1196 	MTER_UNREAD,	"unreadable record",	code22msg,
1197 	MTER_ERROR,	"error",		code22msg,
1198 	MTER_EOTERR,	"EOT error",		code22msg,
1199 	MTER_BADTAPE,	"tape position lost",	code22msg,
1200 	MTER_TMFLTA,	"TM fault A",		tmfltamsg,
1201 	MTER_TUFLTA,	"TU fault A",		tufltamsg,
1202 	MTER_TMFLTB,	"TM fault B",		tmfltbmsg,
1203 	MTER_MBFLT,	"MB fault",		mbfltmsg,
1204 	MTER_KEYFAIL,	"keypad entry error",	nullmsg,
1205 	-1,		"unclassified error",	nullmsg
1206 };
1207 
1208 /*
1209  * Decode an interrupt-time failure.
1210  */
1211 mtintfail(erreg)
1212 	int erreg;
1213 {
1214 	register struct errmsg *e;
1215 	register struct fmesg *f;
1216 	register int ecode, fcode;
1217 
1218 	ecode = erreg & MTER_INTCODE;
1219 	fcode = (erreg & MTER_FAILCODE) >> MTER_FSHIFT;
1220 	for (e = errmsg; e->e_code >= 0; e++)
1221 		if (e->e_code == ecode)
1222 			break;
1223 	for (f = e->e_fmesg; f->f_code >= 0; f++)
1224 		if (f->f_code == fcode)
1225 			break;
1226 	printf("    interrupt code = 0%o <%s>\n", ecode, e->e_mesg);
1227 	printf("    failure code = 0%o <%s>\n", fcode, f->f_mesg);
1228 }
1229 #endif /* MTLERRM */
1230 #endif /* NMT > 0 */
1231