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