implemented IOCTL_SCSI_GET_ADDRESS for nonscsi cdroms for linux

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Changelog:
  * configure, configure.ac, include/config.h.in, dlls/ntdll/cdrom.c,
     files/drive.c:
    Implemented IOCTL_SCSI_GET_ADDRESS for non true scsi cdrom drives (only
    on linux). Added code to initialize registry under
    HKEY_LOCAL_MACHINE/HARDWARE/DEVICEMAP/Scsi which is usually read
    by programs after calling IOCTL_SCSI_GET_ADDRESS
    Also sets up that the already defined IOCTL_CDROM_MEDIA_REMOVAL invokes
    the code which already handles IOCTL_DISK_MEDIA_REMOVAL,
    IOCTL_STORAGE_MEDIA_REMOVAL and IOCTL_STORAGE_EJECTION_CONTROL
    
File ntddscsi.h is where the needed defines are. It is the same as submitted 
by Laurent Pinchart in his SafeDisc patch.
Index: configure
===================================================================
RCS file: /home/wine/wine/configure,v
retrieving revision 1.284
diff -u -u -r1.284 configure
--- configure	30 Apr 2002 21:16:39 -0000	1.284
+++ configure	1 May 2002 00:19:02 -0000
@@ -10466,6 +10466,9 @@
 
 
 
+
+
+
 for ac_header in \
 	arpa/inet.h \
 	arpa/nameser.h \
@@ -10482,6 +10485,8 @@
 	linux/joystick.h \
 	linux/serial.h \
 	linux/ucdrom.h \
+	linux/major.h \
+	linux/hdreg.h \
 	net/if.h \
 	netdb.h \
 	netinet/in.h \
@@ -10491,6 +10496,7 @@
 	pty.h \
 	resolv.h \
 	sched.h \
+	scsi/sg.h \
 	socket.h \
 	stdint.h \
 	strings.h \
Index: configure.ac
===================================================================
RCS file: /home/wine/wine/configure.ac,v
retrieving revision 1.27
diff -u -u -r1.27 configure.ac
--- configure.ac	30 Apr 2002 21:16:39 -0000	1.27
+++ configure.ac	1 May 2002 00:19:06 -0000
@@ -917,6 +917,8 @@
 	linux/joystick.h \
 	linux/serial.h \
 	linux/ucdrom.h \
+	linux/major.h \
+	linux/hdreg.h \
 	net/if.h \
 	netdb.h \
 	netinet/in.h \
@@ -926,6 +928,7 @@
 	pty.h \
 	resolv.h \
 	sched.h \
+	scsi/sg.h \
 	socket.h \
 	stdint.h \
 	strings.h \
Index: dlls/ntdll/cdrom.c
===================================================================
RCS file: /home/wine/wine/dlls/ntdll/cdrom.c,v
retrieving revision 1.7
diff -u -u -r1.7 cdrom.c
--- dlls/ntdll/cdrom.c	2 Apr 2002 19:19:49 -0000	1.7
+++ dlls/ntdll/cdrom.c	1 May 2002 00:19:09 -0000
@@ -27,14 +27,23 @@
 #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"
 #include "ntddcdrm.h"
+#include "ntddscsi.h"
 #include "drive.h"
 #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_CDROM_H
 # include <linux/cdrom.h>
 #endif
@@ -57,6 +66,52 @@
 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
+ */
+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_Open
  *
  *
@@ -830,6 +885,26 @@
 }
 
 /******************************************************************
+ *		CDROM_GetAddress
+ * 
+ * implements IOCTL_SCSI_GET_ADDRESS
+ */
+static DWORD CDROM_GetAddress(int dev, SCSI_ADDRESS* address)
+{
+    int portnum, targetid;
+
+    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;
+}
+
+/******************************************************************
  *		CDROM_DeviceIoControl
  *
  *
@@ -892,6 +967,7 @@
         else error = CDROM_SetTray(dev, TRUE);
         break;
 
+    case IOCTL_CDROM_MEDIA_REMOVAL:
     case IOCTL_DISK_MEDIA_REMOVAL:
     case IOCTL_STORAGE_MEDIA_REMOVAL:
     case IOCTL_STORAGE_EJECTION_CONTROL:
@@ -1008,6 +1084,12 @@
         else if (lpOutBuffer == NULL) error = STATUS_BUFFER_TOO_SMALL;
         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;
     default:
         FIXME("Unsupported IOCTL %lx\n", dwIoControlCode);
Index: files/drive.c
===================================================================
RCS file: /home/wine/wine/files/drive.c,v
retrieving revision 1.68
diff -u -u -r1.68 drive.c
--- files/drive.c	22 Apr 2002 22:34:00 -0000	1.68
+++ files/drive.c	1 May 2002 00:19:20 -0000
@@ -31,12 +31,16 @@
 #include <string.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <sys/ioctl.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
 #include <errno.h>
 #include <unistd.h>
 
+#ifdef HAVE_LINUX_HDREG_H
+# include <linux/hdreg.h>
+#endif
 #ifdef HAVE_SYS_PARAM_H
 # include <sys/param.h>
 #endif
@@ -166,6 +170,136 @@
     return DRIVE_CASE_PRESERVING;
 }
 
+extern int CDROM_GetIdeInterface(int dev, int* iface, int* device);
+
+/******************************************************************
+ *		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
+ */
+static 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;
+    }
+
+    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;
+    if (ioctl(dev,HDIO_GET_DMA, &dma) != -1) {
+        value = dma;
+        TRACE("setting dma to %lx\n", value);
+    }
+    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 );
+}
 
 /***********************************************************************
  *           DRIVE_Init
@@ -250,9 +384,17 @@
                                       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 */
Index: include/config.h.in
===================================================================
RCS file: /home/wine/wine/include/config.h.in,v
retrieving revision 1.110
diff -u -u -r1.110 config.h.in
--- include/config.h.in	26 Apr 2002 19:05:17 -0000	1.110
+++ include/config.h.in	1 May 2002 00:19:28 -0000
@@ -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/serial.h> header file. */
 #undef HAVE_LINUX_SERIAL_H
 
@@ -346,6 +352,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
/*
 * 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_ */

[Index of Archives]     [Gimp for Windows]     [Red Hat]     [Samba]     [Yosemite Camping]     [Graphics Cards]     [Wine Home]

  Powered by Linux