Thread View: comp.sys.next.misc
1 messages
1 total messages
Started by Mark Andrews
Tue, 07 Apr 1992 20:32
MT-02 tape controller on NeXT SCSI
Author: Mark Andrews
Date: Tue, 07 Apr 1992 20:32
Date: Tue, 07 Apr 1992 20:32
269 lines
9146 bytes
9146 bytes
How to make the MT-02 SCSI tape drive useable ...
*****This post has no warranty*****
NeXT Answers hardware.762 gives details of how to set the NeXT st
driver into fixed block mode, allowing it to work with QIC style tape
drives. This has enabled my tape drive to work, but my drive has
performed badly, often bombing out with write errors. I knew it wasn't
the drive or the media because they both work when connected to a sun,
and the tape works in other drives. The clue came from the NeXT
Console where I found the following message.
st: cmd = 0xa sr_io_status = 2H
Sense key = 0x1 Sense Code = 0x0
A sense key of 0x1 indicates a recoverable error, ie one that the tape
drive fixed, e.g. a write failed but was sucessful on a subsequent
retry (provided the max retry limit wasn't reached). Some tape drivers
report the number of recoverable errors, and on some machines "mt
status" will report the number.
Anyway it turns out that the MT-02 tape controller has a bit which
controls how it handles soft errors. The default case when connected
to a NeXT is to for the tape drive to issue a CHECK CONDITION status
code after it executes a command if a recoverable error occured. The
NeXT st driver seems to handle this as if it were a real error and
bombs out at this point. The other mode is to have the drive
accumulate the number of soft errors, so that they can be collected
later by the REQUEST SENSE command.
The following tape utility adds to the code in NA.762 and gives the
option of setting the SEC bit. It also allows the user to set the
driver back to variable block mode, and execute the MODE SENSE and
REQUEST SENSE scsi commands.
Mark Andrews
abekas!mark@pyramid.com <non-NeXT mail>
abekas!cookie!mark@pyramid.com <NeXT mail ok>
/* */
/* NeXT scsi tape driver utility */
/* Mark Andrews 1992 */
/* This Code is Supplied as is with NO WARRANTY of any kind */
/* No resposibility can or will be accepted for any damage that using */
/* this program may cause */
/* It has only been tested on a SCSI tape drive with an MT-02 tape controller */
/* Note the SEC bit is part of the VENDOR unique stuff and may or may not */
/* work with other drives */
/* The MTIOCFIXBLK code is from NA.562 */
/* The REQUEST SENSE code is from a posting by louie@sayshell.umd.edu 3/10/92 */
/* */
#include <stdio.h>
#include <libc.h>
#include <sys/types.h>
#include <sys/file.h>
#include <sys/mtio.h>
#include <nextdev/scsireg.h>
#define SEC 0x1
#define QUIET 0
#define VERBOSE 1
char tape_name[11];
int tape;
struct modesel_parms msp;
struct scsi_req sr;
main(argc,argv)
int argc;
char *argv[];
{
char c;
int sf,sv,ms,rs,sc;
sf=sv=ms=rs=sc=0;
strcpy(tape_name,"/dev/rst0");
while((c=getopt(argc,argv,"hvrmsnf:")) !=EOF)
{
if(c=='n') strcpy(tape_name,"/dev/nrst0"); /* set device to non rewind */
if(c=='f') if(optarg!=NULL)sf=atoi(optarg);else sf=512; /* set to fixed block mode */
if(c=='v') sv=1; /* set to variable block mode */
if(c=='m') ms=1; /* mode sense */
if(c=='r') rs=1; /* request sense */
if(c=='s') sc=1; /* set the soft error bit */
if(c=='h') /* print usage */
fprintf(stderr,"Usage: %s -hvrmsnf [block size]\n%s%s%s%s%s%s%s",argv[0],
"\t-h : print usage,\n",
"\t-f # : set fixed block mode with size #,\n",
"\t-v : set variable block mode,\n",
"\t-m : do a mode sense command and report the results,\n",
"\t-r : do a request sense command and report the results,\n",
"\t-s : set the soft error bit,\n",
"\t-n : use /dev/nrst0 instead of /dev/rst0.\n");
}
/* open /dev/rst0 */
if((tape=open(tape_name,O_RDWR,777))==0)
{
fprintf(stderr,"Unable to open %s\n",tape_name);
exit(1);
}
if(sv)
{
if(!sf)
set_var_blk();
else
{
fprintf(stderr,"Can't set to both fixed and variable block mode\n");
problem();
}
}
if(sf) set_fix_blk(sf);
if(ms) mode_sense(VERBOSE);
if(rs) request_sense();
if(sc) set_sec();
/* close tape */
close (tape);
exit(0);
}
problem()
{
/* close tape */
close (tape);
exit(-1);
}
mode_sense(verbose)
int verbose;
{
/* do a mode sense ioctl */
msp.msp_bcount=13; /* think this is correct */
if(ioctl(tape,MTIOCMODSEN,&msp))
{
perror("mode sense ioctl failed\n");
exit(1);
}
if(!verbose)
return;
/* print out the returned data */
fprintf(stdout,"mode sense data length = %d\n",(int)msp.msp_data.msd_header.msh_sd_length_0);
fprintf(stdout,"media type = %d\n",(int)msp.msp_data.msd_header.msh_med_type);
if(msp.msp_data.msd_header.msh_wp)
fprintf(stdout,"tape is = write protected\n");
else
fprintf(stdout,"tape is = writeable\n");
fprintf(stdout,"buffered mode = %d\n",(int)msp.msp_data.msd_header.msh_bufmode);
fprintf(stdout,"speed = %d\n",(int)msp.msp_data.msd_header.msh_speed);
fprintf(stdout,"block descriptor length = %d\n",(int)msp.msp_data.msd_header.msh_bd_length);
fprintf(stdout,"density code = %d\n",(int)msp.msp_data.msd_blockdescript.msbd_density);
fprintf(stdout,"number of blocks = %d\n",(int)msp.msp_data.msd_blockdescript.msbd_numblocks);
fprintf(stdout,"block length = %d\n",(int)msp.msp_data.msd_blockdescript.msbd_blocklength);
fprintf(stdout,"vendor unique byte[0] = %d\n",(int)msp.msp_data.msd_vudata[0]);
}
mode_slct()
{
/* this routine assumes that the msp structure has already been */
/* initialized, a mode_sense is the best way to do this */
/* do a mode select ioctl */
if(ioctl(tape,MTIOCMODSEL,&msp))
{
perror("mode select ioctl failed\n");
return 1;
}
}
set_sec()
{
mode_sense(QUIET); /* do a mode sense */
msp.msp_data.msd_vudata[0]|=SEC; /* set the SEC bit */
mode_slct(); /* do a mode select */
}
set_fix_blk(blocksize)
int blocksize;
{
if(ioctl(tape,MTIOCFIXBLK,&blocksize))
{
perror("fixed block ioctl failed\n");
return 1;
}
}
set_var_blk()
{
if(ioctl(tape,MTIOCVARBLK))
{
perror("variable block ioctl failed\n");
return 1;
}
}
request_sense()
{
/* set up sr */
bzero(&sr, sizeof(sr));
sr.sr_dma_dir=SR_DMA_RD;
sr.sr_dma_max=sizeof(sr.sr_esense);
sr.sr_addr=(caddr_t)&sr.sr_esense;
sr.sr_ioto=2;
sr.sr_cdb.cdb_c6.c6_opcode=C6OP_REQSENSE;
sr.sr_cdb.cdb_c6.c6_len=sizeof(sr.sr_esense);
/* execute the request sense */
if(ioctl(tape,MTIOCSRQ,&sr))
{
perror("request sense ioctl failed\n");
return 1;
}
/* print the answers */
fprintf(stdout,"io status = %d\n",(int)sr.sr_io_status);
fprintf(stdout,"scsi status = %d\n",(int)sr.sr_scsi_status);
fprintf(stdout,"bytes dma'd = %d\n",(int)sr.sr_dma_xfr);
fprintf(stdout,"sense info bytes are =");
if(sr.sr_esense.er_ibvalid)
fprintf(stdout,"valid\n");
else
fprintf(stdout,"not valid\n");
fprintf(stdout,"error class = %d\n",(int)sr.sr_esense.er_class);
fprintf(stdout,"error code = %d\n",(int)sr.sr_esense.er_code);
fprintf(stdout,"segment number = %d\n",(int)sr.sr_esense.er_segment);
fprintf(stdout,"file mark found = ");
if(sr.sr_esense.er_filemark)
fprintf(stdout,"yes\n");
else
fprintf(stdout,"no\n");
fprintf(stdout,"end of medium = ");
if(sr.sr_esense.er_endofmedium)
fprintf(stdout,"yes\n");
else
fprintf(stdout,"no\n");
fprintf(stdout,"incorect length = ");
if(sr.sr_esense.er_badlen)
fprintf(stdout,"yes\n");
else
fprintf(stdout,"no\n");
fprintf(stdout,"sense key = %d\n",(int)sr.sr_esense.er_sensekey);
fprintf(stdout,"residue length = %d\n",(int)sr.sr_esense.er_info+((int)sr.sr_esense.er_infomsb<<24));
fprintf(stdout,"additional sense length = %d\n",(int)sr.sr_esense.er_addsenselen);
fprintf(stdout,"additional sense code = %d\n",(int)sr.sr_esense.er_addsensecode);
fprintf(stdout,"sense code qualifier = %d\n",(int)sr.sr_esense.er_qualifier);
fprintf(stdout,"status byte 13 = %d\n",(int)sr.sr_esense.er_stat_13);
fprintf(stdout,"status byte 14 = %d\n",(int)sr.sr_esense.er_stat_14);
fprintf(stdout,"status byte 15 = %d\n",(int)sr.sr_esense.er_stat_15);
fprintf(stdout,"recoverable errors = %d\n",(int)sr.sr_esense.er_err_count);
}
--
Mark Andrews
abekas!mark@pyramid.com
Thread Navigation
This is a paginated view of messages in the thread with full content displayed inline.
Messages are displayed in chronological order, with the original post highlighted in green.
Use pagination controls to navigate through all messages in large threads.
Back to All Threads