save r10 (boot device); use it to set rootdev and maybe swap, arg and dump devs
[unix-history] / usr / src / sys / vax / mba / mt.c
CommitLineData
da7c5cc6
KM
1/*
2 * Copyright (c) 1982 Regents of the University of California.
3 * All rights reserved. The Berkeley software License Agreement
4 * specifies the terms and conditions for redistribution.
5 *
8011f5df 6 * @(#)mt.c 6.6 (Berkeley) %G%
da7c5cc6 7 */
83d7e407
BJ
8
9#include "mu.h"
10#if NMT > 0
11/*
12 * TM78/TU78 tape driver
13 *
c0bb0291
KM
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)
83d7e407
BJ
20 *
21 * TODO:
c0bb0291
KM
22 * Add odd byte count kludge from VMS driver (?)
23 * Write dump routine
83d7e407 24 */
c0bb0291 25
961945a8
SL
26#include "../machine/pte.h"
27
969e52ef
JB
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"
48165e7b 40#include "tty.h"
83d7e407 41
c895c266 42#include "../vax/cpu.h"
969e52ef
JB
43#include "mbareg.h"
44#include "mbavar.h"
45#include "mtreg.h"
83d7e407 46
c0bb0291
KM
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 */
83d7e407 50
c0bb0291
KM
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 */
83d7e407 56
c0bb0291 57/* Bits in minor device */
83d7e407 58
83d7e407
BJ
59#define MUUNIT(dev) (minor(dev)&03)
60#define H_NOREWIND 04
c0bb0291 61#define H_6250BPI 010
83d7e407
BJ
62
63#define MTUNIT(dev) (mutomt[MUUNIT(dev)])
64
c0bb0291
KM
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 */
83d7e407
BJ
72
73struct mu_softc {
c0bb0291
KM
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
48165e7b 91 struct tty *sc_ttyp; /* record user's tty for errors */
83d7e407 92} mu_softc[NMU];
83d7e407 93
c0bb0291
KM
94struct buf rmtbuf[NMT]; /* data transfer buffer structures */
95struct buf cmtbuf[NMT]; /* tape command buffer structures */
83d7e407 96
c0bb0291
KM
97struct mba_device *mtinfo[NMT]; /* unit massbus structure pointers */
98short mutomt[NMU]; /* tape unit to controller number map */
99char mtds_bits[] = MTDS_BITS; /* mtds bit names for error messages */
100short mttypes[] = { MBDT_TU78, 0 };
101
102int mtattach(), mtslave(), mtustart(), mtstart(), mtndtint(), mtdtint();
103struct mba_driver mtdriver =
104 { mtattach, mtslave, mtustart, mtstart, mtdtint, mtndtint,
105 mttypes, "mt", "mu", mtinfo };
106
107void mtcreset();
83d7e407
BJ
108
109/*ARGSUSED*/
110mtattach(mi)
111 struct mba_device *mi;
112{
83d7e407
BJ
113}
114
51250c66 115mtslave(mi, ms, sn)
83d7e407
BJ
116 struct mba_device *mi;
117 struct mba_slave *ms;
51250c66 118 int sn;
83d7e407
BJ
119{
120 register struct mu_softc *sc = &mu_softc[ms->ms_unit];
121 register struct mtdevice *mtaddr = (struct mtdevice *)mi->mi_drv;
8011f5df 122 int s = spl5(), rtn = 0, i;
c0bb0291
KM
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. */
83d7e407 126
c0bb0291 127 mtcreset(mtaddr);
83d7e407 128 mtaddr->mtas = -1;
51250c66 129 mtaddr->mtncs[sn] = MT_SENSE|MT_GO;
c0bb0291
KM
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) {
83d7e407 148 sc->sc_mi = mi;
51250c66 149 sc->sc_slave = sn;
83d7e407
BJ
150 mutomt[ms->ms_unit] = mi->mi_unit;
151 rtn = 1;
152 }
c0bb0291
KM
153
154 /* Cancel the interrupt, then wait a little while for it to go away. */
155
83d7e407 156 mtaddr->mtas = mtaddr->mtas;
c0bb0291 157 DELAY(10);
83d7e407
BJ
158 splx(s);
159 return (rtn);
160}
161
162mtopen(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;
83d7e407
BJ
169
170 muunit = MUUNIT(dev);
c0bb0291
KM
171 if ( (muunit >= NMU)
172 || ((mi = mtinfo[MTUNIT(dev)]) == 0)
173 || (mi->mi_alive == 0) )
473a2e47 174 return (ENXIO);
c0bb0291
KM
175 if ((sc = &mu_softc[muunit])->sc_openf)
176 return (EBUSY);
177 sc->sc_dens = (minor(dev) & H_6250BPI) ? MT_GCR : 0;
83d7e407 178 mtcommand(dev, MT_SENSE, 1);
83d7e407
BJ
179 if ((sc->sc_dsreg & MTDS_ONL) == 0) {
180 uprintf("mu%d: not online\n", muunit);
473a2e47 181 return (EIO);
83d7e407 182 }
c0bb0291
KM
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)) {
83d7e407 188 uprintf("mu%d: no write ring\n", muunit);
473a2e47 189 return (EIO);
83d7e407 190 }
c0bb0291
KM
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)))) {
83d7e407 197 uprintf("mu%d: can't change density in mid-tape\n", muunit);
473a2e47 198 return (EIO);
83d7e407
BJ
199 }
200 sc->sc_openf = 1;
201 sc->sc_blkno = (daddr_t)0;
c0bb0291
KM
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;
83d7e407 210 sc->sc_flags = 0;
48165e7b 211 sc->sc_ttyp = u.u_ttyp;
473a2e47 212 return (0);
83d7e407
BJ
213}
214
215mtclose(dev, flag)
216 register dev_t dev;
c0bb0291 217 register int flag;
83d7e407
BJ
218{
219 register struct mu_softc *sc = &mu_softc[MUUNIT(dev)];
220
c0bb0291
KM
221 if ( ((flag & (FREAD | FWRITE)) == FWRITE)
222 || ( (flag & FWRITE)
223 && (sc->sc_flags & H_WRITTEN) ))
83d7e407 224 mtcommand(dev, MT_CLS|sc->sc_dens, 1);
c0bb0291 225 if ((minor(dev) & H_NOREWIND) == 0)
83d7e407
BJ
226 mtcommand(dev, MT_REW, 0);
227 sc->sc_openf = 0;
228}
229
230mtcommand(dev, com, count)
231 dev_t dev;
232 int com, count;
233{
234 register struct buf *bp;
2311123d 235 register int s;
83d7e407
BJ
236
237 bp = &cmtbuf[MTUNIT(dev)];
2311123d 238 s = spl5();
c0bb0291
KM
239 while (bp->b_flags & B_BUSY) {
240 if((bp->b_repcnt == 0) && (bp->b_flags & B_DONE))
83d7e407
BJ
241 break;
242 bp->b_flags |= B_WANTED;
243 sleep((caddr_t)bp, PRIBIO);
244 }
245 bp->b_flags = B_BUSY|B_READ;
2311123d 246 splx(s);
83d7e407
BJ
247 bp->b_dev = dev;
248 bp->b_command = com;
249 bp->b_repcnt = count;
250 bp->b_blkno = 0;
c0bb0291 251 bp->b_error = 0;
83d7e407
BJ
252 mtstrategy(bp);
253 if (count == 0)
254 return;
255 iowait(bp);
c0bb0291 256 if (bp->b_flags & B_WANTED)
83d7e407
BJ
257 wakeup((caddr_t)bp);
258 bp->b_flags &= B_ERROR;
259}
260
261mtstrategy(bp)
262 register struct buf *bp;
263{
264 register struct mba_device *mi = mtinfo[MTUNIT(bp->b_dev)];
265 register struct buf *dp;
2311123d 266 register int s;
83d7e407 267
c0bb0291
KM
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
83d7e407
BJ
278 bp->av_forw = NULL;
279 dp = &mi->mi_tab;
2311123d 280 s = spl5();
83d7e407
BJ
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);
2311123d 288 splx(s);
83d7e407
BJ
289}
290
291mtustart(mi)
292 register struct mba_device *mi;
293{
c0bb0291 294 register struct mtdevice *mtaddr = (struct mtdevice *)mi->mi_drv;
83d7e407
BJ
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;
8011f5df 298 int count;
83d7e407 299
83d7e407
BJ
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)]) {
c0bb0291
KM
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) ) {
83d7e407 311 bp->b_flags |= B_ERROR;
c0bb0291 312 bp->b_error = ENOSPC;
83d7e407
BJ
313 return (MBU_NEXT);
314 }
c0bb0291
KM
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;
83d7e407 341 }
83d7e407 342 } else {
c0bb0291
KM
343
344 /* It's a command, do it now. */
345
83d7e407
BJ
346 mtaddr->mtncs[MUUNIT(bp->b_dev)] =
347 (bp->b_repcnt<<8)|bp->b_command|MT_GO;
348 return (MBU_STARTED);
349 }
c0bb0291
KM
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)) ) {
83d7e407 358 if (mi->mi_tab.b_errcnt == 2) {
c0bb0291 359 mtaddr->mtbc = -(bp->b_bcount);
83d7e407
BJ
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 }
c0bb0291
KM
367
368 /* Issue skip operations to position the next block for cooked I/O. */
369
43d66181 370 if (blkno < bdbtofsb(bp->b_blkno))
8011f5df 371 count = (unsigned)(bdbtofsb(bp->b_blkno) - blkno);
83d7e407 372 else
8011f5df
MK
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;
83d7e407
BJ
377 return (MBU_STARTED);
378}
379
380mtstart(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
395mtdtint(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;
c0bb0291
KM
402 register int er;
403
404 /* I'M still NOT SURE IF THIS SHOULD ALWAYS BE THE CASE SO FOR NOW... */
83d7e407 405
c0bb0291 406 if ((mtaddr->mtca & 3) != MUUNIT(bp->b_dev)) {
83d7e407
BJ
407 printf("mt: wrong unit!\n");
408 mtaddr->mtca = MUUNIT(bp->b_dev);
409 }
c0bb0291
KM
410
411 er = MASKREG(mtaddr->mter);
83d7e407 412 sc = &mu_softc[MUUNIT(bp->b_dev)];
c0bb0291
KM
413 sc->sc_erreg = er;
414 if (bp->b_flags & B_READ)
415 sc->sc_flags &= ~H_WRITTEN;
416 else
83d7e407 417 sc->sc_flags |= H_WRITTEN;
c0bb0291
KM
418 switch (er & MTER_INTCODE) {
419
420 case MTER_EOT:
421 sc->sc_flags |= H_EOT;
422
423 /* fall into MTER_DONE */
424
83d7e407 425 case MTER_DONE:
c0bb0291
KM
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) {
83d7e407 477 sc->sc_blkno++;
c0bb0291
KM
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;
83d7e407 490 bp->b_resid = 0;
c0bb0291
KM
491 bp->b_error = ENOMEM;
492 bp->b_flags |= B_ERROR;
83d7e407
BJ
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:
83d7e407 500
c0bb0291
KM
501 /* End of file. Since the default byte count has */
502 /* already been set, just count the block and proceed. */
503
83d7e407 504 sc->sc_blkno++;
c0bb0291 505 err:
83d7e407 506 if (bp != &rmtbuf[MTUNIT(bp->b_dev)])
c0bb0291 507 sc->sc_nxrec = bdbtofsb(bp->b_blkno);
83d7e407
BJ
508 break;
509
83d7e407
BJ
510 case MTER_OFFLINE:
511 if (sc->sc_openf > 0) {
512 sc->sc_openf = -1;
48165e7b 513 tprintf(sc->sc_ttyp, "mu%d: offline\n", MUUNIT(bp->b_dev));
83d7e407
BJ
514 }
515 bp->b_flags |= B_ERROR;
516 break;
517
c0bb0291
KM
518 case MTER_NOTAVL:
519 if (sc->sc_openf > 0) {
520 sc->sc_openf = -1;
48165e7b
RC
521 tprintf(sc->sc_ttyp, "mu%d: offline (port selector)\n",
522 MUUNIT(bp->b_dev));
c0bb0291
KM
523 }
524 bp->b_flags |= B_ERROR;
525 break;
526
83d7e407 527 case MTER_FPT:
48165e7b 528 tprintf(sc->sc_ttyp, "mu%d: no write ring\n", MUUNIT(bp->b_dev));
83d7e407
BJ
529 bp->b_flags |= B_ERROR;
530 break;
531
c0bb0291
KM
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) {
48165e7b 540 tprintf(sc->sc_ttyp, "mu%d: rn=%d bn=%d unreadable record\n",
c0bb0291
KM
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
83d7e407 549 default:
c0bb0291
KM
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
48165e7b 557 tprintf(sc->sc_ttyp, "mu%d: hard error (data transfer) rn=%d bn=%d mbsr=%b er=%o (octal) ds=%b\n",
c0bb0291
KM
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
83d7e407 567 bp->b_flags |= B_ERROR;
c0bb0291
KM
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 }
83d7e407 576 }
c0bb0291
KM
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;
83d7e407
BJ
584 return (MBD_DONE);
585}
586
587mtndtint(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;
c0bb0291
KM
593 register int er, fc;
594 int unit;
83d7e407
BJ
595
596 unit = (mtaddr->mtner >> 8) & 3;
597 er = MASKREG(mtaddr->mtner);
c0bb0291
KM
598 sc = &mu_softc[unit];
599 sc->sc_erreg = er;
600
601 /* Check for unsolicited interrupts. */
602
83d7e407 603 if (bp == 0 || unit != MUUNIT(bp->b_dev)) { /* consistency check */
c0bb0291
KM
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 }
83d7e407
BJ
630 return (MBN_SKIP);
631 }
632 if (bp == 0)
633 return (MBN_SKIP);
c0bb0291 634
83d7e407 635 fc = (mtaddr->mtncs[unit] >> 8) & 0xff;
83d7e407 636 sc->sc_resid = fc;
c0bb0291
KM
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
83d7e407 645 switch (er & MTER_INTCODE) {
c0bb0291
KM
646
647 case MTER_EOT:
648 sc->sc_flags |= H_EOT;
649
650 /* fall into MTER_DONE */
651
83d7e407 652 case MTER_DONE:
c0bb0291
KM
653
654 /* If this is a command buffer, just update the status. */
655
83d7e407
BJ
656 if (bp == &cmtbuf[MTUNIT(bp->b_dev)]) {
657 done:
658 if (bp->b_command == MT_SENSE)
659 sc->sc_dsreg = MASKREG(mtaddr->mtds);
83d7e407
BJ
660 return (MBN_DONE);
661 }
c0bb0291
KM
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
43d66181 667 if ((fc = bdbtofsb(bp->b_blkno) - sc->sc_blkno) < 0)
155d9ff0 668 sc->sc_blkno -= MIN(0377, -fc);
83d7e407 669 else
155d9ff0 670 sc->sc_blkno += MIN(0377, fc);
83d7e407
BJ
671 return (MBN_RETRY);
672
c0bb0291 673 case MTER_ONLINE: /* ddj -- shouldn't happen but did */
83d7e407
BJ
674 case MTER_RWDING:
675 return (MBN_SKIP); /* ignore "rewind started" interrupt */
676
677 case MTER_NOTCAP:
48165e7b 678 tprintf(sc->sc_ttyp, "mu%d: blank tape\n", MUUNIT(bp->b_dev));
c0bb0291
KM
679 bp->b_flags |= B_ERROR;
680 return (MBN_DONE);
83d7e407
BJ
681
682 case MTER_TM:
83d7e407 683 case MTER_LEOT:
c0bb0291
KM
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;
83d7e407
BJ
701 sc->sc_blkno = sc->sc_nxrec;
702 } else {
c0bb0291
KM
703 sc->sc_nxrec = bdbtofsb(bp->b_blkno) - fc;
704 sc->sc_blkno = sc->sc_nxrec + 1;
83d7e407
BJ
705 }
706 return (MBN_RETRY);
707
708 case MTER_FPT:
48165e7b 709 tprintf(sc->sc_ttyp, "mu%d: no write ring\n", MUUNIT(bp->b_dev));
83d7e407
BJ
710 bp->b_flags |= B_ERROR;
711 return (MBN_DONE);
712
713 case MTER_OFFLINE:
c0bb0291
KM
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);
83d7e407
BJ
720 if (sc->sc_openf > 0) {
721 sc->sc_openf = -1;
48165e7b 722 tprintf(sc->sc_ttyp, "mu%d: offline\n", MUUNIT(bp->b_dev));
83d7e407
BJ
723 }
724 bp->b_flags |= B_ERROR;
725 return (MBN_DONE);
726
c0bb0291
KM
727 case MTER_NOTAVL:
728 if (sc->sc_openf > 0) {
729 sc->sc_openf = -1;
48165e7b 730 tprintf(sc->sc_ttyp, "mu%d: offline (port selector)\n", MUUNIT(bp->b_dev));
c0bb0291
KM
731 }
732 bp->b_flags |= B_ERROR;
733 return (MBN_DONE);
734
83d7e407
BJ
735 case MTER_BOT:
736 if (bp == &cmtbuf[MTUNIT(bp->b_dev)])
737 goto done;
c0bb0291
KM
738
739 /* fall through */
83d7e407
BJ
740
741 default:
48165e7b 742 tprintf(sc->sc_ttyp, "mu%d: hard error (non data transfer) rn=%d bn=%d er=%o (octal) ds=%b\n",
c0bb0291
KM
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 }
83d7e407
BJ
755 bp->b_flags |= B_ERROR;
756 return (MBN_DONE);
757 }
758 /* NOTREACHED */
759}
760
c0bb0291
KM
761void 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
deb8980a 776mtread(dev, uio)
83d7e407 777 dev_t dev;
deb8980a 778 struct uio *uio;
83d7e407 779{
23458a62 780 int errno;
83d7e407 781
23458a62
BJ
782 errno = mtphys(dev, uio);
783 if (errno)
784 return (errno);
785 return (physio(mtstrategy, &rmtbuf[MTUNIT(dev)], dev, B_READ, minphys, uio));
83d7e407
BJ
786}
787
c0bb0291 788
406ddcbe
BJ
789mtwrite(dev, uio)
790 dev_t dev;
791 struct uio *uio;
83d7e407 792{
23458a62 793 int errno;
83d7e407 794
23458a62
BJ
795 errno = mtphys(dev, uio);
796 if (errno)
797 return (errno);
798 return (physio(mtstrategy, &rmtbuf[MTUNIT(dev)], dev, B_WRITE, minphys, uio));
83d7e407
BJ
799}
800
deb8980a 801mtphys(dev, uio)
83d7e407 802 dev_t dev;
deb8980a 803 struct uio *uio;
83d7e407
BJ
804{
805 register int mtunit;
c0bb0291
KM
806 struct mba_device *mi;
807 register int bsize = uio->uio_iov->iov_len;
83d7e407
BJ
808
809 mtunit = MTUNIT(dev);
c0bb0291
KM
810 if ( (mtunit >= NMT)
811 || ((mi = mtinfo[mtunit]) == 0)
812 || (mi->mi_alive == 0) )
deb8980a 813 return (ENXIO);
c0bb0291
KM
814 if ( (bsize > 0xffff) /* controller limit */
815 || (bsize <= 0) ) /* ambiguous */
816 return (EINVAL);
deb8980a 817 return (0);
83d7e407
BJ
818}
819
820/*ARGSUSED*/
942f05a9 821mtioctl(dev, cmd, data, flag)
83d7e407
BJ
822 dev_t dev;
823 int cmd;
942f05a9 824 caddr_t data;
83d7e407
BJ
825 int flag;
826{
827 register struct mu_softc *sc = &mu_softc[MUUNIT(dev)];
828 register struct buf *bp = &cmtbuf[MTUNIT(dev)];
c0bb0291
KM
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
83d7e407
BJ
836 static mtops[] =
837 {MT_WTM,MT_SFORWF,MT_SREVF,MT_SFORW,MT_SREV,MT_REW,MT_UNLOAD,MT_SENSE};
838
839 switch (cmd) {
942f05a9 840
c0bb0291
KM
841 /* tape operation */
842
843 case MTIOCTOP:
2e9f5990
BJ
844 mtop = (struct mtop *)data;
845 switch (mtop->mt_op) {
942f05a9 846
83d7e407 847 case MTWEOF:
942f05a9 848 callcount = mtop->mt_count;
83d7e407
BJ
849 fcount = 1;
850 break;
942f05a9 851
83d7e407 852 case MTFSF: case MTBSF:
942f05a9 853 callcount = mtop->mt_count;
83d7e407
BJ
854 fcount = 1;
855 break;
942f05a9 856
83d7e407
BJ
857 case MTFSR: case MTBSR:
858 callcount = 1;
942f05a9 859 fcount = mtop->mt_count;
83d7e407 860 break;
942f05a9 861
83d7e407
BJ
862 case MTREW: case MTOFFL:
863 callcount = 1;
864 fcount = 1;
865 break;
942f05a9 866
83d7e407 867 default:
473a2e47 868 return (ENXIO);
83d7e407 869 }
c0bb0291 870 if ((callcount <= 0) || (fcount <= 0))
473a2e47 871 return (EINVAL);
942f05a9 872 op = mtops[mtop->mt_op];
83d7e407
BJ
873 if (op == MT_WTM)
874 op |= sc->sc_dens;
875 while (--callcount >= 0) {
c0bb0291 876 register int n, fc = fcount;
83d7e407
BJ
877
878 do {
c0bb0291 879 n = MIN(fc, 0xff);
83d7e407 880 mtcommand(dev, op, n);
c0bb0291
KM
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)
83d7e407
BJ
927 break;
928 }
5a1f132a 929 return (geterror(bp));
942f05a9 930
c0bb0291
KM
931 /* tape status */
932
83d7e407 933 case MTIOCGET:
942f05a9
SL
934 mtget = (struct mtget *)data;
935 mtget->mt_erreg = sc->sc_erreg;
936 mtget->mt_resid = sc->sc_resid;
83d7e407 937 mtcommand(dev, MT_SENSE, 1); /* update drive status */
942f05a9
SL
938 mtget->mt_dsreg = sc->sc_dsreg;
939 mtget->mt_type = MT_ISMT;
473a2e47 940 break;
942f05a9 941
c0bb0291
KM
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
83d7e407 954 default:
473a2e47 955 return (ENXIO);
83d7e407 956 }
473a2e47 957 return (0);
83d7e407
BJ
958}
959
960#define DBSIZE 20
961
962mtdump()
963{
964 register struct mba_device *mi;
965 register struct mba_regs *mp;
83d7e407
BJ
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;
155d9ff0 977#if lint
2e9f5990 978 blk = 0; num = blk; start = num; blk = start;
155d9ff0
SL
979 return (0);
980#endif
83d7e407 981#ifdef notyet
155d9ff0 982 mtaddr = (struct mtdevice *)&mp->mba_drv[mi->mi_drive];
83d7e407
BJ
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
1000mtdwrite(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
1019mtwait(mtaddr)
1020 struct mtdevice *mtaddr;
1021{
1022 register s;
1023
1024 do
1025 s = mtaddr->mtds;
1026 while ((s & MTDS_DRY) == 0);
1027}
1028
1029mteof(mtaddr)
1030 struct mtdevice *mtaddr;
1031{
1032
1033 mtwait(mtaddr);
1034 mtaddr->mtcs1 = MT_WEOF|MT_GO;
1035#endif notyet
1036}
c0bb0291
KM
1037
1038#ifdef MTLERRM
1039mtintfail(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
83d7e407 1500#endif