Reimplement IOCTL_SCSI_PASS_THROUGH_DIRECT and

IOCTL_SCSI_PASS_THROUGH on top of the linux scsi driver.
This commit is contained in:
Ivan Leo Puoti 2005-06-14 12:25:41 +00:00 committed by Alexandre Julliard
parent 8272074b85
commit eacd06264e
1 changed files with 62 additions and 69 deletions

View File

@ -4,6 +4,7 @@
* Copyright 1994 Martin Ayotte * Copyright 1994 Martin Ayotte
* Copyright 1999, 2001, 2003 Eric Pouech * Copyright 1999, 2001, 2003 Eric Pouech
* Copyright 2000 Andreas Mohr * Copyright 2000 Andreas Mohr
* Copyright 2005 Ivan Leo Puoti
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * modify it under the terms of the GNU Lesser General Public
@ -1397,62 +1398,61 @@ static NTSTATUS CDROM_RawRead(int fd, const RAW_READ_INFO* raw, void* buffer, DW
} }
/****************************************************************** /******************************************************************
* CDROM_ScsiPassThroughDirect * CDROM_ScsiPassThroughDirect
* * Implements IOCTL_SCSI_PASS_THROUGH_DIRECT
* *
*/ */
static NTSTATUS CDROM_ScsiPassThroughDirect(int fd, PSCSI_PASS_THROUGH_DIRECT pPacket) static NTSTATUS CDROM_ScsiPassThroughDirect(int fd, PSCSI_PASS_THROUGH_DIRECT pPacket)
{ {
int ret = STATUS_NOT_SUPPORTED; int ret = STATUS_NOT_SUPPORTED;
#if defined(linux) && defined(CDROM_SEND_PACKET)
struct linux_cdrom_generic_command cmd; #if defined(linux)
struct request_sense sense; sg_io_hdr_t cmd;
int io; int io;
if (pPacket->Length < sizeof(SCSI_PASS_THROUGH_DIRECT)) if (pPacket->Length < sizeof(SCSI_PASS_THROUGH_DIRECT))
return STATUS_BUFFER_TOO_SMALL; return STATUS_BUFFER_TOO_SMALL;
if (pPacket->CdbLength > 12) if (pPacket->CdbLength > 16)
return STATUS_INVALID_PARAMETER; return STATUS_INVALID_PARAMETER;
if (pPacket->SenseInfoLength > sizeof(sense)) if (pPacket->SenseInfoLength > sizeof(struct request_sense))
return STATUS_INVALID_PARAMETER; return STATUS_INVALID_PARAMETER;
memset(&cmd, 0, sizeof(cmd)); if (pPacket->DataTransferLength > 0 && !pPacket->DataBuffer)
memset(&sense, 0, sizeof(sense)); return STATUS_INVALID_PARAMETER;
memcpy(&(cmd.cmd), &(pPacket->Cdb), pPacket->CdbLength); RtlZeroMemory(&cmd, sizeof(cmd));
cmd.buffer = pPacket->DataBuffer; cmd.interface_id = 'S';
cmd.buflen = pPacket->DataTransferLength; cmd.cmd_len = pPacket->CdbLength;
cmd.sense = &sense; cmd.mx_sb_len = pPacket->SenseInfoLength;
cmd.quiet = 0; cmd.dxfer_len = pPacket->DataTransferLength;
cmd.timeout = pPacket->TimeOutValue*HZ; cmd.dxferp = pPacket->DataBuffer;
cmd.cmdp = pPacket->Cdb;
cmd.sbp = (char*)pPacket + pPacket->SenseInfoOffset;
cmd.timeout = pPacket->TimeOutValue*1000;
switch (pPacket->DataIn) switch (pPacket->DataIn)
{ {
case SCSI_IOCTL_DATA_OUT:
cmd.data_direction = CGC_DATA_WRITE;
break;
case SCSI_IOCTL_DATA_IN: case SCSI_IOCTL_DATA_IN:
cmd.data_direction = CGC_DATA_READ; cmd.dxfer_direction = SG_DXFER_TO_DEV;
break; break;
case SCSI_IOCTL_DATA_OUT:
cmd.dxfer_direction = SG_DXFER_FROM_DEV;
break;
case SCSI_IOCTL_DATA_UNSPECIFIED: case SCSI_IOCTL_DATA_UNSPECIFIED:
cmd.data_direction = CGC_DATA_NONE; cmd.dxfer_direction = SG_DXFER_NONE;
break; break;
default: default:
return STATUS_INVALID_PARAMETER; return STATUS_INVALID_PARAMETER;
} }
io = ioctl(fd, CDROM_SEND_PACKET, &cmd); io = ioctl(fd, SG_IO, &cmd);
if (pPacket->SenseInfoLength != 0) pPacket->ScsiStatus = cmd.status;
{ pPacket->DataTransferLength = cmd.resid;
memcpy((char*)pPacket + pPacket->SenseInfoOffset, pPacket->SenseInfoLength = cmd.sb_len_wr;
&sense, pPacket->SenseInfoLength);
}
pPacket->ScsiStatus = cmd.stat;
ret = CDROM_GetStatusCode(io); ret = CDROM_GetStatusCode(io);
@ -1521,69 +1521,62 @@ static NTSTATUS CDROM_ScsiPassThroughDirect(int fd, PSCSI_PASS_THROUGH_DIRECT pP
} }
/****************************************************************** /******************************************************************
* CDROM_ScsiPassThrough * CDROM_ScsiPassThrough
* * Implements IOCTL_SCSI_PASS_THROUGH
* *
*/ */
static NTSTATUS CDROM_ScsiPassThrough(int fd, PSCSI_PASS_THROUGH pPacket) static NTSTATUS CDROM_ScsiPassThrough(int fd, PSCSI_PASS_THROUGH pPacket)
{ {
int ret = STATUS_NOT_SUPPORTED; int ret = STATUS_NOT_SUPPORTED;
#if defined(linux) && defined(CDROM_SEND_PACKET) #if defined(linux)
struct linux_cdrom_generic_command cmd; sg_io_hdr_t cmd;
struct request_sense sense;
int io; int io;
if (pPacket->Length < sizeof(SCSI_PASS_THROUGH)) if (pPacket->Length < sizeof(SCSI_PASS_THROUGH))
return STATUS_BUFFER_TOO_SMALL; return STATUS_BUFFER_TOO_SMALL;
if (pPacket->CdbLength > 12) if (pPacket->CdbLength > 16)
return STATUS_INVALID_PARAMETER; return STATUS_INVALID_PARAMETER;
if (pPacket->SenseInfoLength > sizeof(sense)) if (pPacket->SenseInfoLength > sizeof(struct request_sense))
return STATUS_INVALID_PARAMETER; return STATUS_INVALID_PARAMETER;
memset(&cmd, 0, sizeof(cmd)); if (pPacket->DataTransferLength > 0 && pPacket->DataBufferOffset < sizeof(SCSI_PASS_THROUGH))
memset(&sense, 0, sizeof(sense)); return STATUS_INVALID_PARAMETER;
memcpy(&(cmd.cmd), &(pPacket->Cdb), pPacket->CdbLength); RtlZeroMemory(&cmd, sizeof(cmd));
if ( pPacket->DataBufferOffset > 0x1000 ) cmd.interface_id = 'S';
{ cmd.dxfer_len = pPacket->DataTransferLength;
cmd.buffer = (void*)pPacket->DataBufferOffset; cmd.dxferp = (char*)pPacket + pPacket->DataBufferOffset;
} cmd.cmd_len = pPacket->CdbLength;
else cmd.cmdp = pPacket->Cdb;
{ cmd.mx_sb_len = pPacket->SenseInfoLength;
cmd.buffer = (char*)pPacket + pPacket->DataBufferOffset; cmd.timeout = pPacket->TimeOutValue*1000;
}
cmd.buflen = pPacket->DataTransferLength; if(cmd.mx_sb_len > 0)
cmd.sense = &sense; cmd.sbp = (char*)pPacket + pPacket->SenseInfoOffset;
cmd.quiet = 0;
cmd.timeout = pPacket->TimeOutValue*HZ;
switch (pPacket->DataIn) switch (pPacket->DataIn)
{ {
case SCSI_IOCTL_DATA_OUT:
cmd.data_direction = CGC_DATA_WRITE;
break;
case SCSI_IOCTL_DATA_IN: case SCSI_IOCTL_DATA_IN:
cmd.data_direction = CGC_DATA_READ; cmd.dxfer_direction = SG_DXFER_TO_DEV;
break; break;
case SCSI_IOCTL_DATA_OUT:
cmd.dxfer_direction = SG_DXFER_FROM_DEV;
break;
case SCSI_IOCTL_DATA_UNSPECIFIED: case SCSI_IOCTL_DATA_UNSPECIFIED:
cmd.data_direction = CGC_DATA_NONE; cmd.dxfer_direction = SG_DXFER_NONE;
break; break;
default: default:
return STATUS_INVALID_PARAMETER; return STATUS_INVALID_PARAMETER;
} }
io = ioctl(fd, CDROM_SEND_PACKET, &cmd); io = ioctl(fd, SG_IO, &cmd);
if (pPacket->SenseInfoLength != 0) pPacket->ScsiStatus = cmd.status;
{ pPacket->DataTransferLength = cmd.resid;
memcpy((char*)pPacket + pPacket->SenseInfoOffset, pPacket->SenseInfoLength = cmd.sb_len_wr;
&sense, pPacket->SenseInfoLength);
}
pPacket->ScsiStatus = cmd.stat;
ret = CDROM_GetStatusCode(io); ret = CDROM_GetStatusCode(io);