[PATCH] kernel32: Populate HKLM\HARDWARE\DEVICEMAP\Scsi on Mac OS.

Charles Davis cdavis at mymail.mines.edu
Mon Mar 28 11:08:28 CDT 2011


From: Charles Davis <cdavis at mines.edu>

---
 dlls/kernel32/Makefile.in |    2 +-
 dlls/kernel32/oldconfig.c |  157 +++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 154 insertions(+), 5 deletions(-)

diff --git a/dlls/kernel32/Makefile.in b/dlls/kernel32/Makefile.in
index 6c60623..4f5648b 100644
--- a/dlls/kernel32/Makefile.in
+++ b/dlls/kernel32/Makefile.in
@@ -2,7 +2,7 @@ EXTRADEFS = -D_KERNEL32_ -D_NORMALIZE_
 MODULE    = kernel32.dll
 IMPORTLIB = kernel32
 IMPORTS   = winecrt0 ntdll
-EXTRALIBS = @COREFOUNDATIONLIB@ @LIBPOLL@
+EXTRALIBS = @IOKITLIB@ @LIBPOLL@
 EXTRADLLFLAGS = -nodefaultlibs -Wb,-F,KERNEL32.dll -Wl,--image-base,0x7b800000
 
 C_SRCS = \
diff --git a/dlls/kernel32/oldconfig.c b/dlls/kernel32/oldconfig.c
index 02dac06..4474d9c 100644
--- a/dlls/kernel32/oldconfig.c
+++ b/dlls/kernel32/oldconfig.c
@@ -41,6 +41,24 @@
 #ifdef HAVE_LINUX_HDREG_H
 # include <linux/hdreg.h>
 #endif
+#ifdef HAVE_COREFOUNDATION_COREFOUNDATION_H
+# include <CoreFoundation/CoreFoundation.h>
+#endif
+#ifdef HAVE_IOKIT_IOKITLIB_H
+# include <IOKit/IOKitLib.h>
+# include <IOKit/IOBSD.h>
+# include <IOKit/scsi/SCSICmds_INQUIRY_Definitions.h>
+
+typedef struct
+{
+    uint64_t bus;
+    uint64_t port;
+    uint64_t target;
+    uint64_t lun;
+} dk_scsi_identify_t;
+
+#define DKIOCSCSIIDENTIFY _IOR('d', 254, dk_scsi_identify_t)
+#endif
 
 #define NONAMELESSUNION
 #define NONAMELESSSTRUCT
