Implementation of IOCTL_SCSI_PASS_THROUGH and
IOCTL_SCSI_PASS_THROUGH_DIRECT.
This commit is contained in:
parent
b53f13093e
commit
0314a65a58
|
@ -10464,6 +10464,7 @@ done
|
|||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
for ac_header in \
|
||||
|
@ -10480,6 +10481,7 @@ for ac_header in \
|
|||
linux/cdrom.h \
|
||||
linux/input.h \
|
||||
linux/joystick.h \
|
||||
linux/param.h \
|
||||
linux/serial.h \
|
||||
linux/ucdrom.h \
|
||||
net/if.h \
|
||||
|
|
|
@ -915,6 +915,7 @@ AC_CHECK_HEADERS(\
|
|||
linux/cdrom.h \
|
||||
linux/input.h \
|
||||
linux/joystick.h \
|
||||
linux/param.h \
|
||||
linux/serial.h \
|
||||
linux/ucdrom.h \
|
||||
net/if.h \
|
||||
|
|
|
@ -31,10 +31,14 @@
|
|||
#include "winioctl.h"
|
||||
#include "ntddstor.h"
|
||||
#include "ntddcdrm.h"
|
||||
#include "ntddscsi.h"
|
||||
#include "drive.h"
|
||||
#include "file.h"
|
||||
#include "wine/debug.h"
|
||||
|
||||
#ifdef HAVE_LINUX_PARAM_H
|
||||
# include <linux/param.h>
|
||||
#endif
|
||||
#ifdef HAVE_LINUX_CDROM_H
|
||||
# include <linux/cdrom.h>
|
||||
#endif
|
||||
|
@ -829,6 +833,159 @@ static DWORD CDROM_RawRead(int dev, const RAW_READ_INFO* raw, void* buffer, DWOR
|
|||
return ret;
|
||||
}
|
||||
|
||||
/******************************************************************
|
||||
* CDROM_ScsiPassThroughDirect
|
||||
*
|
||||
*
|
||||
*/
|
||||
static DWORD CDROM_ScsiPassThroughDirect(int dev, PSCSI_PASS_THROUGH_DIRECT pPacket)
|
||||
{
|
||||
int ret = STATUS_NOT_SUPPORTED;
|
||||
#if defined(linux)
|
||||
struct cdrom_generic_command cmd;
|
||||
struct request_sense sense;
|
||||
int io;
|
||||
|
||||
if (pPacket->Length < sizeof(SCSI_PASS_THROUGH_DIRECT))
|
||||
return STATUS_BUFFER_TOO_SMALL;
|
||||
|
||||
if (pPacket->CdbLength > 12)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
if (pPacket->SenseInfoLength > sizeof(sense))
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
memset(&cmd, 0, sizeof(cmd));
|
||||
memset(&sense, 0, sizeof(sense));
|
||||
|
||||
memcpy(&(cmd.cmd), &(pPacket->Cdb), pPacket->CdbLength);
|
||||
|
||||
cmd.buffer = pPacket->DataBuffer;
|
||||
cmd.buflen = pPacket->DataTransferLength;
|
||||
cmd.sense = &sense;
|
||||
cmd.quiet = 0;
|
||||
cmd.timeout = pPacket->TimeOutValue*HZ;
|
||||
|
||||
switch (pPacket->DataIn)
|
||||
{
|
||||
case SCSI_IOCTL_DATA_OUT:
|
||||
cmd.data_direction = CGC_DATA_WRITE;
|
||||
break;
|
||||
case SCSI_IOCTL_DATA_IN:
|
||||
cmd.data_direction = CGC_DATA_READ;
|
||||
break;
|
||||
case SCSI_IOCTL_DATA_UNSPECIFIED:
|
||||
cmd.data_direction = CGC_DATA_NONE;
|
||||
break;
|
||||
default:
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
break;
|
||||
}
|
||||
|
||||
io = ioctl(dev, CDROM_SEND_PACKET, &cmd);
|
||||
|
||||
if (pPacket->SenseInfoLength != 0)
|
||||
{
|
||||
memcpy((char*)pPacket + pPacket->SenseInfoOffset,
|
||||
&sense, pPacket->SenseInfoLength);
|
||||
}
|
||||
|
||||
pPacket->ScsiStatus = cmd.stat;
|
||||
|
||||
ret = CDROM_GetStatusCode(io);
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
/******************************************************************
|
||||
* CDROM_ScsiPassThrough
|
||||
*
|
||||
*
|
||||
*/
|
||||
static DWORD CDROM_ScsiPassThrough(int dev, PSCSI_PASS_THROUGH pPacket)
|
||||
{
|
||||
int ret = STATUS_NOT_SUPPORTED;
|
||||
#if defined(linux)
|
||||
struct cdrom_generic_command cmd;
|
||||
struct request_sense sense;
|
||||
int io;
|
||||
|
||||
if (pPacket->Length < sizeof(SCSI_PASS_THROUGH))
|
||||
return STATUS_BUFFER_TOO_SMALL;
|
||||
|
||||
if (pPacket->CdbLength > 12)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
if (pPacket->SenseInfoLength > sizeof(sense))
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
memset(&cmd, 0, sizeof(cmd));
|
||||
memset(&sense, 0, sizeof(sense));
|
||||
|
||||
memcpy(&(cmd.cmd), &(pPacket->Cdb), pPacket->CdbLength);
|
||||
|
||||
if ( pPacket->DataBufferOffset > 0x1000 )
|
||||
{
|
||||
cmd.buffer = (void*)pPacket->DataBufferOffset;
|
||||
}
|
||||
else
|
||||
{
|
||||
cmd.buffer = ((void*)pPacket) + pPacket->DataBufferOffset;
|
||||
}
|
||||
cmd.buflen = pPacket->DataTransferLength;
|
||||
cmd.sense = &sense;
|
||||
cmd.quiet = 0;
|
||||
cmd.timeout = pPacket->TimeOutValue*HZ;
|
||||
|
||||
switch (pPacket->DataIn)
|
||||
{
|
||||
case SCSI_IOCTL_DATA_OUT:
|
||||
cmd.data_direction = CGC_DATA_WRITE;
|
||||
break;
|
||||
case SCSI_IOCTL_DATA_IN:
|
||||
cmd.data_direction = CGC_DATA_READ;
|
||||
break;
|
||||
case SCSI_IOCTL_DATA_UNSPECIFIED:
|
||||
cmd.data_direction = CGC_DATA_NONE;
|
||||
break;
|
||||
default:
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
break;
|
||||
}
|
||||
|
||||
io = ioctl(dev, CDROM_SEND_PACKET, &cmd);
|
||||
|
||||
if (pPacket->SenseInfoLength != 0)
|
||||
{
|
||||
memcpy((char*)pPacket + pPacket->SenseInfoOffset,
|
||||
&sense, pPacket->SenseInfoLength);
|
||||
}
|
||||
|
||||
pPacket->ScsiStatus = cmd.stat;
|
||||
|
||||
ret = CDROM_GetStatusCode(io);
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
/******************************************************************
|
||||
* CDROM_ScsiGetAddress
|
||||
*
|
||||
*
|
||||
*/
|
||||
static DWORD CDROM_ScsiGetAddress(int dev, PSCSI_ADDRESS addr)
|
||||
{
|
||||
FIXME("IOCTL_SCSI_GET_ADDRESS: stub\n");
|
||||
|
||||
addr->Length = sizeof(SCSI_ADDRESS);
|
||||
addr->PortNumber = 0;
|
||||
addr->PathId = 0;
|
||||
addr->TargetId = 1;
|
||||
addr->Lun = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/******************************************************************
|
||||
* CDROM_DeviceIoControl
|
||||
*
|
||||
|
@ -892,6 +1049,12 @@ BOOL CDROM_DeviceIoControl(DWORD clientID, HANDLE hDevice, DWORD dwIoControlCode
|
|||
else error = CDROM_SetTray(dev, TRUE);
|
||||
break;
|
||||
|
||||
case IOCTL_CDROM_MEDIA_REMOVAL:
|
||||
FIXME("IOCTL_CDROM_MEDIA_REMOVAL: stub\n");
|
||||
sz = 0;
|
||||
error = 0;
|
||||
break;
|
||||
|
||||
case IOCTL_DISK_MEDIA_REMOVAL:
|
||||
case IOCTL_STORAGE_MEDIA_REMOVAL:
|
||||
case IOCTL_STORAGE_EJECTION_CONTROL:
|
||||
|
@ -1009,6 +1172,26 @@ BOOL CDROM_DeviceIoControl(DWORD clientID, HANDLE hDevice, DWORD dwIoControlCode
|
|||
else error = CDROM_RawRead(dev, (const RAW_READ_INFO*)lpInBuffer,
|
||||
lpOutBuffer, nOutBufferSize, &sz);
|
||||
break;
|
||||
|
||||
case IOCTL_SCSI_PASS_THROUGH_DIRECT:
|
||||
sz = sizeof(SCSI_PASS_THROUGH_DIRECT);
|
||||
if (lpOutBuffer == NULL) error = STATUS_INVALID_PARAMETER;
|
||||
else if (nOutBufferSize < sizeof(SCSI_PASS_THROUGH_DIRECT)) error = STATUS_BUFFER_TOO_SMALL;
|
||||
else error = CDROM_ScsiPassThroughDirect(dev, (PSCSI_PASS_THROUGH_DIRECT)lpOutBuffer);
|
||||
break;
|
||||
case IOCTL_SCSI_PASS_THROUGH:
|
||||
sz = sizeof(SCSI_PASS_THROUGH);
|
||||
if (lpOutBuffer == NULL) error = STATUS_INVALID_PARAMETER;
|
||||
else if (nOutBufferSize < sizeof(SCSI_PASS_THROUGH)) error = STATUS_BUFFER_TOO_SMALL;
|
||||
else error = CDROM_ScsiPassThrough(dev, (PSCSI_PASS_THROUGH)lpOutBuffer);
|
||||
break;
|
||||
case IOCTL_SCSI_GET_ADDRESS:
|
||||
sz = 0;
|
||||
if (lpOutBuffer == NULL) error = STATUS_INVALID_PARAMETER;
|
||||
else if (nOutBufferSize < sizeof(SCSI_ADDRESS)) error = STATUS_BUFFER_TOO_SMALL;
|
||||
else error = CDROM_ScsiGetAddress(dev, (PSCSI_ADDRESS)lpOutBuffer);
|
||||
break;
|
||||
|
||||
default:
|
||||
FIXME("Unsupported IOCTL %lx\n", dwIoControlCode);
|
||||
sz = 0;
|
||||
|
|
|
@ -248,6 +248,9 @@
|
|||
/* Define to 1 if you have the <linux/joystick.h> header file. */
|
||||
#undef HAVE_LINUX_JOYSTICK_H
|
||||
|
||||
/* Define to 1 if you have the <linux/param.h> header file. */
|
||||
#undef HAVE_LINUX_PARAM_H
|
||||
|
||||
/* Define to 1 if you have the <linux/serial.h> header file. */
|
||||
#undef HAVE_LINUX_SERIAL_H
|
||||
|
||||
|
|
|
@ -0,0 +1,89 @@
|
|||
/*
|
||||
* DDK definitions for scsi media access
|
||||
*
|
||||
* Copyright (C) 2002 Laurent Pinchart
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _NTDDSCSI_H_
|
||||
#define _NTDDSCSI_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define IOCTL_SCSI_BASE FILE_DEVICE_CONTROLLER
|
||||
|
||||
#define IOCTL_SCSI_PASS_THROUGH CTL_CODE(IOCTL_SCSI_BASE, 0x0401, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
|
||||
#define IOCTL_SCSI_MINIPORT CTL_CODE(IOCTL_SCSI_BASE, 0x0402, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
|
||||
#define IOCTL_SCSI_GET_INQUIRY_DATA CTL_CODE(IOCTL_SCSI_BASE, 0x0403, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define IOCTL_SCSI_GET_CAPABILITIES CTL_CODE(IOCTL_SCSI_BASE, 0x0404, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define IOCTL_SCSI_PASS_THROUGH_DIRECT CTL_CODE(IOCTL_SCSI_BASE, 0x0405, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
|
||||
#define IOCTL_SCSI_GET_ADDRESS CTL_CODE(IOCTL_SCSI_BASE, 0x0406, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define IOCTL_SCSI_RESCAN_BUS CTL_CODE(IOCTL_SCSI_BASE, 0x0407, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define IOCTL_SCSI_GET_DUMP_POINTERS CTL_CODE(IOCTL_SCSI_BASE, 0x0408, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define IOCTL_SCSI_FREE_DUMP_POINTERS CTL_CODE(IOCTL_SCSI_BASE, 0x0409, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define IOCTL_IDE_PASS_THROUGH CTL_CODE(IOCTL_SCSI_BASE, 0x040a, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
|
||||
|
||||
#define SCSI_IOCTL_DATA_OUT 0
|
||||
#define SCSI_IOCTL_DATA_IN 1
|
||||
#define SCSI_IOCTL_DATA_UNSPECIFIED 2
|
||||
|
||||
typedef struct _SCSI_PASS_THROUGH {
|
||||
USHORT Length;
|
||||
UCHAR ScsiStatus;
|
||||
UCHAR PathId;
|
||||
UCHAR TargetId;
|
||||
UCHAR Lun;
|
||||
UCHAR CdbLength;
|
||||
UCHAR SenseInfoLength;
|
||||
UCHAR DataIn;
|
||||
ULONG DataTransferLength;
|
||||
ULONG TimeOutValue;
|
||||
ULONG_PTR DataBufferOffset;
|
||||
ULONG SenseInfoOffset;
|
||||
UCHAR Cdb[16];
|
||||
} SCSI_PASS_THROUGH, *PSCSI_PASS_THROUGH;
|
||||
|
||||
typedef struct _SCSI_PASS_THROUGH_DIRECT {
|
||||
USHORT Length;
|
||||
UCHAR ScsiStatus;
|
||||
UCHAR PathId;
|
||||
UCHAR TargetId;
|
||||
UCHAR Lun;
|
||||
UCHAR CdbLength;
|
||||
UCHAR SenseInfoLength;
|
||||
UCHAR DataIn;
|
||||
ULONG DataTransferLength;
|
||||
ULONG TimeOutValue;
|
||||
PVOID DataBuffer;
|
||||
ULONG SenseInfoOffset;
|
||||
UCHAR Cdb[16];
|
||||
} SCSI_PASS_THROUGH_DIRECT, *PSCSI_PASS_THROUGH_DIRECT;
|
||||
|
||||
typedef struct _SCSI_ADDRESS {
|
||||
ULONG Length;
|
||||
UCHAR PortNumber;
|
||||
UCHAR PathId;
|
||||
UCHAR TargetId;
|
||||
UCHAR Lun;
|
||||
} SCSI_ADDRESS, *PSCSI_ADDRESS;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _NTDDSCSI_H_ */
|
Loading…
Reference in New Issue