我正在转换一些旧代码以与自定义SCSI设备通信。原始代码是为WinXP和ASPI编写的,较新的代码需要在Win7和SPTI上运行。我的问题是,新的代码在调用时失败,执行SCSI“模式选择”操作,状态代码为2,这是一个SCSI“检查条件”错误 - 但这不会发生在WinXP下的旧代码中。
通常,当您获得“检查条件”代码时,您可以向设备发出“请求检测”命令以查明发生的情况。不幸的是,这个设备(在我看来)是错误的,当你做一个Request Sense时总是返回“一切都好”。所以我在这里工作。
所以我希望能就SPTI代码的错误提出一些建议,并对任何反馈表示感谢。
以下是我想到的可能影响这一点的一些事情:
有问题的代码是:
void MSSModeSelect(const ModeSelectRequestPacket& inRequest, StatusResponsePacket& outResponse)
{
IPC_LOG("MSSModeSelect(): PathID=%d, TargetID=%d, LUN=%d", inRequest.m_Device.m_PathId,
inRequest.m_Device.m_TargetId, inRequest.m_Device.m_Lun);
int adapterIndex = inRequest.m_Device.m_PathId;
HANDLE adapterHandle = prvOpenScsiAdapter(inRequest.m_Device.m_PathId);
if (adapterHandle == INVALID_HANDLE_VALUE)
{
outResponse.m_Status = eScsiAdapterErr;
return;
}
SCSI_PASS_THROUGH_WITH_BUFFERS sptwb;
memset(&sptwb, 0, sizeof(sptwb));
#define MODESELECT_BUF_SIZE 32
sptwb.spt.Length = sizeof(SCSI_PASS_THROUGH);
sptwb.spt.PathId = inRequest.m_Device.m_PathId;
sptwb.spt.TargetId = inRequest.m_Device.m_TargetId;
sptwb.spt.Lun = inRequest.m_Device.m_Lun;
sptwb.spt.CdbLength = CDB6GENERIC_LENGTH;
sptwb.spt.SenseInfoLength = 0;
sptwb.spt.DataIn = SCSI_IOCTL_DATA_IN;
sptwb.spt.DataTransferLength = MODESELECT_BUF_SIZE;
sptwb.spt.TimeOutValue = 2;
sptwb.spt.DataBufferOffset =
offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS,ucDataBuf);
sptwb.spt.Cdb[0] = SCSIOP_MODE_SELECT;
sptwb.spt.Cdb[4] = MODESELECT_BUF_SIZE;
DWORD length = offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS,ucDataBuf) +
sptwb.spt.DataTransferLength;
memset(sptwb.ucDataBuf, 0, sizeof(sptwb.ucDataBuf));
sptwb.ucDataBuf[2] = 0x10;
sptwb.ucDataBuf[4] = 0x01;
sptwb.ucDataBuf[5] = 0x04;
ULONG bytesReturned = 0;
BOOL okay = DeviceIoControl(adapterHandle,
IOCTL_SCSI_PASS_THROUGH,
&sptwb,
sizeof(SCSI_PASS_THROUGH),
&sptwb,
length,
&bytesReturned,
FALSE);
DWORD gle = GetLastError();
IPC_LOG(" DeviceIoControl() %s", okay ? "worked" : "failed");
if (okay)
{
outResponse.m_Status = (sptwb.spt.ScsiStatus == 0) ? eOk : ePrinterStatusErr;
}
else
{
outResponse.m_Status = eScsiPermissionsErr;
}
CloseHandle(adapterHandle);
}
答案 0 :(得分:0)
解决方案证明有两个部分。
首先,sptwb.spt.DataIn需要是SCSI_IOCTL_DATA_OUT而不是SCSI_IOCTL_DATA_IN - 因为当然,“模式选择”告诉设备该做什么,而不是向它询问信息。这将DeviceIoControl()的结果从TRUE更改为FALSE,然后GetLastError()返回值87,表示参数无效。
其次,正如我推测的那样,ioctl事务需要使用IOCTL_SCSI_PASS_THROUGH_DIRECT而不是IOCTL_SCSI_PASS_THROUGH来完成。
使用这两项更改完成所有设置后,“模式选择”命令成功。