* Copyright (c) 1982, 1986 Regents of the University of California.
* All rights reserved. The Berkeley software License Agreement
* specifies the terms and conditions for redistribution.
* @(#)mt.c 7.1 (Berkeley) %G%
* Most error recovery bug fixes - ggs (ulysses!ggs)
* MTLERRM - Long error message text - twd, Brown University
* MTRDREV - `read reverse' error recovery - ggs (ulysses!ggs)
* Add odd byte count kludge from VMS driver (?)
#include "../machine/pte.h"
#define MTTIMEOUT 10000 /* loop limit for controller test */
#define INF 1000000L /* a block number that won't exist */
#define MASKREG(r) ((r) & 0xffff) /* the control registers have 16 bits */
#define H_WRITTEN 01 /* last operation was a write */
#define H_EOT 02 /* end of tape encountered */
#define H_IEOT 04 /* ignore EOT condition */
/* Bits in minor device */
#define MUUNIT(dev) (minor(dev)&03)
#define MTUNIT(dev) (mutomt[MUUNIT(dev)])
/* Per unit status information */
char sc_openf
; /* unit is open if != 0 */
char sc_flags
; /* state flags */
daddr_t sc_blkno
; /* current physical block number */
daddr_t sc_nxrec
; /* firewall input block number */
u_short sc_erreg
; /* copy of mter or mtner */
u_short sc_dsreg
; /* copy of mtds */
short sc_resid
; /* residual function count for ioctl */
short sc_dens
; /* density code - MT_GCR or zero */
struct mba_device
*sc_mi
; /* massbus structure for unit */
int sc_slave
; /* slave number for unit */
int sc_i_mtas
; /* mtas at slave attach time */
int sc_i_mtner
; /* mtner at slave attach time */
int sc_i_mtds
; /* mtds at slave attach time */
char *sc_mesg
; /* text for interrupt type code */
char *sc_fmesg
; /* text for tape error code */
struct tty
*sc_ttyp
; /* record user's tty for errors */
struct buf rmtbuf
[NMT
]; /* data transfer buffer structures */
struct buf cmtbuf
[NMT
]; /* tape command buffer structures */
struct mba_device
*mtinfo
[NMT
]; /* unit massbus structure pointers */
short mutomt
[NMU
]; /* tape unit to controller number map */
char mtds_bits
[] = MTDS_BITS
; /* mtds bit names for error messages */
short mttypes
[] = { MBDT_TU78
, 0 };
int mtattach(), mtslave(), mtustart(), mtstart(), mtndtint(), mtdtint();
struct mba_driver mtdriver
=
{ mtattach
, mtslave
, mtustart
, mtstart
, mtdtint
, mtndtint
,
mttypes
, "mt", "mu", mtinfo
};
register struct mu_softc
*sc
= &mu_softc
[ms
->ms_unit
];
register struct mtdevice
*mtaddr
= (struct mtdevice
*)mi
->mi_drv
;
int s
= spl5(), rtn
= 0, i
;
/* Just in case the controller is ill, reset it. Then issue */
/* a sense operation and wait about a second for it to respond. */
mtaddr
->mtncs
[sn
] = MT_SENSE
|MT_GO
;
for (i
= MTTIMEOUT
; i
> 0; i
--) {
if (MASKREG(mtaddr
->mtas
) != 0)
sc
->sc_i_mtas
= mtaddr
->mtas
;
sc
->sc_i_mtner
= mtaddr
->mtner
;
sc
->sc_i_mtds
= mtaddr
->mtds
;
/* If no response, whimper. If wrong response, call it an */
/* unsolicited interrupt and use mtndtint to log and correct. */
/* Otherwise, note whether this slave exists. */
printf("mt: controller hung\n");
} else if ((mtaddr
->mtner
& MTER_INTCODE
) != MTER_DONE
) {
} else if (mtaddr
->mtds
& MTDS_PRES
) {
mutomt
[ms
->ms_unit
] = mi
->mi_unit
;
/* Cancel the interrupt, then wait a little while for it to go away. */
mtaddr
->mtas
= mtaddr
->mtas
;
register struct mba_device
*mi
;
register struct mu_softc
*sc
;
|| ((mi
= mtinfo
[MTUNIT(dev
)]) == 0)
if ((sc
= &mu_softc
[muunit
])->sc_openf
)
sc
->sc_dens
= (minor(dev
) & H_6250BPI
) ? MT_GCR
: 0;
mtcommand(dev
, MT_SENSE
, 1);
if ((sc
->sc_dsreg
& MTDS_ONL
) == 0) {
uprintf("mu%d: not online\n", muunit
);
if ((sc
->sc_dsreg
& MTDS_AVAIL
) == 0) {
uprintf("mu%d: not online (port selector)\n", muunit
);
if ((flag
& FWRITE
) && (sc
->sc_dsreg
& MTDS_FPT
)) {
uprintf("mu%d: no write ring\n", muunit
);
if ( ((sc
->sc_dsreg
& MTDS_BOT
) == 0)
&& ( ( (sc
->sc_dens
== MT_GCR
)
&& (sc
->sc_dsreg
& MTDS_PE
) )
|| ( (sc
->sc_dens
!= MT_GCR
)
&& ((sc
->sc_dsreg
& MTDS_PE
) == 0)))) {
uprintf("mu%d: can't change density in mid-tape\n", muunit
);
sc
->sc_blkno
= (daddr_t
)0;
/* Since cooked I/O may do a read-ahead before a write, trash */
/* on a tape can make the first write fail. Suppress the first */
/* read-ahead unless definitely doing read-write */
sc
->sc_nxrec
= ((flag
& (FTRUNC
| FWRITE
)) == (FTRUNC
| FWRITE
))
register struct mu_softc
*sc
= &mu_softc
[MUUNIT(dev
)];
if ( ((flag
& (FREAD
| FWRITE
)) == FWRITE
)
&& (sc
->sc_flags
& H_WRITTEN
) ))
mtcommand(dev
, MT_CLS
|sc
->sc_dens
, 1);
if ((minor(dev
) & H_NOREWIND
) == 0)
mtcommand(dev
, MT_REW
, 0);
mtcommand(dev
, com
, count
)
bp
= &cmtbuf
[MTUNIT(dev
)];
while (bp
->b_flags
& B_BUSY
) {
if((bp
->b_repcnt
== 0) && (bp
->b_flags
& B_DONE
))
sleep((caddr_t
)bp
, PRIBIO
);
bp
->b_flags
= B_BUSY
|B_READ
;
if (bp
->b_flags
& B_WANTED
)
register struct mba_device
*mi
= mtinfo
[MTUNIT(bp
->b_dev
)];
/* If this is a data transfer operation, set the resid to a */
/* default value (EOF) to simplify getting it right during */
/* error recovery or bail out. */
if (bp
!= &cmtbuf
[MTUNIT(bp
->b_dev
)])
bp
->b_resid
= bp
->b_bcount
;
/* Link this request onto the end of the queue for this */
/* controller, then start I/O if not already active. */
dp
->b_actl
->av_forw
= bp
;
register struct mba_device
*mi
;
register struct mtdevice
*mtaddr
= (struct mtdevice
*)mi
->mi_drv
;
register struct buf
*bp
= mi
->mi_tab
.b_actf
;
register struct mu_softc
*sc
= &mu_softc
[MUUNIT(bp
->b_dev
)];
if (bp
!= &cmtbuf
[MTUNIT(bp
->b_dev
)]) {
/* Signal "no space" if out of tape unless suppressed */
if ( ((sc
->sc_flags
& (H_EOT
| H_IEOT
)) == H_EOT
)
&& ((bp
->b_flags
& B_READ
) == 0) ) {
/* special case tests for cooked mode */
if (bp
!= &rmtbuf
[MTUNIT(bp
->b_dev
)]) {
/* seek beyond end of file */
if (bdbtofsb(bp
->b_blkno
) > sc
->sc_nxrec
) {
/* This should be end of file, but the buffer */
/* system wants a one-block look-ahead. Humor it. */
if ( (bdbtofsb(bp
->b_blkno
) == sc
->sc_nxrec
)
&& (bp
->b_flags
& B_READ
) ) {
/* If writing, mark the next block invalid. */
if ((bp
->b_flags
& B_READ
) == 0)
sc
->sc_nxrec
= bdbtofsb(bp
->b_blkno
) + 1;
/* It's a command, do it now. */
mtaddr
->mtncs
[MUUNIT(bp
->b_dev
)] =
(bp
->b_repcnt
<<8)|bp
->b_command
|MT_GO
;
/* If raw I/O, or if the tape is positioned correctly for */
/* cooked I/O, set the byte count, unit number and repeat count */
/* then tell the MASSBUS to proceed. Note that a negative */
/* bcount tells mbstart to map the buffer for "read backwards". */
if ( (bp
== &rmtbuf
[MTUNIT(bp
->b_dev
)])
|| ((blkno
= sc
->sc_blkno
) == bdbtofsb(bp
->b_blkno
)) ) {
if (mi
->mi_tab
.b_errcnt
== 2) {
mtaddr
->mtbc
= -(bp
->b_bcount
);
mtaddr
->mtca
= MUUNIT(bp
->b_dev
);
mtaddr
->mtbc
= bp
->b_bcount
;
mtaddr
->mtca
= (1<<2)|MUUNIT(bp
->b_dev
);
/* Issue skip operations to position the next block for cooked I/O. */
if (blkno
< bdbtofsb(bp
->b_blkno
))
count
= (unsigned)(bdbtofsb(bp
->b_blkno
) - blkno
);
count
= (unsigned)(blkno
- bdbtofsb(bp
->b_blkno
));
mtaddr
->mtncs
[MUUNIT(bp
->b_dev
)] = count
| MT_SFORW
|MT_GO
;
register struct mba_device
*mi
;
register struct buf
*bp
= mi
->mi_tab
.b_actf
;
register struct mu_softc
*sc
= &mu_softc
[MUUNIT(bp
->b_dev
)];
if (bp
->b_flags
& B_READ
)
if (mi
->mi_tab
.b_errcnt
== 2)
return(MT_READREV
|MT_GO
);
return(MT_WRITE
|sc
->sc_dens
|MT_GO
);
register struct mba_device
*mi
;
register struct mtdevice
*mtaddr
= (struct mtdevice
*)mi
->mi_drv
;
register struct buf
*bp
= mi
->mi_tab
.b_actf
;
register struct mu_softc
*sc
;
/* I'M still NOT SURE IF THIS SHOULD ALWAYS BE THE CASE SO FOR NOW... */
if ((mtaddr
->mtca
& 3) != MUUNIT(bp
->b_dev
)) {
printf("mt: wrong unit!\n");
mtaddr
->mtca
= MUUNIT(bp
->b_dev
);
er
= MASKREG(mtaddr
->mter
);
sc
= &mu_softc
[MUUNIT(bp
->b_dev
)];
if (bp
->b_flags
& B_READ
)
sc
->sc_flags
&= ~H_WRITTEN
;
sc
->sc_flags
|= H_WRITTEN
;
switch (er
& MTER_INTCODE
) {
/* fall into MTER_DONE */
if (mi
->mi_tab
.b_errcnt
== 2) {
bp
->b_bcount
= bp
->b_resid
;
bp
->b_resid
-= MASKREG(mtaddr
->mtbc
);
&& (bp
!= &rmtbuf
[MTUNIT(bp
->b_dev
)]) )
bp
->b_bcount
= bp
->b_resid
;
bp
->b_resid
-= MASKREG(mtaddr
->mtbc
);
if (bp
!= &rmtbuf
[MTUNIT(bp
->b_dev
)])
/* Simple re-try. Since resid is always a copy of the */
/* original byte count, use it to restore the count. */
bp
->b_bcount
= bp
->b_resid
;
/* The controller just decided to read it backwards. */
/* If the controller returns a byte count of zero, */
/* change it to 1, since zero encodes 65536, which */
/* isn't quite what we had in mind. The byte count */
/* may be larger than the size of the input buffer, so */
/* limit the count to the buffer size. After */
/* making the byte count reasonable, set bcount to the */
/* negative of the controller's version of the byte */
/* count so that the start address for the transfer is */
if ((bp
->b_bcount
= MASKREG(mtaddr
->mtbc
)) == 0)
if (bp
->b_bcount
> bp
->b_resid
)
bp
->b_bcount
= bp
->b_resid
;
bp
->b_bcount
= -(bp
->b_bcount
);
} else if (MASKREG(mtaddr
->mtbc
) <= bp
->b_resid
) {
bp
->b_bcount
= bp
->b_resid
;
bp
->b_resid
-= MASKREG(mtaddr
->mtbc
);
/* fall into MTER_LONGREC */
bp
->b_bcount
= bp
->b_resid
;
printf("mu%d: blank tape\n", MUUNIT(bp
->b_dev
));
/* End of file. Since the default byte count has */
/* already been set, just count the block and proceed. */
if (bp
!= &rmtbuf
[MTUNIT(bp
->b_dev
)])
sc
->sc_nxrec
= bdbtofsb(bp
->b_blkno
);
tprintf(sc
->sc_ttyp
, "mu%d: offline\n", MUUNIT(bp
->b_dev
));
tprintf(sc
->sc_ttyp
, "mu%d: offline (port selector)\n",
tprintf(sc
->sc_ttyp
, "mu%d: no write ring\n", MUUNIT(bp
->b_dev
));
bp
->b_bcount
= bp
->b_resid
;
bp
->b_resid
-= MIN(MASKREG(mtaddr
->mtbc
), bp
->b_bcount
);
/* Code 010 means a garbage record, nothing serious. */
if (((er
& MTER_FAILCODE
) >> 10) == 010) {
tprintf(sc
->sc_ttyp
, "mu%d: rn=%d bn=%d unreadable record\n",
MUUNIT(bp
->b_dev
), sc
->sc_blkno
, bp
->b_blkno
);
/* Anything else might be a hardware problem, */
/* fall into the error report. */
/* The bits in sc->sc_dsreg are from the last sense */
/* command. To get the most recent copy, you have to */
/* do a sense at interrupt level, which requires nested */
/* error processing. This is a bit messy, so leave */
tprintf(sc
->sc_ttyp
, "mu%d: hard error (data transfer) rn=%d bn=%d mbsr=%b er=%o (octal) ds=%b\n",
MUUNIT(bp
->b_dev
), sc
->sc_blkno
, bp
->b_blkno
,
MASKREG(sc
->sc_dsreg
), mtds_bits
);
printf(" interrupt code = %o (octal) <%s>\n failure code = %o (octal) <%s>\n",
er
& MTER_INTCODE
, sc
->sc_mesg
,
(er
& MTER_FAILCODE
) >> 10, sc
->sc_fmesg
);
/* The TM78 manual says to reset the controller after */
/* TM fault B or MASSBUS fault. */
if ( ((er
& MTER_INTCODE
) == MTER_TMFLTB
)
|| ((er
& MTER_INTCODE
) == MTER_MBFLT
) ) {
/* Just in case some strange error slipped through, (drive off */
/* line during read-reverse error recovery comes to mind) make */
/* sure the byte count is reasonable. */
bp
->b_bcount
= bp
->b_resid
;
register struct mba_device
*mi
;
register struct mtdevice
*mtaddr
= (struct mtdevice
*)mi
->mi_drv
;
register struct buf
*bp
= mi
->mi_tab
.b_actf
;
register struct mu_softc
*sc
;
unit
= (mtaddr
->mtner
>> 8) & 3;
er
= MASKREG(mtaddr
->mtner
);
/* Check for unsolicited interrupts. */
if (bp
== 0 || unit
!= MUUNIT(bp
->b_dev
)) { /* consistency check */
if ((er
& MTER_INTCODE
) != MTER_ONLINE
) {
printf("mt: unit %d unexpected interrupt (non data transfer) er=%o (octal) ds=%b\n",
unit
, er
, MASKREG(sc
->sc_dsreg
), mtds_bits
);
printf(" interrupt code = %o (octal) <%s>\n failure code = %o (octal) <%s>\n",
er
& MTER_INTCODE
, sc
->sc_mesg
,
(er
& MTER_FAILCODE
) >> 10, sc
->sc_fmesg
);
if ( ((er
& MTER_INTCODE
) == MTER_TMFLTB
)
|| ((er
& MTER_INTCODE
) == MTER_MBFLT
) ) {
/* Reset the controller, then set error */
/* status if there was anything active */
/* when the fault occurred. This may */
/* shoot an innocent bystander, but */
/* it's better than letting an error */
fc
= (mtaddr
->mtncs
[unit
] >> 8) & 0xff;
/* Clear the "written" flag after any operation that changes */
/* the position of the tape. */
if ( (bp
!= &cmtbuf
[MTUNIT(bp
->b_dev
)])
|| (bp
->b_command
!= MT_SENSE
) )
sc
->sc_flags
&= ~H_WRITTEN
;
switch (er
& MTER_INTCODE
) {
/* fall into MTER_DONE */
/* If this is a command buffer, just update the status. */
if (bp
== &cmtbuf
[MTUNIT(bp
->b_dev
)]) {
if (bp
->b_command
== MT_SENSE
)
sc
->sc_dsreg
= MASKREG(mtaddr
->mtds
);
/* It's not a command buffer, must be a cooked I/O */
/* skip operation (perhaps a shaky assumption, but it */
if ((fc
= bdbtofsb(bp
->b_blkno
) - sc
->sc_blkno
) < 0)
sc
->sc_blkno
-= MIN(0377, -fc
);
sc
->sc_blkno
+= MIN(0377, fc
);
case MTER_ONLINE
: /* ddj -- shouldn't happen but did */
return (MBN_SKIP
); /* ignore "rewind started" interrupt */
tprintf(sc
->sc_ttyp
, "mu%d: blank tape\n", MUUNIT(bp
->b_dev
));
/* For an ioctl skip operation, count a tape mark as */
/* a record. If there's anything left to do, update */
/* the repeat count and re-start the command. */
if (bp
== &cmtbuf
[MTUNIT(bp
->b_dev
)]) {
if ((sc
->sc_resid
= bp
->b_repcnt
= fc
- 1) == 0)
/* Cooked I/O again. Just update the books and wait */
/* for someone else to return end of file or complain */
} else if (sc
->sc_blkno
> bdbtofsb(bp
->b_blkno
)) {
sc
->sc_nxrec
= bdbtofsb(bp
->b_blkno
) + fc
- 1;
sc
->sc_blkno
= sc
->sc_nxrec
;
sc
->sc_nxrec
= bdbtofsb(bp
->b_blkno
) - fc
;
sc
->sc_blkno
= sc
->sc_nxrec
+ 1;
tprintf(sc
->sc_ttyp
, "mu%d: no write ring\n", MUUNIT(bp
->b_dev
));
/* If `off line' was intentional, don't complain. */
if ( (bp
== &cmtbuf
[MTUNIT(bp
->b_dev
)])
&& (bp
->b_command
== MT_UNLOAD
) )
tprintf(sc
->sc_ttyp
, "mu%d: offline\n", MUUNIT(bp
->b_dev
));
tprintf(sc
->sc_ttyp
, "mu%d: offline (port selector)\n", MUUNIT(bp
->b_dev
));
if (bp
== &cmtbuf
[MTUNIT(bp
->b_dev
)])
tprintf(sc
->sc_ttyp
, "mu%d: hard error (non data transfer) rn=%d bn=%d er=%o (octal) ds=%b\n",
MUUNIT(bp
->b_dev
), sc
->sc_blkno
, bp
->b_blkno
,
er
, MASKREG(sc
->sc_dsreg
), mtds_bits
);
printf(" interrupt code = %o (octal) <%s>\n failure code = %o (octal) <%s>\n",
(er
& MTER_INTCODE
), sc
->sc_mesg
,
(er
& MTER_FAILCODE
) >> 10, sc
->sc_fmesg
);
if ( ((er
& MTER_INTCODE
) == MTER_TMFLTB
)
|| ((er
& MTER_INTCODE
) == MTER_MBFLT
) ) {
mtcreset(mtaddr
); /* reset the controller */
register struct mtdevice
*mtaddr
;
mtaddr
->mtid
= MTID_CLR
; /* reset the TM78 */
for (i
= MTTIMEOUT
; i
> 0; i
--) {
DELAY(50); /* don't nag */
if ((mtaddr
->mtid
& MTID_RDY
) != 0)
return; /* exit when ready */
printf("mt: controller hung\n");
errno
= mtphys(dev
, uio
);
return (physio(mtstrategy
, &rmtbuf
[MTUNIT(dev
)], dev
, B_READ
, minphys
, uio
));
errno
= mtphys(dev
, uio
);
return (physio(mtstrategy
, &rmtbuf
[MTUNIT(dev
)], dev
, B_WRITE
, minphys
, uio
));
register int bsize
= uio
->uio_iov
->iov_len
;
|| ((mi
= mtinfo
[mtunit
]) == 0)
if ( (bsize
> 0xffff) /* controller limit */
|| (bsize
<= 0) ) /* ambiguous */
mtioctl(dev
, cmd
, data
, flag
)
register struct mu_softc
*sc
= &mu_softc
[MUUNIT(dev
)];
register struct buf
*bp
= &cmtbuf
[MTUNIT(dev
)];
register struct mtop
*mtop
;
register struct mtget
*mtget
;
/* We depend on the values and order of the MT codes here. */
{MT_WTM
,MT_SFORWF
,MT_SREVF
,MT_SFORW
,MT_SREV
,MT_REW
,MT_UNLOAD
,MT_SENSE
};
mtop
= (struct mtop
*)data
;
callcount
= mtop
->mt_count
;
callcount
= mtop
->mt_count
;
if ((callcount
<= 0) || (fcount
<= 0))
while (--callcount
>= 0) {
register int n
, fc
= fcount
;
sc
->sc_blkno
+= (daddr_t
)n
;
sc
->sc_nxrec
= sc
->sc_blkno
- 1;
sc
->sc_blkno
= (daddr_t
)0;
sc
->sc_nxrec
= (daddr_t
)INF
;
sc
->sc_blkno
= (daddr_t
)0;
sc
->sc_nxrec
= (daddr_t
)INF
;
sc
->sc_blkno
= (daddr_t
)(-1);
sc
->sc_nxrec
= (daddr_t
)(-1);
sc
->sc_blkno
+= (daddr_t
)n
;
sc
->sc_blkno
-= (daddr_t
)n
;
sc
->sc_resid
= callcount
+ fc
;
if ( (mtop
->mt_op
== MTFSR
)
|| (mtop
->mt_op
== MTBSR
) )
if (bp
->b_flags
& B_ERROR
)
mtget
= (struct mtget
*)data
;
mtget
->mt_erreg
= sc
->sc_erreg
;
mtget
->mt_resid
= sc
->sc_resid
;
mtcommand(dev
, MT_SENSE
, 1); /* update drive status */
mtget
->mt_dsreg
= sc
->sc_dsreg
;
mtget
->mt_type
= MT_ISMT
;
/* ignore EOT condition */
/* enable EOT condition */
register struct mba_device
*mi
;
register struct mba_regs
*mp
;
#define phys(a,b) ((b)((int)(a)&0x7fffffff))
mi
= phys(mtinfo
[0], struct mba_device
*);
mp
= phys(mi
->mi_hd
, struct mba_hd
*)->mh_physmba
;
blk
= 0; num
= blk
; start
= num
; blk
= start
;
mtaddr
= (struct mtdevice
*)&mp
->mba_drv
[mi
->mi_drive
];
mtaddr
->mttc
= MTTC_PDP11
|MTTC_1600BPI
;
mtaddr
->mtcs1
= MT_DCLR
|MT_GO
;
blk
= num
> DBSIZE
? DBSIZE
: num
;
mtdwrite(start
, blk
, mtaddr
, mp
);
if (mtaddr
->mtds
&MTDS_ERR
)
mtaddr
->mtcs1
= MT_REW
|MT_GO
;
mtdwrite(dbuf
, num
, mtaddr
, mp
)
register struct mtdevice
*mtaddr
;
for (i
= 0; i
< num
; i
++)
*(int *)io
++ = dbuf
++ | PG_V
;
mtaddr
->mtfc
= -(num
*NBPG
);
mp
->mba_bcr
= -(num
*NBPG
);
mtaddr
->mtcs1
= MT_WCOM
|MT_GO
;
while ((s
& MTDS_DRY
) == 0);
mtaddr
->mtcs1
= MT_WEOF
|MT_GO
;
register struct mu_softc
*sc
;
switch (sc
->sc_erreg
& MTER_INTCODE
) {
/* unexpected BOT detected */
sc
->sc_mesg
= "unexpected BOT";
switch ((sc
->sc_erreg
& MTER_FAILCODE
) >> 10) {
sc
->sc_fmesg
= "tape was at BOT";
sc
->sc_fmesg
= "BOT seen after tape started";
sc
->sc_fmesg
= "ARA ID detected";
sc
->sc_fmesg
= "unclassified failure code";
/* unexpected LEOT detected */
sc
->sc_mesg
= "unexpected LEOT";
sc
->sc_mesg
= "tape rewinding";
sc
->sc_mesg
= "drive not ready";
switch ((sc
->sc_erreg
& MTER_FAILCODE
) >> 10) {
sc
->sc_fmesg
= "TU on-line but not ready";
sc
->sc_fmesg
= "fatal error has occurred";
sc
->sc_fmesg
= "access allowed but not really";
sc
->sc_fmesg
= "unclassified failure code";
sc
->sc_mesg
= "drive not available";
/* unit does not exist */
sc
->sc_mesg
= "unit does not exist";
sc
->sc_mesg
= "not capable";
switch ((sc
->sc_erreg
& MTER_FAILCODE
) >> 10) {
sc
->sc_fmesg
= "no record found within 25 feet";
sc
->sc_fmesg
= "ID burst neither PE nor GCR";
sc
->sc_fmesg
= "ARA ID not found";
sc
->sc_fmesg
= "no gap found after ID burst";
sc
->sc_fmesg
= "unclassified failure code";
sc
->sc_mesg
= "long record";
switch ((sc
->sc_erreg
& MTER_FAILCODE
) >> 10) {
sc
->sc_fmesg
= "extended sense data not found";
sc
->sc_fmesg
= "extended sense data updated";
sc
->sc_fmesg
= "unclassified failure code";
sc
->sc_mesg
= "unreadable record";
sc
->sc_mesg
= "EOT error";
sc
->sc_mesg
= "bad tape";
switch ((sc
->sc_erreg
& MTER_FAILCODE
) >> 10) {
sc
->sc_fmesg
= "GCR write error";
sc
->sc_fmesg
= "GCR read error";
sc
->sc_fmesg
= "PE read error";
sc
->sc_fmesg
= "PE write error";
sc
->sc_fmesg
= "at least 1 bit set in ECCSTA";
sc
->sc_fmesg
= "PE write error";
sc
->sc_fmesg
= "GCR write error";
sc
->sc_fmesg
= "RSTAT contains bad code";
sc
->sc_fmesg
= "PE write error";
sc
->sc_fmesg
= "MASSBUS parity error";
sc
->sc_fmesg
= "invalid data transferred";
sc
->sc_fmesg
= "unclassified failure code";
sc
->sc_mesg
= "TM fault A";
switch ((sc
->sc_erreg
& MTER_FAILCODE
) >> 10) {
sc
->sc_fmesg
= "illegal command code";
sc
->sc_fmesg
= "DT command issued when NDT command active";
sc
->sc_fmesg
= "WMC error";
sc
->sc_fmesg
= "RUN not received from MASSBUS controller";
sc
->sc_fmesg
= "mismatch in command read - function routine";
sc
->sc_fmesg
= "ECC ROM parity error";
sc
->sc_fmesg
= "XMC ROM parity error";
sc
->sc_fmesg
= "mismatch in command read - ID burst command";
sc
->sc_fmesg
= "mismatch in command read - verify ARA burst command";
sc
->sc_fmesg
= "mismatch in command read - verify ARA ID command";
sc
->sc_fmesg
= "mismatch in command read - verify gap command";
sc
->sc_fmesg
= "mismatch in command read - read id burst command";
sc
->sc_fmesg
= "mismatch in command read - verify ARA ID command";
sc
->sc_fmesg
= "mismatch in command read - verify gap command";
sc
->sc_fmesg
= "mismatch in command read - find gap command";
sc
->sc_fmesg
= "WMC LEFT failed to set";
sc
->sc_fmesg
= "XL PE set in INTSTA register";
sc
->sc_fmesg
= "XMC DONE did not set";
sc
->sc_fmesg
= "WMC ROM PE or RD PE set in WMCERR register";
sc
->sc_fmesg
= "unclassified failure code";
sc
->sc_mesg
= "TU fault A";
switch ((sc
->sc_erreg
& MTER_FAILCODE
) >> 10) {
sc
->sc_fmesg
= "TU status parity error";
sc
->sc_fmesg
= "TU command parity error";
sc
->sc_fmesg
= "rewinding tape went offline";
sc
->sc_fmesg
= "tape went not ready during DSE";
sc
->sc_fmesg
= "TU CMD status changed during DSE";
sc
->sc_fmesg
= "TU never came up to speed";
sc
->sc_fmesg
= "TU velocity changed";
sc
->sc_fmesg
= "TU CMD did not load correctly to start tape motion";
sc
->sc_fmesg
= "TU CMD did not load correctly to set drive density";
sc
->sc_fmesg
= "TU CMD did not load correctly to start tape motion to write BOT ID";
sc
->sc_fmesg
= "TU CMD did not load correctly to backup tape to BOT after failing to write BOT ID";
sc
->sc_fmesg
= "failed to write density ID burst";
sc
->sc_fmesg
= "failed to write ARA burst";
sc
->sc_fmesg
= "failed to write ARA ID";
sc
->sc_fmesg
= "ARA error bit set in MTA status B register";
sc
->sc_fmesg
= "could not find a gap after ID code was written correctly";
sc
->sc_fmesg
= "TU CMD did not load correctly to start tape motion to read ID burst";
sc
->sc_fmesg
= "timeout looking for BOT after detecting ARA ID burst";
sc
->sc_fmesg
= "failed to write tape mark";
sc
->sc_fmesg
= "tape never came up to speed while trying to reposition for retry of writing tape mark";
sc
->sc_fmesg
= "TU CMD did not load correctly to start tape motion in erase gap routine";
sc
->sc_fmesg
= "could not detect a gap in in erase gap routine";
sc
->sc_fmesg
= "could not detect a gap after writing record";
sc
->sc_fmesg
= "read path terminated before entire record was written";
sc
->sc_fmesg
= "could not find a gap after writing record and read path terminated early";
sc
->sc_fmesg
= "TU CMD did not load correctly to backup for retry of write tape mark";
sc
->sc_fmesg
= "TU velocity changed after up to speed while trying to reposition for retry of writing tape mark";
sc
->sc_fmesg
= "TU CMD did not load correctly to backup to retry a load of BOT ID";
sc
->sc_fmesg
= "timeout looking for BOT after failing to write BOT ID";
sc
->sc_fmesg
= "TU velocity changed while writing PE gap before starting to write record";
sc
->sc_fmesg
= "TU CMD did not load correctly to set PE tape density at start of write BOT ID burst";
sc
->sc_fmesg
= "TU CMD did not load correctly to set GCR tape density after writing Density ID";
sc
->sc_fmesg
= "TU CMD did not load correctly to set PE tape density at start of read from BOT";
sc
->sc_fmesg
= "TU CMD did not load correctly to set GCR tape density after reading a GCR Density ID burst";
sc
->sc_fmesg
= "unclassified failure code";
sc
->sc_mesg
= "TM fault B";
switch ((sc
->sc_erreg
& MTER_FAILCODE
) >> 10) {
sc
->sc_fmesg
= "RST0 interrupt occurred with TM RDY set";
sc
->sc_fmesg
= "power failed to interrupt";
sc
->sc_fmesg
= "unknown interrupt on channel 5.5";
sc
->sc_fmesg
= "unknown interrupt on channel 6.5";
sc
->sc_fmesg
= "unknown interrupt on channel 7";
sc
->sc_fmesg
= "unknown interrupt on channel 7.5";
sc
->sc_fmesg
= "CAS contention retry count expired";
sc
->sc_fmesg
= "CAS contention error not retryable";
sc
->sc_fmesg
= "queue error, could not find queue entry";
sc
->sc_fmesg
= "queue entry already full";
sc
->sc_fmesg
= "8085 ROM parity error";
sc
->sc_fmesg
= "inline test failed";
sc
->sc_fmesg
= "unclassified failure code";
sc
->sc_mesg
= "MB fault";
switch ((sc
->sc_erreg
& MTER_FAILCODE
) >> 10) {
sc
->sc_fmesg
= "control bus parity error";
sc
->sc_fmesg
= "illegal register referenced";
sc
->sc_fmesg
= "unclassified failure code";
sc
->sc_mesg
= "keypad entry error";
sc
->sc_mesg
= "unclassified error";