@@ -84,7 +102,7 @@ static NTSTATUS create_key( HANDLE root, const char *name, HANDLE *key, DWORD *d
  *       IOCTL_SCSI_GET_ADDRESS ioctl to the cdrom
  */
 static void create_scsi_entry( PSCSI_ADDRESS scsi_addr, LPCSTR lpDriver, UINT uDriveType,
-    LPSTR lpDriveName, LPSTR lpUnixDeviceName )
+    LPSTR lpDriveName, LPSTR lpUnixDeviceName, UCHAR uInitId )
 {
     static UCHAR uCdromNumber = 0;
     static UCHAR uTapeNumber = 0;
@@ -141,7 +159,7 @@ static void create_scsi_entry( PSCSI_ADDRESS scsi_addr, LPCSTR lpDriver, UINT uD
     snprintf(buffer, sizeof(buffer),"Scsi Bus %d", scsi_addr->PathId);
     if (create_key( portKey, buffer, &busKey, &disp )) return;
 
-    /* FIXME: get real controller Id for SCSI */
+    snprintf(buffer, sizeof(buffer), "Initiator Id %d", uInitId);
     if (create_key( busKey, buffer, &targetKey, &disp )) return;
     NtClose( targetKey );
 
@@ -153,6 +171,50 @@ static void create_scsi_entry( PSCSI_ADDRESS scsi_addr, LPCSTR lpDriver, UINT uD
 
     switch (uDriveType)
     {
+#ifdef HAVE_IOKIT_IOKITLIB_H
+        /* With I/O Kit, we do it by SCSI peripheral type */
+        case 0x00:  /* Disk drives */
+            data = "DiskPeripheral"; break;
+        case 0x01:  /* Tape drives */
+            data = "TapePeripheral";
+            snprintf(buffer, sizeof(buffer), "Tape%d", uTapeNumber++);
+            break;
+        case 0x02:  /* Printers */
+            data = "PrinterPeripheral"; break;
+        case 0x04:  /* WORM disk drives */
+            data = "WormPeripheral"; break;
+        case 0x05:  /* MMC CD/DVD drives */
+            data = "CdRomPeripheral";
+            snprintf(buffer, sizeof(buffer), "Cdrom%d", uCdromNumber++);
+            break;
+        case 0x06:  /* Scanners */
+            data = "ScannerPeripheral"; break;
+        case 0x07:  /* Optical disk drives (NOT CD-ROMs) */
+            data = "OpticalDiskPeripheral"; break;
+        case 0x08:  /* Medium changers */
+            data = "MediumChangerPeripheral"; break;
+        case 0x09:  /* Communications devices */
+            data = "CommunicationsPeripheral"; break;
+        case 0x0A:  /* ASC IT8 pre-press graphic arts devices */
+        case 0x0B:  /* Same here */
+            data = "ASCPrePressGraphicsPeripheral"; break;
+        case 0x0C:  /* Disk drive arrays */
+            data = "ArrayPeripheral"; break;
+        case 0x0D:  /* Device enclosures */
+            data = "EnclosurePeripheral"; break;
+        case 0x0E:  /* Reduced-commands disk drives */
+            data = "RBCPeripheral"; break;
+        case 0x0F:  /* Card readers */
+            data = "CardReaderPeripheral"; break;
+        case 0x10:  /* Bridge controllers */
+            data = "BridgePeripheral"; break;
+        case 0x11:  /* Object-based storage devices */
+        case 0x12:  /* Automation/drive controllers */
+        case 0x15:  /* Reduced-commands MM devices */
+        case 0x03:  /* Processor devices (considered to be "Other" by Windows) */
+        default:
+            data = "OtherPeripheral"; break;
+#else
         case DRIVE_NO_ROOT_DIR:
         default:
             data = "OtherPeripheral"; break;
@@ -166,6 +228,7 @@ static void create_scsi_entry( PSCSI_ADDRESS scsi_addr, LPCSTR lpDriver, UINT uD
             data = "CdRomPeripheral";
             snprintf(buffer, sizeof(buffer), "Cdrom%d", uCdromNumber++);
             break;
+#endif
     }
     RtlCreateUnicodeStringFromAsciiz( &nameW, "Type" );
     RtlMultiByteToUnicodeN( dataW, sizeof(dataW), &sizeW, data, strlen(data)+1);
@@ -177,7 +240,11 @@ static void create_scsi_entry( PSCSI_ADDRESS scsi_addr, LPCSTR lpDriver, UINT uD
     NtSetValueKey( lunKey, &nameW, 0, REG_SZ, dataW, sizeW );
     RtlFreeUnicodeString( &nameW );
 
+#ifdef HAVE_IOKIT_IOKITLIB_H
+    if (uDriveType == 0x01 || uDriveType == 0x05)
+#else
     if (uDriveType == DRIVE_CDROM || uDriveType == DRIVE_REMOVABLE)
+#endif
     {
         RtlCreateUnicodeStringFromAsciiz( &nameW, "DeviceName" );
         RtlMultiByteToUnicodeN( dataW, sizeof(dataW), &sizeW, buffer, strlen(buffer)+1);
@@ -197,6 +264,85 @@ static void create_scsi_entry( PSCSI_ADDRESS scsi_addr, LPCSTR lpDriver, UINT uD
     NtClose( scsiKey );
 }
 
+#ifdef HAVE_IOKIT_IOKITLIB_H
+static int SCSI_ReadIORegEnt( io_service_t spd, SCSI_ADDRESS *scsi_addr, UINT *init, UINT *pdtype,
+                              char *model, UINT model_size, char *unixdev, UINT unixdev_size )
+{
+    CFTypeRef obj;
+    int fd;
+    size_t model_len;
+    dk_scsi_identify_t addr;
+    io_service_t pdn;
+
+    IORegistryEntryGetParentEntry( spd, kIOServicePlane, &pdn );
+    /* First get the vendor, product, and revision strings */
+    obj = IORegistryEntryCreateCFProperty( pdn, CFSTR(kIOPropertySCSIVendorIdentification), NULL, 0 );
+    CFStringGetCString( obj, model, model_size, kCFStringEncodingUTF8 );
+    model_len = CFStringGetLength( obj );
+    CFRelease( obj );
+    model[model_len++] = ' ';
+    obj = IORegistryEntryCreateCFProperty( pdn, CFSTR(kIOPropertySCSIProductIdentification), NULL, 0 );
+    CFStringGetCString( obj, model+model_len, model_size-model_len, kCFStringEncodingUTF8 );
+    model_len += CFStringGetLength( obj );
+    CFRelease( obj );
+    model[model_len++] = ' ';
+    obj = IORegistryEntryCreateCFProperty( pdn, CFSTR(kIOPropertySCSIProductRevisionLevel), NULL, 0 );
+    CFStringGetCString( obj, model+model_len, model_size-model_len, kCFStringEncodingUTF8 );
+    CFRelease( obj );
+    IOObjectRelease( pdn );
+
+    /* Also read the peripheral type */
+    obj = IORegistryEntryCreateCFProperty( spd, CFSTR(kIOPropertySCSIPeripheralDeviceType), NULL, 0 );
+    CFNumberGetValue( obj, kCFNumberIntType, pdtype );
+    CFRelease( obj );
+
+    /* Read the device node name */
+    obj = IORegistryEntryCreateCFProperty( spd, CFSTR(kIOBSDNameKey), NULL, 0 );
+    strcpy( unixdev, "/dev/" );
+    CFStringGetCString( obj, unixdev+strlen("/dev/"), unixdev_size-strlen("/dev/"), kCFStringEncodingUTF8 );
+    CFRelease( obj );
+    /* Get the SCSI address from the device node */
+    fd = open( unixdev, O_RDONLY );
+    if (fd == -1) return 0;
+    if (ioctl( fd, DKIOCSCSIIDENTIFY, &addr ) == -1)
+    {
+        close( fd );
+        return 0;
+    }
+    close( fd );
+    scsi_addr->PortNumber = addr.bus;
+    scsi_addr->PathId = addr.port;
+    scsi_addr->TargetId = addr.target;
+    scsi_addr->Lun = addr.lun;
+    /* FIXME: get real controller Id for SCSI */
+    *init = 255;
+    return 1;
+}
+
+/* create the hardware registry branch */
+static void create_hardware_branch(void)
+{
+    io_service_t svc;
+    io_iterator_t it;
+    char cDevModel[40];
+    char cUnixDeviceName[40];
+    UINT pdtype;
+    UINT init;
+    SCSI_ADDRESS scsi_addr;
+
+    /* Enumerate all the IOSCSIPrimaryCommandsDevices */
+    IOServiceGetMatchingServices( kIOMasterPortDefault, IOServiceMatching( "IOSCSIPrimaryCommandsDevice" ), &it );
+
+    while ((svc = IOIteratorNext( it )))
+    {
+        if (!SCSI_ReadIORegEnt( svc, &scsi_addr, &init, &pdtype, cDevModel, sizeof(cDevModel), cUnixDeviceName, sizeof(cUnixDeviceName) )) continue;
+        /* FIXME: Get real driver name */
+        create_scsi_entry( &scsi_addr, "WINE SCSI", pdtype, cDevModel, cUnixDeviceName, init );
+        IOObjectRelease( svc );
+    }
+    IOObjectRelease( it );
+}
+#else
 struct LinuxProcScsiDevice
 {
     int host;
@@ -332,7 +478,8 @@ static void create_hardware_branch(void)
                 if (scsi_addr.PortNumber + 1 > uFirstSCSIPort)
                     uFirstSCSIPort = scsi_addr.PortNumber + 1;
 
-                create_scsi_entry(&scsi_addr, "atapi", nType, cDevModel, cUnixDeviceName);
+                /* FIXME: get real controller Id for SCSI */
+                create_scsi_entry(&scsi_addr, "atapi", nType, cDevModel, cUnixDeviceName, 255);
             }
         }
         closedir(idedir);
@@ -381,12 +528,14 @@ static void create_hardware_branch(void)
         strcat(cDevModel, dev.rev);
         sprintf(cUnixDeviceName, "/dev/sg%d", nSgNumber++);
         /* FIXME: get real driver name */
-        create_scsi_entry(&scsi_addr, "WINE SCSI", nType, cDevModel, cUnixDeviceName);
+        /* FIXME: get real controller Id for SCSI */
+        create_scsi_entry(&scsi_addr, "WINE SCSI", nType, cDevModel, cUnixDeviceName, 255);
     }
     if( result != EOF )
         WARN("Incorrect %s format\n", procname_scsi);
     fclose( procfile );
 }
+#endif
 
 
 /***********************************************************************
-- 
1.7.4.rc3




More information about the wine-patches mailing list