/* ** TapeIO: performs operations to the tape unit via SCSI-direct for BTNtape ** Version 1.0 09/10/90 ** ** (c) Copyright 1990 Robert Rethemeyer. ** This code is freely distributable and redistributable, ** for non-commercial purposes, provided this notice is included. ** ** This code was derived from programs written by Robert Mitchell. */ #include #include #include #include #include #include #include #include #if defined AZTEC_C #include #elif defined LATTICE #include #include #endif #include "tape.h" #include "tplink.h" /* the following SCSI commands are defined for the 3M MCD-403 tape unit */ #define CMD_TEST_UNIT_READY 0x00 #define CMD_REZERO 0x01 #define CMD_REQUEST_SENSE 0x03 #define CMD_FORMAT_UNIT 0x04 #define CMD_SEND_SYSTEM_DATA 0x05 #define CMD_RECEIVE_SYSTEM_DATA 0x06 #define CMD_REASSIGN_BLOCKS 0x07 #define CMD_SCSI_READ 0x08 #define CMD_VERIFY_UNIT 0x09 #define CMD_SCSI_WRITE 0x0a #define CMD_SEEK 0x0b #define CMD_READ_SCSI_DEFECT 0x0d #define CMD_READ_CONTROLLER_INFO 0x0e #define CMD_WRITE_CONTROLLER_INFO 0x0f #define CMD_DRIVE_PASS_THRU 0x10 #define CMD_READ_DRIVE_LINES 0x11 #define CMD_INQUIRY 0x12 #define CMD_READ_QIC100_INFO 0x13 #define CMD_WRITE_QIC100_INFO 0x14 #define CMD_MODE_SELECT 0x15 #define CMD_RESERVE 0x16 #define CMD_RELEASE 0x17 #define CMD_READ_QIC100_DEFECT 0x19 #define CMD_MODE_SENSE 0x1a #define CMD_LOAD_UNLOAD 0x1b #define CMD_READ_DIAG_RESULT 0x1c #define CMD_SEND_DIAG 0x1d #define CMD_READ_CAPACITY 0x25 #define CMD_READ_EXTENDED 0x28 #define CMD_WRITE_EXTENDED 0x2a #define CMD_SEEK_EXTENDED 0x2b #define CMD_READ_SCSI_DEFECT_DATA 0x37 #define CMD_WRITE_BUFFER 0x3b #define CMD_READ_BUFFER 0x3c #define CBLEN 6 extern UBYTE *cdb; extern UBYTE *sns; extern struct SCSICmd *cmd; extern UBYTE *TapeBuff[2]; extern struct IOStdReq *ior; extern ULONG blknum; extern ULONG numblks; extern ULONG rwlen; extern ULONG bugmask; extern long tpsize; extern struct tplink *linktp; extern short inprog; extern char dbb[80]; long TapeIO(int toper, int bn, UBYTE ctl) { char *z; short i; if(inprog) { WaitIO((struct IORequest *)ior); inprog = FALSE; if(ior->io_Error) return((long)((ior->io_Error << 8) + cmd->scsi_Status)); } if(toper == TFINISH) return(0L); cmd->scsi_Command = cdb; cmd->scsi_CmdLength = CBLEN; cmd->scsi_Status = 0; ior->io_Command = HD_SCSICMD; ior->io_Data = (APTR) cmd; ior->io_Length = sizeof(struct SCSICmd); ior->io_Error = 0; ior->io_Flags = IOF_QUICK; for (i=0 ; i=tpsize) NewTape(); cdb[0] = CMD_SCSI_READ; cdb[2] = (UBYTE) ( (blknum >> 8) & 0x00ff); cdb[3] = (UBYTE) (blknum & 0x00ff); cdb[4] = (UBYTE) numblks ; cmd->scsi_Data = (UWORD *) TapeBuff[bn]; cmd->scsi_Length = rwlen; cmd->scsi_Flags = SCSIF_READ; MPR2("Reading block %d * %d\n",blknum,numblks) break; case TWRITE: if((blknum+numblks)>=tpsize) NewTape(); cdb[0] = CMD_SCSI_WRITE; cdb[2] = (UBYTE)(blknum >> 8) & 0x00ff; cdb[3] = (UBYTE)(blknum & 0x00ff); cdb[4] = (UBYTE) numblks ; /* cmd->scsi_Data = (UWORD *) TapeBuff[bn]; */ /* 2090A bug fix */ cmd->scsi_Data = (UWORD *) ((ULONG) TapeBuff[bn] | bugmask); cmd->scsi_Length = rwlen; cmd->scsi_Flags = SCSIF_WRITE; MPR2("Writing block %d * %d\n",blknum,numblks) break; case TREWIND: cdb[0] = CMD_REZERO; cmd->scsi_Data = (UWORD *) TapeBuff[bn]; cmd->scsi_Length = 0; cmd->scsi_Flags = 0; MPR0("Rewinding\n") break; case TSENSE: cdb[0] = CMD_REQUEST_SENSE; cdb[4] = 28; /* extended sense */ cmd->scsi_Length = 28; cmd->scsi_Data = (UWORD *) sns; cmd->scsi_Flags = SCSIF_READ; MPR0("Sense:") break; case RDCAP: cdb[0] = CMD_READ_CAPACITY; cmd->scsi_Length = 8; cmd->scsi_Data = (UWORD *) sns; cmd->scsi_Flags = SCSIF_READ; MPR0("Capacity:") break; case RAWCMD: /* Convert hex in tape buffer to bytes in command buffer. */ i = 0; /* Bytes are specified by hex digit pairs sep. by blanks */ z = (char *)TapeBuff[bn]; /* terminated by newline */ while(z[0]!='\n' && i<32) cdb[i++] = (UBYTE) 0xff & strtol(z,&z,16); cmd->scsi_Data = (UWORD *) sns; cmd->scsi_Length = 0; cmd->scsi_Flags = 0; MPR0("Raw command\n") break; } if(ctl == CTLWAIT) { DoIO ((struct IORequest *)ior); /* start sync io */ return((long)((ior->io_Error << 8) + cmd->scsi_Status)); } else { BeginIO((struct IORequest *)ior); /* start async io */ if(ior->io_Error) return((long)((ior->io_Error << 8) + cmd->scsi_Status)); if( !(ior->io_Flags & IOF_QUICK) ) inprog = TRUE; return(0L); } } /************************************************************************** * NewTape() Displays a requester asking user to insert a new tape. */ void NewTape(void) { extern ULONG blknum; extern short reserved; extern void DoSense(); static struct IntuiText reqtext[] = { { AUTOFRONTPEN,AUTOBACKPEN,AUTODRAWMODE,AUTOLEFTEDGE,AUTOTOPEDGE,AUTOITEXTFONT, " EOT: Insert next tape", AUTONEXTTEXT }, { AUTOFRONTPEN,AUTOBACKPEN,AUTODRAWMODE,AUTOLEFTEDGE,AUTOTOPEDGE,AUTOITEXTFONT, "Continue", AUTONEXTTEXT }, { AUTOFRONTPEN,AUTOBACKPEN,AUTODRAWMODE,AUTOLEFTEDGE,AUTOTOPEDGE,AUTOITEXTFONT, "Quit", AUTONEXTTEXT } }; TapeIO(TFINISH,0,CTLWAIT); /* yeeks, recursion! */ MPR0("Time for a new tape\n") if( AutoRequest(NULL,&reqtext[0],&reqtext[1],&reqtext[2],NULL,NULL,250,50) ) { blknum=reserved; /* reset block number for new tape */ DoSense(0); /* eat tape change status (recursion again) */ } return; }