Commit in reactos/drivers/storage/cdrom on MAIN
cdrom.c+252-331.26 -> 1.27
- Rewrote parts of the capability detection code.

reactos/drivers/storage/cdrom
cdrom.c 1.26 -> 1.27
diff -u -r1.26 -r1.27
--- cdrom.c	13 Nov 2003 14:18:26 -0000	1.26
+++ cdrom.c	29 Feb 2004 12:26:09 -0000	1.27
@@ -16,7 +16,7 @@
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
-/* $Id: cdrom.c,v 1.26 2003/11/13 14:18:26 ekohl Exp $
+/* $Id: cdrom.c,v 1.27 2004/02/29 12:26:09 hbirr Exp $
  *
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS kernel
@@ -37,6 +37,7 @@
 #include <ddk/scsi.h>
 #include <ddk/class2.h>
 #include <ddk/ntddscsi.h>
+#include <ntos/minmax.h>
 
 #define NDEBUG
 #include <debug.h>
@@ -50,7 +51,6 @@
 typedef struct _ERROR_RECOVERY_DATA6
 {
   MODE_PARAMETER_HEADER Header;
-  MODE_PARAMETER_BLOCK BlockDescriptor;
   MODE_READ_RECOVERY_PAGE ReadRecoveryPage;
 } ERROR_RECOVERY_DATA6, *PERROR_RECOVERY_DATA6;
 
@@ -58,10 +58,20 @@
 typedef struct _ERROR_RECOVERY_DATA10
 {
   MODE_PARAMETER_HEADER10 Header;
-  MODE_PARAMETER_BLOCK BlockDescriptor;
   MODE_READ_RECOVERY_PAGE ReadRecoveryPage;
 } ERROR_RECOVERY_DATA10, *PERROR_RECOVERY_DATA10;
 
+typedef struct _MODE_CAPABILITIES_DATA6
+{
+  MODE_PARAMETER_HEADER Header;
+  MODE_CAPABILITIES_PAGE2 CababilitiesPage;
+} MODE_CAPABILITIES_DATA6, *PMODE_CAPABILITIES_DATA6;
+
+typedef struct _MODE_CAPABILITIES_DATA10
+{
+  MODE_PARAMETER_HEADER10 Header;
+  MODE_CAPABILITIES_PAGE2 CababilitiesPage;
+} MODE_CAPABILITIES_DATA10, *PMODE_CAPABILITIES_DATA10;
 
 typedef struct _CDROM_DATA
 {
@@ -69,12 +79,6 @@
   BOOLEAN RawAccess;
   USHORT XaFlags;
 
-  union
-    {
-      ERROR_RECOVERY_DATA6 Data6;
-      ERROR_RECOVERY_DATA10 Data10;
-    } RecoveryData;
-
 } CDROM_DATA, *PCDROM_DATA;
 
 /* CDROM_DATA.XaFlags */
@@ -440,12 +444,10 @@
   PDEVICE_OBJECT DiskDeviceObject;
   PCDROM_DATA CdromData;
   CHAR NameBuffer[80];
-#if 0
   SCSI_REQUEST_BLOCK Srb;
   PUCHAR Buffer;
   ULONG Length;
   PCDB Cdb;
-#endif
   NTSTATUS Status;
 
   DPRINT("CdromClassCreateDeviceObject() called\n");
@@ -591,10 +593,7 @@
   CdromData->XaFlags |= XA_USE_6_BYTE;
 
   /* Read 'error recovery page' to get additional drive capabilities */
-#if 0
-  Length = sizeof(MODE_READ_RECOVERY_PAGE) +
-	   MODE_BLOCK_DESC_LENGTH +
-	   MODE_HEADER_LENGTH;
+  Length = sizeof(MODE_READ_RECOVERY_PAGE) + MODE_HEADER_LENGTH;
 
   RtlZeroMemory (&Srb,
 		 sizeof(SCSI_REQUEST_BLOCK));
@@ -607,8 +606,10 @@
   Cdb->MODE_SENSE.AllocationLength = (UCHAR)Length;
 
   Buffer = ExAllocatePool (NonPagedPool,
-			   sizeof(MODE_READ_RECOVERY_PAGE) +
-			     MODE_BLOCK_DESC_LENGTH + MODE_HEADER_LENGTH10);
+                           max(sizeof(ERROR_RECOVERY_DATA6), 
+			       max(sizeof(ERROR_RECOVERY_DATA10), 
+			           max(sizeof(MODE_CAPABILITIES_DATA6), 
+				       sizeof(MODE_CAPABILITIES_DATA10)))));
   if (Buffer == NULL)
     {
       DPRINT1("Allocating recovery page buffer failed!\n");
@@ -620,16 +621,15 @@
 					Buffer,
 					Length,
 					FALSE);
