aboutsummaryrefslogtreecommitdiff
path: root/lib/sg_pt_win32.c
diff options
context:
space:
mode:
authorDouglas Gilbert <dgilbert@interlog.com>2009-08-19 01:35:02 +0000
committerDouglas Gilbert <dgilbert@interlog.com>2009-08-19 01:35:02 +0000
commit6fa85931942a499d92e193cfa3150d2a62f6ffc8 (patch)
tree628eb8ac5ea991759b9587759c811e0bc49354ff /lib/sg_pt_win32.c
parent6857c006538197ca621fbdc85719b46f3d865f8f (diff)
downloadsg3_utils-6fa85931942a499d92e193cfa3150d2a62f6ffc8.tar.gz
rework sg_pt_win32.c to have extendable non-direct SPT; change default back to 'non-direct'; add './configure --enable-win32-spt-direct'
git-svn-id: https://svn.bingwo.ca/repos/sg3_utils/trunk@288 6180dd3e-e324-4e3e-922d-17de1ae2f315
Diffstat (limited to 'lib/sg_pt_win32.c')
-rw-r--r--lib/sg_pt_win32.c105
1 files changed, 65 insertions, 40 deletions
diff --git a/lib/sg_pt_win32.c b/lib/sg_pt_win32.c
index 03890a62..95fb3f81 100644
--- a/lib/sg_pt_win32.c
+++ b/lib/sg_pt_win32.c
@@ -27,7 +27,7 @@
*
*/
-/* sg_pt_win32 version 1.08 20090522 */
+/* sg_pt_win32 version 1.10 20090818 */
#include <stdio.h>
#include <stdlib.h>
@@ -47,12 +47,12 @@
/* Use the Microsoft SCSI Pass Through (SPT) interface. It has two
* variants: "SPT" where data is double buffered; and "SPTD" where data
* pointers to the user space are passed to the OS. Only Windows
- * 2000, 2003 and XP are supported (i.e. not 95,98 or ME).
- * Currently there is no ASPI interface which relies on a dll
- * from adaptec.
+ * 2000 and later (i.e. not 95,98 or ME).
+ * There is no ASPI interface which relies on a dll from adaptec.
* This code uses cygwin facilities and is built in a cygwin
* shell. It can be run in a normal DOS shell if the cygwin1.dll
* file is put in an appropriate place.
+ * This code can build in a MinGW environment.
*
* N.B. MSDN says that the "SPT" interface (i.e. double buffered)
* should be used for small amounts of data (it says "< 16 KB").
@@ -81,11 +81,6 @@ struct sg_pt_handle {
struct sg_pt_handle handle_arr[MAX_OPEN_SIMULT];
struct sg_pt_win32_scsi {
-#ifdef WIN32_SPT_DIRECT
- SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER swb;
-#else
- SCSI_PASS_THROUGH_WITH_BUFFERS swb;
-#endif
unsigned char * dxferp;
int dxfer_len;
unsigned char * sensep;
@@ -96,10 +91,18 @@ struct sg_pt_win32_scsi {
int in_err;
int os_err; /* pseudo unix error */
int transport_err; /* windows error number */
+#ifdef WIN32_SPT_DIRECT
+ SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER swb;
+#else
+ /* Last entry in structure so data buffer can be extended */
+ SCSI_PASS_THROUGH_WITH_BUFFERS swb;
+#endif
};
+/* embed pointer so can change on fly if (non-direct) data buffer
+ * is not big enough */
struct sg_pt_base {
- struct sg_pt_win32_scsi impl;
+ struct sg_pt_win32_scsi * implp;
};
@@ -240,33 +243,42 @@ struct sg_pt_base *
construct_scsi_pt_obj()
{
struct sg_pt_win32_scsi * psp;
+ struct sg_pt_base * vp = NULL;
- psp = (struct sg_pt_win32_scsi *)malloc(sizeof(struct sg_pt_win32_scsi));
+ psp = (struct sg_pt_win32_scsi *)calloc(sizeof(struct sg_pt_win32_scsi),
+ 1);
if (psp) {
- memset(psp, 0, sizeof(struct sg_pt_win32_scsi));
psp->swb.spt.DataIn = SCSI_IOCTL_DATA_UNSPECIFIED;
psp->swb.spt.SenseInfoLength = SCSI_MAX_SENSE_LEN;
psp->swb.spt.SenseInfoOffset =
offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS, ucSenseBuf);
psp->swb.spt.TimeOutValue = DEF_TIMEOUT;
+ vp = malloc(sizeof(struct sg_pt_win32_scsi *)); // yes a pointer
+ if (vp)
+ vp->implp = psp;
+ else
+ free(psp);
}
- return (struct sg_pt_base *)psp;
+ return vp;
}
void
destruct_scsi_pt_obj(struct sg_pt_base * vp)
{
- struct sg_pt_win32_scsi * psp = &vp->impl;
+ if (vp) {
+ struct sg_pt_win32_scsi * psp = vp->implp;
- if (psp) {
- free(psp);
+ if (psp) {
+ free(psp);
+ }
+ free(vp);
}
}
void
clear_scsi_pt_obj(struct sg_pt_base * vp)
{
- struct sg_pt_win32_scsi * psp = &vp->impl;
+ struct sg_pt_win32_scsi * psp = vp->implp;
if (psp) {
memset(psp, 0, sizeof(struct sg_pt_win32_scsi));
@@ -282,7 +294,7 @@ void
set_scsi_pt_cdb(struct sg_pt_base * vp, const unsigned char * cdb,
int cdb_len)
{
- struct sg_pt_win32_scsi * psp = &vp->impl;
+ struct sg_pt_win32_scsi * psp = vp->implp;
if (psp->swb.spt.CdbLength > 0)
++psp->in_err;
@@ -298,7 +310,7 @@ void
set_scsi_pt_sense(struct sg_pt_base * vp, unsigned char * sense,
int sense_len)
{
- struct sg_pt_win32_scsi * psp = &vp->impl;
+ struct sg_pt_win32_scsi * psp = vp->implp;
if (psp->sensep)
++psp->in_err;
@@ -312,7 +324,7 @@ void
set_scsi_pt_data_in(struct sg_pt_base * vp, unsigned char * dxferp,
int dxfer_len)
{
- struct sg_pt_win32_scsi * psp = &vp->impl;
+ struct sg_pt_win32_scsi * psp = vp->implp;
if (psp->dxferp)
++psp->in_err;
@@ -328,7 +340,7 @@ void
set_scsi_pt_data_out(struct sg_pt_base * vp, const unsigned char * dxferp,
int dxfer_len)
{
- struct sg_pt_win32_scsi * psp = &vp->impl;
+ struct sg_pt_win32_scsi * psp = vp->implp;
if (psp->dxferp)
++psp->in_err;
@@ -348,7 +360,7 @@ set_scsi_pt_packet_id(struct sg_pt_base * vp __attribute__ ((unused)),
void
set_scsi_pt_tag(struct sg_pt_base * vp, uint64_t tag __attribute__ ((unused)))
{
- struct sg_pt_win32_scsi * psp = &vp->impl;
+ struct sg_pt_win32_scsi * psp = vp->implp;
++psp->in_err;
}
@@ -357,7 +369,7 @@ void
set_scsi_pt_task_management(struct sg_pt_base * vp,
int tmf_code __attribute__ ((unused)))
{
- struct sg_pt_win32_scsi * psp = &vp->impl;
+ struct sg_pt_win32_scsi * psp = vp->implp;
++psp->in_err;
}
@@ -367,7 +379,7 @@ set_scsi_pt_task_attr(struct sg_pt_base * vp,
int attrib __attribute__ ((unused)),
int priority __attribute__ ((unused)))
{
- struct sg_pt_win32_scsi * psp = &vp->impl;
+ struct sg_pt_win32_scsi * psp = vp->implp;
++psp->in_err;
}
@@ -379,7 +391,7 @@ int
do_scsi_pt(struct sg_pt_base * vp, int device_fd, int time_secs, int verbose)
{
int index = device_fd - WIN32_FDOFFSET;
- struct sg_pt_win32_scsi * psp = &vp->impl;
+ struct sg_pt_win32_scsi * psp = vp->implp;
struct sg_pt_handle * shp;
BOOL status;
ULONG returned;
@@ -416,12 +428,25 @@ do_scsi_pt(struct sg_pt_base * vp, int device_fd, int time_secs, int verbose)
psp->swb.spt.Length = sizeof (SCSI_PASS_THROUGH_DIRECT);
#else
if (psp->dxfer_len > (int)sizeof(psp->swb.ucDataBuf)) {
- if (verbose)
- fprintf(sg_warnings_strm, "dxfer_len (%d) too large (limit %d "
- "bytes)\n", psp->dxfer_len, sizeof(psp->swb.ucDataBuf));
- psp->os_err = ENOMEM;
- return -psp->os_err;
-
+ int extra = psp->dxfer_len - (int)sizeof(psp->swb.ucDataBuf);
+ struct sg_pt_win32_scsi * epsp;
+
+ if (verbose > 4)
+ fprintf(sg_warnings_strm, "dxfer_len (%d) too large for initial "
+ "data buffer (%d bytes), try enlarging\n", psp->dxfer_len,
+ sizeof(psp->swb.ucDataBuf));
+ epsp = (struct sg_pt_win32_scsi *)
+ calloc(sizeof(struct sg_pt_win32_scsi) + extra, 1);
+ if (NULL == epsp) {
+ fprintf(sg_warnings_strm, "do_scsi_pt: failed to enlarge data "
+ "buffer to %d bytes\n", psp->dxfer_len);
+ psp->os_err = ENOMEM;
+ return -psp->os_err;
+ }
+ memcpy(epsp, psp, sizeof(struct sg_pt_win32_scsi));
+ free(psp);
+ vp->implp = epsp;
+ psp = epsp;
}
psp->swb.spt.Length = sizeof (SCSI_PASS_THROUGH);
psp->swb.spt.DataBufferOffset =
@@ -502,7 +527,7 @@ do_scsi_pt(struct sg_pt_base * vp, int device_fd, int time_secs, int verbose)
int
get_scsi_pt_result_category(const struct sg_pt_base * vp)
{
- const struct sg_pt_win32_scsi * psp = &vp->impl;
+ const struct sg_pt_win32_scsi * psp = vp->implp;
if (psp->transport_err) /* give transport error highest priority */
return SCSI_PT_RESULT_TRANSPORT_ERR;
@@ -520,7 +545,7 @@ get_scsi_pt_result_category(const struct sg_pt_base * vp)
int
get_scsi_pt_resid(const struct sg_pt_base * vp)
{
- const struct sg_pt_win32_scsi * psp = &vp->impl;
+ const struct sg_pt_win32_scsi * psp = vp->implp;
return psp->resid;
}
@@ -528,7 +553,7 @@ get_scsi_pt_resid(const struct sg_pt_base * vp)
int
get_scsi_pt_status_response(const struct sg_pt_base * vp)
{
- const struct sg_pt_win32_scsi * psp = &vp->impl;
+ const struct sg_pt_win32_scsi * psp = vp->implp;
return psp->scsi_status;
}
@@ -536,7 +561,7 @@ get_scsi_pt_status_response(const struct sg_pt_base * vp)
int
get_scsi_pt_sense_len(const struct sg_pt_base * vp)
{
- const struct sg_pt_win32_scsi * psp = &vp->impl;
+ const struct sg_pt_win32_scsi * psp = vp->implp;
int len;
len = psp->sense_len - psp->sense_resid;
@@ -546,7 +571,7 @@ get_scsi_pt_sense_len(const struct sg_pt_base * vp)
int
get_scsi_pt_duration_ms(const struct sg_pt_base * vp __attribute__ ((unused)))
{
- // const struct sg_pt_freebsd_scsi * psp = &vp->impl;
+ // const struct sg_pt_freebsd_scsi * psp = vp->implp;
return -1;
}
@@ -554,7 +579,7 @@ get_scsi_pt_duration_ms(const struct sg_pt_base * vp __attribute__ ((unused)))
int
get_scsi_pt_transport_err(const struct sg_pt_base * vp)
{
- const struct sg_pt_win32_scsi * psp = &vp->impl;
+ const struct sg_pt_win32_scsi * psp = vp->implp;
return psp->transport_err;
}
@@ -562,7 +587,7 @@ get_scsi_pt_transport_err(const struct sg_pt_base * vp)
int
get_scsi_pt_os_err(const struct sg_pt_base * vp)
{
- const struct sg_pt_win32_scsi * psp = &vp->impl;
+ const struct sg_pt_win32_scsi * psp = vp->implp;
return psp->os_err;
}
@@ -572,7 +597,7 @@ char *
get_scsi_pt_transport_err_str(const struct sg_pt_base * vp, int max_b_len,
char * b)
{
- struct sg_pt_win32_scsi * psp = (struct sg_pt_win32_scsi *)&vp->impl;
+ struct sg_pt_win32_scsi * psp = (struct sg_pt_win32_scsi *)vp->implp;
LPVOID lpMsgBuf;
int k, num, ch;
@@ -607,7 +632,7 @@ get_scsi_pt_transport_err_str(const struct sg_pt_base * vp, int max_b_len,
char *
get_scsi_pt_os_err_str(const struct sg_pt_base * vp, int max_b_len, char * b)
{
- const struct sg_pt_win32_scsi * psp = &vp->impl;
+ const struct sg_pt_win32_scsi * psp = vp->implp;
const char * cp;
cp = safe_strerror(psp->os_err);