Commit e7c6d17b authored by Rizsanyi Zsolt's avatar Rizsanyi Zsolt Committed by Alexandre Julliard

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.
parent b50a532a
......@@ -10467,6 +10467,9 @@ done
for ac_header in \
arpa/inet.h \
arpa/nameser.h \
......@@ -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
......@@ -61,6 +74,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
......
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