change printf error messages to tprintf's.
[unix-history] / usr / src / sys / vax / mba / mt.c
CommitLineData
48165e7b 1/* mt.c 6.4 85/03/13 */
83d7e407
BJ
2
3#include "mu.h"
4#if NMT > 0
5/*
6 * TM78/TU78 tape driver
7 *
c0bb0291
KM
8 * Original author - ?
9 * Most error recovery bug fixes - ggs (ulysses!ggs)
10 *
11 * OPTIONS:
12 * MTLERRM - Long error message text - twd, Brown University
13 * MTRDREV - `read reverse' error recovery - ggs (ulysses!ggs)
83d7e407
BJ
14 *
15 * TODO:
c0bb0291
KM
16 * Add odd byte count kludge from VMS driver (?)
17 * Write dump routine
83d7e407 18 */
c0bb0291 19
961945a8
SL
20#include "../machine/pte.h"
21
969e52ef
JB
22#include "param.h"
23#include "systm.h"
24#include "buf.h"
25#include "conf.h"
26#include "dir.h"
27#include "file.h"
28#include "user.h"
29#include "map.h"
30#include "ioctl.h"
31#include "mtio.h"
32#include "cmap.h"
33#include "uio.h"
48165e7b 34#include "tty.h"
83d7e407 35
c895c266 36#include "../vax/cpu.h"
969e52ef
JB
37#include "mbareg.h"
38#include "mbavar.h"
39#include "mtreg.h"
83d7e407 40
c0bb0291
KM
41#define MTTIMEOUT 10000 /* loop limit for controller test */
42#define INF 1000000L /* a block number that won't exist */
43#define MASKREG(r) ((r) & 0xffff) /* the control registers have 16 bits */
83d7e407 44
c0bb0291
KM
45/* Bits for sc_flags */
46
47#define H_WRITTEN 01 /* last operation was a write */
48#define H_EOT 02 /* end of tape encountered */
49#define H_IEOT 04 /* ignore EOT condition */
83d7e407 50
c0bb0291 51/* Bits in minor device */
83d7e407 52
83d7e407
BJ
53#define MUUNIT(dev) (minor(dev)&03)
54#define H_NOREWIND 04
c0bb0291 55#define H_6250BPI 010
83d7e407
BJ
56
57#define MTUNIT(dev) (mutomt[MUUNIT(dev)])
58
c0bb0291
KM
59#ifdef MTRDREV
60 int mt_do_readrev = 1;
61#else
62 int mt_do_readrev = 0;
63#endif
64
65/* Per unit status information */
83d7e407
BJ
66
67struct mu_softc {
c0bb0291
KM
68 char sc_openf; /* unit is open if != 0 */
69 char sc_flags; /* state flags */
70 daddr_t sc_blkno; /* current physical block number */
71 daddr_t sc_nxrec; /* firewall input block number */
72 u_short sc_erreg; /* copy of mter or mtner */
73 u_short sc_dsreg; /* copy of mtds */
74 short sc_resid; /* residual function count for ioctl */
75 short sc_dens; /* density code - MT_GCR or zero */
76 struct mba_device *sc_mi; /* massbus structure for unit */
77 int sc_slave; /* slave number for unit */
78 int sc_i_mtas; /* mtas at slave attach time */
79 int sc_i_mtner; /* mtner at slave attach time */
80 int sc_i_mtds; /* mtds at slave attach time */
81#ifdef MTLERRM
82 char *sc_mesg; /* text for interrupt type code */
83 char *sc_fmesg; /* text for tape error code */
84#endif
48165e7b 85 struct tty *sc_ttyp; /* record user's tty for errors */
83d7e407 86} mu_softc[NMU];
83d7e407 87
c0bb0291
KM
88struct buf rmtbuf[NMT]; /* data transfer buffer structures */
89struct buf cmtbuf[NMT]; /* tape command buffer structures */
83d7e407 90
c0bb0291
KM
91struct mba_device *mtinfo[NMT]; /* unit massbus structure pointers */
92short mutomt[NMU]; /* tape unit to controller number map */
93char mtds_bits[] = MTDS_BITS; /* mtds bit names for error messages */
94short mttypes[] = { MBDT_TU78, 0 };
95
96int mtattach(), mtslave(), mtustart(), mtstart(), mtndtint(), mtdtint();
97struct mba_driver mtdriver =
98 { mtattach, mtslave, mtustart, mtstart, mtdtint, mtndtint,
99 mttypes, "mt", "mu", mtinfo };
100
101void mtcreset();
83d7e407
BJ
102
103/*ARGSUSED*/
104mtattach(mi)
105 struct mba_device *mi;
106{
c0bb0291
KM
107#ifdef lint
108 mtread(0); mtwrite(0); mtioctl(0, 0, 0, 0);
109#endif
83d7e407
BJ
110}
111
51250c66 112mtslave(mi, ms, sn)
83d7e407
BJ
113 struct mba_device *mi;
114 struct mba_slave *ms;
51250c66 115 int sn;
83d7e407
BJ
116{
117 register struct mu_softc *sc = &mu_softc[ms->ms_unit];
118 register struct mtdevice *mtaddr = (struct mtdevice *)mi->mi_drv;
c0bb0291
KM
119 int s = spl7(), rtn = 0, i;
120
121 /* Just in case the controller is ill, reset it. Then issue */
122 /* a sense operation and wait about a second for it to respond. */
83d7e407 123
c0bb0291 124 mtcreset(mtaddr);
83d7e407 125 mtaddr->mtas = -1;
51250c66 126 mtaddr->mtncs[sn] = MT_SENSE|MT_GO;
c0bb0291
KM
127 for (i = MTTIMEOUT; i> 0; i--) {
128 DELAY(50);
129 if (MASKREG(mtaddr->mtas) != 0)
130 break;
131 }
132 sc->sc_i_mtas = mtaddr->mtas;
133 sc->sc_i_mtner = mtaddr->mtner;
134 sc->sc_i_mtds = mtaddr->mtds;
135
136 /* If no response, whimper. If wrong response, call it an */
137 /* unsolicited interrupt and use mtndtint to log and correct. */
138 /* Otherwise, note whether this slave exists. */
139
140 if (i <= 0) {
141 printf("mt: controller hung\n");
142 } else if ((mtaddr->mtner & MTER_INTCODE) != MTER_DONE) {
143 (void) mtndtint(mi);
144 } else if (mtaddr->mtds & MTDS_PRES) {
83d7e407 145 sc->sc_mi = mi;
51250c66 146 sc->sc_slave = sn;
83d7e407
BJ
147 mutomt[ms->ms_unit] = mi->mi_unit;
148 rtn = 1;
149 }
c0bb0291
KM
150
151 /* Cancel the interrupt, then wait a little while for it to go away. */
152
83d7e407 153 mtaddr->mtas = mtaddr->mtas;
c0bb0291 154 DELAY(10);
83d7e407
BJ
155 splx(s);
156 return (rtn);
157}
158
159mtopen(dev, flag)
160 dev_t dev;
161 int flag;
162{
163 register int muunit;
164 register struct mba_device *mi;
165 register struct mu_softc *sc;
83d7e407
BJ
166
167 muunit = MUUNIT(dev);
c0bb0291
KM
168 if ( (muunit >= NMU)
169 || ((mi = mtinfo[MTUNIT(dev)]) == 0)
170 || (mi->mi_alive == 0) )
473a2e47 171 return (ENXIO);
c0bb0291
KM
172 if ((sc = &mu_softc[muunit])->sc_openf)
173 return (EBUSY);
174 sc->sc_dens = (minor(dev) & H_6250BPI) ? MT_GCR : 0;
83d7e407 175 mtcommand(dev, MT_SENSE, 1);
83d7e407
BJ
176 if ((sc->sc_dsreg & MTDS_ONL) == 0) {
177 uprintf("mu%d: not online\n", muunit);
473a2e47 178 return (EIO);
83d7e407 179 }
c0bb0291
KM
180 if ((sc->sc_dsreg & MTDS_AVAIL) == 0) {
181 uprintf("mu%d: not online (port selector)\n", muunit);
182 return (EIO);
183 }
184 if ((flag & FWRITE) && (sc->sc_dsreg & MTDS_FPT)) {
83d7e407 185 uprintf("mu%d: no write ring\n", muunit);
473a2e47 186 return (EIO);
83d7e407 187 }
c0bb0291
KM
188 if ( ((sc->sc_dsreg & MTDS_BOT) == 0)
189 && (flag & FWRITE)
190 && ( ( (sc->sc_dens == MT_GCR)
191 && (sc->sc_dsreg & MTDS_PE) )
192 || ( (sc->sc_dens != MT_GCR)
193 && ((sc->sc_dsreg & MTDS_PE) == 0)))) {
83d7e407 194 uprintf("mu%d: can't change density in mid-tape\n", muunit);
473a2e47 195 return (EIO);
83d7e407
BJ
196 }
197 sc->sc_openf = 1;
198 sc->sc_blkno = (daddr_t)0;
c0bb0291
KM
199
200 /* Since cooked I/O may do a read-ahead before a write, trash */
201 /* on a tape can make the first write fail. Suppress the first */
202 /* read-ahead unless definitely doing read-write */
203
204 sc->sc_nxrec = ((flag & (FTRUNC | FWRITE)) == (FTRUNC | FWRITE))
205 ? (daddr_t)0
206 : (daddr_t)INF;
83d7e407 207 sc->sc_flags = 0;
48165e7b 208 sc->sc_ttyp = u.u_ttyp;
473a2e47 209 return (0);
83d7e407
BJ
210}
211
212mtclose(dev, flag)
213 register dev_t dev;
c0bb0291 214 register int flag;
83d7e407
BJ
215{
216 register struct mu_softc *sc = &mu_softc[MUUNIT(dev)];
217
c0bb0291
KM
218 if ( ((flag & (FREAD | FWRITE)) == FWRITE)
219 || ( (flag & FWRITE)
220 && (sc->sc_flags & H_WRITTEN) ))
83d7e407 221 mtcommand(dev, MT_CLS|sc->sc_dens, 1);
c0bb0291 222 if ((minor(dev) & H_NOREWIND) == 0)
83d7e407
BJ
223 mtcommand(dev, MT_REW, 0);
224 sc->sc_openf = 0;
225}
226
227mtcommand(dev, com, count)
228 dev_t dev;
229 int com, count;
230{
231 register struct buf *bp;
2311123d 232 register int s;
83d7e407
BJ
233
234 bp = &cmtbuf[MTUNIT(dev)];
2311123d 235 s = spl5();
c0bb0291
KM
236 while (bp->b_flags & B_BUSY) {
237 if((bp->b_repcnt == 0) && (bp->b_flags & B_DONE))
83d7e407
BJ
238 break;
239 bp->b_flags |= B_WANTED;
240 sleep((caddr_t)bp, PRIBIO);
241 }
242 bp->b_flags = B_BUSY|B_READ;
2311123d 243 splx(s);
83d7e407
BJ
244 bp->b_dev = dev;
245 bp->b_command = com;
246 bp->b_repcnt = count;
247 bp->b_blkno = 0;
c0bb0291 248 bp->b_error = 0;
83d7e407
BJ
249 mtstrategy(bp);
250 if (count == 0)
251 return;
252 iowait(bp);
c0bb0291 253 if (bp->b_flags & B_WANTED)
83d7e407
BJ
254 wakeup((caddr_t)bp);
255 bp->b_flags &= B_ERROR;
256}
257
258mtstrategy(bp)
259 register struct buf *bp;
260{
261 register struct mba_device *mi = mtinfo[MTUNIT(bp->b_dev)];
262 register struct buf *dp;
2311123d 263 register int s;
83d7e407 264
c0bb0291
KM
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 /* Link this request onto the end of the queue for this */
273 /* controller, then start I/O if not already active. */
274
83d7e407
BJ
275 bp->av_forw = NULL;
276 dp = &mi->mi_tab;
2311123d 277 s = spl5();
83d7e407
BJ
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);
2311123d 285 splx(s);
83d7e407
BJ
286}
287
288mtustart(mi)
289 register struct mba_device *mi;
290{
c0bb0291 291 register struct mtdevice *mtaddr = (struct mtdevice *)mi->mi_drv;
83d7e407
BJ
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
83d7e407
BJ
296 if (sc->sc_openf < 0) {
297 bp->b_flags |= B_ERROR;
298 return (MBU_NEXT);
299 }
300 if (bp != &cmtbuf[MTUNIT(bp->b_dev)]) {
c0bb0291
KM
301
302 /* Signal "no space" if out of tape unless suppressed */
303 /* by MTIOCIEOT. */
304
305 if ( ((sc->sc_flags & (H_EOT | H_IEOT)) == H_EOT)
306 && ((bp->b_flags & B_READ) == 0) ) {
83d7e407 307 bp->b_flags |= B_ERROR;
c0bb0291 308 bp->b_error = ENOSPC;
83d7e407
BJ
309 return (MBU_NEXT);
310 }
c0bb0291
KM
311
312 /* special case tests for cooked mode */
313
314 if (bp != &rmtbuf[MTUNIT(bp->b_dev)]) {
315
316 /* seek beyond end of file */
317
318 if (bdbtofsb(bp->b_blkno) > sc->sc_nxrec) {
319 bp->b_flags |= B_ERROR;
320 bp->b_error = ENXIO;
321 return (MBU_NEXT);
322 }
323
324 /* This should be end of file, but the buffer */
325 /* system wants a one-block look-ahead. Humor it. */
326
327 if ( (bdbtofsb(bp->b_blkno) == sc->sc_nxrec)
328 && (bp->b_flags & B_READ) ) {
329 clrbuf(bp);
330 return (MBU_NEXT);
331 }
332
333 /* If writing, mark the next block invalid. */
334
335 if ((bp->b_flags & B_READ) == 0)
336 sc->sc_nxrec = bdbtofsb(bp->b_blkno) + 1;
83d7e407 337 }
83d7e407 338 } else {
c0bb0291
KM
339
340 /* It's a command, do it now. */
341
83d7e407
BJ
342 mtaddr->mtncs[MUUNIT(bp->b_dev)] =
343 (bp->b_repcnt<<8)|bp->b_command|MT_GO;
344 return (MBU_STARTED);
345 }
c0bb0291
KM
346
347 /* If raw I/O, or if the tape is positioned correctly for */
348 /* cooked I/O, set the byte count, unit number and repeat count */
349 /* then tell the MASSBUS to proceed. Note that a negative */
350 /* bcount tells mbstart to map the buffer for "read backwards". */
351
352 if ( (bp == &rmtbuf[MTUNIT(bp->b_dev)])
353 || ((blkno = sc->sc_blkno) == bdbtofsb(bp->b_blkno)) ) {
83d7e407 354 if (mi->mi_tab.b_errcnt == 2) {
c0bb0291 355 mtaddr->mtbc = -(bp->b_bcount);
83d7e407
BJ
356 mtaddr->mtca = MUUNIT(bp->b_dev);
357 } else {
358 mtaddr->mtbc = bp->b_bcount;
359 mtaddr->mtca = (1<<2)|MUUNIT(bp->b_dev);
360 }
361 return (MBU_DODATA);
362 }
c0bb0291
KM
363
364 /* Issue skip operations to position the next block for cooked I/O. */
365
43d66181 366 if (blkno < bdbtofsb(bp->b_blkno))
83d7e407 367 mtaddr->mtncs[MUUNIT(bp->b_dev)] =
43d66181 368 (min((unsigned)(bdbtofsb(bp->b_blkno) - blkno), 0377) << 8) |
155d9ff0 369 MT_SFORW|MT_GO;
83d7e407
BJ
370 else
371 mtaddr->mtncs[MUUNIT(bp->b_dev)] =
43d66181 372 (min((unsigned)(blkno - bdbtofsb(bp->b_blkno)), 0377) << 8) |
155d9ff0 373 MT_SREV|MT_GO;
83d7e407
BJ
374 return (MBU_STARTED);
375}
376
377mtstart(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
392mtdtint(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;
c0bb0291
KM
399 register int er;
400
401 /* I'M still NOT SURE IF THIS SHOULD ALWAYS BE THE CASE SO FOR NOW... */
83d7e407 402
c0bb0291 403 if ((mtaddr->mtca & 3) != MUUNIT(bp->b_dev)) {
83d7e407
BJ
404 printf("mt: wrong unit!\n");
405 mtaddr->mtca = MUUNIT(bp->b_dev);
406 }
c0bb0291
KM
407
408 er = MASKREG(mtaddr->mter);
83d7e407 409 sc = &mu_softc[MUUNIT(bp->b_dev)];
c0bb0291
KM
410 sc->sc_erreg = er;
411 if (bp->b_flags & B_READ)
412 sc->sc_flags &= ~H_WRITTEN;
413 else
83d7e407 414 sc->sc_flags |= H_WRITTEN;
c0bb0291
KM
415 switch (er & MTER_INTCODE) {
416
417 case MTER_EOT:
418 sc->sc_flags |= H_EOT;
419
420 /* fall into MTER_DONE */
421
83d7e407 422 case MTER_DONE:
c0bb0291
KM
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)
428 && (bp != &rmtbuf[MTUNIT(bp->b_dev)]) )
429 bp->b_flags |= B_ERROR;
430 } else {
431 bp->b_resid = 0;
432 }
433 break;
434
435 case MTER_SHRTREC:
436 sc->sc_blkno++;
437 bp->b_bcount = bp->b_resid;
438 bp->b_resid -= MASKREG(mtaddr->mtbc);
439 if (bp != &rmtbuf[MTUNIT(bp->b_dev)])
440 bp->b_flags |= B_ERROR;
441 break;
442
443 case MTER_RETRY:
444
445 /* Simple re-try. Since resid is always a copy of the */
446 /* original byte count, use it to restore the count. */
447
448 mi->mi_tab.b_errcnt = 1;
449 bp->b_bcount = bp->b_resid;
450 return(MBD_RETRY);
451
452 case MTER_RDOPP:
453
454 /* The controller just decided to read it backwards. */
455 /* If the controller returns a byte count of zero, */
456 /* change it to 1, since zero encodes 65536, which */
457 /* isn't quite what we had in mind. The byte count */
458 /* may be larger than the size of the input buffer, so */
459 /* limit the count to the buffer size. After */
460 /* making the byte count reasonable, set bcount to the */
461 /* negative of the controller's version of the byte */
462 /* count so that the start address for the transfer is */
463 /* set up correctly. */
464
465 if (mt_do_readrev) {
466 mi->mi_tab.b_errcnt = 2;
467 if ((bp->b_bcount = MASKREG(mtaddr->mtbc)) == 0)
468 bp->b_bcount = 1;
469 if (bp->b_bcount > bp->b_resid)
470 bp->b_bcount = bp->b_resid;
471 bp->b_bcount = -(bp->b_bcount);
472 return(MBD_RETRY);
473 } else if (MASKREG(mtaddr->mtbc) <= bp->b_resid) {
83d7e407 474 sc->sc_blkno++;
c0bb0291
KM
475 bp->b_bcount = bp->b_resid;
476 bp->b_resid -= MASKREG(mtaddr->mtbc);
477 bp->b_flags |= B_ERROR;
478 break;
479 }
480 bp->b_flags |= B_ERROR;
481
482 /* fall into MTER_LONGREC */
483
484 case MTER_LONGREC:
485 sc->sc_blkno++;
486 bp->b_bcount = bp->b_resid;
83d7e407 487 bp->b_resid = 0;
c0bb0291
KM
488 bp->b_error = ENOMEM;
489 bp->b_flags |= B_ERROR;
83d7e407
BJ
490 break;
491
492 case MTER_NOTCAP:
493 printf("mu%d: blank tape\n", MUUNIT(bp->b_dev));
494 goto err;
495
496 case MTER_TM:
83d7e407 497
c0bb0291
KM
498 /* End of file. Since the default byte count has */
499 /* already been set, just count the block and proceed. */
500
83d7e407 501 sc->sc_blkno++;
c0bb0291 502 err:
83d7e407 503 if (bp != &rmtbuf[MTUNIT(bp->b_dev)])
c0bb0291 504 sc->sc_nxrec = bdbtofsb(bp->b_blkno);
83d7e407
BJ
505 break;
506
83d7e407
BJ
507 case MTER_OFFLINE:
508 if (sc->sc_openf > 0) {
509 sc->sc_openf = -1;
48165e7b 510 tprintf(sc->sc_ttyp, "mu%d: offline\n", MUUNIT(bp->b_dev));
83d7e407
BJ
511 }
512 bp->b_flags |= B_ERROR;
513 break;
514
c0bb0291
KM
515 case MTER_NOTAVL:
516 if (sc->sc_openf > 0) {
517 sc->sc_openf = -1;
48165e7b
RC
518 tprintf(sc->sc_ttyp, "mu%d: offline (port selector)\n",
519 MUUNIT(bp->b_dev));
c0bb0291
KM
520 }
521 bp->b_flags |= B_ERROR;
522 break;
523
83d7e407 524 case MTER_FPT:
48165e7b 525 tprintf(sc->sc_ttyp, "mu%d: no write ring\n", MUUNIT(bp->b_dev));
83d7e407
BJ
526 bp->b_flags |= B_ERROR;
527 break;
528
c0bb0291
KM
529 case MTER_UNREAD:
530 sc->sc_blkno++;
531 bp->b_bcount = bp->b_resid;
532 bp->b_resid -= MIN(MASKREG(mtaddr->mtbc), bp->b_bcount);
533
534 /* Code 010 means a garbage record, nothing serious. */
535
536 if (((er & MTER_FAILCODE) >> 10) == 010) {
48165e7b 537 tprintf(sc->sc_ttyp, "mu%d: rn=%d bn=%d unreadable record\n",
c0bb0291
KM
538 MUUNIT(bp->b_dev), sc->sc_blkno, bp->b_blkno);
539 bp->b_flags |= B_ERROR;
540 break;
541 }
542
543 /* Anything else might be a hardware problem, */
544 /* fall into the error report. */
545
83d7e407 546 default:
c0bb0291
KM
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
48165e7b 554 tprintf(sc->sc_ttyp, "mu%d: hard error (data transfer) rn=%d bn=%d mbsr=%b er=%o (octal) ds=%b\n",
c0bb0291
KM
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(sc);
560 printf(" interrupt code = %o (octal) <%s>\n failure code = %o (octal) <%s>\n",
561 er & MTER_INTCODE, sc->sc_mesg,
562 (er & MTER_FAILCODE) >> 10, sc->sc_fmesg);
563#endif
83d7e407 564 bp->b_flags |= B_ERROR;
c0bb0291
KM
565
566 /* The TM78 manual says to reset the controller after */
567 /* TM fault B or MASSBUS fault. */
568
569 if ( ((er & MTER_INTCODE) == MTER_TMFLTB)
570 || ((er & MTER_INTCODE) == MTER_MBFLT) ) {
571 mtcreset(mtaddr);
572 }
83d7e407 573 }
c0bb0291
KM
574
575 /* Just in case some strange error slipped through, (drive off */
576 /* line during read-reverse error recovery comes to mind) make */
577 /* sure the byte count is reasonable. */
578
579 if (bp->b_bcount < 0)
580 bp->b_bcount = bp->b_resid;
83d7e407
BJ
581 return (MBD_DONE);
582}
583
584mtndtint(mi)
585 register struct mba_device *mi;
586{
587 register struct mtdevice *mtaddr = (struct mtdevice *)mi->mi_drv;
588 register struct buf *bp = mi->mi_tab.b_actf;
589 register struct mu_softc *sc;
c0bb0291
KM
590 register int er, fc;
591 int unit;
83d7e407
BJ
592
593 unit = (mtaddr->mtner >> 8) & 3;
594 er = MASKREG(mtaddr->mtner);
c0bb0291
KM
595 sc = &mu_softc[unit];
596 sc->sc_erreg = er;
597
598 /* Check for unsolicited interrupts. */
599
83d7e407 600 if (bp == 0 || unit != MUUNIT(bp->b_dev)) { /* consistency check */
c0bb0291
KM
601 if ((er & MTER_INTCODE) != MTER_ONLINE) {
602 printf("mt: unit %d unexpected interrupt (non data transfer) er=%o (octal) ds=%b\n",
603 unit, er, MASKREG(sc->sc_dsreg), mtds_bits);
604#ifdef MTLERRM
605 mtintfail(sc);
606 printf(" interrupt code = %o (octal) <%s>\n failure code = %o (octal) <%s>\n",
607 er & MTER_INTCODE, sc->sc_mesg,
608 (er & MTER_FAILCODE) >> 10, sc->sc_fmesg);
609#endif
610 if ( ((er & MTER_INTCODE) == MTER_TMFLTB)
611 || ((er & MTER_INTCODE) == MTER_MBFLT) ) {
612
613 /* Reset the controller, then set error */
614 /* status if there was anything active */
615 /* when the fault occurred. This may */
616 /* shoot an innocent bystander, but */
617 /* it's better than letting an error */
618 /* slip through. */
619
620 mtcreset(mtaddr);
621 if (bp != 0) {
622 bp->b_flags |= B_ERROR;
623 return (MBN_DONE);
624 }
625 }
626 }
83d7e407
BJ
627 return (MBN_SKIP);
628 }
629 if (bp == 0)
630 return (MBN_SKIP);
c0bb0291 631
83d7e407 632 fc = (mtaddr->mtncs[unit] >> 8) & 0xff;
83d7e407 633 sc->sc_resid = fc;
c0bb0291
KM
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)])
639 || (bp->b_command != MT_SENSE) )
640 sc->sc_flags &= ~H_WRITTEN;
641
83d7e407 642 switch (er & MTER_INTCODE) {
c0bb0291
KM
643
644 case MTER_EOT:
645 sc->sc_flags |= H_EOT;
646
647 /* fall into MTER_DONE */
648
83d7e407 649 case MTER_DONE:
c0bb0291
KM
650
651 /* If this is a command buffer, just update the status. */
652
83d7e407
BJ
653 if (bp == &cmtbuf[MTUNIT(bp->b_dev)]) {
654 done:
655 if (bp->b_command == MT_SENSE)
656 sc->sc_dsreg = MASKREG(mtaddr->mtds);
83d7e407
BJ
657 return (MBN_DONE);
658 }
c0bb0291
KM
659
660 /* It's not a command buffer, must be a cooked I/O */
661 /* skip operation (perhaps a shaky assumption, but it */
662 /* wasn't my idea). */
663
43d66181 664 if ((fc = bdbtofsb(bp->b_blkno) - sc->sc_blkno) < 0)
155d9ff0 665 sc->sc_blkno -= MIN(0377, -fc);
83d7e407 666 else
155d9ff0 667 sc->sc_blkno += MIN(0377, fc);
83d7e407
BJ
668 return (MBN_RETRY);
669
c0bb0291 670 case MTER_ONLINE: /* ddj -- shouldn't happen but did */
83d7e407
BJ
671 case MTER_RWDING:
672 return (MBN_SKIP); /* ignore "rewind started" interrupt */
673
674 case MTER_NOTCAP:
48165e7b 675 tprintf(sc->sc_ttyp, "mu%d: blank tape\n", MUUNIT(bp->b_dev));
c0bb0291
KM
676 bp->b_flags |= B_ERROR;
677 return (MBN_DONE);
83d7e407
BJ
678
679 case MTER_TM:
83d7e407 680 case MTER_LEOT:
c0bb0291
KM
681
682 /* For an ioctl skip operation, count a tape mark as */
683 /* a record. If there's anything left to do, update */
684 /* the repeat count and re-start the command. */
685
686 if (bp == &cmtbuf[MTUNIT(bp->b_dev)]) {
687 if ((sc->sc_resid = bp->b_repcnt = fc - 1) == 0)
688 return (MBN_DONE);
689 else
690 return (MBN_RETRY);
691
692 /* Cooked I/O again. Just update the books and wait */
693 /* for someone else to return end of file or complain */
694 /* about a bad seek. */
695
696 } else if (sc->sc_blkno > bdbtofsb(bp->b_blkno)) {
697 sc->sc_nxrec = bdbtofsb(bp->b_blkno) + fc - 1;
83d7e407
BJ
698 sc->sc_blkno = sc->sc_nxrec;
699 } else {
c0bb0291
KM
700 sc->sc_nxrec = bdbtofsb(bp->b_blkno) - fc;
701 sc->sc_blkno = sc->sc_nxrec + 1;
83d7e407
BJ
702 }
703 return (MBN_RETRY);
704
705 case MTER_FPT:
48165e7b 706 tprintf(sc->sc_ttyp, "mu%d: no write ring\n", MUUNIT(bp->b_dev));
83d7e407
BJ
707 bp->b_flags |= B_ERROR;
708 return (MBN_DONE);
709
710 case MTER_OFFLINE:
c0bb0291
KM
711
712 /* If `off line' was intentional, don't complain. */
713
714 if ( (bp == &cmtbuf[MTUNIT(bp->b_dev)])
715 && (bp->b_command == MT_UNLOAD) )
716 return(MBN_DONE);
83d7e407
BJ
717 if (sc->sc_openf > 0) {
718 sc->sc_openf = -1;
48165e7b 719 tprintf(sc->sc_ttyp, "mu%d: offline\n", MUUNIT(bp->b_dev));
83d7e407
BJ
720 }
721 bp->b_flags |= B_ERROR;
722 return (MBN_DONE);
723
c0bb0291
KM
724 case MTER_NOTAVL:
725 if (sc->sc_openf > 0) {
726 sc->sc_openf = -1;
48165e7b 727 tprintf(sc->sc_ttyp, "mu%d: offline (port selector)\n", MUUNIT(bp->b_dev));
c0bb0291
KM
728 }
729 bp->b_flags |= B_ERROR;
730 return (MBN_DONE);
731
83d7e407
BJ
732 case MTER_BOT:
733 if (bp == &cmtbuf[MTUNIT(bp->b_dev)])
734 goto done;
c0bb0291
KM
735
736 /* fall through */
83d7e407
BJ
737
738 default:
48165e7b 739 tprintf(sc->sc_ttyp, "mu%d: hard error (non data transfer) rn=%d bn=%d er=%o (octal) ds=%b\n",
c0bb0291
KM
740 MUUNIT(bp->b_dev), sc->sc_blkno, bp->b_blkno,
741 er, MASKREG(sc->sc_dsreg), mtds_bits);
742#ifdef MTLERRM
743 mtintfail(sc);
744 printf(" interrupt code = %o (octal) <%s>\n failure code = %o (octal) <%s>\n",
745 (er & MTER_INTCODE), sc->sc_mesg,
746 (er & MTER_FAILCODE) >> 10, sc->sc_fmesg);
747#endif
748 if ( ((er & MTER_INTCODE) == MTER_TMFLTB)
749 || ((er & MTER_INTCODE) == MTER_MBFLT) ) {
750 mtcreset(mtaddr); /* reset the controller */
751 }
83d7e407
BJ
752 bp->b_flags |= B_ERROR;
753 return (MBN_DONE);
754 }
755 /* NOTREACHED */
756}
757
c0bb0291
KM
758void mtcreset(mtaddr)
759 register struct mtdevice *mtaddr;
760{
761 register int i;
762
763 mtaddr->mtid = MTID_CLR; /* reset the TM78 */
764 DELAY(200);
765 for (i = MTTIMEOUT; i > 0; i--) {
766 DELAY(50); /* don't nag */
767 if ((mtaddr->mtid & MTID_RDY) != 0)
768 return; /* exit when ready */
769 }
770 printf("mt: controller hung\n");
771}
772
deb8980a 773mtread(dev, uio)
83d7e407 774 dev_t dev;
deb8980a 775 struct uio *uio;
83d7e407 776{
23458a62 777 int errno;
83d7e407 778
23458a62
BJ
779 errno = mtphys(dev, uio);
780 if (errno)
781 return (errno);
782 return (physio(mtstrategy, &rmtbuf[MTUNIT(dev)], dev, B_READ, minphys, uio));
83d7e407
BJ
783}
784
c0bb0291 785
406ddcbe
BJ
786mtwrite(dev, uio)
787 dev_t dev;
788 struct uio *uio;
83d7e407 789{
23458a62 790 int errno;
83d7e407 791
23458a62
BJ
792 errno = mtphys(dev, uio);
793 if (errno)
794 return (errno);
795 return (physio(mtstrategy, &rmtbuf[MTUNIT(dev)], dev, B_WRITE, minphys, uio));
83d7e407
BJ
796}
797
deb8980a 798mtphys(dev, uio)
83d7e407 799 dev_t dev;
deb8980a 800 struct uio *uio;
83d7e407
BJ
801{
802 register int mtunit;
c0bb0291
KM
803 struct mba_device *mi;
804 register int bsize = uio->uio_iov->iov_len;
83d7e407
BJ
805
806 mtunit = MTUNIT(dev);
c0bb0291
KM
807 if ( (mtunit >= NMT)
808 || ((mi = mtinfo[mtunit]) == 0)
809 || (mi->mi_alive == 0) )
deb8980a 810 return (ENXIO);
c0bb0291
KM
811 if ( (bsize > 0xffff) /* controller limit */
812 || (bsize <= 0) ) /* ambiguous */
813 return (EINVAL);
deb8980a 814 return (0);
83d7e407
BJ
815}
816
817/*ARGSUSED*/
942f05a9 818mtioctl(dev, cmd, data, flag)
83d7e407
BJ
819 dev_t dev;
820 int cmd;
942f05a9 821 caddr_t data;
83d7e407
BJ
822 int flag;
823{
824 register struct mu_softc *sc = &mu_softc[MUUNIT(dev)];
825 register struct buf *bp = &cmtbuf[MTUNIT(dev)];
c0bb0291
KM
826 register struct mtop *mtop;
827 register struct mtget *mtget;
828 int callcount, fcount;
829 int op;
830
831 /* We depend on the values and order of the MT codes here. */
832
83d7e407
BJ
833 static mtops[] =
834 {MT_WTM,MT_SFORWF,MT_SREVF,MT_SFORW,MT_SREV,MT_REW,MT_UNLOAD,MT_SENSE};
835
836 switch (cmd) {
942f05a9 837
c0bb0291
KM
838 /* tape operation */
839
840 case MTIOCTOP:
2e9f5990
BJ
841 mtop = (struct mtop *)data;
842 switch (mtop->mt_op) {
942f05a9 843
83d7e407 844 case MTWEOF:
942f05a9 845 callcount = mtop->mt_count;
83d7e407
BJ
846 fcount = 1;
847 break;
942f05a9 848
83d7e407 849 case MTFSF: case MTBSF:
942f05a9 850 callcount = mtop->mt_count;
83d7e407
BJ
851 fcount = 1;
852 break;
942f05a9 853
83d7e407
BJ
854 case MTFSR: case MTBSR:
855 callcount = 1;
942f05a9 856 fcount = mtop->mt_count;
83d7e407 857 break;
942f05a9 858
83d7e407
BJ
859 case MTREW: case MTOFFL:
860 callcount = 1;
861 fcount = 1;
862 break;
942f05a9 863
83d7e407 864 default:
473a2e47 865 return (ENXIO);
83d7e407 866 }
c0bb0291 867 if ((callcount <= 0) || (fcount <= 0))
473a2e47 868 return (EINVAL);
942f05a9 869 op = mtops[mtop->mt_op];
83d7e407
BJ
870 if (op == MT_WTM)
871 op |= sc->sc_dens;
872 while (--callcount >= 0) {
c0bb0291 873 register int n, fc = fcount;
83d7e407
BJ
874
875 do {
c0bb0291 876 n = MIN(fc, 0xff);
83d7e407 877 mtcommand(dev, op, n);
c0bb0291
KM
878 n -= sc->sc_resid;
879 fc -= n;
880 switch (mtop->mt_op) {
881
882 case MTWEOF:
883 sc->sc_blkno += (daddr_t)n;
884 sc->sc_nxrec = sc->sc_blkno - 1;
885 break;
886
887 case MTOFFL:
888 case MTREW:
889 case MTFSF:
890 sc->sc_blkno = (daddr_t)0;
891 sc->sc_nxrec = (daddr_t)INF;
892 break;
893
894 case MTBSF:
895 if (sc->sc_resid) {
896 sc->sc_blkno = (daddr_t)0;
897 sc->sc_nxrec = (daddr_t)INF;
898 } else {
899 sc->sc_blkno = (daddr_t)(-1);
900 sc->sc_nxrec = (daddr_t)(-1);
901 }
902 break;
903
904 case MTFSR:
905 sc->sc_blkno += (daddr_t)n;
906 break;
907
908 case MTBSR:
909 sc->sc_blkno -= (daddr_t)n;
910 break;
911 }
912 if (sc->sc_resid)
913 break;
914 } while (fc);
915 if (fc) {
916 sc->sc_resid = callcount + fc;
917 if ( (mtop->mt_op == MTFSR)
918 || (mtop->mt_op == MTBSR) )
919 return (EIO);
920 else
921 break;
922 }
923 if (bp->b_flags & B_ERROR)
83d7e407
BJ
924 break;
925 }
5a1f132a 926 return (geterror(bp));
942f05a9 927
c0bb0291
KM
928 /* tape status */
929
83d7e407 930 case MTIOCGET:
942f05a9
SL
931 mtget = (struct mtget *)data;
932 mtget->mt_erreg = sc->sc_erreg;
933 mtget->mt_resid = sc->sc_resid;
83d7e407 934 mtcommand(dev, MT_SENSE, 1); /* update drive status */
942f05a9
SL
935 mtget->mt_dsreg = sc->sc_dsreg;
936 mtget->mt_type = MT_ISMT;
473a2e47 937 break;
942f05a9 938
c0bb0291
KM
939 /* ignore EOT condition */
940
941 case MTIOCIEOT:
942 sc->sc_flags |= H_IEOT;
943 break;
944
945 /* enable EOT condition */
946
947 case MTIOCEEOT:
948 sc->sc_flags &= ~H_IEOT;
949 break;
950
83d7e407 951 default:
473a2e47 952 return (ENXIO);
83d7e407 953 }
473a2e47 954 return (0);
83d7e407
BJ
955}
956
957#define DBSIZE 20
958
959mtdump()
960{
961 register struct mba_device *mi;
962 register struct mba_regs *mp;
83d7e407
BJ
963 int blk, num;
964 int start;
965
966 start = 0;
967 num = maxfree;
968#define phys(a,b) ((b)((int)(a)&0x7fffffff))
969 if (mtinfo[0] == 0)
970 return (ENXIO);
971 mi = phys(mtinfo[0], struct mba_device *);
972 mp = phys(mi->mi_hd, struct mba_hd *)->mh_physmba;
973 mp->mba_cr = MBCR_IE;
155d9ff0 974#if lint
2e9f5990 975 blk = 0; num = blk; start = num; blk = start;
155d9ff0
SL
976 return (0);
977#endif
83d7e407 978#ifdef notyet
155d9ff0 979 mtaddr = (struct mtdevice *)&mp->mba_drv[mi->mi_drive];
83d7e407
BJ
980 mtaddr->mttc = MTTC_PDP11|MTTC_1600BPI;
981 mtaddr->mtcs1 = MT_DCLR|MT_GO;
982 while (num > 0) {
983 blk = num > DBSIZE ? DBSIZE : num;
984 mtdwrite(start, blk, mtaddr, mp);
985 start += blk;
986 num -= blk;
987 }
988 mteof(mtaddr);
989 mteof(mtaddr);
990 mtwait(mtaddr);
991 if (mtaddr->mtds&MTDS_ERR)
992 return (EIO);
993 mtaddr->mtcs1 = MT_REW|MT_GO;
994 return (0);
995}
996
997mtdwrite(dbuf, num, mtaddr, mp)
998 register dbuf, num;
999 register struct mtdevice *mtaddr;
1000 struct mba_regs *mp;
1001{
1002 register struct pte *io;
1003 register int i;
1004
1005 mtwait(mtaddr);
1006 io = mp->mba_map;
1007 for (i = 0; i < num; i++)
1008 *(int *)io++ = dbuf++ | PG_V;
1009 mtaddr->mtfc = -(num*NBPG);
1010 mp->mba_sr = -1;
1011 mp->mba_bcr = -(num*NBPG);
1012 mp->mba_var = 0;
1013 mtaddr->mtcs1 = MT_WCOM|MT_GO;
1014}
1015
1016mtwait(mtaddr)
1017 struct mtdevice *mtaddr;
1018{
1019 register s;
1020
1021 do
1022 s = mtaddr->mtds;
1023 while ((s & MTDS_DRY) == 0);
1024}
1025
1026mteof(mtaddr)
1027 struct mtdevice *mtaddr;
1028{
1029
1030 mtwait(mtaddr);
1031 mtaddr->mtcs1 = MT_WEOF|MT_GO;
1032#endif notyet
1033}
c0bb0291
KM
1034
1035#ifdef MTLERRM
1036mtintfail(sc)
1037 register struct mu_softc *sc;
1038{
1039 switch (sc->sc_erreg & MTER_INTCODE) {
1040
1041 /* unexpected BOT detected */
1042
1043 case MTER_BOT:
1044 sc->sc_mesg = "unexpected BOT";
1045 switch ((sc->sc_erreg & MTER_FAILCODE) >> 10) {
1046 case 01:
1047 sc->sc_fmesg = "tape was at BOT";
1048 break;
1049 case 02:
1050 sc->sc_fmesg = "BOT seen after tape started";
1051 break;
1052 case 03:
1053 sc->sc_fmesg = "ARA ID detected";
1054 break;
1055 default:
1056 sc->sc_fmesg = "unclassified failure code";
1057 }
1058 break;
1059
1060 /* unexpected LEOT detected */
1061
1062 case MTER_LEOT:
1063 sc->sc_mesg = "unexpected LEOT";
1064 sc->sc_fmesg = "";
1065 break;
1066
1067 /* rewinding */
1068
1069 case MTER_RWDING:
1070 sc->sc_mesg = "tape rewinding";
1071 sc->sc_fmesg = "";
1072 break;
1073
1074 /* not ready */
1075
1076 case MTER_NOTRDY:
1077 sc->sc_mesg = "drive not ready";
1078 switch ((sc->sc_erreg & MTER_FAILCODE) >> 10) {
1079 case 01:
1080 sc->sc_fmesg = "TU on-line but not ready";
1081 break;
1082 case 02:
1083 sc->sc_fmesg = "fatal error has occurred";
1084 break;
1085 case 03:
1086 sc->sc_fmesg = "access allowed but not really";
1087 break;
1088 default:
1089 sc->sc_fmesg = "unclassified failure code";
1090 }
1091 break;
1092
1093 /* not available */
1094
1095 case MTER_NOTAVL:
1096 sc->sc_mesg = "drive not available";
1097 sc->sc_fmesg = "";
1098 break;
1099
1100 /* unit does not exist */
1101
1102 case MTER_NONEX:
1103 sc->sc_mesg = "unit does not exist";
1104 sc->sc_fmesg = "";
1105 break;
1106
1107 /* not capable */
1108
1109 case MTER_NOTCAP:
1110 sc->sc_mesg = "not capable";
1111 switch ((sc->sc_erreg & MTER_FAILCODE) >> 10) {
1112 case 01:
1113 sc->sc_fmesg = "no record found within 25 feet";
1114 break;
1115 case 02:
1116 sc->sc_fmesg = "ID burst neither PE nor GCR";
1117 break;
1118 case 03:
1119 sc->sc_fmesg = "ARA ID not found";
1120 break;
1121 case 04:
1122 sc->sc_fmesg = "no gap found after ID burst";
1123 break;
1124 default:
1125 sc->sc_fmesg = "unclassified failure code";
1126 }
1127 break;
1128
1129 /* long tape record */
1130
1131 case MTER_LONGREC:
1132 sc->sc_mesg = "long record";
1133 switch ((sc->sc_erreg & MTER_FAILCODE) >> 10) {
1134 case 00:
1135 sc->sc_fmesg = "extended sense data not found";
1136 break;
1137 case 01:
1138 sc->sc_fmesg = "extended sense data updated";
1139 break;
1140 default:
1141 sc->sc_fmesg = "unclassified failure code";
1142 }
1143 break;
1144
1145 /* unreadable */
1146
1147 case MTER_UNREAD:
1148 sc->sc_mesg = "unreadable record";
1149 goto code22;
1150
1151 /* error */
1152
1153 case MTER_ERROR:
1154 sc->sc_mesg = "error";
1155 goto code22;
1156
1157 /* EOT error */
1158
1159 case MTER_EOTERR:
1160 sc->sc_mesg = "EOT error";
1161 goto code22;
1162
1163 /* tape position lost */
1164
1165 case MTER_BADTAPE:
1166 sc->sc_mesg = "bad tape";
1167 code22:
1168 switch ((sc->sc_erreg & MTER_FAILCODE) >> 10) {
1169 case 01:
1170 sc->sc_fmesg = "GCR write error";
1171 break;
1172 case 02:
1173 sc->sc_fmesg = "GCR read error";
1174 break;
1175 case 03:
1176 sc->sc_fmesg = "PE read error";
1177 break;
1178 case 04:
1179 sc->sc_fmesg = "PE write error";
1180 break;
1181 case 05:
1182 sc->sc_fmesg = "at least 1 bit set in ECCSTA";
1183 break;
1184 case 06:
1185 sc->sc_fmesg = "PE write error";
1186 break;
1187 case 07:
1188 sc->sc_fmesg = "GCR write error";
1189 break;
1190 case 010:
1191 sc->sc_fmesg = "RSTAT contains bad code";
1192 break;
1193 case 011:
1194 sc->sc_fmesg = "PE write error";
1195 break;
1196 case 012:
1197 sc->sc_fmesg = "MASSBUS parity error";
1198 break;
1199 case 013:
1200 sc->sc_fmesg = "invalid data transferred";
1201 break;
1202 default:
1203 sc->sc_fmesg = "unclassified failure code";
1204 }
1205 break;
1206
1207 /* TM fault A */
1208
1209 case MTER_TMFLTA:
1210 sc->sc_mesg = "TM fault A";
1211 switch ((sc->sc_erreg & MTER_FAILCODE) >> 10) {
1212 case 01:
1213 sc->sc_fmesg = "illegal command code";
1214 break;
1215 case 02:
1216 sc->sc_fmesg = "DT command issued when NDT command active";
1217 break;
1218 case 03:
1219 sc->sc_fmesg = "WMC error";
1220 break;
1221 case 04:
1222 sc->sc_fmesg = "RUN not received from MASSBUS controller";
1223 break;
1224 case 05:
1225 sc->sc_fmesg = "mismatch in command read - function routine";
1226 break;
1227 case 06:
1228 sc->sc_fmesg = "ECC ROM parity error";
1229 break;
1230 case 07:
1231 sc->sc_fmesg = "XMC ROM parity error";
1232 break;
1233 case 010:
1234 sc->sc_fmesg = "mismatch in command read - ID burst command";
1235 break;
1236 case 011:
1237 sc->sc_fmesg = "mismatch in command read - verify ARA burst command";
1238 break;
1239 case 012:
1240 sc->sc_fmesg = "mismatch in command read - verify ARA ID command";
1241 break;
1242 case 013:
1243 sc->sc_fmesg = "mismatch in command read - verify gap command";
1244 break;
1245 case 014:
1246 sc->sc_fmesg = "mismatch in command read - read id burst command";
1247 break;
1248 case 015:
1249 sc->sc_fmesg = "mismatch in command read - verify ARA ID command";
1250 break;
1251 case 016:
1252 sc->sc_fmesg = "mismatch in command read - verify gap command";
1253 break;
1254 case 017:
1255 sc->sc_fmesg = "mismatch in command read - find gap command";
1256 break;
1257 case 020:
1258 sc->sc_fmesg = "WMC LEFT failed to set";
1259 break;
1260 case 021:
1261 sc->sc_fmesg = "XL PE set in INTSTA register";
1262 break;
1263 case 022:
1264 sc->sc_fmesg = "XMC DONE did not set";
1265 break;
1266 case 023:
1267 sc->sc_fmesg = "WMC ROM PE or RD PE set in WMCERR register";
1268 break;
1269 default:
1270 sc->sc_fmesg = "unclassified failure code";
1271 }
1272 break;
1273
1274 /* TU fault A */
1275
1276 case MTER_TUFLTA:
1277 sc->sc_mesg = "TU fault A";
1278 switch ((sc->sc_erreg & MTER_FAILCODE) >> 10) {
1279 case 01:
1280 sc->sc_fmesg = "TU status parity error";
1281 break;
1282 case 02:
1283 sc->sc_fmesg = "TU command parity error";
1284 break;
1285 case 03:
1286 sc->sc_fmesg = "rewinding tape went offline";
1287 break;
1288 case 04:
1289 sc->sc_fmesg = "tape went not ready during DSE";
1290 break;
1291 case 05:
1292 sc->sc_fmesg = "TU CMD status changed during DSE";
1293 break;
1294 case 06:
1295 sc->sc_fmesg = "TU never came up to speed";
1296 break;
1297 case 07:
1298 sc->sc_fmesg = "TU velocity changed";
1299 break;
1300 case 010:
1301 sc->sc_fmesg = "TU CMD did not load correctly to start tape motion";
1302 break;
1303 case 011:
1304 sc->sc_fmesg = "TU CMD did not load correctly to set drive density";
1305 break;
1306 case 012:
1307 sc->sc_fmesg = "TU CMD did not load correctly to start tape motion to write BOT ID";
1308 break;
1309 case 013:
1310 sc->sc_fmesg = "TU CMD did not load correctly to backup tape to BOT after failing to write BOT ID";
1311 break;
1312 case 014:
1313 sc->sc_fmesg = "failed to write density ID burst";
1314 break;
1315 case 015:
1316 sc->sc_fmesg = "failed to write ARA burst";
1317 break;
1318 case 016:
1319 sc->sc_fmesg = "failed to write ARA ID";
1320 break;
1321 case 017:
1322 sc->sc_fmesg = "ARA error bit set in MTA status B register";
1323 break;
1324 case 021:
1325 sc->sc_fmesg = "could not find a gap after ID code was written correctly";
1326 break;
1327 case 022:
1328 sc->sc_fmesg = "TU CMD did not load correctly to start tape motion to read ID burst";
1329 break;
1330 case 023:
1331 sc->sc_fmesg = "timeout looking for BOT after detecting ARA ID burst";
1332 break;
1333 case 024:
1334 sc->sc_fmesg = "failed to write tape mark";
1335 break;
1336 case 025:
1337 sc->sc_fmesg = "tape never came up to speed while trying to reposition for retry of writing tape mark";
1338 break;
1339 case 026:
1340 sc->sc_fmesg = "TU CMD did not load correctly to start tape motion in erase gap routine";
1341 break;
1342 case 027:
1343 sc->sc_fmesg = "could not detect a gap in in erase gap routine";
1344 break;
1345 case 030:
1346 sc->sc_fmesg = "could not detect a gap after writing record";
1347 break;
1348 case 031:
1349 sc->sc_fmesg = "read path terminated before entire record was written";
1350 break;
1351 case 032:
1352 sc->sc_fmesg = "could not find a gap after writing record and read path terminated early";
1353 break;
1354 case 033:
1355 sc->sc_fmesg = "TU CMD did not load correctly to backup for retry of write tape mark";
1356 break;
1357 case 034:
1358 sc->sc_fmesg = "TU velocity changed after up to speed while trying to reposition for retry of writing tape mark";
1359 break;
1360 case 035:
1361 sc->sc_fmesg = "TU CMD did not load correctly to backup to retry a load of BOT ID";
1362 break;
1363 case 036:
1364 sc->sc_fmesg = "timeout looking for BOT after failing to write BOT ID";
1365 break;
1366 case 037:
1367 sc->sc_fmesg = "TU velocity changed while writing PE gap before starting to write record";
1368 break;
1369 case 040:
1370 sc->sc_fmesg = "TU CMD did not load correctly to set PE tape density at start of write BOT ID burst";
1371 break;
1372 case 041:
1373 sc->sc_fmesg = "TU CMD did not load correctly to set GCR tape density after writing Density ID";
1374 break;
1375 case 042:
1376 sc->sc_fmesg = "TU CMD did not load correctly to set PE tape density at start of read from BOT";
1377 break;
1378 case 043:
1379 sc->sc_fmesg = "TU CMD did not load correctly to set GCR tape density after reading a GCR Density ID burst";
1380 break;
1381 default:
1382 sc->sc_fmesg = "unclassified failure code";
1383 }
1384 break;
1385
1386 /* TM fault B */
1387
1388 case MTER_TMFLTB:
1389 sc->sc_mesg = "TM fault B";
1390 switch ((sc->sc_erreg & MTER_FAILCODE) >> 10) {
1391 case 00:
1392 sc->sc_fmesg = "RST0 interrupt occurred with TM RDY set";
1393 break;
1394 case 01:
1395 sc->sc_fmesg = "power failed to interrupt";
1396 break;
1397 case 02:
1398 sc->sc_fmesg = "unknown interrupt on channel 5.5";
1399 break;
1400 case 03:
1401 sc->sc_fmesg = "unknown interrupt on channel 6.5";
1402 break;
1403 case 04:
1404 sc->sc_fmesg = "unknown interrupt on channel 7";
1405 break;
1406 case 05:
1407 sc->sc_fmesg = "unknown interrupt on channel 7.5";
1408 break;
1409 case 06:
1410 sc->sc_fmesg = "CAS contention retry count expired";
1411 break;
1412 case 07:
1413 sc->sc_fmesg = "CAS contention error not retryable";
1414 break;
1415 case 010:
1416 sc->sc_fmesg = "queue error, could not find queue entry";
1417 break;
1418 case 011:
1419 sc->sc_fmesg = "queue entry already full";
1420 break;
1421 case 012:
1422 sc->sc_fmesg = "8085 ROM parity error";
1423 break;
1424 case 013:
1425 case 014:
1426 case 015:
1427 case 016:
1428 case 017:
1429 case 020:
1430 case 021:
1431 case 022:
1432 case 023:
1433 case 024:
1434 case 025:
1435 case 026:
1436 case 027:
1437 case 030:
1438 case 031:
1439 case 032:
1440 case 033:
1441 case 034:
1442 case 035:
1443 case 036:
1444 case 037:
1445 case 040:
1446 case 041:
1447 case 042:
1448 case 043:
1449 case 044:
1450 case 045:
1451 case 046:
1452 case 047:
1453 case 050:
1454 case 051:
1455 case 052:
1456 case 053:
1457 case 054:
1458 case 055:
1459 case 056:
1460 case 057:
1461 sc->sc_fmesg = "inline test failed";
1462 break;
1463 default:
1464 sc->sc_fmesg = "unclassified failure code";
1465 }
1466 break;
1467
1468 /* MASSBUS fault */
1469
1470 case MTER_MBFLT:
1471 sc->sc_mesg = "MB fault";
1472 switch ((sc->sc_erreg & MTER_FAILCODE) >> 10) {
1473 case 01:
1474 sc->sc_fmesg = "control bus parity error";
1475 break;
1476 case 02:
1477 sc->sc_fmesg = "illegal register referenced";
1478 break;
1479 default:
1480 sc->sc_fmesg = "unclassified failure code";
1481 }
1482 break;
1483
1484 /* keypad entry error */
1485
1486 case MTER_KEYFAIL:
1487 sc->sc_mesg = "keypad entry error";
1488 sc->sc_fmesg = "";
1489 break;
1490 default:
1491 sc->sc_mesg = "unclassified error";
1492 sc->sc_fmesg = "";
1493 break;
1494 }
1495}
1496#endif MTLERRM
83d7e407 1497#endif