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