/* Copyright 1997, 1998 Leonard Zubkoff <lnz@dandelion.com>
- Changes in Feb 2000 Eric Green <eric@estinc.com>
+ Changes in Feb 2000 Eric Green <eric@badtux.org>
+ Copyright 2007-2008 by Robert Nelson <robertn@the-nelsons.org>
-$Date: 2001/06/19 21:51:32 $
-$Revision: 1.2 $
+$Date: 2008-08-19 03:03:38 -0700 (Tue, 19 Aug 2008) $
+$Revision: 193 $
This program is free software; you may redistribute and/or modify it under
the terms of the GNU General Public License Version 2 as published by the
*/
-#include <linux/param.h>
-#include <scsi/sg.h>
-
-/* this is the SCSI commands for Linux. Note that <eric@estinc.com> changed
+/* this is the SCSI commands for Linux. Note that <eric@badtux.org> changed
* it from using SCSI_IOCTL_SEND_COMMAND to using the SCSI generic interface.
*/
#ifndef HZ
#warning "HZ is not defined, mtx might not work correctly!"
-#define HZ 100
+#define HZ 100 /* Jiffys for SG_SET_TIMEOUT */
#endif
/* These are copied out of BRU 16.1, with all the boolean masks changed
#define STILL_A_VALID_READ(s) (HIT_FILEMARK(s) || SHORT_READ(s) || HIT_EOD(s) || HIT_EOP(s) || HIT_EOM(s))
+#define SG_SCSI_DEFAULT_TIMEOUT (HZ*60*5) /* 5 minutes? */
-#define SG_SCSI_DEFAULT_TIMEOUT HZ*60*5 /* 5 minutes */
+static int pack_id;
+static int sg_timeout;
DEVICE_TYPE SCSI_OpenDevice(char *DeviceName)
{
- int timeout=SG_SCSI_DEFAULT_TIMEOUT;
- int DeviceFD = open(DeviceName, O_RDWR);
- if (DeviceFD < 0)
- FatalError("cannot open SCSI device '%s' - %m\n", DeviceName);
+ int timeout = SG_SCSI_DEFAULT_TIMEOUT;
+#ifdef SG_IO
+ int k; /* version */
+#endif
+ int DeviceFD = open(DeviceName, O_RDWR);
- if(ioctl(DeviceFD, SG_SET_TIMEOUT, &timeout)) {
- FatalError("failed to set sg timeout - %m\n");
- }
+ if (DeviceFD < 0)
+ FatalError("cannot open SCSI device '%s' - %m\n", DeviceName);
- return (DEVICE_TYPE) DeviceFD;
-}
-static int sg_timeout = SG_SCSI_DEFAULT_TIMEOUT ;
+#ifdef SG_IO
+ /* It is prudent to check we have a sg device by trying an ioctl */
+ if ((ioctl(DeviceFD, SG_GET_VERSION_NUM, &k) < 0) || (k < 30000))
+ {
+ FatalError("%s is not an sg device, or old sg driver\n", DeviceName);
+ }
+#endif
-void SCSI_Set_Timeout(int secs) {
- sg_timeout=secs*HZ;
+ if (ioctl(DeviceFD, SG_SET_TIMEOUT, &timeout))
+ {
+ FatalError("failed to set sg timeout - %m\n");
+ }
+ pack_id = 1; /* used for SG v3 interface if possible. */
+ return (DEVICE_TYPE) DeviceFD;
+}
+
+void SCSI_Set_Timeout(int secs)
+{
+ sg_timeout = secs * HZ;
}
-void SCSI_Default_Timeout(void) {
- sg_timeout=SG_SCSI_DEFAULT_TIMEOUT;
+void SCSI_Default_Timeout(void)
+{
+ sg_timeout = SG_SCSI_DEFAULT_TIMEOUT;
}
-void SCSI_CloseDevice(char *DeviceName,
- DEVICE_TYPE DeviceFD)
+void SCSI_CloseDevice(char *DeviceName, DEVICE_TYPE DeviceFD)
{
- if (close(DeviceFD) < 0)
- FatalError("cannot close SCSI device '%s' - %m\n", DeviceName);
+ if (close(DeviceFD) < 0)
+ FatalError("cannot close SCSI device '%s' - %m\n", DeviceName);
}
* Seagate autoloader (hopefully!).
*/
/* Get the SCSI ID and LUN... */
-scsi_id_t *SCSI_GetIDLun(DEVICE_TYPE fd) {
- int status;
- scsi_id_t *retval;
-
- struct my_scsi_idlun {
- int word1;
- int word2;
- } idlun;
-
- status=ioctl(fd,SCSI_IOCTL_GET_IDLUN,&idlun);
- if (status) {
- return NULL; /* sorry! */
- }
-
- retval=(scsi_id_t *)xmalloc(sizeof(scsi_id_t));
- retval->id=idlun.word1 & 0xff;
- retval->lun=idlun.word1 >> 8 & 0xff;
+scsi_id_t *SCSI_GetIDLun(DEVICE_TYPE fd)
+{
+ int status;
+ scsi_id_t *retval;
+
+ struct my_scsi_idlun
+ {
+ int word1;
+ int word2;
+ } idlun;
+
+ status = ioctl(fd, SCSI_IOCTL_GET_IDLUN, &idlun);
+ if (status)
+ {
+ return NULL; /* sorry! */
+ }
+
+ retval = (scsi_id_t *)xmalloc(sizeof(scsi_id_t));
+ retval->id = idlun.word1 & 0xff;
+ retval->lun = idlun.word1 >> 8 & 0xff;
+
#ifdef DEBUG
- fprintf(stderr,"SCSI:ID=%d LUN=%d\n",retval->id,retval->lun);
+ fprintf(stderr, "SCSI:ID=%d LUN=%d\n", retval->id, retval->lun);
#endif
- return retval;
+
+ return retval;
+}
+
+
+/* Changed January 2001 by Eric Green <eric@badtux.org> to
+ * use the Linux version 2.4 SCSI Generic facility if available.
+ * Liberally cribbed code from Doug Gilbert's sg3 utils.
+ */
+
+#ifdef SG_IO
+#include "sg_err.h" /* error stuff. */
+#include "sg_err.c" /* some of Doug Gilbert's routines */
+
+/* Use the new SG_IO structure */
+int SCSI_ExecuteCommand(DEVICE_TYPE DeviceFD,
+ Direction_T Direction,
+ CDB_T *CDB,
+ int CDB_Length,
+ void *DataBuffer,
+ int DataBufferLength,
+ RequestSense_T *RequestSense)
+{
+ unsigned int status;
+ sg_io_hdr_t io_hdr;
+
+ memset(&io_hdr, 0, sizeof(sg_io_hdr_t));
+ memset(RequestSense, 0, sizeof(RequestSense_T));
+
+ /* Fill in the common stuff... */
+ io_hdr.interface_id = 'S';
+ io_hdr.cmd_len = CDB_Length;
+ io_hdr.mx_sb_len = sizeof(RequestSense_T);
+ io_hdr.dxfer_len = DataBufferLength;
+ io_hdr.cmdp = (unsigned char *) CDB;
+ io_hdr.sbp = (unsigned char *) RequestSense;
+ io_hdr.dxferp = DataBuffer;
+ io_hdr.timeout = sg_timeout * 10; /* Convert from Jiffys to milliseconds */
+
+ if (Direction==Input)
+ {
+ /* fprintf(stderr,"direction=input\n"); */
+ io_hdr.dxfer_direction=SG_DXFER_FROM_DEV;
+ }
+ else
+ {
+ /* fprintf(stderr,"direction=output\n"); */
+ io_hdr.dxfer_direction=SG_DXFER_TO_DEV;
+ }
+
+ /* Now do it: */
+ if ((status = ioctl(DeviceFD, SG_IO , &io_hdr)) || io_hdr.masked_status)
+ {
+ /* fprintf(stderr, "smt_scsi_cmd: Rval=%d Status=%d, errno=%d [%s]\n",status, io_hdr.masked_status,
+ errno,
+ strerror(errno)); */
+
+ switch (sg_err_category3(&io_hdr))
+ {
+ case SG_ERR_CAT_CLEAN:
+ case SG_ERR_CAT_RECOVERED:
+ break;
+
+ case SG_ERR_CAT_MEDIA_CHANGED:
+ return 2;
+
+ default:
+ return -1;
+ }
+
+ /* fprintf(stderr,"host_status=%d driver_status=%d residual=%d writelen=%d\n",io_hdr.host_status,io_hdr.driver_status,io_hdr.resid,io_hdr.sb_len_wr ); */
+
+ return -errno;
+ }
+
+ /* Now check the returned statuses: */
+ /* fprintf(stderr,"host_status=%d driver_status=%d residual=%d writelen=%d\n",io_hdr.host_status,io_hdr.driver_status,io_hdr.resid,io_hdr.sb_len_wr ); */
+
+ SCSI_Default_Timeout(); /* reset back to default timeout, sigh. */
+ return 0;
}
-
+
+#else
/* Changed February 2000 by Eric Green <eric@estinc.com> to
* use the SCSI generic interface rather than SCSI_IOCTL_SEND_COMMAND
* manner. This sucks. But sucks less than SCSI_IOCTL_SEND_COMMAND, sigh.
*/
+
#ifndef OLD_EXECUTE_COMMAND_STUFF
static void slow_memcopy(unsigned char *src, unsigned char *dest, int numbytes)
{
- while (numbytes--) {
- *dest++ = *src++;
- }
+ while (numbytes--)
+ {
+ *dest++ = *src++;
+ }
}
int SCSI_ExecuteCommand(DEVICE_TYPE DeviceFD,
- Direction_T Direction,
- CDB_T *CDB,
- int CDB_Length,
- void *DataBuffer,
- int DataBufferLength,
- RequestSense_T *RequestSense)
+ Direction_T Direction,
+ CDB_T *CDB,
+ int CDB_Length,
+ void *DataBuffer,
+ int DataBufferLength,
+ RequestSense_T *RequestSense)
{
+ unsigned char *Command=NULL; /* the command data struct sent to them... */
+ unsigned char *ResultBuf=NULL; /* the data we read in return... */
- unsigned char *Command=NULL; /* the command data struct sent to them... */
- unsigned char *ResultBuf=NULL; /* the data we read in return... */
-
- unsigned char *src; /* for copying stuff, sigh. */
- unsigned char *dest; /* for copy stuff, again, sigh. */
+ unsigned char *src; /* for copying stuff, sigh. */
+ unsigned char *dest; /* for copy stuff, again, sigh. */
- int write_length = sizeof(struct sg_header)+CDB_Length;
- int i; /* a random index... */
- int result; /* the result of the write... */
-
-
- struct sg_header *Header; /* we actually point this into Command... */
- struct sg_header *ResultHeader; /* we point this into ResultBuf... */
+ int write_length = sizeof(struct sg_header)+CDB_Length;
+ int i; /* a random index... */
+ int result; /* the result of the write... */
+ struct sg_header *Header; /* we actually point this into Command... */
+ struct sg_header *ResultHeader; /* we point this into ResultBuf... */
- /* First, see if we need to set our SCSI timeout to something different */
- if (sg_timeout != SG_SCSI_DEFAULT_TIMEOUT) {
- /* if not default, set it: */
+ /* First, see if we need to set our SCSI timeout to something different */
+ if (sg_timeout != SG_SCSI_DEFAULT_TIMEOUT)
+ {
+ /* if not default, set it: */
#ifdef DEBUG_TIMEOUT
- fprintf(stderr,"Setting timeout to %d\n", sg_timeout);
- fflush(stderr);
+ fprintf(stderr,"Setting timeout to %d\n", sg_timeout);
+ fflush(stderr);
#endif
- if(ioctl(DeviceFD, SG_SET_TIMEOUT, &sg_timeout)) {
- FatalError("failed to set sg timeout - %m\n");
- }
- }
-
- if (Direction == Output) { /* if we're writing, our length is longer... */
- write_length += DataBufferLength;
- }
-
- /* allocate some memory... enough for the command plus the header +
- * any other data that we may need here...
- */
-
- Command=(unsigned char *)xmalloc(write_length);
- Header = (struct sg_header *) Command; /* make it point to start of buf */
-
- dest=Command; /* now to copy the CDB... from start of buffer,*/
- dest+= sizeof(struct sg_header); /* increment it past the header. */
-
- slow_memcopy((char *)CDB,dest,CDB_Length);
-
- /* if we are writing additional data, tack it on here! */
- if (Direction == Output) {
- dest += CDB_Length;
- slow_memcopy(DataBuffer,dest,DataBufferLength); /* copy to end of command */
- }
- /* Now to fill in the Header struct: */
- Header->reply_len=DataBufferLength+sizeof(struct sg_header);
+ if(ioctl(DeviceFD, SG_SET_TIMEOUT, &sg_timeout))
+ {
+ FatalError("failed to set sg timeout - %m\n");
+ }
+ }
+
+ if (Direction == Output)
+ {
+ /* if we're writing, our length is longer... */
+ write_length += DataBufferLength;
+ }
+
+ /* allocate some memory... enough for the command plus the header +
+ * any other data that we may need here...
+ */
+
+ Command = (unsigned char *)xmalloc(write_length);
+ Header = (struct sg_header *) Command; /* make it point to start of buf */
+
+ dest = Command; /* now to copy the CDB... from start of buffer,*/
+ dest += sizeof(struct sg_header); /* increment it past the header. */
+
+ slow_memcopy((char *)CDB, dest, CDB_Length);
+
+ /* if we are writing additional data, tack it on here! */
+ if (Direction == Output)
+ {
+ dest += CDB_Length;
+ slow_memcopy(DataBuffer, dest, DataBufferLength); /* copy to end of command */
+ }
+
+ /* Now to fill in the Header struct: */
+ Header->reply_len=DataBufferLength+sizeof(struct sg_header);
#ifdef DEBUG
- fprintf(stderr,"sg:reply_len(sent)=%d\n",Header->reply_len);
+ fprintf(stderr,"sg:reply_len(sent)=%d\n",Header->reply_len);
#endif
- Header->twelve_byte = CDB_Length == 12;
- Header->result = 0;
- Header->pack_len = write_length; /* # of bytes written... */
- Header->pack_id = 0; /* not used */
- Header->other_flags = 0; /* not used. */
- Header->sense_buffer[0]=0; /* used? */
-
- /* Now to do the write... */
- result=write(DeviceFD,Command,write_length);
-
- /* Now to check the result :-(. */
- /* Note that we don't have any request sense here. So we have no
- * idea what's going on.
- */
- if ( (result < 0) || (result != write_length) || Header->result ||
- Header->sense_buffer[0] ) {
+ Header->twelve_byte = CDB_Length == 12;
+ Header->result = 0;
+ Header->pack_len = write_length; /* # of bytes written... */
+ Header->pack_id = 0; /* not used */
+ Header->other_flags = 0; /* not used. */
+ Header->sense_buffer[0]=0; /* used? */
+
+ /* Now to do the write... */
+ result = write(DeviceFD,Command,write_length);
+
+ /* Now to check the result :-(. */
+ /* Note that we don't have any request sense here. So we have no
+ * idea what's going on.
+ */
+ if (result < 0 || result != write_length || Header->result || Header->sense_buffer[0])
+ {
#ifdef DEBUG_SCSI
- fprintf(stderr,"scsi:result=%d Header->result=%d Header->sense_buffer[0]=%d\n",
- result,Header->result,Header->sense_buffer[0]);
+ fprintf(stderr,"scsi:result=%d Header->result=%d Header->sense_buffer[0]=%d\n",
+ result,Header->result,Header->sense_buffer[0]);
#endif
- /* we don't have any real sense data, sigh :-(. */
- if (Header->sense_buffer[0]) {
- /* well, I guess we DID have some! eep! copy the sense data! */
- slow_memcopy((char *)Header->sense_buffer,(char *)RequestSense,
- sizeof(Header->sense_buffer));
- } else {
- dest=(unsigned char *)RequestSense;
- *dest=(unsigned char)Header->result; /* may chop, sigh... */
- }
-
- /* okay, now, we may or may not need to find a non-zero value to return.
- * For tape drives, we may get a BLANK_CHECK or MEDIUM_ERROR and find
- * that it's *STILL* a good read! Use the STILL_A_VALID_READ macro
- * that calls all those macros I cribbed from Richard.
- */
-
- if (!STILL_A_VALID_READ(RequestSense)) {
- free(Command); /* zap memory leak, sigh */
- /* okay, find us a non-zero value to return :-(. */
- if (result) {
- return result;
- } else if (Header->result) {
- return Header->result;
- } else {
- return -1; /* sigh */
- }
- } else {
- result=-1;
- }
- } else {
- result=0; /* we're okay! */
- }
-
-
- /* now to allocate the new block.... */
- ResultBuf=(unsigned char *)xmalloc(Header->reply_len);
- /* now to clear ResultBuf... */
- slow_bzero(ResultBuf,Header->reply_len);
-
- ResultHeader=(struct sg_header *)ResultBuf;
-
- /* copy the original Header... */
- ResultHeader->result=0;
- ResultHeader->pack_id=0;
- ResultHeader->other_flags=0;
- ResultHeader->reply_len=Header->reply_len;
- ResultHeader->twelve_byte = CDB_Length == 12;
- ResultHeader->pack_len = write_length; /* # of bytes written... */
- ResultHeader->sense_buffer[0]=0; /* whoops! Zero that! */
+ /* we don't have any real sense data, sigh :-(. */
+ if (Header->sense_buffer[0])
+ {
+ /* well, I guess we DID have some! eep! copy the sense data! */
+ slow_memcopy((char *)Header->sense_buffer,(char *)RequestSense,
+ sizeof(Header->sense_buffer));
+ }
+ else
+ {
+ dest=(unsigned char *)RequestSense;
+ *dest=(unsigned char)Header->result; /* may chop, sigh... */
+ }
+
+ /* okay, now, we may or may not need to find a non-zero value to return.
+ * For tape drives, we may get a BLANK_CHECK or MEDIUM_ERROR and find
+ * that it's *STILL* a good read! Use the STILL_A_VALID_READ macro
+ * that calls all those macros I cribbed from Richard.
+ */
+
+ if (!STILL_A_VALID_READ(RequestSense))
+ {
+ free(Command); /* zap memory leak, sigh */
+ /* okay, find us a non-zero value to return :-(. */
+ if (result)
+ {
+ return result;
+ }
+ else if (Header->result)
+ {
+ return Header->result;
+ }
+ else
+ {
+ return -1; /* sigh */
+ }
+ }
+ else
+ {
+ result=-1;
+ }
+ }
+ else
+ {
+ result=0; /* we're okay! */
+ }
+
+ /* now to allocate the new block.... */
+ ResultBuf=(unsigned char *)xmalloc(Header->reply_len);
+ /* now to clear ResultBuf... */
+ slow_bzero(ResultBuf,Header->reply_len);
+
+ ResultHeader=(struct sg_header *)ResultBuf;
+
+ /* copy the original Header... */
+ ResultHeader->result=0;
+ ResultHeader->pack_id=0;
+ ResultHeader->other_flags=0;
+ ResultHeader->reply_len=Header->reply_len;
+ ResultHeader->twelve_byte = CDB_Length == 12;
+ ResultHeader->pack_len = write_length; /* # of bytes written... */
+ ResultHeader->sense_buffer[0]=0; /* whoops! Zero that! */
#ifdef DEBUG
- fprintf(stderr,"sg:Reading %d bytes from DeviceFD\n",Header->reply_len);
- fflush(stderr);
+ fprintf(stderr,"sg:Reading %d bytes from DeviceFD\n",Header->reply_len);
+ fflush(stderr);
#endif
- result=read(DeviceFD,ResultBuf,Header->reply_len);
+ result=read(DeviceFD,ResultBuf,Header->reply_len);
#ifdef DEBUG
- fprintf(stderr,"sg:result=%d ResultHeader->result=%d\n",
- result,ResultHeader->result);
- fflush(stderr);
+ fprintf(stderr,"sg:result=%d ResultHeader->result=%d\n",
+ result,ResultHeader->result);
+ fflush(stderr);
#endif
- /* New: added check to see if the result block is still all zeros! */
- if ( (result < 0) || (result != Header->reply_len) || ResultHeader->result ||
- ResultHeader->sense_buffer[0] ) {
+ /* New: added check to see if the result block is still all zeros! */
+ if (result < 0 ||
+ result != Header->reply_len ||
+ ResultHeader->result ||
+ ResultHeader->sense_buffer[0])
+ {
#ifdef DEBUG
- fprintf(stderr,
- "scsi: result=%d Header->reply_len=%d ResultHeader->result=%d ResultHeader->sense_buffer[0]=%d\n",
- result,
- Header->reply_len,
- ResultHeader->result,
- ResultHeader->sense_buffer[0]);
+ fprintf(stderr,
+ "scsi: result=%d Header->reply_len=%d ResultHeader->result=%d ResultHeader->sense_buffer[0]=%d\n",
+ result,
+ Header->reply_len,
+ ResultHeader->result,
+ ResultHeader->sense_buffer[0]);
#endif
- /* eep! copy the sense data! */
- slow_memcopy((char *)ResultHeader->sense_buffer,(char *)RequestSense,
- sizeof(ResultHeader->sense_buffer));
- /* sense data copied, now find us a non-zero value to return :-(. */
- /* NOTE: Some commands return sense data even though they validly
- * executed! We catch a few of those with the macro STILL_A_VALID_READ.
- */
-
- if (!STILL_A_VALID_READ(RequestSense)) {
- free(Command);
- if (result) {
- free(ResultBuf);
- return result;
- } else if (ResultHeader->result) {
- free(ResultBuf);
- return ResultHeader->result;
- } else {
- free(ResultBuf);
- return -1; /* sigh! */
- }
- } else {
- result=-1; /* if it was a valid read, still have -1 result. */
- }
- } else {
- result=0;
- }
-
- /* See if we need to reset our SCSI timeout */
- if (sg_timeout != SG_SCSI_DEFAULT_TIMEOUT) {
- sg_timeout = SG_SCSI_DEFAULT_TIMEOUT; /* reset it back to default */
+ /* eep! copy the sense data! */
+ slow_memcopy((char *)ResultHeader->sense_buffer,(char *)RequestSense,
+ sizeof(ResultHeader->sense_buffer));
+ /* sense data copied, now find us a non-zero value to return :-(. */
+ /* NOTE: Some commands return sense data even though they validly
+ * executed! We catch a few of those with the macro STILL_A_VALID_READ.
+ */
+
+ if (!STILL_A_VALID_READ(RequestSense))
+ {
+ free(Command);
+ if (result)
+ {
+ free(ResultBuf);
+ return result;
+ }
+ else if (ResultHeader->result)
+ {
+ free(ResultBuf);
+ return ResultHeader->result;
+ }
+ else
+ {
+ free(ResultBuf);
+ return -1; /* sigh! */
+ }
+ }
+ else
+ {
+ result=-1; /* if it was a valid read, still have -1 result. */
+ }
+ }
+ else
+ {
+ result=0;
+ }
+
+ /* See if we need to reset our SCSI timeout */
+ if (sg_timeout != SG_SCSI_DEFAULT_TIMEOUT)
+ {
+ sg_timeout = SG_SCSI_DEFAULT_TIMEOUT; /* reset it back to default */
+
#ifdef DEBUG_TIMEOUT
- fprintf(stderr,"Setting timeout to %d\n", sg_timeout);
- fflush(stderr);
+ fprintf(stderr,"Setting timeout to %d\n", sg_timeout);
+ fflush(stderr);
#endif
- /* if not default, set it: */
- if(ioctl(DeviceFD, SG_SET_TIMEOUT, &sg_timeout)) {
- FatalError("failed to set sg timeout - %m\n");
- }
- }
-
-
- /* now for the crowning moment: copying any result into the DataBuffer! */
- /* (but only if it were an input command and not an output command :-} */
- if (Direction == Input) {
+ /* if not default, set it: */
+ if (ioctl(DeviceFD, SG_SET_TIMEOUT, &sg_timeout))
+ {
+ FatalError("failed to set sg timeout - %m\n");
+ }
+ }
+
+ /* now for the crowning moment: copying any result into the DataBuffer! */
+ /* (but only if it were an input command and not an output command :-} */
+ if (Direction == Input)
+ {
#ifdef DEBUG
- fprintf(stderr,"Header->reply_len=%d,ResultHeader->reply_len=%d\n",
- Header->reply_len,ResultHeader->reply_len);
+ fprintf(stderr,"Header->reply_len=%d,ResultHeader->reply_len=%d\n",
+ Header->reply_len,ResultHeader->reply_len);
#endif
- src=ResultBuf+sizeof(struct sg_header);
- dest=DataBuffer;
- for (i=0;i< (ResultHeader->reply_len);i++) {
- if (i>=DataBufferLength) break; /* eep! */
- *dest++=*src++;
- }
- }
-
- /* and return! */
- free(Command); /* clean up memory leak... */
- free(ResultBuf);
- return result; /* good stuff ! */
+ src=ResultBuf+sizeof(struct sg_header);
+ dest=DataBuffer;
+ for (i = 0; i < ResultHeader->reply_len; i++)
+ {
+ if (i >= DataBufferLength)
+ break; /* eep! */
+ *dest++ = *src++;
+ }
+ }
+
+ /* and return! */
+ free(Command); /* clean up memory leak... */
+ free(ResultBuf);
+ return result; /* good stuff ! */
}
#endif
-
-
-#ifdef OLD_EXECUTE_COMMAND_STUFF
-
-int SCSI_ExecuteCommand(int DeviceFD,
- Direction_T Direction,
- CDB_T CDB,
- int CDB_Length,
- void *DataBuffer,
- int DataBufferLength,
- RequestSense_T *RequestSense)
-{
- unsigned char *Command;
- int Zero = 0, Result;
- memset(RequestSense, 0, sizeof(RequestSense_T));
- switch (Direction)
- {
- case Input:
- Command = (unsigned char *)
- xmalloc(8 + max(DataBufferLength, sizeof(RequestSense_T)));
- memcpy(&Command[0], &Zero, 4);
- memcpy(&Command[4], &DataBufferLength, 4);
- memcpy(&Command[8], CDB, CDB_Length);
- break;
- case Output:
- Command = (unsigned char *)
- xmalloc(8 + max(CDB_Length + DataBufferLength, sizeof(RequestSense_T)));
- memcpy(&Command[0], &DataBufferLength, 4);
- memcpy(&Command[4], &Zero, 4);
- memcpy(&Command[8], CDB, CDB_Length);
- memcpy(&Command[8 + CDB_Length], DataBuffer, DataBufferLength);
- break;
- }
- Result = ioctl(DeviceFD, SCSI_IOCTL_SEND_COMMAND, Command);
- if (Result != 0)
- memcpy(RequestSense, &Command[8], sizeof(RequestSense_T));
- else if (Direction == Input)
- memcpy(DataBuffer, &Command[8], DataBufferLength);
- free(Command);
- return Result;
-}
-
-#endif
+#endif /* #ifdef SG_IO */