+
   if (!NT_SUCCESS (Status))
     {
       DPRINT("MODE_SENSE(6) failed\n");
 
       /* Try the 10 byte version */
-      Length = sizeof(MODE_READ_RECOVERY_PAGE) +
-	       MODE_BLOCK_DESC_LENGTH +
-	       MODE_HEADER_LENGTH10;
+      Length = sizeof(MODE_READ_RECOVERY_PAGE) + MODE_HEADER_LENGTH10;
 
-      RtlZeroMemory (&Srb,
+      RtlZeroMemory (&Srb, 
 		     sizeof(SCSI_REQUEST_BLOCK));
       Srb.CdbLength = 10;
       Srb.TimeOutValue = DiskDeviceExtension->TimeOutValue;
@@ -638,13 +638,14 @@
       Cdb->MODE_SENSE10.OperationCode = SCSIOP_MODE_SENSE10;
       Cdb->MODE_SENSE10.PageCode = 0x01;
       Cdb->MODE_SENSE10.AllocationLength[0] = (UCHAR)(Length >> 8);
-      Cdb->MODE_SENSE10.AllocationLength[1] = (UCHAR)(Length && 0xFF);
+      Cdb->MODE_SENSE10.AllocationLength[1] = (UCHAR)(Length & 0xFF);
 
       Status = ScsiClassSendSrbSynchronous (DiskDeviceObject,
 					    &Srb,
 					    Buffer,
 					    Length,
 					    FALSE);
+
       if (Status == STATUS_DATA_OVERRUN)
 	{
 	  DPRINT1("Data overrun\n");
@@ -654,12 +655,6 @@
       else if (NT_SUCCESS (Status))
 	{
 	  DPRINT("Use 10 byte commands\n");
-	  RtlCopyMemory (&CdromData->RecoveryData.Data10.Header,
-			 Buffer,
-			 sizeof (ERROR_RECOVERY_DATA10));
-	  CdromData->RecoveryData.Data10.Header.ModeDataLength[0] = 0;
-	  CdromData->RecoveryData.Data10.Header.ModeDataLength[1] = 0;
-
 	  CdromData->XaFlags &= XA_USE_6_BYTE;
 	  CdromData->XaFlags |= XA_USE_10_BYTE;
 	}
@@ -672,13 +667,237 @@
   else
     {
       DPRINT("Use 6 byte commands\n");
-      RtlCopyMemory (&CdromData->RecoveryData.Data6.Header,
-		     Buffer,
-		     sizeof (ERROR_RECOVERY_DATA6));
-      CdromData->RecoveryData.Data6.Header.ModeDataLength = 0;
     }
-  ExFreePool (Buffer);
+
+  /* Read 'capabilities & mechanical status page' to get additional drive capabilities */
+  Length = sizeof(MODE_READ_RECOVERY_PAGE) + MODE_HEADER_LENGTH;
+
+  if (!(CdromData->XaFlags & XA_NOT_SUPPORTED))
+    {
+      RtlZeroMemory (&Srb, sizeof(SCSI_REQUEST_BLOCK));
+      Srb.CdbLength = 10;
+      Srb.TimeOutValue = DiskDeviceExtension->TimeOutValue;
+      Cdb = (PCDB)Srb.Cdb;
+
+      if (CdromData->XaFlags & XA_USE_10_BYTE)
+        {
+          /* Try the 10 byte version */
+          Length = sizeof(MODE_CAPABILITIES_PAGE2) + MODE_HEADER_LENGTH10;
+
+          Cdb->MODE_SENSE10.OperationCode = SCSIOP_MODE_SENSE10;
+          Cdb->MODE_SENSE10.PageCode = 0x2a;
+          Cdb->MODE_SENSE10.AllocationLength[0] = (UCHAR)(Length >> 8);
+          Cdb->MODE_SENSE10.AllocationLength[1] = (UCHAR)(Length & 0xFF);
+	}
+      else
+        {
+          Length = sizeof(MODE_CAPABILITIES_PAGE2) + MODE_HEADER_LENGTH;
+
+          Cdb->MODE_SENSE.OperationCode = SCSIOP_MODE_SENSE;
+          Cdb->MODE_SENSE.PageCode = 0x2a;
+          Cdb->MODE_SENSE.AllocationLength = (UCHAR)Length;
+        }
+      Status = ScsiClassSendSrbSynchronous (DiskDeviceObject,
+					    &Srb,
+					    Buffer,
+					    Length,
+					    FALSE);
+      if (NT_SUCCESS (Status))
+	{
+#if 0
+          PMODE_CAPABILITIES_PAGE2 CapabilitiesData;
+	  if (CdromData->XaFlags & XA_USE_10_BYTE)
+	    {
+	      CapabilitiesData = (PMODE_CAPABILITIES_PAGE2)(Buffer + sizeof(MODE_PARAMETER_HEADER10));
+	    }
+	  else
+	    {
+	      CapabilitiesData = (PMODE_CAPABILITIES_PAGE2)(Buffer + sizeof(MODE_PARAMETER_HEADER));
+	    }
+
+	  DbgPrint("Capabilities for '%s':\n", NameBuffer);
+	  if (CapabilitiesData->Reserved2[0] & 0x20)
+	    {
+	      DbgPrint("  Drive supports reading of DVD-RAM discs\n");
+	    }
+	  if (CapabilitiesData->Reserved2[0] & 0x10)
+	    {
+	      DbgPrint("  Drive supports reading of DVD-R discs\n");
+	    }
+	  if (CapabilitiesData->Reserved2[0] & 0x08)
+	    {
+	      DbgPrint("  Drive supports reading of DVD-ROM discs\n");
+	    }
+	  if (CapabilitiesData->Reserved2[0] & 0x04)
+	    {
+	      DbgPrint("  Drive supports reading CD-R discs with addressing method 2\n");
+	    }
+	  if (CapabilitiesData->Reserved2[0] & 0x02)
+	    {
+	      DbgPrint("  Drive can read from CD-R/W (CD-E) discs (orange book, part III)\n");
+	    }
+	  if (CapabilitiesData->Reserved2[0] & 0x01)
+	    {
+	      DbgPrint("  Drive supports read from CD-R discs (orange book, part II)\n");
+	    }
+	  DPRINT("CapabilitiesData.Reserved2[1] %x\n", CapabilitiesData->Reserved2[1]);
+	  if (CapabilitiesData->Reserved2[1] & 0x01)
+	    {
+	      DbgPrint("  Drive can write to CD-R discs (orange book, part II)\n");
+	    }
+	  if (CapabilitiesData->Reserved2[1] & 0x02)
+	    {
+	      DbgPrint("  Drive can write to CD-R/W (CD-E) discs (orange book, part III)\n");
+	    }
+	  if (CapabilitiesData->Reserved2[1] & 0x04)
+	    {
+	      DbgPrint("  Drive can fake writes\n");
+	    }
+	  if (CapabilitiesData->Reserved2[1] & 0x10)
+	    {
+	      DbgPrint("  Drive can write DVD-R discs\n");
+	    }
+	  if (CapabilitiesData->Reserved2[1] & 0x20)
+	    {
+	      DbgPrint("  Drive can write DVD-RAM discs\n");
+	    }
+	  DPRINT("CapabilitiesData.Capabilities[0] %x\n", CapabilitiesData->Capabilities[0]);
+	  if (CapabilitiesData->Capabilities[0] & 0x01)
+	    {
+	      DbgPrint("  Drive supports audio play operations\n");
+	    }
+	  if (CapabilitiesData->Capabilities[0] & 0x02)
+	    {
+	      DbgPrint("  Drive can deliver a composite audio/video data stream\n");
+	    }
+	  if (CapabilitiesData->Capabilities[0] & 0x04)
+	    {
+	      DbgPrint("  Drive supports digital output on port 1\n");
+	    }
+	  if (CapabilitiesData->Capabilities[0] & 0x08)
+	    {
+	      DbgPrint("  Drive supports digital output on port 2\n");
+	    }
+	  if (CapabilitiesData->Capabilities[0] & 0x10)
+	    {
+	      DbgPrint("  Drive can read mode 2, form 1 (XA) data\n");
+	    }
+	  if (CapabilitiesData->Capabilities[0] & 0x20)
+	    {
+	      DbgPrint("  Drive can read mode 2, form 2 data\n");
+	    }
+	  if (CapabilitiesData->Capabilities[0] & 0x40)
+	    {
+	      DbgPrint("  Drive can read multisession discs\n");
+	    }
+	  DPRINT("CapabilitiesData.Capabilities[1] %x\n", CapabilitiesData->Capabilities[1]);
+	  if (CapabilitiesData->Capabilities[1] & 0x01)
+	    {
+	      DbgPrint("  Drive can read Red Book audio data\n");
+	    }
+	  if (CapabilitiesData->Capabilities[1] & 0x02)
+	    {
+	      DbgPrint("  Drive can continue a read cdda operation from a loss of streaming\n");
+	    }
+	  if (CapabilitiesData->Capabilities[1] & 0x04)
+	    {
+	      DbgPrint("  Subchannel reads can return combined R-W information\n");
+	    }
+	  if (CapabilitiesData->Capabilities[1] & 0x08)
+	    {
+	      DbgPrint("  R-W data will be returned deinterleaved and error corrected\n");
+	    }
+	  if (CapabilitiesData->Capabilities[1] & 0x10)
+	    {
+	      DbgPrint("  Drive supports C2 error pointers\n");
+	    }
+	  if (CapabilitiesData->Capabilities[1] & 0x20)
+	    {
+	      DbgPrint("  Drive can return International Standard Recording Code info\n");
+	    }
+	  if (CapabilitiesData->Capabilities[1] & 0x40)
+	    {
+	      DbgPrint("  Drive can return Media Catalog Number (UPC) info\n");
+	    }
+	  DPRINT("CapabilitiesData.Capabilities[2] %x\n", CapabilitiesData->Capabilities[2]);
+	  if (CapabilitiesData->Capabilities[2] & 0x01)
+	    {
+	      DbgPrint("  Drive can lock the door\n");
+	    }
+	  if (CapabilitiesData->Capabilities[2] & 0x02)
+	    {
+	      DbgPrint("  The door is locked\n");
+	    }
+	  if (CapabilitiesData->Capabilities[2] & 0x04)
+	    {
+	    }
+	  if (CapabilitiesData->Capabilities[2] & 0x08)
+	    {
+	      DbgPrint("  Drive can eject a disc or changer cartridge\n");
+	    }
+	  if (CapabilitiesData->Capabilities[2] & 0x10)
+	    {
+	      DbgPrint("  Drive supports C2 error pointers\n");
+	    }
+	  switch (CapabilitiesData->Capabilities[2] >> 5)
+	    {
+	      case 0:
+	        DbgPrint("  Drive use a caddy type loading mechanism\n");
+		break;
+	      case 1:
+	        DbgPrint("  Drive use a tray type loading mechanism\n");
+		break;
+	      case 2:
+	        DbgPrint("  Drive use a pop-up type loading mechanism\n");
+		break;
+	      case 4:
+	        DbgPrint("  Drive is a changer with individually changeable discs\n");
+		break;
+	      case 5:
+	        DbgPrint("  Drive is a changer with cartridge mechanism\n");
+		break;
+	    }
+	  DPRINT("CapabilitiesData.Capabilities[3] %x\n", CapabilitiesData->Capabilities[3]);
+	  if (CapabilitiesData->Capabilities[3] & 0x01)
+	    {
+	      DbgPrint("  Audio level for each channel can be controlled independently\n");
+	    }
+	  if (CapabilitiesData->Capabilities[3] & 0x02)
+	    {
+	      DbgPrint("  Audio for each channel can be muted independently\n");
+	    }
+	  if (CapabilitiesData->Capabilities[3] & 0x04)
+	    {
+	      DbgPrint("  Changer can report exact contents of slots\n");
+	    }
+	  if (CapabilitiesData->Capabilities[3] & 0x08)
+	    {
+	      DbgPrint("  Drive supports software slot selection\n");
+	    }
+	  DbgPrint("  Maximum speed is %d kB/s\n", 
+	          (CapabilitiesData->MaximumSpeedSupported[0] << 8) 
+		  | CapabilitiesData->MaximumSpeedSupported[1]);
+	  DbgPrint("  Current speed is %d kB/s\n", 
+	          (CapabilitiesData->CurrentSpeed[0] << 8) 
+		  | CapabilitiesData->CurrentSpeed[1]);
+	  DbgPrint("  Number of discrete volume levels is %d\n",
+	          (CapabilitiesData->Reserved3 << 8) 
+		  | CapabilitiesData->NumberVolumeLevels);
+	  DbgPrint("  Buffer size is %d kB\n",
+	          (CapabilitiesData->BufferSize[0] << 8) 
+		  | CapabilitiesData->BufferSize[1]);
 #endif
+	}
+      else
+	{
+	  DPRINT("XA not supported\n");
+	  CdromData->XaFlags |= XA_NOT_SUPPORTED;
+	}
+
+    }
+
+
+  ExFreePool (Buffer);
 
   /* Initialize device timer */
   IoInitializeTimer(DiskDeviceObject,
CVSspam 0.2.8