home *** CD-ROM | disk | FTP | other *** search
- #ident "$Id: aspi.c,v 1.1 1992/01/15 01:14:12 chris Exp $"
-
- #include <stdio.h>
- #include <fcntl.h>
- #include <dos.h>
- #include <string.h>
- #include <malloc.h>
- #include <ctype.h>
- #include <errno.h>
-
- /*
- * $Log: aspi.c,v $
- * Revision 1.1 1992/01/15 01:14:12 chris
- * Initial revision
- *
- *
- *
- * chris@alderan.sdata.de
- */
-
- #define DWORD unsigned long
- #ifndef TAPE_ID
- #define TAPE_ID "0:4:0"
- #endif
-
- #include "aspi.h"
- #include "scsi.h"
- #include "scsierr.h"
-
- #ifndef CTCTRL
- #include "tar.h"
- #endif
-
- static char *aspi_c_id = "$Id: aspi.c,v 1.1 1992/01/15 01:14:12 chris Exp $";
-
- void aspiinit();
- extern int errno;
-
-
- /*
- * The complete scsi address of our tape device
- */
- int adapter_id, scsi_tape_id, lun_id;
-
- /*
- * Because all the scsi functions start with:
- * SCSIfunc(adapter_id, scsi_tape_id, lun, .......)
- * .. we define a macro "TARGET", so that we can write SCSIfunc(TARGET, ...);
- */
- #define TARGET adapter_id, scsi_tape_id, lun_id
-
- #ifndef CTCTRL
-
- /* Flags to for use with the streamer (detected at aspiopen()) */
- static int aspifile, no_rewind;
-
- /* This holds the max., and min. recordsize, the streamer can deal with */
- static blocklimit lim;
- static long recsize; /* the record size to use */
- static int logrec; /* log2(recordsize) */
- static long apos; /* this holds the current archive file pointer */
- static int write_file_mark_on_close;
- static int end_of_medium;
- static unsigned char rsense[14]; /* array for scsi-sense-data */
-
- /*
- * The next two functions are called when you open a file.
- * They check if the filename specifies the scsi-tape.
- * The filenames used for that are "/dev/ct" - "rewind cartridge tape"
- * and "/dev/nrct" - "no rewind cartridge tape" (no rewind on close)
- * I just choose those names "/dev/ct" and "/dev/nrct" because the
- * filenames are unusual to exist on a MSDOS filesystem and also because
- * I'm used to them from my ix386. Anyway, there are no other dependencies
- * on those names in the whole program. So, if you prefer to change the
- * names to "/dev/rmt0" or whatever, just change them !
- * As you can see in aspicreate() and aspiopen(), I still open a
- * MSDOS-output-dummy-file. "nul:" is kind of /dev/null for MSDOS
- * and I had to do this because the MSDOS code from tar still
- * does some operations on this file like setmode(stream) etc. and
- * I was too lazy to change the code in tar. So, with this they
- * may do setmode()'s on the null-device as long as they want :-)
- */
-
-
- /*
- * Create an archive file
- */
-
- aspicreat(path, mode)
- char *path;
- int mode;
- {
- end_of_medium = 0;
-
- if ( !strcmp(path, "/dev/ct") ) {
- apos = 0l;
- no_rewind = 0;
- aspiinit();
- write_file_mark_on_close = 1;
- return (aspifile=creat("NUL", mode));
- } else if ( !strcmp(path,"/dev/nrct") ) {
- apos = 0l;
- no_rewind = 1;
- aspiinit();
- write_file_mark_on_close = 1;
- return (aspifile=creat("NUL", mode));
- }
- aspifile = -1;
- return creat(path, mode);
- }
-
- /*
- * Open an archive file
- */
-
- aspiopen(path, oflag, mode)
- char *path;
- int oflag;
- int mode;
- {
- end_of_medium = 0;
-
- if ( !strcmp(path, "/dev/ct") ) {
- apos = 0l;
- no_rewind = 0;
- aspiinit();
- if ( (oflag & O_WRONLY) || (oflag & O_RDWR) )
- write_file_mark_on_close = 1;
- else write_file_mark_on_close = 0;
- return (aspifile=open("NUL", oflag, mode));
- } else if ( !strcmp(path,"/dev/nrct") ) {
- apos = 0l;
- no_rewind = 1;
- aspiinit();
- if ( (oflag & O_WRONLY) || (oflag & O_RDWR) )
- write_file_mark_on_close = 1;
- else write_file_mark_on_close = 0;
- return (aspifile=open("NUL", oflag, mode));
- }
- aspifile = -1;
- return open(path, oflag, mode);
- }
-
-
- /*
- * So, all the other functions now just check if (fileds == aspifile)
- * and do redirect the opereation to the tape. Otherwise they just
- * hand the request to the original function (e.g aspiread()->read() etc.).
- */
-
-
- /*
- * Read data from an archive file
- */
-
- aspiread(fileds, buf, nbyte)
- int fileds;
- char *buf;
- int nbyte;
- {
- int i;
- unsigned int *u;
-
- if ( fileds == aspifile ) {
- u = ( unsigned int * ) &nbyte; /* Hack, I know */
- if ( nbyte % ( int ) recsize ) {
- ( void ) fprintf(stderr,
- "aspiread: Illegal blocklen for tape: %u\n", nbyte);
- ( void ) aspiclose(fileds);
- exit(EX_SYSTEM);
- }
- i = SCSIRead(TARGET, buf, ( long ) *u, logrec, 0, 1, rsense);
- if ( i ) { /* If any error ... */
- unsigned bytes_read;
-
- if ( i == E$BlankCheck ) { /* EEOM (early end of medium) */
- errno = ENOSPC;
- if ( (rsense[2] & 0x40) && (rsense[0] &0x80) ) {
- /* compute the number of bytes read */
- bytes_read = *u - ((rsense[6]+(rsense[5]<<8))<<logrec);
- apos += ( long ) bytes_read;
- return ( int ) bytes_read;
- } else return 0;
- } else if ( (i==E$Medium) && (rsense[2] & 0x40) && (rsense[0] & 0x80) ) {
- errno = ENOSPC;
- bytes_read = *u - ((rsense[6]+(rsense[5]<<8))<<logrec);
- apos += ( long ) bytes_read;
- return ( int ) bytes_read;
- } else {
- ( void ) fprintf(stderr,"aspiread: errno: %d\n", i);
- ( void ) aspiclose(fileds);
- exit(EX_SYSTEM);
- }
- }
- apos += ( long ) *u;
- return nbyte;
- }
- return read(fileds, buf, nbyte);
- }
-
- /*
- * Write data to an archive file
- */
-
- aspiwrite(fileds, buf, nbyte)
- int fileds;
- char *buf;
- int nbyte;
- {
- int i;
- unsigned int *u;
-
-
- if ( fileds == aspifile ) {
-
- if ( end_of_medium ) {
- /*
- * This only happens when an end_of_medium condition was detected
- * at the previous aspiwrite() call but all bytes were written to
- * the tape anyway. In this case we don't make anymore attempts to
- * write to the tape but return an ENOSPC error and set the size
- * of transfered bytes to 0
- */
- errno = ENOSPC;
- return 0;
- }
-
- u = ( unsigned int * ) &nbyte; /* Hack , i know */
-
- if ( nbyte % ( int ) recsize ) {
- ( void ) fprintf(stderr,
- "aspiwrite: Illegal blocklen for tape: %u\n", nbyte);
- ( void ) aspiclose(fileds);
- exit(EX_SYSTEM);
- }
-
- i = SCSIWrite(TARGET, buf, ( long ) *u, logrec, 1, rsense);
-
- if ( i == E$EndOfMedium ) {
- unsigned int bytes_read;
-
- end_of_medium = 1;
- if ( (rsense[0] & 0x80) && (rsense[6] || rsense[5]) ) {
- /* return the real number of bytes that were written to the tape */
- errno = ENOSPC;
- bytes_read = *u - ((rsense[6]+(rsense[5]<<8))<<logrec);
- apos += ( long ) bytes_read;
- return ( int ) bytes_read;
- } else i = 0; /* do not return an error if all bytes were written */
- }
- if ( i ) { /* any other error we can't recover */
- ( void ) fprintf(stderr,"aspiwrite: errno: %d\n", i);
- ( void ) aspiclose(fileds);
- exit(EX_SYSTEM);
- }
- apos += ( long ) *u;
- return nbyte;
- }
- return write(fileds, buf, nbyte);
- }
-
- /*
- * close an archive file
- */
-
- aspiclose(fileds)
- int fileds;
- {
- int i;
-
- if ( fileds == aspifile ) {
- /* first, write a filemark ! */
- if ( write_file_mark_on_close && (!end_of_medium) )
- if ( (i=SCSIWriteFilemarks(TARGET, 1l, 0, 0, 0)) )
- ( void ) fprintf(stderr,"aspiclose: Error writing filemark\n");
- /* then rewind the tape if we have to */
- if ( ! no_rewind ) {
- if ( (i=SCSIRewind(TARGET, 0, 0)) )
- ( void ) fprintf(stderr,"aspiclose: Error rewinding the tape\n");
- } else if ( ! write_file_mark_on_close ) {
- /*
- * This means we've been reading an archive on a "/dev/nrct" tape.
- * In this case we have seek over the filemark at the end of the
- * archive.
- */
- if ( (i=SCSISpace(TARGET, 1, 1l, 0)) )
- ( void ) fprintf(stderr,"aspiclose: Error seeking filemark\n");
- }
- apos = 0l;
- }
- return close(fileds);
- }
-
- /*
- * Seek on the archive file
- */
-
- long aspilseek(fileds, offset, whence)
- int fileds;
- long offset;
- int whence;
- {
- int i;
- long newpos;
-
- if ( fileds == aspifile ) {
- /*
- * NOTE: seeking backwards is not supported by every streamer.
- * The Archive Viper 2150S does, but I don't know about others.
- */
- switch ( whence ) {
- case SEEK_SET:
- newpos = offset;
- break;
- case SEEK_CUR:
- newpos = apos + offset;
- break;
- default:
- ( void ) fprintf(stderr, "aspilseek: mode %d not supported\n", whence);
- ( void ) aspiclose(fileds);
- exit(EX_SYSTEM);
- break;
- }
- if ( newpos % recsize ) {
- ( void ) fprintf(stderr,
- "aspilseek: can't seek to a non-block-boundary position (%ld)\n",
- newpos);
- ( void ) aspiclose(fileds);
- exit(EX_SYSTEM);
- }
- if ( (i=SCSISpace(TARGET, 0, (newpos-apos)>>logrec, 0)) ) {
- ( void ) fprintf(stderr, "aspilseek: SCSISpace retuned errno %d\n", i);
- ( void ) aspiclose(fileds);
- exit(EX_SYSTEM);
- }
- apos = newpos;
- return newpos;
- }
- return lseek(fileds, offset, whence);
- }
-
- #endif /* CTCTRL */
-
- /*
- * Here we start with all that aspi stuff !!!
- * --------------------------------------------
- * the way we get the entrypoint of the aspi - module is quite strange,
- * but anyway ..
- */
-
- /*
- * This will be the function for all aspi requests, it gets
- * initialized at aspiinit() and called from aspirequest()
- */
-
- void (far *aspi)(void far *) = (void far *) 0;
-
-
- /*
- * Initialize aspi and the tape device
- */
-
- void aspiinit()
- {
- int h,i;
- long l;
- union REGS inregs;
- union REGS outregs;
- char *getenv(), *tapeid;
-
- if ( (h=open("SCSIMGR$",0)) == -1 ) {
- perror("Opening ASPI Manager");
- exit(1);
- }
-
- /*
- * This is an ioctl(READ) to the "SCSIMGR$".
- * It returns the entrypoint of the aspi-module (far pointer)
- * in the 4 bytes, pointed to by the dx register.
- */
-
- inregs.x.ax = 0x4402;
- inregs.x.dx = ( int ) &aspi;
- inregs.x.cx = 4;
- inregs.x.bx = h;
- intdos(&inregs, &outregs);
-
- /*
- * Now find out on which device we have to operate
- */
- tapeid = getenv("TAPEID");
- if ( !tapeid ) tapeid = TAPE_ID;
- if ( (tapeid[1] != ':') || (tapeid[3] != ':') ||
- (!isdigit(tapeid[0])) || (!isdigit(tapeid[2])) || (!isdigit(tapeid[4])) ) {
- ( void ) fprintf(stderr,"aspiinit: Illegal TAPEID: \"%s\"\n", tapeid);
- exit(1);
- } else {
- adapter_id = tapeid[0] - '0';
- scsi_tape_id = tapeid[2] - '0';
- lun_id = tapeid[4] - '0';
- }
-
- #ifndef CTCTRL
-
- /*
- * Now, check the device ...
- */
- if ( (i=GetDeviceTyp( TARGET )) < 0 ) {
- ( void ) fprintf(stderr,
- "aspiinit: Can't determine type of device \"%s\"\n", tapeid);
- ( void ) fprintf(stderr,"aspiinit: GetDeviceTyp() returned errno %d\n", i);
- exit(EX_SYSTEM);
- } else if ( i != 1 ) {
- ( void ) fprintf(stderr,"aspiinit: device \"%s\" is not a streamer !\n",
- tapeid);
- ( void ) fprintf(stderr,"the typ returned by GetDeviceTyp was %d\n",i);
- exit(EX_SYSTEM);
- }
-
- /*
- * Now get the max. and min. recordsize for the streamer
- */
- if ( (i=SCSIReadBlockLimits(TARGET, &lim, 0)) != E$NoErr ) {
- ( void ) fprintf(stderr,"aspiinit: Can't read blocklimits. errno %d\n", i);
- exit(EX_SYSTEM);
- }
-
- /*
- * *** FIXME ***
- * I don't really know how to handle this. What I do is, check if we have
- * fixed record size (lim.max == lim.min), if this is not true, I don't
- * really know which record size I should take. For now I try 512 bytes,
- * and if 512 is not in range I try lim.min. This is probably not the
- * way to do it. Let me know if you know better.
- * chris@alderan.sdata.de
- */
-
- if ( lim.max == lim.min ) recsize = lim.max;
- else if ( (lim.min <= 512) && (lim.max>=512) ) recsize = 512;
- else recsize = lim.min;
-
- l = recsize; logrec = 0;
- while ( (l>>=1) ) ++logrec; /* logrec = log2(recsize) */
-
- #endif /* CTCTRL */
-
- }
-
- /*
- * This is the function that we call for all out aspi-requests.
- * The function simply takes our requestblock and hands it to
- * aspi() (the real aspi request function) and then it polls
- * and waits for the request to finish.
- */
-
- int aspireq(srb)
- void *srb;
- {
- int cnt;
-
- struct _srbinquiry *s;
- s = ( struct _srbinquiry *) srb;
- aspi(s);
- cnt = 10;
- while ( cnt-- ) while ( ! s->h.status ) ; /* POLL ! */
- if ( s->h.status == 1 ) return E$NoErr;
- return E$AspiErr;
- }
-
- /*
- * The following two commandos are supported directly by the ASPI module
- * and do not require the construction of a SCSI-CCB.
- */
-
- int HostAdapterInquiry(inq)
- aspiinquiry *inq;
- {
- struct _srbinquiry *srb;
- int i;
-
- /* allocate a SCSI Request Block (SRB) in the lower 1 MB */
-
- if ( (srb=calloc(sizeof(struct _srbinquiry), 1)) == ( char *) 0 )
- return(E$NoMem);
-
- srb->h.cmd = 0; /* Host Adapter Inquiry */
- srb->h.adapter = inq->adapter_num;
-
- /* issue the request */
- if ( (i=aspireq(srb)) ) { /* if error status */
- free(srb);
- return(i);
- }
-
- inq->adapters = srb->adapters; /* number of hostadapters */
- inq->target_id = srb->target_id;
-
- for(i=0; i<16; ++i) inq->manager_id[i] = srb->manager_id[i];
- inq->manager_id[16] = '\0';
-
- for(i=0; i<16; ++i) inq->adapter_id[i] = srb->adapter_id[i];
- inq->adapter_id[16] = '\0';
-
- free(srb);
- return(E$NoErr);
- }
-
- /*
- * GetDeviceTyp: The returned typ corresponds to the typ of an
- * SCSI-Inquiry command.
- */
-
- int GetDeviceTyp(adapter, target_id, lun)
- int adapter;
- int target_id;
- int lun;
- {
- struct _srbgettyp *srb;
- int i;
-
- /* allocate a SCSI Request Block (SRB) */
-
- if ( (srb=calloc(sizeof( struct _srbgettyp), 1)) == 0 ) return(E$NoMem);
-
- srb->h.cmd = 1;
- srb->h.adapter = adapter;
- srb->target_id = target_id;
- srb->lun = lun;
-
- /* Issue the request */
- if ( (i=aspireq(srb)) ) {
- switch ( srb->h.status ) {
- case 0x82:
- i = E$NoDevice;
- break;
- case 0x80:
- i = E$AspiInval;
- break;
- case 0x81:
- i = E$NoAdapter;
- break;
- case 0x02:
- i = E$Abort;
- break;
- }
- } else i = srb->typ;
-
- ( void ) free(srb);
- return(i);
- }
-
-
- /*
- * The ScsiIoError function is used to generate an unique errorcode
- * from the three different errorcode sources.
- * The errorcode sources are:
- * - The exit status of the aspi request
- * - The host adapter status
- * - The scsi target status
- * - The sense data structure
- *
- * Ahhmm ..... actually this makes FOUR different sources not three :-)
- * The function is local to this module and called by all the SCSI-IO
- * functions upon exit.
- */
-
- static int ScsiIoError(aspi_status, adapter_status, target_status, sense)
- int aspi_status;
- int adapter_status;
- int target_status;
- unsigned char *sense;
- {
- int i;
-
- switch ( aspi_status ) { /* check the aspi status */
- case 0x82:
- i = E$NoDevice;
- break;
- case 0x80:
- i = E$AspiInval;
- break;
- case 0x81:
- i = E$NoAdapter;
- break;
- case 0x02:
- i = E$Abort;
- break;
- case 0x04:
- /*
- * Ok, this means scsi-io-error, so we see if
- * we can find more details about the error.
- */
- i = E$IOErr;
- if ( adapter_status ) {
- switch ( adapter_status ) {
- case 0x11:
- i = E$SelTimeout;
- break;
- case 0x12:
- i = E$DataOverrun;
- break;
- case 0x13:
- i = E$BusFree;
- break;
- case 0x14:
- i = E$BusFail;
- break;
- }
- } else switch ( target_status ) {
- /*
- * If the adapter didn't show any errors
- * we going to check the target to see if
- * the target was the source of the error.
- */
- case 0x08:
- i = E$TargetBusy;
- break;
- case 0x18:
- i = E$Reservation;
- break;
- case 0x02:
- /*
- * Allright, the target has send
- * sense data to the sense-data allocation
- * area at the end of the srb.
- */
- if ( sense != ( unsigned char *) 0 ) switch ( sense[2] & 0x0f ) {
- case 0x00: /* This means "no sense", but we check for End of Medium */
- if ( sense[2] & 0x40 ) i = E$EndOfMedium;
- break;
- case 0x01:
- i = E$NoErr;/* this would be pretty stupid to report, but anyway */
- break;
- case 0x02:
- i = E$NotReady;
- break;
- case 0x03:
- i = E$Medium;
- break;
- case 0x04:
- i = E$Hardware;
- break;
- case 0x05:
- i = E$IllegalReq;
- break;
- case 0x06:
- i = E$UnitAttention;
- break;
- case 0x07:
- i = E$DataProtect;
- break;
- case 0x08:
- i = E$BlankCheck;
- break;
- case 0x0b:
- i = E$TargetAbort;
- break;
- case 0x0d:
- i = E$VolOverflow;
- break;
- }
- break;
- }
- break;
- }
- return(i);
- }
-
- int SCSIInquiry(adapter, target_id, lun, inq, sense)
- int adapter;
- int target_id;
- int lun;
- scsiinquiry far *inq;
- unsigned char *sense;
- {
- struct _srbio *srb;
- int i,j;
-
- /* allocate a SCSI Request Block (SRB) */
- if ( (srb=calloc(sizeof(struct _srbio), 1)) == 0 ) return(E$NoMem);
-
- srb->h.cmd = 2;
- srb->h.adapter = adapter;
- srb->h.flags = (1<<3);
- srb->target_id = target_id;
- srb->lun = lun;
- srb->buf_seg = FP_SEG(inq);
- srb->buf_off = FP_OFF(inq);
- srb->alloc_len = sizeof( scsiinquiry );
- srb->sense_len = 14;
- srb->cdb_len = 6;
- srb->ccb.inq.cmd = 0x12;
- srb->ccb.inq.lun = lun;
- srb->ccb.inq.len = sizeof( scsiinquiry );
-
- if ( (i=aspireq(srb)) ) {
- i = ScsiIoError(srb->h.status, srb->adapter_status,
- srb->target_status, srb->ccb.inq.sense);
- }
-
- if ( sense ) for(j=0; j<14; ++j) sense[j] = srb->ccb.inq.sense[j];
-
- ( void ) free(srb);
- return(i);
- }
-
-
- int SCSIResetDevice(adapter, target_id, lun)
- int adapter;
- int target_id;
- int lun;
- {
- struct _srbreset *srb;
- int i;
-
-
- /* allocate a SCSI Request Block (SRB) */
-
- if ( (srb=calloc(sizeof(struct _srbreset), 1)) == 0 ) return(E$NoMem);
-
- srb->h.cmd = 4;
- srb->h.adapter = 0;
- srb->target_id = target_id;
- srb->lun = lun;
-
- if ( (i=aspireq(srb)) )
- i = ScsiIoError(srb->h.status, srb->adapter_status,
- srb->target_status, ( unsigned char far * ) 0);
-
- ( void ) free (srb);
- return(i);
- }
-
- /*
- * The following commands are "Sequencial-Access Device" specific.
- */
-
- int SCSIErase(adapter, target_id, lun, immediate, lng, sense)
- int adapter;
- int target_id;
- int lun;
- int immediate;
- int lng;
- unsigned char *sense;
- {
- struct _srbio *srb;
- int i;
-
- /* allocate a SCSI Request Block (SRB) */
- if ( (srb=calloc(sizeof(struct _srbio), 1)) == 0 ) return(E$NoMem);
-
- srb->h.cmd = 2;
- srb->h.adapter = adapter;
- srb->target_id = target_id;
- srb->lun = lun;
- srb->sense_len = 14;
- srb->cdb_len = 6;
- srb->ccb.c6.cmd = 0x19;
- srb->ccb.c6.flag0 = lng;
- srb->ccb.c6.flag1 = immediate;
- srb->ccb.c6.lun = lun;
-
- if ( (i=aspireq(srb)) ) {
- if ( sense ) for(i=0; i<14; ++i) sense[i] = srb->ccb.c6.sense[i];
- i = ScsiIoError(srb->h.status, srb->adapter_status,
- srb->target_status, srb->ccb.c6.sense);
- }
-
- ( void ) free(srb);
-
- return(i);
- }
-
-
- int SCSILoad(adapter, target_id, lun, immediate, load, retention, eot, sense)
- int adapter;
- int target_id;
- int lun;
- int immediate;
- int load;
- int retention;
- int eot;
- unsigned char *sense;
- {
- struct _srbio *srb;
- int i;
-
-
- /* allocate a SCSI Request Block (SRB) */
- if ( (srb=calloc(sizeof(struct _srbio), 1)) == 0 ) return(E$NoMem);
-
- srb->h.cmd = 2;
- srb->h.adapter = adapter;
- srb->target_id = target_id;
- srb->lun = lun;
- srb->sense_len = 14;
- srb->cdb_len = 6;
- srb->ccb.ld.cmd = 0x1b;
- srb->ccb.ld.immediate = immediate;
- srb->ccb.ld.lun = lun;
- srb->ccb.ld.load = load;
- srb->ccb.ld.retention = retention;
- srb->ccb.ld.eot = eot;
-
- if ( (i=aspireq(srb)) ) {
- if ( sense ) for(i=0; i<14; ++i) sense[i] = srb->ccb.ld.sense[i];
- i = ScsiIoError(srb->h.status, srb->adapter_status,
- srb->target_status, srb->ccb.ld.sense);
- }
-
- ( void ) free(srb);
-
- return(i);
- }
-
-
- int SCSIRead(adapter, target_id, lun, buf, len, l2bf, sili, fixed, sense)
- int adapter;
- int target_id;
- int lun;
- char far *buf;
- DWORD len;
- int l2bf;
- int sili;
- int fixed;
- unsigned char *sense;
- {
- DWORD length;
- struct _srbio *srb;
- int i;
-
- /* allocate a SCSI Request Block (SRB) in the lower 1 MB */
-
- if ( (srb=calloc((DWORD) sizeof(struct _srbio), 1)) == 0 ) return(E$NoMem);
-
- length = ( fixed ) ? len>>l2bf : len;
-
- srb->h.cmd = 2; /* scsi I/O request */
- srb->h.adapter = adapter;
- srb->h.flags = (1<<3);
- srb->target_id = target_id;
- srb->lun = lun;
- srb->alloc_len = len;
- srb->sense_len = 14;
- srb->buf_seg = FP_SEG(buf);
- srb->buf_off = FP_OFF(buf);
- srb->cdb_len = 6;
- srb->ccb.rdwr.cmd = 0x08;
- srb->ccb.rdwr.fixed = fixed;
- srb->ccb.rdwr.sili = sili;
- srb->ccb.rdwr.lun = lun;
- srb->ccb.rdwr.len_0 = (length & 0xff);
- srb->ccb.rdwr.len_1 = ((length>>8) & 0xff);
- srb->ccb.rdwr.len_2 = ((length>>16) & 0xff);
-
- if ( (i=aspireq(srb)) ) {
- if ( sense ) for(i=0; i<14; ++i) sense[i] = srb->ccb.rdwr.sense[i];
- i = ScsiIoError(srb->h.status, srb->adapter_status,
- srb->target_status, srb->ccb.rdwr.sense);
- }
-
- ( void ) free(srb);
- return(i);
- }
-
-
- int SCSIReadBlockLimits(adapter, target_id, lun, lim, sense)
- int adapter;
- int target_id;
- int lun;
- blocklimit *lim;
- unsigned char *sense;
- {
- struct _srbio *srb;
- char *buf;
- unsigned char far *block;
- int i, j;
-
- /* allocate a SCSI Request Block (SRB) */
- if ( (srb=calloc(sizeof(struct _srbio), 1)) == 0 ) return(E$NoMem);
-
- /* allocate small data buffer */
- if ( (buf=calloc(64, 1)) == 0 ) return(E$NoMem);
-
- block = ( unsigned char far * ) buf;
-
- srb->h.cmd = 2;
- srb->h.adapter = adapter;
- srb->h.flags = (1<<3);
- srb->target_id = target_id;
- srb->lun = lun;
- srb->alloc_len = 6;
- srb->sense_len = 14;
- srb->buf_seg = FP_SEG(block);
- srb->buf_off = FP_OFF(block);
- srb->cdb_len = 6;
- srb->ccb.c6.cmd = 0x05;
- srb->ccb.c6.lun = lun;
-
- if ( (i=aspireq(srb)) ) {
- if ( sense ) for(i=0; i<14; ++i) sense[i] = srb->ccb.c6.sense[i];
- i = ScsiIoError(srb->h.status, srb->adapter_status,
- srb->target_status, srb->ccb.c6.sense);
- } else {
- lim->max = ( ((( DWORD ) buf[1])<<16) |
- ((( DWORD ) buf[2])<<8) |
- ((( DWORD ) buf[3])) );
- lim->min = ( ((( DWORD ) buf[4])<<8) |
- ((( DWORD ) buf[5])) );
- }
-
- ( void ) free(buf);
- ( void ) free(srb);
-
- return(i);
- }
-
- int SCSIRewind(adapter, target_id, lun, immediate, sense)
- int adapter;
- int target_id;
- int lun;
- int immediate;
- unsigned char *sense;
- {
- struct _srbio *srb;
- int i;
-
- /* allocate a SCSI Request Block (SRB) */
- if ( (srb=calloc(sizeof(struct _srbio), 1)) == 0 ) return(E$NoMem);
-
- srb->h.cmd = 2;
- srb->h.adapter = adapter;
- srb->target_id = target_id;
- srb->lun = lun;
- srb->sense_len = 14;
- srb->cdb_len = 6;
- srb->ccb.c6.cmd = 0x01;
- srb->ccb.c6.lun = lun;
- srb->ccb.c6.flag0 = immediate;
-
- if ( (i=aspireq(srb)) ) {
- if ( sense ) for(i=0; i<14; ++i) sense[i] = srb->ccb.c6.sense[i];
- i = ScsiIoError(srb->h.status, srb->adapter_status,
- srb->target_status, srb->ccb.c6.sense);
- }
-
- ( void ) free(srb);
-
- return(i);
- }
-
-
- int SCSISpace(adapter, target_id, lun, code, count, sense)
- int adapter;
- int target_id;
- int lun;
- int code;
- long count;
- unsigned char *sense;
- {
- DWORD lcount;
- struct _srbio *srb;
- int i;
-
- /* allocate a SCSI Request Block (SRB) */
- if ( (srb=calloc(sizeof(struct _srbio), 1)) == 0 ) return(E$NoMem);
-
- lcount = count;
-
- srb->h.cmd = 2;
- srb->h.adapter = adapter;
- srb->target_id = target_id;
- srb->lun = lun;
- srb->sense_len = 14;
- srb->cdb_len = 6;
- srb->ccb.spc.cmd = 0x11;
- srb->ccb.spc.code = code;
- srb->ccb.spc.lun = lun;
- srb->ccb.spc.cnt0 = (lcount & 0xff);
- srb->ccb.spc.cnt1 = ((lcount>>8) & 0xff);
- srb->ccb.spc.cnt2 = ((lcount>>16) & 0xff);
-
- if ( (i=aspireq(srb)) ) {
- if ( sense ) for(i=0; i<14; ++i) sense[i] = srb->ccb.spc.sense[i];
- i = ScsiIoError(srb->h.status, srb->adapter_status,
- srb->target_status, srb->ccb.spc.sense);
- }
-
- ( void ) free(srb);
-
- return(i);
- }
-
-
- int SCSIWrite(adapter, target_id, lun, buf, len, l2bf, fixed, sense)
- int adapter;
- int target_id;
- int lun;
- char far *buf;
- DWORD len;
- int l2bf;
- int fixed;
- unsigned char *sense;
- {
- DWORD length;
- struct _srbio *srb;
- int i;
-
- /* allocate a SCSI Request Block (SRB) in the lower 1 MB */
-
- if ( (srb=calloc(sizeof(struct _srbio), 1)) == 0 ) return(E$NoMem);
-
- length = ( fixed ) ? len>>l2bf : len;
-
- srb->h.cmd = 2; /* scsi I/O request */
- srb->h.adapter = adapter;
- srb->h.flags = (1<<4);
- srb->target_id = target_id;
- srb->lun = lun;
- srb->alloc_len = len;
- srb->sense_len = 14;
- srb->buf_seg = FP_SEG(buf);
- srb->buf_off = FP_OFF(buf);
- srb->cdb_len = 6;
- srb->ccb.rdwr.cmd = 0x0a;
- srb->ccb.rdwr.fixed = fixed;
- srb->ccb.rdwr.lun = lun;
- srb->ccb.rdwr.len_0 = (length & 0xff);
- srb->ccb.rdwr.len_1 = ((length>>8) & 0xff);
- srb->ccb.rdwr.len_2 = ((length>>16) & 0xff);
-
- if ( (i=aspireq(srb)) ) {
- if ( sense ) for(i=0; i<14; ++i) sense[i] = srb->ccb.rdwr.sense[i];
- i = ScsiIoError(srb->h.status, srb->adapter_status,
- srb->target_status, srb->ccb.rdwr.sense);
- }
-
- ( void ) free(srb);
- return(i);
- }
-
-
-
- int SCSIWriteFilemarks(adapter, target_id, lun, len, setmark, immediate, sense)
- int adapter;
- int target_id;
- int lun;
- DWORD len;
- int setmark;
- int immediate;
- unsigned char *sense;
- {
- DWORD length;
- struct _srbio *srb;
- int i;
-
- /* allocate a SCSI Request Block (SRB) */
-
- if ( (srb=calloc(sizeof(struct _srbio), 1)) == 0 ) return(E$NoMem);
-
- length = len;
-
- srb->h.cmd = 2; /* scsi I/O request */
- srb->h.adapter = adapter;
- srb->target_id = target_id;
- srb->lun = lun;
- srb->sense_len = 14;
- srb->cdb_len = 6;
- srb->ccb.rdwr.cmd = 0x10;
- srb->ccb.rdwr.fixed = immediate;
- srb->ccb.rdwr.sili = setmark;
- srb->ccb.rdwr.lun = lun;
- srb->ccb.rdwr.len_0 = (length & 0xff);
- srb->ccb.rdwr.len_1 = ((length>>8) & 0xff);
- srb->ccb.rdwr.len_2 = ((length>>16) & 0xff);
-
- if ( (i=aspireq(srb)) ) {
- if ( sense ) for(i=0; i<14; ++i) sense[i] = srb->ccb.rdwr.sense[i];
- i = ScsiIoError(srb->h.status, srb->adapter_status,
- srb->target_status, srb->ccb.rdwr.sense);
- }
-
- ( void ) free(srb);
- return(i);
- }
-
- #ifdef TEST_ASPI
- main()
- {
- aspiinquiry inq;
- scsiinquiry sinq;
- int i, j;
- long l;
- char *buf;
-
- aspiinit();
-
- inq.adapter_num = 0;
- HostAdapterInquiry(&inq);
-
-
- printf("%d adapters, target:%d\n", inq.adapters, inq.target_id);
- printf("Manager id: %s\n", inq.manager_id);
- printf("adapter id: %s\n", inq.adapter_id);
-
- printf("\nrecsize: %ld, log2(recsize)= %d\n", recsize, logrec);
-
- if ( (i=SCSIInquiry(TARGET, &sinq, 0)) != E$NoErr ) {
- printf("Scsi Inquiry returned %d\n", i);
- } else {
- printf("type,pqual,dqual: %d, %d, %d\n", sinq.per_type,
- sinq.per_qualify, sinq.dev_qualify);
- printf("vendor_id:%.8s\n", sinq.vendor_id);
- printf("product_id:%.16s\n", sinq.product_id);
- printf("revision:%.4s\n", sinq.revision);
- printf("vendor:%.20s\n", sinq.vendor);
- }
-
- if ( (buf=malloc(32768)) == 0 ) {
- printf("can't alloc buf\n");
- exit(0);
- }
-
- printf("\nBlocklimits, max:%ld min:%ld\n", lim.max, lim.min);
-
- i = SCSILoad(TARGET, 0, 1, 0, 0, 0);
- printf("\nLoad returned %d\n -->", i);
-
- #if 0
- printf("seeking to tape file 2...\n");
-
- if ( (i=SCSISpace(TARGET, 1, ( DWORD ) 1, 0)) )
- printf("Error %d\n", i );
- else printf("OK\n");
-
- printf("seeking to tape block 400 on file 2...\n");
- if ( (i=SCSISpace(TARGET, 0, ( DWORD ) 400, 0)) )
- printf("Error %d\n", i );
- else printf("OK\n");
-
- printf("Writing two sectors..(this should return an error)...\n");
- i = SCSIWrite(TARGET, buf, 1024l, 9, 1, 0);
- printf("Write returned %d\n", i);
-
- printf("seeking back two sectors...\n");
- if ( (i=SCSISpace(TARGET, 0, -2l, 0)) )
- printf("Error %d\n", i );
- else printf("OK\n");
-
- printf("reading back the two sectors...\n");
- i = SCSIRead(TARGET, buf, 1024l, 9, 0, 1, 0);
- printf("Read returned %d\n", i);
-
- printf("rewinding the tape...\n");
- i = SCSIRewind(TARGET, 0, 0);
- printf("Rewind returned %d\n", i);
-
- printf("seeking to the end of the data...\n");
- if ( (i=SCSISpace(TARGET, 3, 0l, 0)) )
- printf("Error %d\n", i );
- else printf("OK\n");
-
- printf("Writing two sectors...\n");
- i = SCSIWrite(TARGET, buf, 1024l, 9, 1, 0);
- printf("Write returned %d\n", i);
-
- printf("Writing two sectors...\n");
- i = SCSIWrite(TARGET, buf, 1024l, 9, 1, 0);
- printf("Write returned %d\n", i);
-
- printf("Writing a file mark !\n");
- i = SCSIWriteFilemarks(TARGET, 1l, 0, 0, 0);
- printf("Write returned %d\n", i);
-
- printf("rewinding the tape...\n");
- i = SCSIRewind(TARGET, 0, 0);
- printf("Rewind returned %d\n", i);
-
- printf("Now counting files ...\n");
- i = 0;
- while ( !SCSISpace(TARGET, 1, 1l, 0) ) ++ i;
- printf("... there are %d files on the tape now\n",i);
-
- printf("rewinding the tape...\n");
- i = SCSIRewind(TARGET, 0, 0);
- printf("Rewind returned %d\n", i);
-
- printf("eraseing the tape...\n");
- i = SCSIErase(TARGET, 0, 0, 0);
- printf("erase returned %d\n", i);
- #endif
-
- l = 0l;
-
- printf("Now see what kind of errors we get at Overflow\n");
- while ( l < 4080l ) {
- i = SCSIRead(TARGET, buf, 32768l, 9, 0, 1, rsense);
- if ( i ) {
- printf("reading block # %ld: errno: %d rsense:", l, i);
- for(j=0; j<14; ++j) printf(" %02x", rsense[j]);
- printf("\n");
- }
- ++l;
- }
-
- /*
- while ( !(i=SCSIWrite(TARGET, buf, 32768l, 9, 1, rsense)) ) ++l;
- printf("last block was %ld\n", l);
- printf("errno: %d sense:", i);
- for(j=0; j<14; ++j) printf(" %02x", rsense[j]);
- printf("\n");
- */
-
- i = SCSILoad(TARGET, 0, 0, 0, 0, 0);
- printf("Unload returned %d\n -->", i);
- free(buf);
- }
- #endif
-