Commit 0314a65a authored by Laurent Pinchart's avatar Laurent Pinchart Committed by Alexandre Julliard

Implementation of IOCTL_SCSI_PASS_THROUGH and

IOCTL_SCSI_PASS_THROUGH_DIRECT.
parent b53f1309
......@@ -10466,6 +10466,7 @@ done
for ac_header in \
arpa/inet.h \
arpa/nameser.h \
......@@ -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
......@@ -830,6 +834,159 @@ static DWORD CDROM_RawRead(int dev, const RAW_READ_INFO* raw, void* buffer, DWOR
}
/******************************************************************
* 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
......
/*
* 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_ */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment