MS Windows driver hacking hopefully to get closer to passing back sense data.

For now it seems that some pass-through direct doesn't work while the less-good passthrough does. Sigh.
This commit is contained in:
R. Bernstein
2010-01-31 21:31:08 -05:00
parent a41cfed2a1
commit 5f10331adb
2 changed files with 115 additions and 14 deletions

View File

@@ -1,6 +1,4 @@
/*
$Id: win32_ioctl.c,v 1.30 2008/04/21 18:30:21 karl Exp $
Copyright (C) 2004, 2005, 2008, 2010 Rocky Bernstein <rocky@gnu.org>
This program is free software: you can redistribute it and/or modify
@@ -92,10 +90,19 @@ typedef struct _CDROM_TOC_FULL {
typedef struct {
SCSI_PASS_THROUGH_DIRECT sptd;
ULONG Filler;
ULONG Filler; /* Realign buffer to double-word boundary */
UCHAR ucSenseBuf[32];
UCHAR DataBuf[512];
} SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER;
typedef struct _SCSI_PASS_THROUGH_WITH_BUFFER {
SCSI_PASS_THROUGH Spt;
ULONG Filler; /* realign buffer to double-word boundary */
UCHAR SenseBuf[32];
UCHAR DataBuf[512];
} SCSI_PASS_THROUGH_WITH_BUFFER;
#include "win32.h"
@@ -478,6 +485,7 @@ set_scsi_tuple_win32ioctl(_img_private_t *env)
Return 0 if command completed successfully.
*/
#if 0
int
run_mmc_cmd_win32ioctl( void *p_user_data,
unsigned int i_timeout_ms,
@@ -489,6 +497,7 @@ run_mmc_cmd_win32ioctl( void *p_user_data,
SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER sptdwb;
bool b_success;
unsigned long length = 0;
DWORD dw_bytes_returned;
memset(&sptdwb, 0, sizeof(sptdwb));
@@ -506,19 +515,28 @@ run_mmc_cmd_win32ioctl( void *p_user_data,
SCSI_IOCTL_DATA_UNSPECIFIED;
sptdwb.sptd.DataTransferLength= i_buf;
sptdwb.sptd.TimeOutValue = msecs2secs(i_timeout_ms);
sptdwb.sptd.DataBuffer = (void *) p_buf;
/*
sptdwb.sptd.SenseInfoOffset = offsetof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER,
ucSenseBuf);
*/
sptdwb.sptd.SenseInfoOffset = 0;
memcpy(sptdwb.sptd.Cdb, p_cdb, i_cdb);
length = offsetof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER,DataBuf) +
sptdwb.sptd.DataTransferLength;
/* Send the command to drive */
b_success = DeviceIoControl(p_env->h_device_handle,
IOCTL_SCSI_PASS_THROUGH_DIRECT,
IOCTL_SCSI_PASS_THROUGH,
(void *)&sptdwb,
(DWORD)sizeof(sptdwb),
sizeof(SCSI_PASS_THROUGH),
NULL, 0,
/*
&sptdwb,
(DWORD)sizeof(sptdwb),
length,
*/
&dw_bytes_returned,
NULL);
@@ -548,6 +566,89 @@ run_mmc_cmd_win32ioctl( void *p_user_data,
return DRIVER_OP_SUCCESS;
}
#else
int
run_mmc_cmd_win32ioctl( void *p_user_data,
unsigned int i_timeout_ms,
unsigned int i_cdb, const mmc_cdb_t * p_cdb,
cdio_mmc_direction_t e_direction,
unsigned int i_buf, /*in/out*/ void *p_buf )
{
_img_private_t *p_env = p_user_data;
SCSI_PASS_THROUGH_WITH_BUFFER sptwb;
bool b_success;
unsigned long length = 0;
DWORD dw_bytes_returned;
memset(&sptwb, 0, sizeof(sptwb));
sptwb.Spt.Length = sizeof(sptwb.Spt);
sptwb.Spt.PathId = 0; /* SCSI card ID will be filled in
automatically */
sptwb.Spt.TargetId= 0; /* SCSI target ID will also be filled in */
sptwb.Spt.Lun = 0; /* SCSI lun ID will also be filled in */
sptwb.Spt.CdbLength = i_cdb;
sptwb.Spt.SenseInfoLength = sizeof(sptwb.SenseBuf);
sptwb.Spt.DataIn =
(SCSI_MMC_DATA_READ == e_direction) ? SCSI_IOCTL_DATA_IN :
(SCSI_MMC_DATA_WRITE == e_direction) ? SCSI_IOCTL_DATA_OUT :
SCSI_IOCTL_DATA_UNSPECIFIED;
if (SCSI_MMC_DATA_WRITE == e_direction) memcpy(&sptwb.DataBuf, p_buf, i_buf);
sptwb.Spt.DataTransferLength= i_buf;
sptwb.Spt.TimeOutValue = msecs2secs(i_timeout_ms);
sptwb.Spt.DataBufferOffset =
offsetof(SCSI_PASS_THROUGH_WITH_BUFFER,DataBuf);
sptwb.Spt.SenseInfoOffset =
offsetof(SCSI_PASS_THROUGH_WITH_BUFFER, SenseBuf);
memcpy(sptwb.Spt.Cdb, p_cdb, i_cdb);
sptwb.Spt.Cdb[4] = i_buf;
length = offsetof(SCSI_PASS_THROUGH_WITH_BUFFER,DataBuf) +
sptwb.Spt.DataTransferLength;
/* Send the command to drive */
b_success = DeviceIoControl(p_env->h_device_handle,
IOCTL_SCSI_PASS_THROUGH,
(void *)&sptwb,
sizeof(SCSI_PASS_THROUGH),
&sptwb,
length,
&dw_bytes_returned,
NULL);
if ( !b_success ) {
char *psz_msg = NULL;
long int i_err = GetLastError();
FORMAT_ERROR(i_err, psz_msg);
if (psz_msg)
cdio_info("Error: %s", psz_msg);
else
cdio_info("Error: %ld", i_err);
LocalFree(psz_msg);
return DRIVER_OP_ERROR;
}
memcpy(p_buf, &sptwb.DataBuf, i_buf);
/* Record SCSI sense reply for API call mmc_last_cmd_sense().
*/
if (sptwb.SenseBuf[7]) {
int sense_size = sptwb.SenseBuf[7] + 8; /* SPC 4.5.3, Table 26:
252 bytes legal, 263 bytes
possible */
if (sense_size > sizeof(sptwb.SenseBuf))
sense_size = sizeof(sptwb.SenseBuf);
memcpy((void *) p_env->gen.scsi_mmc_sense, &sptwb.SenseBuf, sense_size);
p_env->gen.scsi_mmc_sense_valid = sense_size;
}
return DRIVER_OP_SUCCESS;
}
#endif
/*!
Get disc type associated with cd object.
@@ -1112,7 +1213,7 @@ get_mcn_win32ioctl (const _img_private_t *p_env) {
&dw_bytes_returned, NULL ) ) {
cdio_warn( "could not read Q Channel at track %d", 1);
} else if (mcn.Mcval)
return strdup(mcn.MediaCatalog);
return strdup((const char *) mcn.MediaCatalog);
return NULL;
}

View File

@@ -1,6 +1,6 @@
/* -*- C -*-
Copyright (C) 2009 Thomas Schmitt <scdbackup@gmx.net>
Copyright (C) 20010 Rocky Bernstein <rocky@gnu.org>
Copyright (C) 2010 Rocky Bernstein <rocky@gnu.org>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -629,19 +629,19 @@ tmmc_test(char *drive_path, int flag)
sense_avail);
{ret = 2; goto ex;}
}
/* Provoke sense reply by requesting inappropriate mode page 3Eh */
/* Cause sense reply failure by requesting inappropriate mode page 3Eh */
ret = tmmc_mode_sense(p_cdio, &sense_avail, sense,
0x3e, 0, alloc_len, buf, &buf_fill, !!verbose);
if (ret != 0 && sense_avail < 18) {
fprintf(stderr,
"Error: Deliberately illegal command yields only %d sense bytes. Expected >= 18.\n",
"Error: An illegal command yields only %d sense bytes. Expected >= 18.\n",
sense_avail);
{ret = 2; goto ex;}
} else if(ret == 0) {
fprintf(stderr,
"Warning: tmmc_mode_sense() cannot provoke failure by mode page 3Eh\n");
"Warning: tmmc_mode_sense() cannot cause a failure via mode page 3Eh\n");
fprintf(stderr,
"Hint: Consider to set in tmmc_test(): with_tray_dance = 1\n");
"Consider to set in tmmc_test(): with_tray_dance = 1\n");
}
/* Test availability of sense reply in case of unready drive.
@@ -665,9 +665,9 @@ tmmc_test(char *drive_path, int flag)
{ret = 2; goto ex;}
} else if(ret == 0) {
fprintf(stderr,
"Warning: tmmc_mode_sense() cannot provoke failure by mode page 3Eh\n");
"Warning: tmmc_mode_sense() cannot cause failure via mode page 3Eh\n");
fprintf(stderr,
"Hint: Consider to set in tmmc_test(): with_tray_dance = 1\n");
"Consider to set in tmmc_test(): with_tray_dance = 1\n");
}