Implemented IOCTL_SCSI_GET_ADDRESS for non true scsi cdrom drives
(only on linux). Initialize registry under HKEY_LOCAL_MACHINE/HARDWARE/DEVICEMAP/Scsi. Added IOCTL_CDROM_MEDIA_REMOVAL support.
This commit is contained in:
parent
b50a532aff
commit
e7c6d17b3e
|
@ -10463,6 +10463,9 @@ done
|
|||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -10479,8 +10482,10 @@ for ac_header in \
|
|||
libutil.h \
|
||||
link.h \
|
||||
linux/cdrom.h \
|
||||
linux/hdreg.h \
|
||||
linux/input.h \
|
||||
linux/joystick.h \
|
||||
linux/major.h \
|
||||
linux/param.h \
|
||||
linux/serial.h \
|
||||
linux/ucdrom.h \
|
||||
|
@ -10493,6 +10498,7 @@ for ac_header in \
|
|||
pty.h \
|
||||
resolv.h \
|
||||
sched.h \
|
||||
scsi/sg.h \
|
||||
socket.h \
|
||||
stdint.h \
|
||||
strings.h \
|
||||
|
@ -10511,8 +10517,8 @@ for ac_header in \
|
|||
sys/param.h \
|
||||
sys/ptrace.h \
|
||||
sys/reg.h \
|
||||
sys/signal.h \
|
||||
sys/shm.h \
|
||||
sys/signal.h \
|
||||
sys/socket.h \
|
||||
sys/sockio.h \
|
||||
sys/statfs.h \
|
||||
|
@ -10520,11 +10526,11 @@ for ac_header in \
|
|||
sys/syscall.h \
|
||||
sys/time.h \
|
||||
sys/user.h \
|
||||
sys/wait.h \
|
||||
sys/v86.h \
|
||||
sys/v86intr.h \
|
||||
sys/vfs.h \
|
||||
sys/vm86.h \
|
||||
sys/wait.h \
|
||||
syscall.h \
|
||||
ucontext.h \
|
||||
unistd.h \
|
||||
|
|
|
@ -913,8 +913,10 @@ AC_CHECK_HEADERS(\
|
|||
libutil.h \
|
||||
link.h \
|
||||
linux/cdrom.h \
|
||||
linux/hdreg.h \
|
||||
linux/input.h \
|
||||
linux/joystick.h \
|
||||
linux/major.h \
|
||||
linux/param.h \
|
||||
linux/serial.h \
|
||||
linux/ucdrom.h \
|
||||
|
@ -927,6 +929,7 @@ AC_CHECK_HEADERS(\
|
|||
pty.h \
|
||||
resolv.h \
|
||||
sched.h \
|
||||
scsi/sg.h \
|
||||
socket.h \
|
||||
stdint.h \
|
||||
strings.h \
|
||||
|
@ -945,8 +948,8 @@ AC_CHECK_HEADERS(\
|
|||
sys/param.h \
|
||||
sys/ptrace.h \
|
||||
sys/reg.h \
|
||||
sys/signal.h \
|
||||
sys/shm.h \
|
||||
sys/signal.h \
|
||||
sys/socket.h \
|
||||
sys/sockio.h \
|
||||
sys/statfs.h \
|
||||
|
@ -954,11 +957,11 @@ AC_CHECK_HEADERS(\
|
|||
sys/syscall.h \
|
||||
sys/time.h \
|
||||
sys/user.h \
|
||||
sys/wait.h \
|
||||
sys/v86.h \
|
||||
sys/v86intr.h \
|
||||
sys/vfs.h \
|
||||
sys/vm86.h \
|
||||
sys/wait.h \
|
||||
syscall.h \
|
||||
ucontext.h \
|
||||
unistd.h \
|
||||
|
|
|
@ -24,9 +24,13 @@
|
|||
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "ntddk.h"
|
||||
#include "winioctl.h"
|
||||
#include "ntddstor.h"
|
||||
|
@ -36,6 +40,15 @@
|
|||
#include "file.h"
|
||||
#include "wine/debug.h"
|
||||
|
||||
#ifdef HAVE_SCSI_SG_H
|
||||
# include <scsi/sg.h>
|
||||
#endif
|
||||
#ifdef HAVE_LINUX_MAJOR_H
|
||||
# include <linux/major.h>
|
||||
#endif
|
||||
#ifdef HAVE_LINUX_HDREG_H
|
||||
# include <linux/hdreg.h>
|
||||
#endif
|
||||
#ifdef HAVE_LINUX_PARAM_H
|
||||
# include <linux/param.h>
|
||||
#endif
|
||||
|
@ -60,6 +73,187 @@ struct cdrom_cache {
|
|||
};
|
||||
static struct cdrom_cache cdrom_cache[26];
|
||||
|
||||
/******************************************************************
|
||||
* CDROM_GetIdeInterface
|
||||
*
|
||||
* Determines the ide interface (the number after the ide), and the
|
||||
* number of the device on that interface for ide cdroms.
|
||||
* Returns false if the info could not be get
|
||||
*
|
||||
* NOTE: this function is used in CDROM_InitRegistry and CDROM_GetAddress
|
||||
*/
|
||||
static int CDROM_GetIdeInterface(int dev, int* iface, int* device)
|
||||
{
|
||||
#if defined(linux)
|
||||
{
|
||||
struct stat st;
|
||||
if (ioctl(dev, SG_EMULATED_HOST) != -1) {
|
||||
FIXME("not implemented for true scsi drives\n");
|
||||
return 0;
|
||||
}
|
||||
if ( fstat(dev, &st) == -1 || ! S_ISBLK(st.st_mode)) {
|
||||
FIXME("cdrom not a block device!!!\n");
|
||||
return 0;
|
||||
}
|
||||
switch (major(st.st_rdev)) {
|
||||
case IDE0_MAJOR: *iface = 0; break;
|
||||
case IDE1_MAJOR: *iface = 1; break;
|
||||
case IDE2_MAJOR: *iface = 2; break;
|
||||
case IDE3_MAJOR: *iface = 3; break;
|
||||
case IDE4_MAJOR: *iface = 4; break;
|
||||
case IDE5_MAJOR: *iface = 5; break;
|
||||
case IDE6_MAJOR: *iface = 6; break;
|
||||
case IDE7_MAJOR: *iface = 7; break;
|
||||
default:
|
||||
FIXME("major %d not supported\n", major(st.st_rdev));
|
||||
}
|
||||
*device = (minor(st.st_rdev) == 63 ? 1 : 0);
|
||||
return 1;
|
||||
}
|
||||
#elif defined(__FreeBSD__) || defined(__NetBSD__)
|
||||
FIXME("not implemented for BSD\n");
|
||||
return 0;
|
||||
#else
|
||||
FIXME("not implemented for nonlinux\n");
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* CDROM_InitRegistry
|
||||
*
|
||||
* Initializes registry to contain scsi info about the cdrom in NT.
|
||||
* All devices (even not real scsi ones) have this info in NT.
|
||||
* TODO: for now it only works for non scsi devices
|
||||
* NOTE: programs usually read these registry entries after sending the
|
||||
* IOCTL_SCSI_GET_ADDRESS ioctl to the cdrom
|
||||
*/
|
||||
void CDROM_InitRegistry(int dev)
|
||||
{
|
||||
int portnum, targetid;
|
||||
int dma;
|
||||
OBJECT_ATTRIBUTES attr;
|
||||
UNICODE_STRING nameW;
|
||||
WCHAR dataW[50];
|
||||
DWORD lenW;
|
||||
char buffer[40];
|
||||
DWORD value;
|
||||
const char *data;
|
||||
HKEY scsiKey;
|
||||
HKEY portKey;
|
||||
HKEY busKey;
|
||||
HKEY targetKey;
|
||||
DWORD disp;
|
||||
|
||||
attr.Length = sizeof(attr);
|
||||
attr.RootDirectory = HKEY_LOCAL_MACHINE;
|
||||
attr.ObjectName = &nameW;
|
||||
attr.Attributes = 0;
|
||||
attr.SecurityDescriptor = NULL;
|
||||
attr.SecurityQualityOfService = NULL;
|
||||
|
||||
if ( ! CDROM_GetIdeInterface(dev, &portnum, &targetid))
|
||||
return;
|
||||
|
||||
/* Ensure there is Scsi key */
|
||||
if (!RtlCreateUnicodeStringFromAsciiz( &nameW, "HARDWARE\\DEVICEMAP\\Scsi" ) ||
|
||||
NtCreateKey( &scsiKey, KEY_ALL_ACCESS, &attr, 0,
|
||||
NULL, REG_OPTION_VOLATILE, &disp ))
|
||||
{
|
||||
ERR("Cannot create DEVICEMAP\\Scsi registry key\n" );
|
||||
return;
|
||||
}
|
||||
RtlFreeUnicodeString( &nameW );
|
||||
|
||||
snprintf(buffer,40,"Scsi Port %d",portnum);
|
||||
attr.RootDirectory = scsiKey;
|
||||
if (!RtlCreateUnicodeStringFromAsciiz( &nameW, buffer ) ||
|
||||
NtCreateKey( &portKey, KEY_ALL_ACCESS, &attr, 0,
|
||||
NULL, REG_OPTION_VOLATILE, &disp ))
|
||||
{
|
||||
ERR("Cannot create DEVICEMAP\\Scsi Port registry key\n" );
|
||||
return;
|
||||
}
|
||||
RtlFreeUnicodeString( &nameW );
|
||||
|
||||
RtlCreateUnicodeStringFromAsciiz( &nameW, "Driver" );
|
||||
data = "atapi";
|
||||
RtlMultiByteToUnicodeN( dataW, 50, &lenW, data, strlen(data));
|
||||
NtSetValueKey( portKey, &nameW, 0, REG_SZ, (BYTE*)dataW, lenW );
|
||||
RtlFreeUnicodeString( &nameW );
|
||||
value = 10;
|
||||
RtlCreateUnicodeStringFromAsciiz( &nameW, "FirstBusTimeScanInMs" );
|
||||
NtSetValueKey( portKey,&nameW, 0, REG_DWORD, (BYTE *)&value, sizeof(DWORD));
|
||||
RtlFreeUnicodeString( &nameW );
|
||||
value = 0;
|
||||
#ifdef HDIO_GET_DMA
|
||||
if (ioctl(dev,HDIO_GET_DMA, &dma) != -1) {
|
||||
value = dma;
|
||||
TRACE("setting dma to %lx\n", value);
|
||||
}
|
||||
#endif
|
||||
RtlCreateUnicodeStringFromAsciiz( &nameW, "DMAEnabled" );
|
||||
NtSetValueKey( portKey,&nameW, 0, REG_DWORD, (BYTE *)&value, sizeof(DWORD));
|
||||
RtlFreeUnicodeString( &nameW );
|
||||
|
||||
attr.RootDirectory = portKey;
|
||||
if (!RtlCreateUnicodeStringFromAsciiz( &nameW, "Scsi Bus 0" ) ||
|
||||
NtCreateKey( &busKey, KEY_ALL_ACCESS, &attr, 0,
|
||||
NULL, REG_OPTION_VOLATILE, &disp ))
|
||||
{
|
||||
ERR("Cannot create DEVICEMAP\\Scsi Port\\Scsi Bus registry key\n" );
|
||||
return;
|
||||
}
|
||||
RtlFreeUnicodeString( &nameW );
|
||||
|
||||
attr.RootDirectory = busKey;
|
||||
if (!RtlCreateUnicodeStringFromAsciiz( &nameW, "Initiator Id 255" ) ||
|
||||
NtCreateKey( &targetKey, KEY_ALL_ACCESS, &attr, 0,
|
||||
NULL, REG_OPTION_VOLATILE, &disp ))
|
||||
{
|
||||
ERR("Cannot create DEVICEMAP\\Scsi Port\\Scsi Bus\\Initiator Id 255 registry key\n" );
|
||||
return;
|
||||
}
|
||||
RtlFreeUnicodeString( &nameW );
|
||||
NtClose( targetKey );
|
||||
|
||||
snprintf(buffer,40,"Target Id %d", targetid);
|
||||
attr.RootDirectory = busKey;
|
||||
if (!RtlCreateUnicodeStringFromAsciiz( &nameW, buffer ) ||
|
||||
NtCreateKey( &targetKey, KEY_ALL_ACCESS, &attr, 0,
|
||||
NULL, REG_OPTION_VOLATILE, &disp ))
|
||||
{
|
||||
ERR("Cannot create DEVICEMAP\\Scsi Port\\Scsi Bus 0\\Target Id registry key\n" );
|
||||
return;
|
||||
}
|
||||
RtlFreeUnicodeString( &nameW );
|
||||
|
||||
RtlCreateUnicodeStringFromAsciiz( &nameW, "Type" );
|
||||
data = "CdRomPeripheral";
|
||||
RtlMultiByteToUnicodeN( dataW, 50, &lenW, data, strlen(data));
|
||||
NtSetValueKey( targetKey, &nameW, 0, REG_SZ, (BYTE*)dataW, lenW );
|
||||
RtlFreeUnicodeString( &nameW );
|
||||
/* FIXME - maybe read the real identifier?? */
|
||||
RtlCreateUnicodeStringFromAsciiz( &nameW, "Identifier" );
|
||||
data = "Wine CDROM";
|
||||
RtlMultiByteToUnicodeN( dataW, 50, &lenW, data, strlen(data));
|
||||
NtSetValueKey( targetKey, &nameW, 0, REG_SZ, (BYTE*)dataW, lenW );
|
||||
RtlFreeUnicodeString( &nameW );
|
||||
/* FIXME - we always use Cdrom0 - do not know about the nt behaviour */
|
||||
RtlCreateUnicodeStringFromAsciiz( &nameW, "DeviceName" );
|
||||
data = "Cdrom0";
|
||||
RtlMultiByteToUnicodeN( dataW, 50, &lenW, data, strlen(data));
|
||||
NtSetValueKey( targetKey, &nameW, 0, REG_SZ, (BYTE*)dataW, lenW );
|
||||
RtlFreeUnicodeString( &nameW );
|
||||
|
||||
NtClose( targetKey );
|
||||
NtClose( busKey );
|
||||
NtClose( portKey );
|
||||
NtClose( scsiKey );
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* CDROM_Open
|
||||
*
|
||||
|
@ -969,20 +1163,22 @@ static DWORD CDROM_ScsiPassThrough(int dev, PSCSI_PASS_THROUGH pPacket)
|
|||
}
|
||||
|
||||
/******************************************************************
|
||||
* CDROM_ScsiGetAddress
|
||||
*
|
||||
*
|
||||
* CDROM_GetAddress
|
||||
*
|
||||
* implements IOCTL_SCSI_GET_ADDRESS
|
||||
*/
|
||||
static DWORD CDROM_ScsiGetAddress(int dev, PSCSI_ADDRESS addr)
|
||||
static DWORD CDROM_GetAddress(int dev, SCSI_ADDRESS* address)
|
||||
{
|
||||
FIXME("IOCTL_SCSI_GET_ADDRESS: stub\n");
|
||||
int portnum, targetid;
|
||||
|
||||
addr->Length = sizeof(SCSI_ADDRESS);
|
||||
addr->PortNumber = 0;
|
||||
addr->PathId = 0;
|
||||
addr->TargetId = 1;
|
||||
addr->Lun = 0;
|
||||
address->Length = sizeof(SCSI_ADDRESS);
|
||||
address->PathId = 0; /* bus number */
|
||||
address->Lun = 0;
|
||||
if ( ! CDROM_GetIdeInterface(dev, &portnum, &targetid))
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
|
||||
address->PortNumber = portnum;
|
||||
address->TargetId = targetid;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1050,11 +1246,6 @@ BOOL CDROM_DeviceIoControl(DWORD clientID, HANDLE hDevice, DWORD dwIoControlCode
|
|||
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:
|
||||
|
@ -1172,7 +1363,12 @@ 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_GET_ADDRESS:
|
||||
sz = sizeof(SCSI_ADDRESS);
|
||||
if (lpInBuffer != NULL || nInBufferSize != 0) error = STATUS_INVALID_PARAMETER;
|
||||
else if (nOutBufferSize < sz) error = STATUS_BUFFER_TOO_SMALL;
|
||||
else error = CDROM_GetAddress(dev, (SCSI_ADDRESS*)lpOutBuffer);
|
||||
break;
|
||||
case IOCTL_SCSI_PASS_THROUGH_DIRECT:
|
||||
sz = sizeof(SCSI_PASS_THROUGH_DIRECT);
|
||||
if (lpOutBuffer == NULL) error = STATUS_INVALID_PARAMETER;
|
||||
|
@ -1185,12 +1381,6 @@ BOOL CDROM_DeviceIoControl(DWORD clientID, HANDLE hDevice, DWORD dwIoControlCode
|
|||
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);
|
||||
|
@ -1208,4 +1398,3 @@ BOOL CDROM_DeviceIoControl(DWORD clientID, HANDLE hDevice, DWORD dwIoControlCode
|
|||
CDROM_Close(clientID, dev);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
|
@ -133,6 +133,8 @@ inline static char *heap_strdup( const char *str )
|
|||
return p;
|
||||
}
|
||||
|
||||
extern void CDROM_InitRegistry(int dev);
|
||||
|
||||
/***********************************************************************
|
||||
* DRIVE_GetDriveType
|
||||
*/
|
||||
|
@ -250,9 +252,17 @@ int DRIVE_Init(void)
|
|||
buffer, sizeof(buffer) );
|
||||
if (buffer[0])
|
||||
{
|
||||
int cd_fd;
|
||||
drive->device = heap_strdup( buffer );
|
||||
if (PROFILE_GetWineIniBool( name, "ReadVolInfo", 1))
|
||||
drive->flags |= DRIVE_READ_VOL_INFO;
|
||||
if (drive->type == DRIVE_CDROM)
|
||||
{
|
||||
if ((cd_fd = open(buffer,O_RDONLY|O_NONBLOCK)) != -1) {
|
||||
CDROM_InitRegistry(cd_fd);
|
||||
close(cd_fd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Get the FailReadOnly flag */
|
||||
|
|
|
@ -242,12 +242,18 @@
|
|||
/* Define if Linux-style gethostbyname_r and gethostbyaddr_r are available */
|
||||
#undef HAVE_LINUX_GETHOSTBYNAME_R_6
|
||||
|
||||
/* Define to 1 if you have the <linux/hdreg.h> header file. */
|
||||
#undef HAVE_LINUX_HDREG_H
|
||||
|
||||
/* Define to 1 if you have the <linux/input.h> header file. */
|
||||
#undef HAVE_LINUX_INPUT_H
|
||||
|
||||
/* 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/major.h> header file. */
|
||||
#undef HAVE_LINUX_MAJOR_H
|
||||
|
||||
/* Define to 1 if you have the <linux/param.h> header file. */
|
||||
#undef HAVE_LINUX_PARAM_H
|
||||
|
||||
|
@ -350,6 +356,9 @@
|
|||
/* Define to 1 if you have the <sched.h> header file. */
|
||||
#undef HAVE_SCHED_H
|
||||
|
||||
/* Define to 1 if you have the <scsi/sg.h> header file. */
|
||||
#undef HAVE_SCSI_SG_H
|
||||
|
||||
/* Define to 1 if you have the `select' function. */
|
||||
#undef HAVE_SELECT
|
||||
|
||||
|
|
Loading…
Reference in New Issue