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