aboutsummaryrefslogtreecommitdiff
path: root/lib/sg_pt_win32.c
diff options
context:
space:
mode:
authorDouglas Gilbert <dgilbert@interlog.com>2018-02-22 07:00:28 +0000
committerDouglas Gilbert <dgilbert@interlog.com>2018-02-22 07:00:28 +0000
commit252086533f8af0736c2a4987cd70a44366837ec1 (patch)
tree1f9245e247673fdb6ebea13b9aa559e1f869d78c /lib/sg_pt_win32.c
parent39ea1b548f21c006c311ace897b221b100bfa88d (diff)
downloadsg3_utils-252086533f8af0736c2a4987cd70a44366837ec1.tar.gz
sg_lib: add sg_if_can2stdout(); use uint8_t instead of unsigned char; Windows pass-through work
git-svn-id: https://svn.bingwo.ca/repos/sg3_utils/trunk@754 6180dd3e-e324-4e3e-922d-17de1ae2f315
Diffstat (limited to 'lib/sg_pt_win32.c')
-rw-r--r--lib/sg_pt_win32.c143
1 files changed, 110 insertions, 33 deletions
diff --git a/lib/sg_pt_win32.c b/lib/sg_pt_win32.c
index e9bcb094..0357c7ef 100644
--- a/lib/sg_pt_win32.c
+++ b/lib/sg_pt_win32.c
@@ -125,11 +125,13 @@ struct sg_pt_handle {
int bus; /* a.k.a. PathId in MS docs */
int target;
int lun;
- int scsi_pid; /* -1 if not known */
+ int scsi_pdt; /* Peripheral Device Type, -1 if not known */
+ // uint32_t nvme_nsid; /* how do we find this given file handle ?? */
int verbose; /* tunnel verbose through to scsi_pt_close_device */
char dname[20];
};
+/* Start zeroed but need to zeroed before use because could be re-use */
static struct sg_pt_handle handle_arr[MAX_OPEN_SIMULT];
struct sg_pt_win32_scsi {
@@ -159,7 +161,7 @@ struct sg_pt_win32_scsi {
uint32_t dxfer_len;
uint32_t mdxfer_len;
uint8_t * dxferp;
- uint8_t * mdxferp; /* NVMe has metadata buffer */
+ uint8_t * mdxferp; /* NVMe has metadata buffer */
uint8_t * sensep;
uint8_t * nvme_id_ctlp;
uint8_t * free_nvme_id_ctlp;
@@ -190,8 +192,8 @@ static int pr2ws(const char * fmt, ...)
static int pr2ws(const char * fmt, ...);
#endif
-static int do_nvme_pt(struct sg_pt_win32_scsi * psp,
- struct sg_pt_handle * shp, int time_secs, int vb);
+static int nvme_pt(struct sg_pt_win32_scsi * psp, struct sg_pt_handle * shp,
+ int time_secs, int vb);
static int
@@ -388,8 +390,11 @@ scsi_pt_open_flags(const char * device_name, int flags, int vb)
if (vb)
pr2ws("too many open handles (%d)\n", MAX_OPEN_SIMULT);
return -EMFILE;
- } else
+ } else {
+ /* clear any previous contents */
+ memset(handle_arr + k, 0, sizeof(struct sg_pt_handle));
handle_arr[k].in_use = true;
+ }
/* unlock */
index = k;
shp = handle_arr + index;
@@ -438,7 +443,7 @@ scsi_pt_open_flags(const char * device_name, int flags, int vb)
shp->bus = bus;
shp->target = target;
shp->lun = lun;
- shp->scsi_pid = -1;
+ shp->scsi_pdt = -1;
shp->verbose = vb;
memset(shp->adapter, 0, sizeof(shp->adapter));
strncpy(shp->adapter, "\\\\.\\", 4);
@@ -550,15 +555,15 @@ get_scsi_pdt(struct sg_pt_handle *shp, int vb)
if ((shp->bus == pid->PathId) &&
(shp->target == pid->TargetId) &&
(shp->lun == pid->Lun)) { /* got match */
- shp->scsi_pid = pid->InquiryData[0] & 0x3f;
+ shp->scsi_pdt = pid->InquiryData[0] & 0x3f;
shp->not_claimed = ! pid->DeviceClaimed;
shp->checked_handle = true;
shp->bus_type_failed = false;
if (vb > 3)
- pr2ws("%s: found, scsi_pid=%d, claimed=%d, "
- "target=%d, lun=%d\n", __func__, shp->scsi_pid,
+ pr2ws("%s: found, scsi_pdt=%d, claimed=%d, "
+ "target=%d, lun=%d\n", __func__, shp->scsi_pdt,
pid->DeviceClaimed, shp->target, shp->lun);
- ret = shp->scsi_pid;
+ ret = shp->scsi_pdt;
goto fini;
}
off = pid->NextInquiryDataOffset;
@@ -694,8 +699,11 @@ construct_scsi_pt_obj_with_fd(int dev_fd, int vb)
psp = (struct sg_pt_win32_scsi *)calloc(sizeof(struct sg_pt_win32_scsi),
1);
if (psp) {
- if (shp && shp->is_nvme) {
- psp->is_nvme = true;
+ psp->dev_fd = (dev_fd < 0) ? -1 : dev_fd;
+ if (shp)
+ psp->is_nvme = shp->is_nvme;
+ if (psp->is_nvme) {
+ ; /* should be 'psp->nvme_nsid = shp->nvme_nsid' */
} else if (spt_direct) {
psp->swb_d.spt.DataIn = SCSI_IOCTL_DATA_UNSPECIFIED;
psp->swb_d.spt.SenseInfoLength = SCSI_MAX_SENSE_LEN;
@@ -709,9 +717,8 @@ construct_scsi_pt_obj_with_fd(int dev_fd, int vb)
offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS, ucSenseBuf);
psp->swb_i.spt.TimeOutValue = DEF_TIMEOUT;
}
- psp->dev_fd = (dev_fd < 0) ? -1 : dev_fd;
vp = (struct sg_pt_base *)malloc(sizeof(struct sg_pt_win32_scsi *));
- /* yes, allocating the size of a pointer (8 bytes) */
+ /* yes, allocating the size of a pointer (4 or 8 bytes) */
if (vp)
vp->implp = psp;
else
@@ -741,6 +748,76 @@ destruct_scsi_pt_obj(struct sg_pt_base * vp)
}
}
+/* Forget any previous dev_han and install the one given. May attempt to
+ * find file type (e.g. if pass-though) from OS so there could be an error.
+ * Returns 0 for success or the same value as get_scsi_pt_os_err()
+ * will return. dev_han should be >= 0 for a valid file handle or -1 . */
+int
+set_pt_file_handle(struct sg_pt_base * vp, int dev_han, int vb)
+{
+ int res;
+ struct sg_pt_win32_scsi * psp;
+
+ if (NULL == vp) {
+ if (vb)
+ pr2ws(">>>> %s: pointer to object is NULL\n", __func__);
+ return EINVAL;
+ }
+ if ((psp = vp->implp)) {
+ struct sg_pt_handle * shp;
+
+ if (dev_han < 0) {
+ psp->dev_fd = -1;
+ psp->is_nvme = false;
+ psp->nvme_nsid = 0;
+ return 0;
+ }
+ shp = get_open_pt_handle(psp, dev_han, vb > 1);
+ if (NULL == shp) {
+ if (vb)
+ pr2ws("%s: dev_han (%d) is invalid\n", __func__, dev_han);
+ psp->os_err = EINVAL;
+ return psp->os_err;
+ }
+ psp->os_err = 0;
+ psp->transport_err = 0;
+ psp->in_err = 0;
+ psp->scsi_status = 0;
+ psp->dev_fd = dev_han;
+ if (! (shp->bus_type_failed || shp->checked_handle)) {
+ res = get_bus_type(shp, shp->dname, NULL, vb);
+ if (res < 0) {
+ res = get_scsi_pdt(shp, vb);
+ if (res >= 0) /* clears shp->bus_type_failed on success */
+ psp->os_err = 0;
+ }
+ if ((res < 0) && (vb > 2))
+ pr2ws("%s: get_bus_type() errno=%d\n", __func__, -res);
+ }
+ if (shp->bus_type_failed)
+ psp->os_err = EIO;
+ if (psp->os_err)
+ return psp->os_err;
+ psp->is_nvme = shp->is_nvme;
+ psp->nvme_nsid = 0; /* should be 'psp->nvme_nsid = shp->nvme_nsid' */
+ }
+ return 0;
+}
+
+/* Valid file handles (which is the return value) are >= 0 . Returns -1
+ * if there is no valid file handle. */
+int
+get_pt_file_handle(const struct sg_pt_base * vp)
+{
+ const struct sg_pt_win32_scsi * psp;
+
+ if (vp) {
+ psp = vp->implp;
+ return psp ? psp->dev_fd : -1;
+ }
+ return -1;
+}
+
/* Keep state information such as dev_fd and nvme_nsid */
void
clear_scsi_pt_obj(struct sg_pt_base * vp)
@@ -775,7 +852,7 @@ clear_scsi_pt_obj(struct sg_pt_base * vp)
}
void
-set_scsi_pt_cdb(struct sg_pt_base * vp, const unsigned char * cdb,
+set_scsi_pt_cdb(struct sg_pt_base * vp, const uint8_t * cdb,
int cdb_len)
{
bool scsi_cdb = sg_is_scsi_cdb(cdb, cdb_len);
@@ -809,7 +886,7 @@ set_scsi_pt_cdb(struct sg_pt_base * vp, const unsigned char * cdb,
}
void
-set_scsi_pt_sense(struct sg_pt_base * vp, unsigned char * sense,
+set_scsi_pt_sense(struct sg_pt_base * vp, uint8_t * sense,
int sense_len)
{
struct sg_pt_win32_scsi * psp = vp->implp;
@@ -823,7 +900,7 @@ set_scsi_pt_sense(struct sg_pt_base * vp, unsigned char * sense,
/* from device */
void
-set_scsi_pt_data_in(struct sg_pt_base * vp, unsigned char * dxferp,
+set_scsi_pt_data_in(struct sg_pt_base * vp, uint8_t * dxferp,
int dxfer_len)
{
struct sg_pt_win32_scsi * psp = vp->implp;
@@ -843,7 +920,7 @@ set_scsi_pt_data_in(struct sg_pt_base * vp, unsigned char * dxferp,
/* to device */
void
-set_scsi_pt_data_out(struct sg_pt_base * vp, const unsigned char * dxferp,
+set_scsi_pt_data_out(struct sg_pt_base * vp, const uint8_t * dxferp,
int dxfer_len)
{
struct sg_pt_win32_scsi * psp = vp->implp;
@@ -851,7 +928,7 @@ set_scsi_pt_data_out(struct sg_pt_base * vp, const unsigned char * dxferp,
if (psp->dxferp)
++psp->in_err;
if (dxfer_len > 0) {
- psp->dxferp = (unsigned char *)dxferp;
+ psp->dxferp = (uint8_t *)dxferp;
psp->dxfer_len = (uint32_t)dxfer_len;
if (spt_direct)
psp->swb_d.spt.DataIn = SCSI_IOCTL_DATA_OUT;
@@ -861,7 +938,7 @@ set_scsi_pt_data_out(struct sg_pt_base * vp, const unsigned char * dxferp,
}
void
-set_pt_metadata_xfer(struct sg_pt_base * vp, unsigned char * mdxferp,
+set_pt_metadata_xfer(struct sg_pt_base * vp, uint8_t * mdxferp,
uint32_t mdxfer_len, bool out_true)
{
struct sg_pt_win32_scsi * psp = vp->implp;
@@ -920,8 +997,8 @@ set_scsi_pt_flags(struct sg_pt_base * objp, int flags)
* using direct interface. Clears os_err field prior to active call (whose
* result may set it again). */
static int
-do_scsi_pt_direct(struct sg_pt_win32_scsi * psp, struct sg_pt_handle * shp,
- int time_secs, int vb)
+scsi_pt_direct(struct sg_pt_win32_scsi * psp, struct sg_pt_handle * shp,
+ int time_secs, int vb)
{
BOOL status;
DWORD returned;
@@ -996,8 +1073,8 @@ do_scsi_pt_direct(struct sg_pt_win32_scsi * psp, struct sg_pt_handle * shp,
* indirect interface. Clears os_err field prior to active call (whose
* result may set it again). */
static int
-do_scsi_pt_indirect(struct sg_pt_base * vp, struct sg_pt_handle * shp,
- int time_secs, int vb)
+scsi_pt_indirect(struct sg_pt_base * vp, struct sg_pt_handle * shp,
+ int time_secs, int vb)
{
BOOL status;
DWORD returned;
@@ -1019,7 +1096,7 @@ do_scsi_pt_indirect(struct sg_pt_base * vp, struct sg_pt_handle * shp,
epsp = (struct sg_pt_win32_scsi *)
calloc(sizeof(struct sg_pt_win32_scsi) + extra, 1);
if (NULL == epsp) {
- pr2ws("do_scsi_pt: failed to enlarge data buffer to %d bytes\n",
+ pr2ws("%s: failed to enlarge data buffer to %d bytes\n", __func__,
psp->dxfer_len);
psp->os_err = ENOMEM;
return -psp->os_err;
@@ -1149,11 +1226,11 @@ do_scsi_pt(struct sg_pt_base * vp, int dev_fd, int time_secs, int vb)
psp->is_nvme = shp->is_nvme;
if (psp->is_nvme)
- return do_nvme_pt(psp, shp, time_secs, vb);
+ return nvme_pt(psp, shp, time_secs, vb);
else if (spt_direct)
- return do_scsi_pt_direct(psp, shp, time_secs, vb);
+ return scsi_pt_direct(psp, shp, time_secs, vb);
else
- return do_scsi_pt_indirect(vp, shp, time_secs, vb);
+ return scsi_pt_indirect(vp, shp, time_secs, vb);
}
int
@@ -1215,7 +1292,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->implp;
+ // const struct sg_pt_win32_scsi * psp = vp->implp;
return -1;
}
@@ -2744,8 +2821,8 @@ sntl_rep_tmfs(struct sg_pt_win32_scsi * psp, struct sg_pt_handle * shp,
* When time_secs is 0 the Linux NVMe Admin command default of 60 seconds
* is used. */
static int
-do_nvme_pt(struct sg_pt_win32_scsi * psp, struct sg_pt_handle * shp,
- int time_secs, int vb)
+nvme_pt(struct sg_pt_win32_scsi * psp, struct sg_pt_handle * shp,
+ int time_secs, int vb)
{
bool scsi_cdb = false;
uint32_t cmd_len = 0;
@@ -2832,8 +2909,8 @@ do_nvme_pt(struct sg_pt_win32_scsi * psp, struct sg_pt_handle * shp,
#else /* (HAVE_NVME && (! IGNORE_NVME)) */
static int
-do_nvme_pt(struct sg_pt_win32_scsi * psp, struct sg_pt_handle * shp,
- int time_secs, int vb)
+nvme_pt(struct sg_pt_win32_scsi * psp, struct sg_pt_handle * shp,
+ int time_secs, int vb)
{
if (vb)
pr2ws("%s: not supported [time_secs=%d]\n", __func__, time_secs);