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