ReactOS  0.4.14-dev-606-g14ebc0b
cdrom.c
Go to the documentation of this file.
1 /*
2  * PROJECT: ReactOS Storage Stack
3  * LICENSE: DDK - see license.txt in the root dir
4  * FILE: drivers/storage/cdrom/cdrom.c
5  * PURPOSE: CDROM driver
6  * PROGRAMMERS: Based on a source code sample from Microsoft NT4 DDK
7  */
8 
9 #include "precomp.h"
10 
11 #include <ntddk.h>
12 #include <scsi.h>
13 #include <ntdddisk.h>
14 #include <ntddcdrm.h>
15 #include <include/class2.h>
16 #include <stdio.h>
17 
18 //#define NDEBUG
19 #include <debug.h>
20 
21 #define CDB12GENERIC_LENGTH 12
22 
23 typedef struct _XA_CONTEXT {
24 
25  //
26  // Pointer to the device object.
27  //
28 
30 
31  //
32  // Pointer to the original request when
33  // a mode select must be sent.
34  //
35 
37 
38  //
39  // Pointer to the mode select srb.
40  //
41 
44 
45 typedef struct _ERROR_RECOVERY_DATA {
50 
51 typedef struct _ERROR_RECOVERY_DATA10 {
56 
57 //
58 // CdRom specific addition to device extension.
59 //
60 
61 typedef struct _CDROM_DATA {
62 
63  //
64  // Indicates whether an audio play operation
65  // is currently being performed.
66  //
67 
69 
70  //
71  // Indicates whether the blocksize used for user data
72  // is 2048 or 2352.
73  //
74 
76 
77  //
78  // Indicates whether 6 or 10 byte mode sense/select
79  // should be used.
80  //
81 
83 
84  //
85  // Storage for the error recovery page. This is used
86  // as an easy method to switch block sizes.
87  //
88 
89  union {
92  };
93 
94 
95  //
96  // Pointer to the original irp for the raw read.
97  //
98 
100 
101  //
102  // Used to protect accesses to the RawAccess flag.
103  //
104 
106 
107  //
108  // Even if media change support is requested, there are some devices
109  // that are not supported. This flag will indicate that such a device
110  // is present when it is FALSE.
111  //
112 
114 
115  //
116  // The media change event is being supported. The media change timer
117  // should be running whenever this is true.
118  //
119 
121 
122  //
123  // The timer value to support media change events. This is a countdown
124  // value used to determine when to poll the device for a media change.
125  // The max value for the timer is 255 seconds.
126  //
127 
129 
130 #if DBG
131  //
132  // Second timer to keep track of how long the media change IRP has been
133  // in use. If this value exceeds the timeout (#defined) then we should
134  // print out a message to the user and set the MediaChangeIrpLost flag
135  //
136 
137  SHORT MediaChangeIrpTimeInUse;
138 
139  //
140  // Set by CdRomTickHandler when we determine that the media change irp has
141  // been lost
142  //
143 
144  BOOLEAN MediaChangeIrpLost;
145 #endif
146 
147  UCHAR PadReserve; // use this for new flags.
148 
149  //
150  // An IRP is allocated and kept for the duration that media change
151  // detection is in effect. If this is NULL and MediaChange is TRUE,
152  // the detection is in progress. This should always be NULL when
153  // MediaChange is FALSE.
154  //
155 
157 
158  //
159  // The timer work list is a collection of IRPS that are prepared for
160  // submission, but need to allow some time to pass before they are
161  // run.
162  //
163 
166 
168 
169 #define DEVICE_EXTENSION_SIZE sizeof(DEVICE_EXTENSION) + sizeof(CDROM_DATA)
170 #define SCSI_CDROM_TIMEOUT 10
171 #define SCSI_CHANGER_BONUS_TIMEOUT 10
172 #define HITACHI_MODE_DATA_SIZE 12
173 #define MODE_DATA_SIZE 64
174 #define RAW_SECTOR_SIZE 2352
175 #define COOKED_SECTOR_SIZE 2048
176 #define MEDIA_CHANGE_DEFAULT_TIME 4
177 #define CDROM_SRB_LIST_SIZE 4
178 
179 
180 #if DBG
181 
182 //
183 // Used to detect the loss of the autorun irp. The driver prints out a message
184 // (debug level 0) if this timeout ever occurs
185 //
186 #define MEDIA_CHANGE_TIMEOUT_TIME 300
187 
188 #endif
189 
190 #define PLAY_ACTIVE(DeviceExtension) (((PCDROM_DATA)(DeviceExtension + 1))->PlayActive)
191 
192 #define MSF_TO_LBA(Minutes,Seconds,Frames) \
193  (ULONG)((60 * 75 * (Minutes)) + (75 * (Seconds)) + ((Frames) - 150))
194 
195 #define LBA_TO_MSF(Lba,Minutes,Seconds,Frames) \
196 { \
197  (Minutes) = (UCHAR)(Lba / (60 * 75)); \
198  (Seconds) = (UCHAR)((Lba % (60 * 75)) / 75); \
199  (Frames) = (UCHAR)((Lba % (60 * 75)) % 75); \
200 }
201 
202 #define DEC_TO_BCD(x) (((x / 10) << 4) + (x % 10))
203 
204 //
205 // Define flags for XA, CDDA, and Mode Select/Sense
206 //
207 
208 #define XA_USE_6_BYTE 0x01
209 #define XA_USE_10_BYTE 0x02
210 #define XA_USE_READ_CD 0x04
211 #define XA_NOT_SUPPORTED 0x08
212 
213 #define PLEXTOR_CDDA 0x10
214 #define NEC_CDDA 0x20
215 
216 //
217 // Sector types for READ_CD
218 //
219 
220 #define ANY_SECTOR 0
221 #define CD_DA_SECTOR 1
222 #define YELLOW_MODE1_SECTOR 2
223 #define YELLOW_MODE2_SECTOR 3
224 #define FORM2_MODE1_SECTOR 4
225 #define FORM2_MODE2_SECTOR 5
226 
227 
228 #ifdef POOL_TAGGING
229 #ifdef ExAllocatePool
230 #undef ExAllocatePool
231 #endif
232 #define ExAllocatePool(a,b) ExAllocatePoolWithTag(a,b,'CscS')
233 #endif
234 
235 NTSTATUS
236 NTAPI
240  );
241 
242 BOOLEAN
243 NTAPI
248  IN PDEVICE_OBJECT PortDeviceObject,
250  );
251 
252 NTSTATUS
253 NTAPI
256  IN PIRP Irp
257  );
258 
259 NTSTATUS
260 NTAPI
263  IN PIRP Irp
264  );
265 
266 NTSTATUS
267 NTAPI
272  );
273 
274 NTSTATUS
275 NTAPI
278  IN PIRP Irp
279  );
280 
281 IO_COMPLETION_ROUTINE CdRomDeviceControlCompletion;
282 NTSTATUS
283 NTAPI
286  IN PIRP Irp,
288  );
289 
291 NTSTATUS
292 NTAPI
295  IN PIRP Irp,
297  );
298 
299 IO_COMPLETION_ROUTINE CdRomSwitchModeCompletion;
300 NTSTATUS
301 NTAPI
304  IN PIRP Irp,
306  );
307 
308 IO_COMPLETION_ROUTINE CdRomXACompletion;
309 NTSTATUS
310 NTAPI
313  IN PIRP Irp,
315  );
316 
317 IO_COMPLETION_ROUTINE CdRomClassIoctlCompletion;
318 NTSTATUS
319 NTAPI
322  IN PIRP Irp,
324  );
325 
326 VOID
327 NTAPI
330  IN PIRP Irp
331  );
332 
333 VOID
334 NTAPI
338  );
339 
340 BOOLEAN
341 NTAPI
345  );
346 
347 NTSTATUS
348 NTAPI
350  IN PDEVICE_EXTENSION DeviceExtension,
351  IN PIRP IrpToComplete,
352  IN OPTIONAL PKEVENT IoctlEvent
353  );
354 
355 NTSTATUS
356 NTAPI
359  IN PDEVICE_OBJECT PortDeviceObject,
362  PIO_SCSI_CAPABILITIES PortCapabilities,
363  IN PSCSI_INQUIRY_DATA LunInfo,
366  );
367 
368 VOID
369 NTAPI
372  PINQUIRYDATA InquiryData,
373  PIO_SCSI_CAPABILITIES PortCapabilities
374  );
375 
376 BOOLEAN
377 NTAPI
380  );
381 
382 VOID
383 NTAPI
387  NTSTATUS *Status,
388  BOOLEAN *Retry
389  );
390 
391 IO_COMPLETION_ROUTINE ToshibaProcessErrorCompletion;
392 VOID
393 NTAPI
397  NTSTATUS *Status,
398  BOOLEAN *Retry
399  );
400 
401 BOOLEAN
402 NTAPI
405  OUT PULONG DiscsPresent
406  );
407 
408 BOOLEAN
409 NTAPI
412  IN UCHAR PathId,
414  );
415 
416 BOOLEAN
417 NTAPI
420  IN PDEVICE_OBJECT PortDeviceObject
421  );
422 
423 VOID
424 NTAPI
426  IN PDEVICE_EXTENSION DeviceExtension,
428  );
429 
430 #ifdef _PPC_
431 NTSTATUS
434  IN UNICODE_STRING ScsiUnicodeString[],
435  OUT PUCHAR IntermediateController
436  );
437 #endif
438 
439 #ifdef ALLOC_PRAGMA
440 #pragma alloc_text(PAGE, DriverEntry)
441 #pragma alloc_text(PAGE, ScsiCdRomFindDevices)
442 #pragma alloc_text(PAGE, CreateCdRomDeviceObject)
443 #pragma alloc_text(PAGE, ScanForSpecial)
444 //#pragma alloc_text(PAGE, CdRomDeviceControl)
445 #pragma alloc_text(PAGE, HitachProcessError)
446 #pragma alloc_text(PAGE, CdRomIsPlayActive)
447 #pragma alloc_text(PAGE, ScsiCdRomReadVerification)
448 #pragma alloc_text(INIT, CdRomCheckRegistryForMediaChangeValue)
449 #pragma alloc_text(INIT, IsThisAnAtapiChanger)
450 #pragma alloc_text(INIT, IsThisASanyo)
451 #pragma alloc_text(INIT, IsThisAMultiLunDevice)
452 #pragma alloc_text(INIT, CdRomCreateNamedEvent)
453 #ifdef _PPC_
454 #pragma alloc_text(PAGE, FindScsiAdapter)
455 #endif
456 #endif
457 
459 
460 NTSTATUS
461 NTAPI
465  )
466 
467 /*++
468 
469 Routine Description:
470 
471  This routine initializes the cdrom class driver.
472 
473 Arguments:
474 
475  DriverObject - Pointer to driver object created by system.
476 
477  RegistryPath - Pointer to the name of the services node for this driver.
478 
479 Return Value:
480 
481  The function value is the final status from the initialization operation.
482 
483 --*/
484 
485 {
487 
488  if(NoLoad) {
489  return STATUS_NO_SUCH_DEVICE;
490  }
491 
492  //
493  // Zero InitData
494  //
495 
497 
498  //
499  // Set sizes
500  //
501 
502  InitializationData.InitializationDataSize = sizeof(CLASS_INIT_DATA);
503  InitializationData.DeviceExtensionSize = DEVICE_EXTENSION_SIZE;
504 
507 
508  //
509  // Set entry points
510  //
511 
512  InitializationData.ClassReadWriteVerification = ScsiCdRomReadVerification;
513  InitializationData.ClassDeviceControl = CdRomDeviceControl;
514  InitializationData.ClassFindDevices = ScsiCdRomFindDevices;
515  InitializationData.ClassShutdownFlush = NULL;
516  InitializationData.ClassCreateClose = NULL;
517  InitializationData.ClassStartIo = ScsiCdRomStartIo;
518 
519  //
520  // Call the class init routine
521  //
522 
524 
525 } // end DriverEntry()
526 
527 BOOLEAN
528 NTAPI
533  IN PDEVICE_OBJECT PortDeviceObject,
535  )
536 
537 /*++
538 
539 Routine Description:
540 
541  Connect to SCSI port driver. Get adapter capabilities and
542  SCSI bus configuration information. Search inquiry data
543  for CDROM devices to process.
544 
545 Arguments:
546 
547  DriverObject - CDROM class driver object.
548  PortDeviceObject - SCSI port driver device object.
549  PortNumber - The system ordinal for this scsi adapter.
550 
551 Return Value:
552 
553  TRUE if CDROM device present on this SCSI adapter.
554 
555 --*/
556 
557 {
558  PIO_SCSI_CAPABILITIES portCapabilities;
559  PULONG cdRomCount;
560  PCHAR buffer;
561  PSCSI_INQUIRY_DATA lunInfo;
562  PSCSI_ADAPTER_BUS_INFO adapterInfo;
563  PINQUIRYDATA inquiryData;
564  ULONG scsiBus;
566  BOOLEAN foundDevice = FALSE;
567 
568  //
569  // Call port driver to get adapter capabilities.
570  //
571 
572  status = ScsiClassGetCapabilities(PortDeviceObject, &portCapabilities);
573 
574  if (!NT_SUCCESS(status)) {
575  DebugPrint((1,"FindScsiDevices: ScsiClassGetCapabilities failed\n"));
576  return foundDevice;
577  }
578 
579  //
580  // Call port driver to get inquiry information to find cdroms.
581  //
582 
584 
585  if (!NT_SUCCESS(status)) {
586  DebugPrint((1,"FindScsiDevices: ScsiClassGetInquiryData failed\n"));
587  return foundDevice;
588  }
589 
590  //
591  // Get the address of the count of the number of cdroms already initialized.
592  //
593 
594  cdRomCount = &IoGetConfigurationInformation()->CdRomCount;
595  adapterInfo = (PVOID) buffer;
596 
597  //
598  // For each SCSI bus this adapter supports ...
599  //
600 
601  for (scsiBus=0; scsiBus < adapterInfo->NumberOfBuses; scsiBus++) {
602 
603  //
604  // Get the SCSI bus scan data for this bus.
605  //
606 
607  lunInfo = (PVOID) (buffer + adapterInfo->BusData[scsiBus].InquiryDataOffset);
608 
609  //
610  // Search list for unclaimed disk devices.
611  //
612 
613  while (adapterInfo->BusData[scsiBus].InquiryDataOffset) {
614 
615  inquiryData = (PVOID)lunInfo->InquiryData;
616 
617  if ((inquiryData->DeviceType == READ_ONLY_DIRECT_ACCESS_DEVICE) &&
618  (inquiryData->DeviceTypeQualifier == 0) &&
619  (!lunInfo->DeviceClaimed)) {
620 
621  DebugPrint((1,"FindScsiDevices: Vendor string is %.24s\n",
622  inquiryData->VendorId));
623 
624  //
625  // Create device objects for cdrom
626  //
627 
629  PortDeviceObject,
630  PortNumber,
631  cdRomCount,
632  portCapabilities,
633  lunInfo,
635  RegistryPath);
636 
637  if (NT_SUCCESS(status)) {
638 
639  //
640  // Increment system cdrom device count.
641  //
642 
643  (*cdRomCount)++;
644 
645  //
646  // Indicate that a cdrom device was found.
647  //
648 
649  foundDevice = TRUE;
650  }
651  }
652 
653  //
654  // Get next LunInfo.
655  //
656 
657  if (lunInfo->NextInquiryDataOffset == 0) {
658  break;
659  }
660 
661  lunInfo = (PVOID) (buffer + lunInfo->NextInquiryDataOffset);
662  }
663  }
664 
666 
667 
668  return foundDevice;
669 
670 } // end FindScsiCdRoms()
671 
672 VOID
673 NTAPI
675  IN PDEVICE_EXTENSION DeviceExtension,
677  )
678 
679 /*++
680 
681 Routine Description:
682 
683  Create the named synchronization event for notification of media change
684  events to the system. The event is reset before this function returns.
685 
686 Arguments:
687 
688  DeviceExtension - the device extension pointer for storage of the event pointer.
689 
690 Return Value:
691 
692  None.
693 
694 --*/
695 
696 {
697  UNICODE_STRING unicodeString;
698  OBJECT_ATTRIBUTES objectAttributes;
699  CCHAR eventNameBuffer[MAXIMUM_FILENAME_LENGTH];
700  STRING eventNameString;
701  HANDLE handle;
703 
704 
705  sprintf(eventNameBuffer,"\\Device\\MediaChangeEvent%ld",
706  DeviceNumber);
707 
708  RtlInitString(&eventNameString,
709  eventNameBuffer);
710 
711  status = RtlAnsiStringToUnicodeString(&unicodeString,
712  &eventNameString,
713  TRUE);
714 
715  if (!NT_SUCCESS(status)) {
716  return;
717  }
718 
719  InitializeObjectAttributes(&objectAttributes,
720  &unicodeString,
722  NULL,
723  NULL);
724 
725  DeviceExtension->MediaChangeEvent = IoCreateSynchronizationEvent(&unicodeString,
726  &handle);
727  DeviceExtension->MediaChangeEventHandle = handle;
728 
729  KeClearEvent(DeviceExtension->MediaChangeEvent);
730 
731  RtlFreeUnicodeString(&unicodeString);
732 }
733 
734 
735 VOID
736 NTAPI
738  IN PDEVICE_OBJECT CdDeviceObject
739  )
740 
741 /*++
742 
743 Routine Description:
744 
745  This routine reports the creation of a cdrom device object to the
746  MountMgr to fake PnP.
747 
748 Arguments:
749 
750  CdDeviceObject - Pointer to the created cdrom device.
751 
752 Return Value:
753 
754  VOID
755 
756 --*/
757 {
759  UNICODE_STRING mountMgrDevice;
760  PDEVICE_OBJECT deviceObject;
761  PFILE_OBJECT fileObject;
762  PMOUNTMGR_TARGET_NAME mountTarget;
763  ULONG cdLen;
764  PDEVICE_EXTENSION deviceExtension;
765  PIRP irp;
766  KEVENT event;
767  IO_STATUS_BLOCK ioStatus;
768 
769  //
770  // First, get MountMgr DeviceObject.
771  //
772 
773  RtlInitUnicodeString(&mountMgrDevice, MOUNTMGR_DEVICE_NAME);
775  &fileObject, &deviceObject);
776 
777  if (!NT_SUCCESS(status)) {
778 
779  DebugPrint((1,
780  "ReportToMountMgr: Can't get MountMgr pointers %lx\n",
781  status));
782 
783  return;
784  }
785 
786  deviceExtension = CdDeviceObject->DeviceExtension;
787  cdLen = deviceExtension->DeviceName.Length;
788 
789  //
790  // Allocate input buffer to report our partition device.
791  //
792 
793  mountTarget = ExAllocatePool(NonPagedPool,
794  sizeof(MOUNTMGR_TARGET_NAME) + cdLen);
795 
796  if (!mountTarget) {
797 
798  DebugPrint((1,
799  "ReportToMountMgr: Allocation of mountTarget failed\n"));
800 
801  ObDereferenceObject(fileObject);
802  return;
803  }
804 
805  mountTarget->DeviceNameLength = cdLen;
806  RtlCopyMemory(mountTarget->DeviceName, deviceExtension->DeviceName.Buffer, cdLen);
807 
809 
810  //
811  // Build the IRP used to communicate with the MountMgr.
812  //
813 
815  deviceObject,
816  mountTarget,
817  sizeof(MOUNTMGR_TARGET_NAME) + cdLen,
818  NULL,
819  0,
820  FALSE,
821  &event,
822  &ioStatus);
823 
824  if (!irp) {
825 
826  DebugPrint((1,
827  "ReportToMountMgr: Allocation of irp failed\n"));
828 
829  ExFreePool(mountTarget);
830  ObDereferenceObject(fileObject);
831  return;
832  }
833 
834  //
835  // Call the MountMgr.
836  //
837 
838  status = IoCallDriver(deviceObject, irp);
839 
840  if (status == STATUS_PENDING) {
842  status = ioStatus.Status;
843  }
844 
845  //
846  // We're done.
847  //
848 
849  DPRINT1("Reported to the MountMgr: %lx\n", status);
850 
851  ExFreePool(mountTarget);
852  ObDereferenceObject(fileObject);
853 
854  return;
855 }
856 
857 
858 NTSTATUS
859 NTAPI
862  IN PDEVICE_OBJECT PortDeviceObject,
865  IN PIO_SCSI_CAPABILITIES PortCapabilities,
866  IN PSCSI_INQUIRY_DATA LunInfo,
869  )
870 
871 /*++
872 
873 Routine Description:
874 
875  This routine creates an object for the device and then calls the
876  SCSI port driver for media capacity and sector size.
877 
878 Arguments:
879 
880  DriverObject - Pointer to driver object created by system.
881  PortDeviceObject - to connect to SCSI port driver.
882  DeviceCount - Number of previously installed CDROMs.
883  PortCapabilities - Pointer to structure returned by SCSI port
884  driver describing adapter capabilities (and limitations).
885  LunInfo - Pointer to configuration information for this device.
886 
887 Return Value:
888 
889  NTSTATUS
890 
891 --*/
892 {
893  CHAR ntNameBuffer[64];
895  BOOLEAN changerDevice;
896  SCSI_REQUEST_BLOCK srb;
897  ULONG length;
898  PCDROM_DATA cddata;
899  PCDB cdb;
900  PVOID senseData = NULL;
901  PDEVICE_OBJECT deviceObject = NULL;
902  PDEVICE_EXTENSION deviceExtension = NULL;
903  PUCHAR buffer;
904  ULONG bps;
905  ULONG lastBit;
906  ULONG timeOut;
907  BOOLEAN srbListInitialized = FALSE;
908 
909  //
910  // Claim the device. Note that any errors after this
911  // will goto the generic handler, where the device will
912  // be released.
913  //
914 
915  status = ScsiClassClaimDevice(PortDeviceObject,
916  LunInfo,
917  FALSE,
918  &PortDeviceObject);
919 
920  if (!NT_SUCCESS(status)) {
921  return(status);
922  }
923 
924  //
925  // Create device object for this device.
926  //
927 
928  sprintf(ntNameBuffer,
929  "\\Device\\CdRom%lu",
930  *DeviceCount);
931 
933  ntNameBuffer,
934  NULL,
935  &deviceObject,
937 
938  if (!NT_SUCCESS(status)) {
939  DebugPrint((1,"CreateCdRomDeviceObjects: Can not create device %s\n",
940  ntNameBuffer));
941 
942  goto CreateCdRomDeviceObjectExit;
943  }
944 
945  //
946  // Indicate that IRPs should include MDLs.
947  //
948 
949  deviceObject->Flags |= DO_DIRECT_IO;
950 
951  //
952  // Set up required stack size in device object.
953  //
954 
955  deviceObject->StackSize = PortDeviceObject->StackSize + 2;
956 
957  deviceExtension = deviceObject->DeviceExtension;
958 
959  //
960  // Allocate spinlock for split request completion.
961  //
962 
963  KeInitializeSpinLock(&deviceExtension->SplitRequestSpinLock);
964 
965  //
966  // This is the physical device.
967  //
968 
969  deviceExtension->PhysicalDevice = deviceObject;
970 
971  //
972  // Initialize lock count to zero. The lock count is used to
973  // disable the ejection mechanism when media is mounted.
974  //
975 
976  deviceExtension->LockCount = 0;
977 
978  //
979  // Save system cdrom number
980  //
981 
982  deviceExtension->DeviceNumber = *DeviceCount;
983 
984  //
985  // Copy port device object to device extension.
986  //
987 
988  deviceExtension->PortDeviceObject = PortDeviceObject;
989 
990  //
991  // Set the alignment requirements for the device based on the
992  // host adapter requirements
993  //
994 
995  if (PortDeviceObject->AlignmentRequirement > deviceObject->AlignmentRequirement) {
996  deviceObject->AlignmentRequirement = PortDeviceObject->AlignmentRequirement;
997  }
998 
999  //
1000  // Save address of port driver capabilities.
1001  //
1002 
1003  deviceExtension->PortCapabilities = PortCapabilities;
1004 
1005  //
1006  // Clear SRB flags.
1007  //
1008 
1009  deviceExtension->SrbFlags = 0;
1010  deviceExtension->SrbFlags |= SRB_FLAGS_DISABLE_SYNCH_TRANSFER;
1011 
1012  //
1013  // Allocate request sense buffer.
1014  //
1015 
1017 
1018  if (senseData == NULL) {
1019 
1020  //
1021  // The buffer cannot be allocated.
1022  //
1023 
1025  goto CreateCdRomDeviceObjectExit;
1026  }
1027 
1028  //
1029  // Set the sense data pointer in the device extension.
1030  //
1031 
1032  deviceExtension->SenseData = senseData;
1033 
1034  //
1035  // CDROMs are not partitionable so starting offset is 0.
1036  //
1037 
1038  deviceExtension->StartingOffset.LowPart = 0;
1039  deviceExtension->StartingOffset.HighPart = 0;
1040 
1041  //
1042  // Path/TargetId/LUN describes a device location on the SCSI bus.
1043  // This information comes from the LunInfo buffer.
1044  //
1045 
1046  deviceExtension->PortNumber = (UCHAR)PortNumber;
1047  deviceExtension->PathId = LunInfo->PathId;
1048  deviceExtension->TargetId = LunInfo->TargetId;
1049  deviceExtension->Lun = LunInfo->Lun;
1050 
1051  //
1052  // Set timeout value in seconds.
1053  //
1054 
1056  if (timeOut) {
1057  deviceExtension->TimeOutValue = timeOut;
1058  } else {
1059  deviceExtension->TimeOutValue = SCSI_CDROM_TIMEOUT;
1060  }
1061 
1062  //
1063  // Build the lookaside list for srb's for the physical disk. Should only
1064  // need a couple.
1065  //
1066 
1067  ScsiClassInitializeSrbLookasideList(deviceExtension,
1069 
1070  srbListInitialized = TRUE;
1071 
1072  //
1073  // Back pointer to device object.
1074  //
1075 
1076  deviceExtension->DeviceObject = deviceObject;
1077 
1078  //
1079  // Allocate buffer for drive geometry.
1080  //
1081 
1082  deviceExtension->DiskGeometry =
1084 
1085  if (deviceExtension->DiskGeometry == NULL) {
1086 
1088  goto CreateCdRomDeviceObjectExit;
1089  }
1090 
1091  //
1092  // Set up media change support defaults.
1093  //
1094 
1095  cddata = (PCDROM_DATA)(deviceExtension + 1);
1096 
1099  InitializeListHead(&cddata->TimerIrpList);
1100 
1102  cddata->MediaChangeSupported = FALSE;
1103  cddata->MediaChange = FALSE;
1104 
1105  //
1106  // Assume that there is initially no media in the device
1107  // only notify upper layers if there is something there
1108  //
1109 
1110  deviceExtension->MediaChangeNoMedia = TRUE;
1111  cddata->MediaChangeIrp = NULL;
1112 #if DBG
1113  cddata->MediaChangeIrpTimeInUse = 0;
1114  cddata->MediaChangeIrpLost = FALSE;
1115 #endif
1116 
1117  //
1118  // Scan for Scsi controllers that require special processing.
1119  //
1120 
1121  ScanForSpecial(deviceObject,
1122  (PINQUIRYDATA) LunInfo->InquiryData,
1123  PortCapabilities);
1124 
1125  //
1126  // Do READ CAPACITY. This SCSI command
1127  // returns the last sector address on the device
1128  // and the bytes per sector.
1129  // These are used to calculate the drive capacity
1130  // in bytes.
1131  //
1132 
1133  status = ScsiClassReadDriveCapacity(deviceObject);
1134  bps = deviceExtension->DiskGeometry->Geometry.BytesPerSector;
1135 
1136  if (!NT_SUCCESS(status) || !bps) {
1137 
1138  DebugPrint((1,
1139  "CreateCdRomDeviceObjects: Can't read capacity for device %s\n",
1140  ntNameBuffer));
1141 
1142  //
1143  // Set disk geometry to default values (per ISO 9660).
1144  //
1145 
1146  bps = 2048;
1147  deviceExtension->SectorShift = 11;
1148  deviceExtension->PartitionLength.QuadPart = (LONGLONG)(0x7fffffff);
1149  } else {
1150 
1151  //
1152  // Insure that bytes per sector is a power of 2
1153  // This corrects a problem with the HP 4020i CDR where it
1154  // returns an incorrect number for bytes per sector.
1155  //
1156 
1157  lastBit = (ULONG) -1;
1158  while (bps) {
1159  lastBit++;
1160  bps = bps >> 1;
1161  }
1162 
1163  bps = 1 << lastBit;
1164  }
1165  deviceExtension->DiskGeometry->Geometry.BytesPerSector = bps;
1166  DebugPrint((2, "CreateCdRomDeviceObject: Calc'd bps = %x\n", bps));
1167 
1168  //
1169  // Check to see if this is some sort of changer device
1170  //
1171 
1172  changerDevice = FALSE;
1173 
1174  //
1175  // Search for devices that have special requirements for media
1176  // change support.
1177  //
1178 
1179  if (deviceExtension->Lun > 0) {
1180  changerDevice = TRUE;
1181  }
1182 
1183  if (!changerDevice) {
1184  changerDevice = IsThisASanyo(deviceObject, deviceExtension->PathId,
1185  deviceExtension->TargetId);
1186  }
1187 
1188  if (!changerDevice) {
1189  ULONG tmp;
1190  changerDevice = IsThisAnAtapiChanger(deviceObject, &tmp);
1191  }
1192 
1193  if (!changerDevice) {
1194  changerDevice = IsThisAMultiLunDevice(deviceObject, PortDeviceObject);
1195  }
1196 
1197  //
1198  // If it is a changer device, increment the timeout to take platter-swapping
1199  // time into account
1200  //
1201 
1202  if(changerDevice) {
1203  deviceExtension->TimeOutValue += SCSI_CHANGER_BONUS_TIMEOUT;
1204  }
1205 
1206  //
1207  // Create the media change named event. If this succeeds then continue
1208  // initializing the media change support data items.
1209  //
1210 
1211  CdRomCreateNamedEvent(deviceExtension,*DeviceCount);
1212  if (deviceExtension->MediaChangeEvent) {
1213 
1214  //
1215  // If this is not a changer, get an IRP for the timer request
1216  // and initialize the timer.
1217  //
1218 
1219  if (!changerDevice) {
1220 
1221  //
1222  // Not a changer device - continue with media change initialization.
1223  // Determine if the user actually wants media change events.
1224  //
1225 
1227  PIO_STACK_LOCATION irpStack;
1228  PSCSI_REQUEST_BLOCK srb;
1229  PIRP irp;
1230 
1231  //
1232  // User wants it - preallocate IRP and SRB.
1233  //
1234 
1235  irp = IoAllocateIrp((CCHAR)(deviceObject->StackSize+1),
1236  FALSE);
1237  if (irp) {
1238  PVOID buffer;
1239 
1242 
1243  if (srb && buffer) {
1244  PCDB cdb;
1245 
1246  //
1247  // All resources have been allocated set up the IRP.
1248  //
1249 
1251  irpStack = IoGetCurrentIrpStackLocation(irp);
1252  irpStack->DeviceObject = deviceObject;
1253  irpStack = IoGetNextIrpStackLocation(irp);
1254  cddata->MediaChangeIrp = irp;
1255  irpStack->Parameters.Scsi.Srb = srb;
1256 
1257  //
1258  // Initialize the SRB
1259  //
1260 
1261  RtlZeroMemory(srb, sizeof(SCSI_REQUEST_BLOCK));
1262 
1263  srb->CdbLength = 6;
1264  srb->TimeOutValue = deviceExtension->TimeOutValue * 2;
1265  srb->QueueTag = SP_UNTAGGED;
1268  srb->PathId = deviceExtension->PathId;
1269  srb->TargetId = deviceExtension->TargetId;
1270  srb->Lun = deviceExtension->Lun;
1272 
1273  //
1274  // Initialize and set up the sense information buffer
1275  //
1276 
1278  srb->SenseInfoBuffer = buffer;
1280 
1281  //
1282  // Initialize the CDB
1283  //
1284 
1285  cdb = (PCDB)&srb->Cdb[0];
1286  cdb->CDB6GENERIC.OperationCode = SCSIOP_TEST_UNIT_READY;
1287  cdb->CDB6GENERIC.LogicalUnitNumber = deviceExtension->Lun;
1288 
1289  //
1290  // It is ok to support media change events on this device.
1291  //
1292 
1293  cddata->MediaChangeSupported = TRUE;
1294  cddata->MediaChange = TRUE;
1295 
1296  } else {
1297 
1298  if (srb) {
1299  ExFreePool(srb);
1300  }
1301  if (buffer) {
1302  ExFreePool(buffer);
1303  }
1304  IoFreeIrp(irp);
1305  }
1306  }
1307  } else {
1308  deviceExtension->MediaChangeEvent = NULL;
1309  }
1310  } else {
1311  deviceExtension->MediaChangeEvent = NULL;
1312  }
1313  }
1314 
1315  //
1316  // Assume use of 6-byte mode sense/select for now.
1317  //
1318 
1319  cddata->XAFlags |= XA_USE_6_BYTE;
1320 
1321  //
1322  // Build and issue mode sense with Read error recovery page. This will be used to change
1323  // block size in case of any raw reads (Mode 2, Form 2).
1324  //
1325 
1327 
1328  RtlZeroMemory(&srb, sizeof(SCSI_REQUEST_BLOCK));
1329 
1330  srb.CdbLength = 6;
1331  cdb = (PCDB)srb.Cdb;
1332 
1333  //
1334  // Set timeout value from device extension.
1335  //
1336 
1337  srb.TimeOutValue = deviceExtension->TimeOutValue;
1338 
1339  //
1340  // Build the MODE SENSE CDB. The data returned will be kept in the device extension
1341  // and used to set block size.
1342  //
1343 
1344  cdb->MODE_SENSE.OperationCode = SCSIOP_MODE_SENSE;
1345  cdb->MODE_SENSE.PageCode = 0x1;
1346  cdb->MODE_SENSE.AllocationLength = (UCHAR)length;
1347 
1349  if (!buffer) {
1351  goto CreateCdRomDeviceObjectExit;
1352  }
1353 
1354  status = ScsiClassSendSrbSynchronous(deviceObject,
1355  &srb,
1356  buffer,
1357  length,
1358  FALSE);
1359  if (!NT_SUCCESS(status)) {
1360 
1361  //
1362  // May be Atapi, try 10-byte.
1363  //
1364 
1366 
1367  RtlZeroMemory(&srb, sizeof(SCSI_REQUEST_BLOCK));
1368 
1369  //
1370  // Build the MODE SENSE CDB.
1371  //
1372 
1373  srb.CdbLength = 10;
1374  cdb = (PCDB)srb.Cdb;
1375 
1376  //
1377  // Set timeout value from device extension.
1378  //
1379 
1380  srb.TimeOutValue = deviceExtension->TimeOutValue;
1381 
1382  cdb->MODE_SENSE10.OperationCode = SCSIOP_MODE_SENSE10;
1383  cdb->MODE_SENSE10.PageCode = 0x1;
1384 
1385  cdb->MODE_SENSE10.AllocationLength[0] = (UCHAR)(length >> 8);
1386  cdb->MODE_SENSE10.AllocationLength[1] = (UCHAR)(length & 0xFF);
1387 
1388  status = ScsiClassSendSrbSynchronous(deviceObject,
1389  &srb,
1390  buffer,
1391  length,
1392  FALSE);
1393  if (status == STATUS_DATA_OVERRUN) {
1394 
1395  //
1396  // Build and issue the ReadCd command to ensure that this device supports it.
1397  //
1398 
1399  RtlZeroMemory(cdb, 12);
1400 
1401  cdb->READ_CD.OperationCode = SCSIOP_READ_CD;
1402 
1403  status = ScsiClassSendSrbSynchronous(deviceObject,
1404  &srb,
1405  NULL,
1406  0,
1407  FALSE);
1408 
1409  //
1410  // If the command wasn't rejected then support the READ_CD.
1411  //
1412 
1414 
1415  //
1416  // Using Read CD precludes issuing a mode select to
1417  // set the user data size. So, no buffer copy is
1418  // necessary.
1419  //
1420 
1421  cddata->XAFlags &= ~XA_USE_6_BYTE;
1422  cddata->XAFlags |= XA_USE_READ_CD | XA_USE_10_BYTE;
1423  } else {
1424 
1425  RtlCopyMemory(&cddata->u1.Header, buffer, sizeof(ERROR_RECOVERY_DATA10));
1426  cddata->u1.Header.ModeDataLength = 0;
1427 
1428  cddata->XAFlags &= ~XA_USE_6_BYTE;
1429  cddata->XAFlags |= XA_USE_10_BYTE;
1430  }
1431 
1432  } else if (NT_SUCCESS(status)) {
1433 
1434  RtlCopyMemory(&cddata->u1.Header, buffer, sizeof(ERROR_RECOVERY_DATA10));
1435  cddata->u1.Header.ModeDataLength = 0;
1436 
1437  cddata->XAFlags &= ~XA_USE_6_BYTE;
1438  cddata->XAFlags |= XA_USE_10_BYTE;
1439 
1440  } else {
1441  cddata->XAFlags |= XA_NOT_SUPPORTED;
1442  }
1443  } else {
1444  RtlCopyMemory(&cddata->u1.Header, buffer, sizeof(ERROR_RECOVERY_DATA));
1445  cddata->u1.Header.ModeDataLength = 0;
1446  }
1447 
1448  ExFreePool(buffer);
1449 
1450  ReportToMountMgr(deviceObject);
1451 
1452  //
1453  // Start the timer now regardless of if Autorun is enabled.
1454  // The timer must run forever since IoStopTimer faults.
1455  //
1456 
1457  IoInitializeTimer(deviceObject, CdRomTickHandler, NULL);
1458  IoStartTimer(deviceObject);
1459 
1460  return(STATUS_SUCCESS);
1461 
1462 CreateCdRomDeviceObjectExit:
1463 
1464  //
1465  // Release the device since an error occured.
1466  //
1467 
1468  ScsiClassClaimDevice(PortDeviceObject,
1469  LunInfo,
1470  TRUE,
1471  NULL);
1472 
1473  if (senseData != NULL) {
1474  ExFreePool(senseData);
1475  }
1476 
1477  if (deviceExtension->DiskGeometry != NULL) {
1478  ExFreePool(deviceExtension->DiskGeometry);
1479  }
1480 
1481  if (deviceObject != NULL) {
1482  if (srbListInitialized) {
1483  ExDeleteNPagedLookasideList(&deviceExtension->SrbLookasideListHead);
1484  }
1485  IoDeleteDevice(deviceObject);
1486  }
1487 
1488 
1489  return status;
1490 
1491 } // end CreateCdRomDeviceObject()
1492 
1493 VOID
1494 NTAPI
1497  IN PIRP Irp
1498  )
1499 {
1500 
1501  PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
1504  PIO_STACK_LOCATION irpStack;
1505  PIRP irp2 = NULL;
1506  ULONG transferPages;
1507  ULONG transferByteCount = currentIrpStack->Parameters.Read.Length;
1508  ULONG maximumTransferLength = deviceExtension->PortCapabilities->MaximumTransferLength;
1509  PCDROM_DATA cdData;
1510  PSCSI_REQUEST_BLOCK srb = NULL;
1511  PCDB cdb;
1512  PUCHAR senseBuffer = NULL;
1513  PVOID dataBuffer;
1514  NTSTATUS status;
1515  BOOLEAN use6Byte;
1516 
1517  //
1518  // Mark IRP with status pending.
1519  //
1520 
1522 
1523  //
1524  // If the flag is set in the device object, force a verify.
1525  //
1526 
1528  DebugPrint((2, "ScsiCdRomStartIo: [%lx] Volume needs verified\n", Irp));
1529  if (!(currentIrpStack->Flags & SL_OVERRIDE_VERIFY_VOLUME)) {
1530 
1531  if (Irp->Tail.Overlay.Thread) {
1533  }
1534 
1535  Irp->IoStatus.Status = STATUS_VERIFY_REQUIRED;
1536 
1537  DebugPrint((2, "ScsiCdRomStartIo: [%lx] Calling UpdateCapacity - "
1538  "ioctl event = %lx\n",
1539  Irp,
1540  nextIrpStack->Parameters.Others.Argument1
1541  ));
1542 
1543  //
1544  // our device control dispatch routine stores an event in the next
1545  // stack location to signal when startio has completed. We need to
1546  // pass this in so that the update capacity completion routine can
1547  // set it rather than completing the Irp.
1548  //
1549 
1550  status = CdRomUpdateCapacity(deviceExtension,
1551  Irp,
1552  nextIrpStack->Parameters.Others.Argument1
1553  );
1554 
1555  DebugPrint((2, "ScsiCdRomStartIo: [%lx] UpdateCapacity returned %lx\n", Irp, status));
1557  return;
1558  }
1559  }
1560 
1561  cdData = (PCDROM_DATA)(deviceExtension + 1);
1562  use6Byte = cdData->XAFlags & XA_USE_6_BYTE;
1563 
1564  if (currentIrpStack->MajorFunction == IRP_MJ_READ) {
1565 
1566  //
1567  // Add partition byte offset to make starting byte relative to
1568  // beginning of disk. In addition, add in skew for DM Driver, if any.
1569  //
1570 
1571  currentIrpStack->Parameters.Read.ByteOffset.QuadPart += (deviceExtension->StartingOffset.QuadPart);
1572 
1573  //
1574  // Calculate number of pages in this transfer.
1575  //
1576 
1577  transferPages = ADDRESS_AND_SIZE_TO_SPAN_PAGES(MmGetMdlVirtualAddress(Irp->MdlAddress),
1578  currentIrpStack->Parameters.Read.Length);
1579 
1580  //
1581  // Check if request length is greater than the maximum number of
1582  // bytes that the hardware can transfer.
1583  //
1584 
1585  if (cdData->RawAccess) {
1586 
1587  ASSERT(!(cdData->XAFlags & XA_USE_READ_CD));
1588 
1589  //
1590  // Fire off a mode select to switch back to cooked sectors.
1591  //
1592 
1593  irp2 = IoAllocateIrp((CCHAR)(deviceExtension->DeviceObject->StackSize+1),
1594  FALSE);
1595 
1596  if (!irp2) {
1597  Irp->IoStatus.Information = 0;
1598  Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
1601  return;
1602  }
1603 
1605  if (!srb) {
1606  Irp->IoStatus.Information = 0;
1607  Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
1609  IoFreeIrp(irp2);
1611  return;
1612  }
1613 
1614  RtlZeroMemory(srb, sizeof(SCSI_REQUEST_BLOCK));
1615 
1616  cdb = (PCDB)srb->Cdb;
1617 
1618  //
1619  // Allocate sense buffer.
1620  //
1621 
1623 
1624  if (!senseBuffer) {
1625  Irp->IoStatus.Information = 0;
1626  Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
1628  ExFreePool(srb);
1629  IoFreeIrp(irp2);
1631  return;
1632  }
1633 
1634  //
1635  // Set up the irp.
1636  //
1637 
1639  irp2->IoStatus.Status = STATUS_SUCCESS;
1640  irp2->IoStatus.Information = 0;
1641  irp2->Flags = 0;
1642  irp2->UserBuffer = NULL;
1643 
1644  //
1645  // Save the device object and irp in a private stack location.
1646  //
1647 
1648  irpStack = IoGetCurrentIrpStackLocation(irp2);
1649  irpStack->DeviceObject = deviceExtension->DeviceObject;
1650  irpStack->Parameters.Others.Argument2 = (PVOID) Irp;
1651 
1652  //
1653  // The retry count will be in the real Irp, as the retry logic will
1654  // recreate our private irp.
1655  //
1656 
1657  if (!(nextIrpStack->Parameters.Others.Argument1)) {
1658 
1659  //
1660  // Only jam this in if it doesn't exist. The completion routines can
1661  // call StartIo directly in the case of retries and resetting it will
1662  // cause infinite loops.
1663  //
1664 
1665  nextIrpStack->Parameters.Others.Argument1 = (PVOID) MAXIMUM_RETRIES;
1666  }
1667 
1668  //
1669  // Construct the IRP stack for the lower level driver.
1670  //
1671 
1672  irpStack = IoGetNextIrpStackLocation(irp2);
1674  irpStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_SCSI_EXECUTE_IN;
1675  irpStack->Parameters.Scsi.Srb = srb;
1676 
1678  srb->PathId = deviceExtension->PathId;
1679  srb->TargetId = deviceExtension->TargetId;
1680  srb->Lun = deviceExtension->Lun;
1682  srb->Cdb[1] |= deviceExtension->Lun << 5;
1683  srb->SrbStatus = srb->ScsiStatus = 0;
1684  srb->NextSrb = 0;
1685  srb->OriginalRequest = irp2;
1687  srb->SenseInfoBuffer = senseBuffer;
1688 
1689  transferByteCount = (use6Byte) ? sizeof(ERROR_RECOVERY_DATA) : sizeof(ERROR_RECOVERY_DATA10);
1690  dataBuffer = ExAllocatePool(NonPagedPoolCacheAligned, transferByteCount );
1691  if (!dataBuffer) {
1692  Irp->IoStatus.Information = 0;
1693  Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
1695  ExFreePool(senseBuffer);
1696  ExFreePool(srb);
1697  IoFreeIrp(irp2);
1699  return;
1700 
1701  }
1702 
1703  irp2->MdlAddress = IoAllocateMdl(dataBuffer,
1704  transferByteCount,
1705  FALSE,
1706  FALSE,
1707  (PIRP) NULL);
1708 
1709  if (!irp2->MdlAddress) {
1710  Irp->IoStatus.Information = 0;
1711  Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
1713  ExFreePool(senseBuffer);
1714  ExFreePool(srb);
1715  ExFreePool(dataBuffer);
1716  IoFreeIrp(irp2);
1718  return;
1719  }
1720 
1721  //
1722  // Prepare the MDL
1723  //
1724 
1725  MmBuildMdlForNonPagedPool(irp2->MdlAddress);
1726 
1727  srb->DataBuffer = dataBuffer;
1728 
1729  //
1730  // Set the new block size in the descriptor.
1731  //
1732 
1733  cdData->u1.BlockDescriptor.BlockLength[0] = (UCHAR)(COOKED_SECTOR_SIZE >> 16) & 0xFF;
1734  cdData->u1.BlockDescriptor.BlockLength[1] = (UCHAR)(COOKED_SECTOR_SIZE >> 8) & 0xFF;
1735  cdData->u1.BlockDescriptor.BlockLength[2] = (UCHAR)(COOKED_SECTOR_SIZE & 0xFF);
1736 
1737  //
1738  // Move error page into dataBuffer.
1739  //
1740 
1741  RtlCopyMemory(srb->DataBuffer, &cdData->u1.Header, transferByteCount);
1742 
1743  //
1744  // Build and send a mode select to switch into raw mode.
1745  //
1746 
1747  srb->SrbFlags = deviceExtension->SrbFlags;
1749  srb->DataTransferLength = transferByteCount;
1750  srb->TimeOutValue = deviceExtension->TimeOutValue * 2;
1751 
1752  if (use6Byte) {
1753  srb->CdbLength = 6;
1754  cdb->MODE_SELECT.OperationCode = SCSIOP_MODE_SELECT;
1755  cdb->MODE_SELECT.PFBit = 1;
1756  cdb->MODE_SELECT.ParameterListLength = (UCHAR)transferByteCount;
1757  } else {
1758 
1759  srb->CdbLength = 10;
1760  cdb->MODE_SELECT10.OperationCode = SCSIOP_MODE_SELECT10;
1761  cdb->MODE_SELECT10.PFBit = 1;
1762  cdb->MODE_SELECT10.ParameterListLength[0] = (UCHAR)(transferByteCount >> 8);
1763  cdb->MODE_SELECT10.ParameterListLength[1] = (UCHAR)(transferByteCount & 0xFF);
1764  }
1765 
1766  //
1767  // Update completion routine.
1768  //
1769 
1772  srb,
1773  TRUE,
1774  TRUE,
1775  TRUE);
1776 
1777  IoCallDriver(deviceExtension->PortDeviceObject, irp2);
1778  return;
1779  }
1780 
1781  if ((currentIrpStack->Parameters.Read.Length > maximumTransferLength) ||
1782  (transferPages >
1783  deviceExtension->PortCapabilities->MaximumPhysicalPages)) {
1784 
1785  //
1786  // Request needs to be split. Completion of each portion of the
1787  // request will fire off the next portion. The final request will
1788  // signal Io to send a new request.
1789  //
1790 
1791  transferPages =
1792  deviceExtension->PortCapabilities->MaximumPhysicalPages - 1;
1793 
1794  if(maximumTransferLength > transferPages << PAGE_SHIFT) {
1795  maximumTransferLength = transferPages << PAGE_SHIFT;
1796  }
1797 
1798  //
1799  // Check that the maximum transfer size is not zero
1800  //
1801 
1802  if(maximumTransferLength == 0) {
1803  maximumTransferLength = PAGE_SIZE;
1804  }
1805 
1806  ScsiClassSplitRequest(DeviceObject, Irp, maximumTransferLength);
1807  return;
1808 
1809  } else {
1810 
1811  //
1812  // Build SRB and CDB for this IRP.
1813  //
1814 
1816 
1817  }
1818 
1819 
1820  } else if (currentIrpStack->MajorFunction == IRP_MJ_DEVICE_CONTROL) {
1821 
1822  //
1823  // Allocate an irp, srb and associated structures.
1824  //
1825 
1826  irp2 = IoAllocateIrp((CCHAR)(deviceExtension->DeviceObject->StackSize+1),
1827  FALSE);
1828 
1829  if (!irp2) {
1830  Irp->IoStatus.Information = 0;
1831  Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
1834  DebugPrint((2, "ScsiCdRomStartIo: [%lx] bailing with status %lx at line %s\n", Irp, Irp->IoStatus.Status, __LINE__));
1835  return;
1836  }
1837 
1839  if (!srb) {
1840  Irp->IoStatus.Information = 0;
1841  Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
1843  IoFreeIrp(irp2);
1845  DebugPrint((2, "ScsiCdRomStartIo: [%lx] bailing with status %lx at line %s\n", Irp, Irp->IoStatus.Status, __LINE__));
1846  return;
1847  }
1848 
1849  RtlZeroMemory(srb, sizeof(SCSI_REQUEST_BLOCK));
1850 
1851  cdb = (PCDB)srb->Cdb;
1852 
1853  //
1854  // Allocate sense buffer.
1855  //
1856 
1858 
1859  if (!senseBuffer) {
1860  Irp->IoStatus.Information = 0;
1861  Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
1863  ExFreePool(srb);
1864  IoFreeIrp(irp2);
1866  DebugPrint((2, "ScsiCdRomStartIo: [%lx] bailing with status %lx at line %s\n", Irp, Irp->IoStatus.Status, __LINE__));
1867  return;
1868  }
1869 
1870  //
1871  // Set up the irp.
1872  //
1873 
1875  irp2->IoStatus.Status = STATUS_SUCCESS;
1876  irp2->IoStatus.Information = 0;
1877  irp2->Flags = 0;
1878  irp2->UserBuffer = NULL;
1879 
1880  //
1881  // Save the device object and irp in a private stack location.
1882  //
1883 
1884  irpStack = IoGetCurrentIrpStackLocation(irp2);
1885  irpStack->DeviceObject = deviceExtension->DeviceObject;
1886  irpStack->Parameters.Others.Argument2 = (PVOID) Irp;
1887 
1888  //
1889  // The retry count will be in the real Irp, as the retry logic will
1890  // recreate our private irp.
1891  //
1892 
1893  if (!(nextIrpStack->Parameters.Others.Argument1)) {
1894 
1895  //
1896  // Only jam this in if it doesn't exist. The completion routines can
1897  // call StartIo directly in the case of retries and resetting it will
1898  // cause infinite loops.
1899  //
1900 
1901  nextIrpStack->Parameters.Others.Argument1 = (PVOID) MAXIMUM_RETRIES;
1902  }
1903 
1904  //
1905  // Construct the IRP stack for the lower level driver.
1906  //
1907 
1908  irpStack = IoGetNextIrpStackLocation(irp2);
1910  irpStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_SCSI_EXECUTE_IN;
1911  irpStack->Parameters.Scsi.Srb = srb;
1912 
1915  srb,
1916  TRUE,
1917  TRUE,
1918  TRUE);
1919  //
1920  // Setup those fields that are generic to all requests.
1921  //
1922 
1924  srb->PathId = deviceExtension->PathId;
1925  srb->TargetId = deviceExtension->TargetId;
1926  srb->Lun = deviceExtension->Lun;
1928  srb->Cdb[1] |= deviceExtension->Lun << 5;
1929  srb->SrbStatus = srb->ScsiStatus = 0;
1930  srb->NextSrb = 0;
1931  srb->OriginalRequest = irp2;
1933  srb->SenseInfoBuffer = senseBuffer;
1934 
1935  switch (currentIrpStack->Parameters.DeviceIoControl.IoControlCode) {
1936 
1937  case IOCTL_CDROM_RAW_READ: {
1938 
1939  //
1940  // Determine whether the drive is currently in raw or cooked mode,
1941  // and which command to use to read the data.
1942  //
1943 
1944  if (!(cdData->XAFlags & XA_USE_READ_CD)) {
1945 
1946  PRAW_READ_INFO rawReadInfo =
1947  (PRAW_READ_INFO)currentIrpStack->Parameters.DeviceIoControl.Type3InputBuffer;
1948  ULONG maximumTransferLength;
1949  ULONG transferPages;
1950 
1951  if (cdData->RawAccess) {
1952 
1953  ULONG startingSector;
1954 
1955  //
1956  // Free the recently allocated irp, as we don't need it.
1957  //
1958 
1959  IoFreeIrp(irp2);
1960 
1961  cdb = (PCDB)srb->Cdb;
1962  RtlZeroMemory(cdb, 12);
1963 
1964  //
1965  // Calculate starting offset.
1966  //
1967 
1968  startingSector = (ULONG)(rawReadInfo->DiskOffset.QuadPart >> deviceExtension->SectorShift);
1969  transferByteCount = rawReadInfo->SectorCount * RAW_SECTOR_SIZE;
1970  maximumTransferLength = deviceExtension->PortCapabilities->MaximumTransferLength;
1971  transferPages = ADDRESS_AND_SIZE_TO_SPAN_PAGES(MmGetMdlVirtualAddress(Irp->MdlAddress),
1972  transferByteCount);
1973 
1974  //
1975  // Determine if request is within limits imposed by miniport.
1976  //
1977 
1978  if (transferByteCount > maximumTransferLength ||
1979  transferPages > deviceExtension->PortCapabilities->MaximumPhysicalPages) {
1980 
1981  //
1982  // The claim is that this won't happen, and is backed up by
1983  // ActiveMovie usage, which does unbuffered XA reads of 0x18000, yet
1984  // we get only 4 sector requests.
1985  //
1986 
1987 
1988  Irp->IoStatus.Information = 0;
1989  Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
1991  ExFreePool(senseBuffer);
1992  ExFreePool(srb);
1994  return;
1995 
1996  }
1997 
1998  srb->OriginalRequest = Irp;
1999  srb->SrbFlags = deviceExtension->SrbFlags;
2001  srb->DataTransferLength = transferByteCount;
2002  srb->TimeOutValue = deviceExtension->TimeOutValue;
2003  srb->CdbLength = 10;
2004  srb->DataBuffer = MmGetMdlVirtualAddress(Irp->MdlAddress);
2005 
2006  if (rawReadInfo->TrackMode == CDDA) {
2007  if (cdData->XAFlags & PLEXTOR_CDDA) {
2008 
2009  srb->CdbLength = 12;
2010 
2011  cdb->PLXTR_READ_CDDA.LogicalUnitNumber = deviceExtension->Lun;
2012  cdb->PLXTR_READ_CDDA.LogicalBlockByte3 = (UCHAR) (startingSector & 0xFF);
2013  cdb->PLXTR_READ_CDDA.LogicalBlockByte2 = (UCHAR) ((startingSector >> 8) & 0xFF);
2014  cdb->PLXTR_READ_CDDA.LogicalBlockByte1 = (UCHAR) ((startingSector >> 16) & 0xFF);
2015  cdb->PLXTR_READ_CDDA.LogicalBlockByte0 = (UCHAR) ((startingSector >> 24) & 0xFF);
2016 
2017  cdb->PLXTR_READ_CDDA.TransferBlockByte3 = (UCHAR) (rawReadInfo->SectorCount & 0xFF);
2018  cdb->PLXTR_READ_CDDA.TransferBlockByte2 = (UCHAR) (rawReadInfo->SectorCount >> 8);
2019  cdb->PLXTR_READ_CDDA.TransferBlockByte1 = 0;
2020  cdb->PLXTR_READ_CDDA.TransferBlockByte0 = 0;
2021 
2022  cdb->PLXTR_READ_CDDA.SubCode = 0;
2023  cdb->PLXTR_READ_CDDA.OperationCode = 0xD8;
2024 
2025  } else if (cdData->XAFlags & NEC_CDDA) {
2026 
2027  cdb->NEC_READ_CDDA.LogicalBlockByte3 = (UCHAR) (startingSector & 0xFF);
2028  cdb->NEC_READ_CDDA.LogicalBlockByte2 = (UCHAR) ((startingSector >> 8) & 0xFF);
2029  cdb->NEC_READ_CDDA.LogicalBlockByte1 = (UCHAR) ((startingSector >> 16) & 0xFF);
2030  cdb->NEC_READ_CDDA.LogicalBlockByte0 = (UCHAR) ((startingSector >> 24) & 0xFF);
2031 
2032  cdb->NEC_READ_CDDA.TransferBlockByte1 = (UCHAR) (rawReadInfo->SectorCount & 0xFF);
2033  cdb->NEC_READ_CDDA.TransferBlockByte0 = (UCHAR) (rawReadInfo->SectorCount >> 8);
2034 
2035  cdb->NEC_READ_CDDA.OperationCode = 0xD4;
2036  }
2037  } else {
2038 
2039  cdb->CDB10.LogicalUnitNumber = deviceExtension->Lun;
2040 
2041  cdb->CDB10.TransferBlocksMsb = (UCHAR) (rawReadInfo->SectorCount >> 8);
2042  cdb->CDB10.TransferBlocksLsb = (UCHAR) (rawReadInfo->SectorCount & 0xFF);
2043 
2044  cdb->CDB10.LogicalBlockByte3 = (UCHAR) (startingSector & 0xFF);
2045  cdb->CDB10.LogicalBlockByte2 = (UCHAR) ((startingSector >> 8) & 0xFF);
2046  cdb->CDB10.LogicalBlockByte1 = (UCHAR) ((startingSector >> 16) & 0xFF);
2047  cdb->CDB10.LogicalBlockByte0 = (UCHAR) ((startingSector >> 24) & 0xFF);
2048 
2049  cdb->CDB10.OperationCode = SCSIOP_READ;
2050  }
2051 
2052  srb->SrbStatus = srb->ScsiStatus = 0;
2053 
2054  nextIrpStack->MajorFunction = IRP_MJ_SCSI;
2055  nextIrpStack->Parameters.Scsi.Srb = srb;
2056 
2057  if (!(nextIrpStack->Parameters.Others.Argument1)) {
2058 
2059  //
2060  // Only jam this in if it doesn't exist. The completion routines can
2061  // call StartIo directly in the case of retries and resetting it will
2062  // cause infinite loops.
2063  //
2064 
2065  nextIrpStack->Parameters.Others.Argument1 = (PVOID) MAXIMUM_RETRIES;
2066  }
2067 
2068  //
2069  // Set up IoCompletion routine address.
2070  //
2071 
2074  srb,
2075  TRUE,
2076  TRUE,
2077  TRUE);
2078 
2079  IoCallDriver(deviceExtension->PortDeviceObject, Irp);
2080  return;
2081 
2082  } else {
2083 
2084  transferByteCount = (use6Byte) ? sizeof(ERROR_RECOVERY_DATA) : sizeof(ERROR_RECOVERY_DATA10);
2085  dataBuffer = ExAllocatePool(NonPagedPoolCacheAligned, transferByteCount );
2086  if (!dataBuffer) {
2087  Irp->IoStatus.Information = 0;
2088  Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
2090  ExFreePool(senseBuffer);
2091  ExFreePool(srb);
2092  IoFreeIrp(irp2);
2094  return;
2095 
2096  }
2097 
2098  irp2->MdlAddress = IoAllocateMdl(dataBuffer,
2099  transferByteCount,
2100  FALSE,
2101  FALSE,
2102  (PIRP) NULL);
2103 
2104  if (!irp2->MdlAddress) {
2105  Irp->IoStatus.Information = 0;
2106  Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
2108  ExFreePool(senseBuffer);
2109  ExFreePool(srb);
2110  ExFreePool(dataBuffer);
2111  IoFreeIrp(irp2);
2113  return;
2114  }
2115 
2116  //
2117  // Prepare the MDL
2118  //
2119 
2120  MmBuildMdlForNonPagedPool(irp2->MdlAddress);
2121 
2122  srb->DataBuffer = dataBuffer;
2123 
2124  //
2125  // Set the new block size in the descriptor.
2126  //
2127 
2128  cdData->u1.BlockDescriptor.BlockLength[0] = (UCHAR)(RAW_SECTOR_SIZE >> 16) & 0xFF;
2129  cdData->u1.BlockDescriptor.BlockLength[1] = (UCHAR)(RAW_SECTOR_SIZE >> 8) & 0xFF;
2130  cdData->u1.BlockDescriptor.BlockLength[2] = (UCHAR)(RAW_SECTOR_SIZE & 0xFF);
2131 
2132 
2133  //
2134  // TODO: Set density code, based on operation
2135  //
2136 
2137  cdData->u1.BlockDescriptor.DensityCode = 0;
2138 
2139 
2140  //
2141  // Move error page into dataBuffer.
2142  //
2143 
2144  RtlCopyMemory(srb->DataBuffer, &cdData->u1.Header, transferByteCount);
2145 
2146 
2147  //
2148  // Build and send a mode select to switch into raw mode.
2149  //
2150 
2151  srb->SrbFlags = deviceExtension->SrbFlags;
2153  srb->DataTransferLength = transferByteCount;
2154  srb->TimeOutValue = deviceExtension->TimeOutValue * 2;
2155 
2156  if (use6Byte) {
2157  srb->CdbLength = 6;
2158  cdb->MODE_SELECT.OperationCode = SCSIOP_MODE_SELECT;
2159  cdb->MODE_SELECT.PFBit = 1;
2160  cdb->MODE_SELECT.ParameterListLength = (UCHAR)transferByteCount;
2161  } else {
2162 
2163  srb->CdbLength = 10;
2164  cdb->MODE_SELECT10.OperationCode = SCSIOP_MODE_SELECT10;
2165  cdb->MODE_SELECT10.PFBit = 1;
2166  cdb->MODE_SELECT10.ParameterListLength[0] = (UCHAR)(transferByteCount >> 8);
2167  cdb->MODE_SELECT10.ParameterListLength[1] = (UCHAR)(transferByteCount & 0xFF);
2168  }
2169 
2170  //
2171  // Update completion routine.
2172  //
2173 
2176  srb,
2177  TRUE,
2178  TRUE,
2179  TRUE);
2180 
2181  }
2182 
2183  } else {
2184 
2185  PRAW_READ_INFO rawReadInfo =
2186  (PRAW_READ_INFO)currentIrpStack->Parameters.DeviceIoControl.Type3InputBuffer;
2187  ULONG startingSector;
2188 
2189  //
2190  // Free the recently allocated irp, as we don't need it.
2191  //
2192 
2193  IoFreeIrp(irp2);
2194 
2195  cdb = (PCDB)srb->Cdb;
2196  RtlZeroMemory(cdb, 12);
2197 
2198 
2199  //
2200  // Calculate starting offset.
2201  //
2202 
2203  startingSector = (ULONG)(rawReadInfo->DiskOffset.QuadPart >> deviceExtension->SectorShift);
2204  transferByteCount = rawReadInfo->SectorCount * RAW_SECTOR_SIZE;
2205 
2206 
2207  srb->OriginalRequest = Irp;
2208  srb->SrbFlags = deviceExtension->SrbFlags;
2210  srb->DataTransferLength = transferByteCount;
2211  srb->TimeOutValue = deviceExtension->TimeOutValue;
2212  srb->DataBuffer = MmGetMdlVirtualAddress(Irp->MdlAddress);
2213  srb->CdbLength = 12;
2214  srb->SrbStatus = srb->ScsiStatus = 0;
2215 
2216  //
2217  // Fill in CDB fields.
2218  //
2219 
2220  cdb = (PCDB)srb->Cdb;
2221 
2222 
2223  cdb->READ_CD.TransferBlocks[2] = (UCHAR) (rawReadInfo->SectorCount & 0xFF);
2224  cdb->READ_CD.TransferBlocks[1] = (UCHAR) (rawReadInfo->SectorCount >> 8 );
2225  cdb->READ_CD.TransferBlocks[0] = (UCHAR) (rawReadInfo->SectorCount >> 16);
2226 
2227 
2228  cdb->READ_CD.StartingLBA[3] = (UCHAR) (startingSector & 0xFF);
2229  cdb->READ_CD.StartingLBA[2] = (UCHAR) ((startingSector >> 8));
2230  cdb->READ_CD.StartingLBA[1] = (UCHAR) ((startingSector >> 16));
2231  cdb->READ_CD.StartingLBA[0] = (UCHAR) ((startingSector >> 24));
2232 
2233  //
2234  // Setup cdb depending upon the sector type we want.
2235  //
2236 
2237  switch (rawReadInfo->TrackMode) {
2238  case CDDA:
2239 
2240  cdb->READ_CD.ExpectedSectorType = CD_DA_SECTOR;
2241  cdb->READ_CD.IncludeUserData = 1;
2242  cdb->READ_CD.HeaderCode = 3;
2243  cdb->READ_CD.IncludeSyncData = 1;
2244  break;
2245 
2246  case YellowMode2:
2247 
2248  cdb->READ_CD.ExpectedSectorType = YELLOW_MODE2_SECTOR;
2249  cdb->READ_CD.IncludeUserData = 1;
2250  cdb->READ_CD.HeaderCode = 1;
2251  cdb->READ_CD.IncludeSyncData = 1;
2252  break;
2253 
2254  case XAForm2:
2255 
2256  cdb->READ_CD.ExpectedSectorType = FORM2_MODE2_SECTOR;
2257  cdb->READ_CD.IncludeUserData = 1;
2258  cdb->READ_CD.HeaderCode = 3;
2259  cdb->READ_CD.IncludeSyncData = 1;
2260  break;
2261 
2262  default:
2263  Irp->IoStatus.Information = 0;
2264  Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
2266  ExFreePool(senseBuffer);
2267  ExFreePool(srb);
2269  DebugPrint((2, "ScsiCdRomStartIo: [%lx] bailing with status %lx at line %s\n", Irp, Irp->IoStatus.Status, __LINE__));
2270  return;
2271  }
2272 
2273  cdb->READ_CD.OperationCode = SCSIOP_READ_CD;
2274 
2275  nextIrpStack->MajorFunction = IRP_MJ_SCSI;
2276  nextIrpStack->Parameters.Scsi.Srb = srb;
2277 
2278  if (!(nextIrpStack->Parameters.Others.Argument1)) {
2279 
2280  //
2281  // Only jam this in if it doesn't exist. The completion routines can
2282  // call StartIo directly in the case of retries and resetting it will
2283  // cause infinite loops.
2284  //
2285 
2286  nextIrpStack->Parameters.Others.Argument1 = (PVOID) MAXIMUM_RETRIES;
2287  }
2288 
2289  //
2290  // Set up IoCompletion routine address.
2291  //
2292 
2295  srb,
2296  TRUE,
2297  TRUE,
2298  TRUE);
2299 
2300  IoCallDriver(deviceExtension->PortDeviceObject, Irp);
2301  return;
2302 
2303  }
2304 
2305  IoCallDriver(deviceExtension->PortDeviceObject, irp2);
2306  return;
2307  }
2308 
2314 
2315  //
2316  // Issue ReadCapacity to update device extension
2317  // with information for current media.
2318  //
2319 
2320  DebugPrint((3,
2321  "CdRomStartIo: Get drive capacity\n"));
2322 
2323  //
2324  // setup remaining srb and cdb parameters.
2325  //
2326 
2327  srb->SrbFlags = deviceExtension->SrbFlags;
2329  srb->DataTransferLength = sizeof(READ_CAPACITY_DATA);
2330  srb->CdbLength = 10;
2331  srb->TimeOutValue = deviceExtension->TimeOutValue;
2332 
2334  if (!dataBuffer) {
2335  Irp->IoStatus.Information = 0;
2336  Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
2338  ExFreePool(senseBuffer);
2339  ExFreePool(srb);
2340  IoFreeIrp(irp2);
2342  DebugPrint((2, "ScsiCdRomStartIo: [%lx] bailing with status %lx at line %s\n", Irp, Irp->IoStatus.Status, __LINE__));
2343  return;
2344 
2345  }
2346 
2347  irp2->MdlAddress = IoAllocateMdl(dataBuffer,
2348  sizeof(READ_CAPACITY_DATA),
2349  FALSE,
2350  FALSE,
2351  (PIRP) NULL);
2352 
2353  if (!irp2->MdlAddress) {
2354  Irp->IoStatus.Information = 0;
2355  Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
2357  ExFreePool(senseBuffer);
2358  ExFreePool(srb);
2359  ExFreePool(dataBuffer);
2360  IoFreeIrp(irp2);
2362  DebugPrint((2, "ScsiCdRomStartIo: [%lx] bailing with status %lx at line %s\n", Irp, Irp->IoStatus.Status, __LINE__));
2363  return;
2364  }
2365 
2366  //
2367  // Prepare the MDL
2368  //
2369 
2370  MmBuildMdlForNonPagedPool(irp2->MdlAddress);
2371 
2372  srb->DataBuffer = dataBuffer;
2373  cdb->CDB10.OperationCode = SCSIOP_READ_CAPACITY;
2374 
2375  IoCallDriver(deviceExtension->PortDeviceObject, irp2);
2376  return;
2377  }
2378 
2379  case IOCTL_CDROM_CHECK_VERIFY: {
2380 
2381  //
2382  // Since a test unit ready is about to be performed, reset the timer
2383  // value to decrease the opportunities for it to race with this code.
2384  //
2385 
2387 
2388  //
2389  // Set up the SRB/CDB
2390  //
2391 
2392  srb->CdbLength = 6;
2393  cdb->CDB6GENERIC.OperationCode = SCSIOP_TEST_UNIT_READY;
2394  srb->TimeOutValue = deviceExtension->TimeOutValue * 2;
2395  srb->SrbFlags = deviceExtension->SrbFlags;
2397 
2398  DebugPrint((2, "ScsiCdRomStartIo: [%lx] Sending CHECK_VERIFY irp %lx\n", Irp, irp2));
2399  IoCallDriver(deviceExtension->PortDeviceObject, irp2);
2400  return;
2401  }
2402 
2404 
2405  //
2406  // Set format to return first and last session numbers.
2407  //
2408 
2409  cdb->READ_TOC.Format = GET_LAST_SESSION;
2410 
2411  //
2412  // Fall through to READ TOC code.
2413  //
2414 
2415  case IOCTL_CDROM_READ_TOC: {
2416 
2417 
2418  if (currentIrpStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_CDROM_READ_TOC) {
2419 
2420  //
2421  // Use MSF addressing if not request for session information.
2422  //
2423 
2424  cdb->READ_TOC.Msf = CDB_USE_MSF;
2425  }
2426 
2427  //
2428  // Set size of TOC structure.
2429  //
2430 
2431  transferByteCount =
2432  currentIrpStack->Parameters.Read.Length >
2433  sizeof(CDROM_TOC) ? sizeof(CDROM_TOC):
2434  currentIrpStack->Parameters.Read.Length;
2435 
2436  cdb->READ_TOC.AllocationLength[0] = (UCHAR) (transferByteCount >> 8);
2437  cdb->READ_TOC.AllocationLength[1] = (UCHAR) (transferByteCount & 0xFF);
2438 
2439  cdb->READ_TOC.Control = 0;
2440 
2441  //
2442  // Start at beginning of disc.
2443  //
2444 
2445  cdb->READ_TOC.StartingTrack = 0;
2446 
2447  //
2448  // setup remaining srb and cdb parameters.
2449  //
2450 
2451  srb->SrbFlags = deviceExtension->SrbFlags;
2453  srb->DataTransferLength = transferByteCount;
2454  srb->CdbLength = 10;
2455  srb->TimeOutValue = deviceExtension->TimeOutValue;
2456 
2457  dataBuffer = ExAllocatePool(NonPagedPoolCacheAligned, transferByteCount);
2458  if (!dataBuffer) {
2459  Irp->IoStatus.Information = 0;
2460  Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
2462  ExFreePool(senseBuffer);
2463  ExFreePool(srb);
2464  IoFreeIrp(irp2);
2466  return;
2467 
2468  }
2469 
2470  irp2->MdlAddress = IoAllocateMdl(dataBuffer,
2471  transferByteCount,
2472  FALSE,
2473  FALSE,
2474  (PIRP) NULL);
2475 
2476  if (!irp2->MdlAddress) {
2477  Irp->IoStatus.Information = 0;
2478  Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
2480  ExFreePool(senseBuffer);
2481  ExFreePool(srb);
2482  ExFreePool(dataBuffer);
2483  IoFreeIrp(irp2);
2485  return;
2486  }
2487 
2488  //
2489  // Prepare the MDL
2490  //
2491 
2492  MmBuildMdlForNonPagedPool(irp2->MdlAddress);
2493 
2494  srb->DataBuffer = dataBuffer;
2495  cdb->READ_TOC.OperationCode = SCSIOP_READ_TOC;
2496 
2497  IoCallDriver(deviceExtension->PortDeviceObject, irp2);
2498  return;
2499 
2500  }
2501 
2503 
2504  PCDROM_PLAY_AUDIO_MSF inputBuffer = Irp->AssociatedIrp.SystemBuffer;
2505 
2506  //
2507  // Set up the SRB/CDB
2508  //
2509 
2510  srb->CdbLength = 10;
2511  cdb->PLAY_AUDIO_MSF.OperationCode = SCSIOP_PLAY_AUDIO_MSF;
2512 
2513  cdb->PLAY_AUDIO_MSF.StartingM = inputBuffer->StartingM;
2514  cdb->PLAY_AUDIO_MSF.StartingS = inputBuffer->StartingS;
2515  cdb->PLAY_AUDIO_MSF.StartingF = inputBuffer->StartingF;
2516 
2517  cdb->PLAY_AUDIO_MSF.EndingM = inputBuffer->EndingM;
2518  cdb->PLAY_AUDIO_MSF.EndingS = inputBuffer->EndingS;
2519  cdb->PLAY_AUDIO_MSF.EndingF = inputBuffer->EndingF;
2520 
2521  srb->TimeOutValue = deviceExtension->TimeOutValue;
2522  srb->SrbFlags = deviceExtension->SrbFlags;
2524 
2525  IoCallDriver(deviceExtension->PortDeviceObject, irp2);
2526  return;
2527 
2528  }
2529 
2531 
2532  PCDROM_SUB_Q_DATA_FORMAT inputBuffer =
2533  Irp->AssociatedIrp.SystemBuffer;
2534 
2535  //
2536  // Allocate buffer for subq channel information.
2537  //
2538 
2540  sizeof(SUB_Q_CHANNEL_DATA));
2541 
2542  if (!dataBuffer) {
2543  Irp->IoStatus.Information = 0;
2544  Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
2546  ExFreePool(senseBuffer);
2547  ExFreePool(srb);
2548  IoFreeIrp(irp2);
2550  return;
2551 
2552  }
2553 
2554  irp2->MdlAddress = IoAllocateMdl(dataBuffer,
2555  transferByteCount,
2556  FALSE,
2557  FALSE,
2558  (PIRP) NULL);
2559 
2560  if (!irp2->MdlAddress) {
2561  Irp->IoStatus.Information = 0;
2562  Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
2564  ExFreePool(senseBuffer);
2565  ExFreePool(srb);
2566  ExFreePool(dataBuffer);
2567  IoFreeIrp(irp2);
2569  return;
2570  }
2571 
2572  //
2573  // Prepare the MDL
2574  //
2575 
2576  MmBuildMdlForNonPagedPool(irp2->MdlAddress);
2577 
2578  srb->DataBuffer = dataBuffer;
2579 
2580  //
2581  // Always logical unit 0, but only use MSF addressing
2582  // for IOCTL_CDROM_CURRENT_POSITION
2583  //
2584 
2585  if (inputBuffer->Format==IOCTL_CDROM_CURRENT_POSITION)
2586  cdb->SUBCHANNEL.Msf = CDB_USE_MSF;
2587 
2588  //
2589  // Return subchannel data
2590  //
2591 
2592  cdb->SUBCHANNEL.SubQ = CDB_SUBCHANNEL_BLOCK;
2593 
2594  //
2595  // Specify format of information to return
2596  //
2597 
2598  cdb->SUBCHANNEL.Format = inputBuffer->Format;
2599 
2600  //
2601  // Specify which track to access (only used by Track ISRC reads)
2602  //
2603 
2604  if (inputBuffer->Format==IOCTL_CDROM_TRACK_ISRC) {
2605  cdb->SUBCHANNEL.TrackNumber = inputBuffer->Track;
2606  }
2607 
2608  //
2609  // Set size of channel data -- however, this is dependent on
2610  // what information we are requesting (which Format)
2611  //
2612 
2613  switch( inputBuffer->Format ) {
2614 
2616  transferByteCount = sizeof(SUB_Q_CURRENT_POSITION);
2617  break;
2618 
2620  transferByteCount = sizeof(SUB_Q_MEDIA_CATALOG_NUMBER);
2621  break;
2622 
2624  transferByteCount = sizeof(SUB_Q_TRACK_ISRC);
2625  break;
2626  }
2627 
2628  cdb->SUBCHANNEL.AllocationLength[0] = (UCHAR) (transferByteCount >> 8);
2629  cdb->SUBCHANNEL.AllocationLength[1] = (UCHAR) (transferByteCount & 0xFF);
2630  cdb->SUBCHANNEL.OperationCode = SCSIOP_READ_SUB_CHANNEL;
2631  srb->SrbFlags = deviceExtension->SrbFlags;
2633  srb->DataTransferLength = transferByteCount;
2634  srb->CdbLength = 10;
2635  srb->TimeOutValue = deviceExtension->TimeOutValue;
2636 
2637  IoCallDriver(deviceExtension->PortDeviceObject, irp2);
2638  return;
2639 
2640  }
2641 
2642  case IOCTL_CDROM_PAUSE_AUDIO: {
2643 
2644  cdb->PAUSE_RESUME.OperationCode = SCSIOP_PAUSE_RESUME;
2645  cdb->PAUSE_RESUME.Action = CDB_AUDIO_PAUSE;
2646 
2647  srb->CdbLength = 10;
2648  srb->TimeOutValue = deviceExtension->TimeOutValue;
2649  srb->SrbFlags = deviceExtension->SrbFlags;
2651 
2652  IoCallDriver(deviceExtension->PortDeviceObject, irp2);
2653  return;
2654  }
2655 
2656  case IOCTL_CDROM_RESUME_AUDIO: {
2657 
2658  cdb->PAUSE_RESUME.OperationCode = SCSIOP_PAUSE_RESUME;
2659  cdb->PAUSE_RESUME.Action = CDB_AUDIO_RESUME;
2660 
2661  srb->CdbLength = 10;
2662  srb->TimeOutValue = deviceExtension->TimeOutValue;
2663  srb->SrbFlags = deviceExtension->SrbFlags;
2665 
2666  IoCallDriver(deviceExtension->PortDeviceObject, irp2);
2667  return;
2668  }
2669 
2671 
2672  PCDROM_SEEK_AUDIO_MSF inputBuffer = Irp->AssociatedIrp.SystemBuffer;
2673  ULONG logicalBlockAddress;
2674 
2675  logicalBlockAddress = MSF_TO_LBA(inputBuffer->M, inputBuffer->S, inputBuffer->F);
2676 
2677  cdb->SEEK.OperationCode = SCSIOP_SEEK;
2678  cdb->SEEK.LogicalBlockAddress[0] = ((PFOUR_BYTE)&logicalBlockAddress)->Byte3;
2679  cdb->SEEK.LogicalBlockAddress[1] = ((PFOUR_BYTE)&logicalBlockAddress)->Byte2;
2680  cdb->SEEK.LogicalBlockAddress[2] = ((PFOUR_BYTE)&logicalBlockAddress)->Byte1;
2681  cdb->SEEK.LogicalBlockAddress[3] = ((PFOUR_BYTE)&logicalBlockAddress)->Byte0;
2682 
2683  srb->CdbLength = 10;
2684  srb->TimeOutValue = deviceExtension->TimeOutValue;
2685  srb->SrbFlags = deviceExtension->SrbFlags;
2687 
2688  IoCallDriver(deviceExtension->PortDeviceObject, irp2);
2689  return;
2690 
2691  }
2692 
2693  case IOCTL_CDROM_STOP_AUDIO: {
2694 
2695  cdb->START_STOP.OperationCode = SCSIOP_START_STOP_UNIT;
2696  cdb->START_STOP.Immediate = 1;
2697  cdb->START_STOP.Start = 0;
2698  cdb->START_STOP.LoadEject = 0;
2699 
2700  srb->CdbLength = 6;
2701  srb->TimeOutValue = deviceExtension->TimeOutValue;
2702 
2703  srb->SrbFlags = deviceExtension->SrbFlags;
2705 
2706  IoCallDriver(deviceExtension->PortDeviceObject, irp2);
2707  return;
2708  }
2709 
2710  case IOCTL_CDROM_GET_CONTROL: {
2711  //
2712  // Allocate buffer for volume control information.
2713  //
2714 
2716  MODE_DATA_SIZE);
2717 
2718  if (!dataBuffer) {
2719  Irp->IoStatus.Information = 0;
2720  Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
2722  ExFreePool(senseBuffer);
2723  ExFreePool(srb);
2724  IoFreeIrp(irp2);
2726  return;
2727 
2728  }
2729 
2730  irp2->MdlAddress = IoAllocateMdl(dataBuffer,
2732  FALSE,
2733  FALSE,
2734  (PIRP) NULL);
2735 
2736  if (!irp2->MdlAddress) {
2737  Irp->IoStatus.Information = 0;
2738  Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
2740  ExFreePool(senseBuffer);
2741  ExFreePool(srb);
2742  ExFreePool(dataBuffer);
2743  IoFreeIrp(irp2);
2745  return;
2746  }
2747 
2748  //
2749  // Prepare the MDL
2750  //
2751 
2752  MmBuildMdlForNonPagedPool(irp2->MdlAddress);
2753  srb->DataBuffer = dataBuffer;
2754 
2755  RtlZeroMemory(dataBuffer, MODE_DATA_SIZE);
2756 
2757  //
2758  // Setup for either 6 or 10 byte CDBs.
2759  //
2760 
2761  if (use6Byte) {
2762 
2763  cdb->MODE_SENSE.OperationCode = SCSIOP_MODE_SENSE;
2764  cdb->MODE_SENSE.PageCode = CDROM_AUDIO_CONTROL_PAGE;
2765  cdb->MODE_SENSE.AllocationLength = MODE_DATA_SIZE;
2766 
2767  //
2768  // Disable block descriptors.
2769  //
2770 
2771  cdb->MODE_SENSE.Dbd = TRUE;
2772 
2773  srb->CdbLength = 6;
2774  } else {
2775 
2776  cdb->MODE_SENSE10.OperationCode = SCSIOP_MODE_SENSE10;
2777  cdb->MODE_SENSE10.PageCode = CDROM_AUDIO_CONTROL_PAGE;
2778  cdb->MODE_SENSE10.AllocationLength[0] = (UCHAR)(MODE_DATA_SIZE >> 8);
2779  cdb->MODE_SENSE10.AllocationLength[1] = (UCHAR)(MODE_DATA_SIZE & 0xFF);
2780 
2781  //
2782  // Disable block descriptors.
2783  //
2784 
2785  cdb->MODE_SENSE10.Dbd = TRUE;
2786 
2787  srb->CdbLength = 10;
2788  }
2789 
2790  srb->TimeOutValue = deviceExtension->TimeOutValue;
2792  srb->SrbFlags = deviceExtension->SrbFlags;
2794 
2795  IoCallDriver(deviceExtension->PortDeviceObject, irp2);
2796  return;
2797 
2798  }
2799 
2801  case IOCTL_CDROM_SET_VOLUME: {
2802 
2804  MODE_DATA_SIZE);
2805 
2806  if (!dataBuffer) {
2807  Irp->IoStatus.Information = 0;
2808  Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
2810  ExFreePool(senseBuffer);
2811  ExFreePool(srb);
2812  IoFreeIrp(irp2);
2814  return;
2815  }
2816 
2817  irp2->MdlAddress = IoAllocateMdl(dataBuffer,
2819  FALSE,
2820  FALSE,
2821  (PIRP) NULL);
2822 
2823  if (!irp2->MdlAddress) {
2824  Irp->IoStatus.Information = 0;
2825  Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
2827  ExFreePool(senseBuffer);
2828  ExFreePool(srb);
2829  ExFreePool(dataBuffer);
2830  IoFreeIrp(irp2);
2832  return;
2833  }
2834 
2835  //
2836  // Prepare the MDL
2837  //
2838 
2839  MmBuildMdlForNonPagedPool(irp2->MdlAddress);
2840  srb->DataBuffer = dataBuffer;
2841 
2842  RtlZeroMemory(dataBuffer, MODE_DATA_SIZE);
2843 
2844 
2845  if (use6Byte) {
2846  cdb->MODE_SENSE.OperationCode = SCSIOP_MODE_SENSE;
2847  cdb->MODE_SENSE.PageCode = CDROM_AUDIO_CONTROL_PAGE;
2848  cdb->MODE_SENSE.AllocationLength = MODE_DATA_SIZE;
2849 
2850  srb->CdbLength = 6;
2851 
2852  } else {
2853 
2854  cdb->MODE_SENSE10.OperationCode = SCSIOP_MODE_SENSE10;
2855  cdb->MODE_SENSE10.PageCode = CDROM_AUDIO_CONTROL_PAGE;
2856  cdb->MODE_SENSE10.AllocationLength[0] = (UCHAR)(MODE_DATA_SIZE >> 8);
2857  cdb->MODE_SENSE10.AllocationLength[1] = (UCHAR)(MODE_DATA_SIZE & 0xFF);
2858 
2859  srb->CdbLength = 10;
2860  }
2861 
2862  srb->TimeOutValue = deviceExtension->TimeOutValue;
2864  srb->SrbFlags = deviceExtension->SrbFlags;
2866 
2867  if (currentIrpStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_CDROM_SET_VOLUME) {
2868 
2869  //
2870  // Setup a different completion routine as the mode sense data is needed in order
2871  // to send the mode select.
2872  //
2873 
2876  srb,
2877  TRUE,
2878  TRUE,
2879  TRUE);
2880 
2881  }
2882 
2883  IoCallDriver(deviceExtension->PortDeviceObject, irp2);
2884  return;
2885 
2886  }
2887 
2888  default:
2889 
2890  //
2891  // Just complete the request - CdRomClassIoctlCompletion will take
2892  // care of it for us
2893  //
2894 
2896  ExFreePool(senseBuffer);
2897  ExFreePool(srb);
2898  IoFreeIrp(irp2);
2899  return;
2900 
2901  } // end switch()
2902  }
2903 
2904  //
2905  // If a read or an unhandled IRP_MJ_XX, end up here. The unhandled IRP_MJ's
2906  // are expected and composed of AutoRun Irps, at present.
2907  //
2908 
2909  IoCallDriver(deviceExtension->PortDeviceObject, Irp);
2910  return;
2911 }
2912 
2913 
2914 NTSTATUS
2915 NTAPI
2918  IN PIRP Irp
2919  )
2920 
2921 /*++
2922 
2923 Routine Description:
2924 
2925  This is the entry called by the I/O system for read requests.
2926  It builds the SRB and sends it to the port driver.
2927 
2928 Arguments:
2929 
2930  DeviceObject - the system object for the device.
2931  Irp - IRP involved.
2932 
2933 Return Value:
2934 
2935  NT Status
2936 
2937 --*/
2938 
2939 {
2940  PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
2942  ULONG transferByteCount = currentIrpStack->Parameters.Read.Length;
2943  LARGE_INTEGER startingOffset = currentIrpStack->Parameters.Read.ByteOffset;
2944 
2945  //
2946  // If the cd is playing music then reject this request.
2947  //
2948 
2949  if (PLAY_ACTIVE(deviceExtension)) {
2950  Irp->IoStatus.Status = STATUS_DEVICE_BUSY;
2951  return STATUS_DEVICE_BUSY;
2952  }
2953 
2954  //
2955  // Verify parameters of this request.
2956  // Check that ending sector is on disc and
2957  // that number of bytes to transfer is a multiple of
2958  // the sector size.
2959  //
2960 
2961  startingOffset.QuadPart = currentIrpStack->Parameters.Read.ByteOffset.QuadPart +
2962  transferByteCount;
2963 
2964  if (!deviceExtension->DiskGeometry->Geometry.BytesPerSector) {
2965  deviceExtension->DiskGeometry->Geometry.BytesPerSector = 2048;
2966  }
2967 
2968  if ((startingOffset.QuadPart > deviceExtension->PartitionLength.QuadPart) ||
2969  (transferByteCount & (deviceExtension->DiskGeometry->Geometry.BytesPerSector - 1))) {
2970 
2971  DebugPrint((1,"ScsiCdRomRead: Invalid I/O parameters\n"));
2972  DebugPrint((1, "\toffset %x:%x, Length %x:%x\n",
2973  startingOffset.u.HighPart,
2974  startingOffset.u.LowPart,
2975  deviceExtension->PartitionLength.u.HighPart,
2976  deviceExtension->PartitionLength.u.LowPart));
2977  DebugPrint((1, "\tbps %x\n", deviceExtension->DiskGeometry->Geometry.BytesPerSector));
2978 
2979  //
2980  // Fail request with status of invalid parameters.
2981  //
2982 
2983  Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
2984 
2985  return STATUS_INVALID_PARAMETER;
2986  }
2987 
2988 
2989  return STATUS_SUCCESS;
2990 
2991 } // end ScsiCdRomReadVerification()
2992 
2993 
2994 NTSTATUS
2995 NTAPI
2998  IN PIRP Irp,
2999  IN PVOID Context
3000  )
3001 {
3002  PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
3003  PDEVICE_EXTENSION physicalExtension = deviceExtension->PhysicalDevice->DeviceExtension;
3005  PCDROM_DATA cdData = (PCDROM_DATA)(deviceExtension + 1);
3006  BOOLEAN use6Byte = cdData->XAFlags & XA_USE_6_BYTE;
3007  PIO_STACK_LOCATION realIrpStack;
3008  PIO_STACK_LOCATION realIrpNextStack;
3010  PIRP realIrp = NULL;
3011  NTSTATUS status;
3012  BOOLEAN retry;
3013 
3014  //
3015  // Extract the 'real' irp from the irpstack.
3016  //
3017 
3018  realIrp = (PIRP) irpStack->Parameters.Others.Argument2;
3019  realIrpStack = IoGetCurrentIrpStackLocation(realIrp);
3020  realIrpNextStack = IoGetNextIrpStackLocation(realIrp);
3021 
3022  //
3023  // Check SRB status for success of completing request.
3024  //
3025 
3026  if (SRB_STATUS(srb->SrbStatus) != SRB_STATUS_SUCCESS) {
3027 
3028  DebugPrint((2,
3029  "CdRomDeviceControlCompletion: Irp %lx, Srb %lx Real Irp %lx Status %lx\n",
3030  Irp,
3031  srb,
3032  realIrp,
3033  srb->SrbStatus));
3034 
3035  //
3036  // Release the queue if it is frozen.
3037  //
3038 
3039  if (srb->SrbStatus & SRB_STATUS_QUEUE_FROZEN) {
3040  DebugPrint((2, "CdRomDeviceControlCompletion: Releasing Queue\n"));
3042  }
3043 
3044 
3046  srb,
3047  irpStack->MajorFunction,
3048  irpStack->Parameters.DeviceIoControl.IoControlCode,
3049  MAXIMUM_RETRIES - ((ULONG_PTR)realIrpNextStack->Parameters.Others.Argument1),
3050  &status);
3051 
3052  DebugPrint((2, "CdRomDeviceControlCompletion: IRP will %sbe retried\n",
3053  (retry ? "" : "not ")));
3054 
3055  //
3056  // Some of the Device Controls need special cases on non-Success status's.
3057  //
3058 
3059  if (realIrpStack->MajorFunction == IRP_MJ_DEVICE_CONTROL) {
3060  if ((realIrpStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_CDROM_GET_LAST_SESSION) ||
3061  (realIrpStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_CDROM_READ_TOC) ||
3062  (realIrpStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_CDROM_GET_CONTROL) ||
3063  (realIrpStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_CDROM_GET_VOLUME)) {
3064 
3065  if (status == STATUS_DATA_OVERRUN) {
3067  retry = FALSE;
3068  }
3069  }
3070 
3071  if (realIrpStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_CDROM_READ_Q_CHANNEL) {
3072  PLAY_ACTIVE(deviceExtension) = FALSE;
3073  }
3074  }
3075 
3076  //
3077  // If the status is verified required and the this request
3078  // should bypass verify required then retry the request.
3079  //
3080 
3081  if (realIrpStack->Flags & SL_OVERRIDE_VERIFY_VOLUME &&
3083 
3084  if (((realIrpStack->MajorFunction == IRP_MJ_DEVICE_CONTROL) ||
3085  (realIrpStack->MajorFunction == IRP_MJ_INTERNAL_DEVICE_CONTROL)) &&
3086  (realIrpStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_CDROM_CHECK_VERIFY)) {
3087 
3089  if (srb->DataBuffer) {
3090  ExFreePool(srb->DataBuffer);
3091  }
3092  ExFreePool(srb);
3093  if (Irp->MdlAddress) {
3094  IoFreeMdl(Irp->MdlAddress);
3095  }
3096 
3097  IoFreeIrp(Irp);
3098 
3099  //
3100  // Update the geometry information, as the media could have changed.
3101  // The completion routine for this will complete the real irp and start
3102  // the next packet.
3103  //
3104 
3105  status = CdRomUpdateCapacity(deviceExtension,realIrp, NULL);
3106  DebugPrint((2, "CdRomDeviceControlCompletion: [%lx] CdRomUpdateCapacity completed with status %lx\n", realIrp, status));
3108 
3110 
3111  } else {
3112 
3114  retry = TRUE;
3115  }
3116 
3117  }
3118 
3119  if (retry && (realIrpNextStack->Parameters.Others.Argument1 = (PVOID)((ULONG_PTR)realIrpNextStack->Parameters.Others.Argument1-1))) {
3120 
3121 
3122  if (((ULONG_PTR)realIrpNextStack->Parameters.Others.Argument1)) {
3123 
3124  //
3125  // Retry request.
3126  //
3127 
3128  DebugPrint((1, "Retry request %lx - Calling StartIo\n", Irp));
3129 
3130 
3132  if (srb->DataBuffer) {
3133  ExFreePool(srb->DataBuffer);
3134  }
3135  ExFreePool(srb);
3136  if (Irp->MdlAddress) {
3137  IoFreeMdl(Irp->MdlAddress);
3138  }
3139 
3140  IoFreeIrp(Irp);
3141 
3142  //
3143  // Call StartIo directly since IoStartNextPacket hasn't been called,
3144  // the serialisation is still intact.
3145  //
3146 
3147  ScsiCdRomStartIo(DeviceObject, realIrp);
3149 
3150  }
3151 
3152  //
3153  // Exhausted retries. Fall through and complete the request with the appropriate status.
3154  //
3155 
3156  }
3157  } else {
3158 
3159  //
3160  // Set status for successful request.
3161  //
3162 
3164  }
3165 
3166  if (NT_SUCCESS(status)) {
3167 
3168  switch (realIrpStack->Parameters.DeviceIoControl.IoControlCode) {
3169 
3171 
3172  PREAD_CAPACITY_DATA readCapacityBuffer = srb->DataBuffer;
3173  ULONG lastSector;
3174  ULONG bps;
3175  ULONG lastBit;
3176  ULONG tmp;
3177 
3178  //
3179  // Swizzle bytes from Read Capacity and translate into
3180  // the necessary geometry information in the device extension.
3181  //
3182 
3183  tmp = readCapacityBuffer->BytesPerBlock;
3184  ((PFOUR_BYTE)&bps)->Byte0 = ((PFOUR_BYTE)&tmp)->Byte3;
3185  ((PFOUR_BYTE)&bps)->Byte1 = ((PFOUR_BYTE)&tmp)->Byte2;
3186  ((PFOUR_BYTE)&bps)->Byte2 = ((PFOUR_BYTE)&tmp)->Byte1;
3187  ((PFOUR_BYTE)&bps)->Byte3 = ((PFOUR_BYTE)&tmp)->Byte0;
3188 
3189  //
3190  // Insure that bps is a power of 2.
3191  // This corrects a problem with the HP 4020i CDR where it
3192  // returns an incorrect number for bytes per sector.
3193  //
3194 
3195  if (!bps) {
3196  bps = 2048;
3197  } else {
3198  lastBit = (ULONG) -1;
3199  while (bps) {
3200  lastBit++;
3201  bps = bps >> 1;
3202  }
3203 
3204  bps = 1 << lastBit;
3205  }
3206  deviceExtension->DiskGeometry->Geometry.BytesPerSector = bps;
3207 
3208  DebugPrint((2,
3209  "CdRomDeviceControlCompletion: Calculated bps %#x\n",
3210  deviceExtension->DiskGeometry->Geometry.BytesPerSector));
3211 
3212  //
3213  // Copy last sector in reverse byte order.
3214  //
3215 
3216  tmp = readCapacityBuffer->LogicalBlockAddress;
3217  ((PFOUR_BYTE)&lastSector)->Byte0 = ((PFOUR_BYTE)&tmp)->Byte3;
3218  ((PFOUR_BYTE)&lastSector)->Byte1 = ((PFOUR_BYTE)&tmp)->Byte2;
3219  ((PFOUR_BYTE)&lastSector)->Byte2 = ((PFOUR_BYTE)&tmp)->Byte1;
3220  ((PFOUR_BYTE)&lastSector)->Byte3 = ((PFOUR_BYTE)&tmp)->Byte0;
3221 
3222  //
3223  // Calculate sector to byte shift.
3224  //
3225 
3226  WHICH_BIT(bps, deviceExtension->SectorShift);
3227 
3228  DebugPrint((2,"SCSI ScsiClassReadDriveCapacity: Sector size is %d\n",
3229  deviceExtension->DiskGeometry->Geometry.BytesPerSector));
3230 
3231  DebugPrint((2,"SCSI ScsiClassReadDriveCapacity: Number of Sectors is %d\n",
3232  lastSector + 1));
3233 
3234  //
3235  // Calculate media capacity in bytes.
3236  //
3237 
3238  deviceExtension->PartitionLength.QuadPart = (LONGLONG)(lastSector + 1);
3239 
3240  //
3241  // Calculate number of cylinders.
3242  //
3243 
3244  deviceExtension->DiskGeometry->Geometry.Cylinders.QuadPart = (LONGLONG)((lastSector + 1)/(32 * 64));
3245 
3246  deviceExtension->PartitionLength.QuadPart =
3247  (deviceExtension->PartitionLength.QuadPart << deviceExtension->SectorShift);
3248 
3249  if (DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) {
3250 
3251  //
3252  // This device supports removable media.
3253  //
3254 
3255  deviceExtension->DiskGeometry->Geometry.MediaType = RemovableMedia;
3256 
3257  } else {
3258 
3259  //
3260  // Assume media type is fixed disk.
3261  //
3262 
3263  deviceExtension->DiskGeometry->Geometry.MediaType = FixedMedia;
3264  }
3265 
3266  //
3267  // Assume sectors per track are 32;
3268  //
3269 
3270  deviceExtension->DiskGeometry->Geometry.SectorsPerTrack = 32;
3271 
3272  //
3273  // Assume tracks per cylinder (number of heads) is 64.
3274  //
3275 
3276  deviceExtension->DiskGeometry->Geometry.TracksPerCylinder = 64;
3277 
3278  //
3279  // Copy the device extension's geometry info into the user buffer.
3280  //
3281 
3282  RtlMoveMemory(realIrp->AssociatedIrp.SystemBuffer,
3283  &deviceExtension->PartitionLength,
3284  sizeof(GET_LENGTH_INFORMATION));
3285 
3286  //
3287  // update information field.
3288  //
3289 
3290  realIrp->IoStatus.Information = sizeof(DISK_GEOMETRY);
3291  break;
3292  }
3293 
3296 
3297  PREAD_CAPACITY_DATA readCapacityBuffer = srb->DataBuffer;
3298  ULONG lastSector;
3299  ULONG bps;
3300  ULONG lastBit;
3301  ULONG tmp;
3302  PDISK_GEOMETRY_EX geometryEx;
3303 
3304  //
3305  // Swizzle bytes from Read Capacity and translate into
3306  // the necessary geometry information in the device extension.
3307  //
3308 
3309  tmp = readCapacityBuffer->BytesPerBlock;
3310  ((PFOUR_BYTE)&bps)->Byte0 = ((PFOUR_BYTE)&tmp)->Byte3;
3311  ((PFOUR_BYTE)&bps)->Byte1 = ((PFOUR_BYTE)&tmp)->Byte2;
3312  ((PFOUR_BYTE)&bps)->Byte2 = ((PFOUR_BYTE)&tmp)->Byte1;
3313  ((PFOUR_BYTE)&bps)->Byte3 = ((PFOUR_BYTE)&tmp)->Byte0;
3314 
3315  //
3316  // Insure that bps is a power of 2.
3317  // This corrects a problem with the HP 4020i CDR where it
3318  // returns an incorrect number for bytes per sector.
3319  //
3320 
3321  if (!bps) {
3322  bps = 2048;
3323  } else {
3324  lastBit = (ULONG) -1;
3325  while (bps) {
3326  lastBit++;
3327  bps = bps >> 1;
3328  }
3329 
3330  bps = 1 << lastBit;
3331  }
3332  deviceExtension->DiskGeometry->Geometry.BytesPerSector = bps;
3333 
3334  DebugPrint((2,
3335  "CdRomDeviceControlCompletion: Calculated bps %#x\n",
3336  deviceExtension->DiskGeometry->Geometry.BytesPerSector));
3337 
3338  //
3339  // Copy last sector in reverse byte order.
3340  //
3341 
3342  tmp = readCapacityBuffer->LogicalBlockAddress;
3343  ((PFOUR_BYTE)&lastSector)->Byte0 = ((PFOUR_BYTE)&tmp)->Byte3;
3344  ((PFOUR_BYTE)&lastSector)->Byte1 = ((PFOUR_BYTE)&tmp)->Byte2;
3345  ((PFOUR_BYTE)&lastSector)->Byte2 = ((PFOUR_BYTE)&tmp)->Byte1;
3346  ((PFOUR_BYTE)&lastSector)->Byte3 = ((PFOUR_BYTE)&tmp)->Byte0;
3347 
3348  //
3349  // Calculate sector to byte shift.
3350  //
3351 
3352  WHICH_BIT(bps, deviceExtension->SectorShift);
3353 
3354  DebugPrint((2,"SCSI ScsiClassReadDriveCapacity: Sector size is %d\n",
3355  deviceExtension->DiskGeometry->Geometry.BytesPerSector));
3356 
3357  DebugPrint((2,"SCSI ScsiClassReadDriveCapacity: Number of Sectors is %d\n",
3358  lastSector + 1));
3359 
3360  //
3361  // Calculate media capacity in bytes.
3362  //
3363 
3364  deviceExtension->PartitionLength.QuadPart = (LONGLONG)(lastSector + 1);
3365 
3366  //
3367  // Calculate number of cylinders.
3368  //
3369 
3370  deviceExtension->DiskGeometry->Geometry.Cylinders.QuadPart = (LONGLONG)((lastSector + 1)/(32 * 64));
3371 
3372  deviceExtension->PartitionLength.QuadPart =
3373  (deviceExtension->PartitionLength.QuadPart << deviceExtension->SectorShift);
3374 
3375  if (DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) {
3376 
3377  //
3378  // This device supports removable media.
3379  //
3380 
3381  deviceExtension->DiskGeometry->Geometry.MediaType = RemovableMedia;
3382 
3383  } else {
3384 
3385  //
3386  // Assume media type is fixed disk.
3387  //
3388 
3389  deviceExtension->DiskGeometry->Geometry.MediaType = FixedMedia;
3390  }
3391 
3392  //
3393  // Assume sectors per track are 32;
3394  //
3395 
3396  deviceExtension->DiskGeometry->Geometry.SectorsPerTrack = 32;
3397 
3398  //
3399  // Assume tracks per cylinder (number of heads) is 64.
3400  //
3401 
3402  deviceExtension->DiskGeometry->Geometry.TracksPerCylinder = 64;
3403 
3404  //
3405  // Copy the device extension's geometry info into the user buffer.
3406  //
3407 
3408  geometryEx = realIrp->AssociatedIrp.SystemBuffer;
3409  RtlMoveMemory(&geometryEx->Geometry,
3410  &deviceExtension->DiskGeometry->Geometry,
3411  sizeof(DISK_GEOMETRY));
3412 
3413  //
3414  // Copy the extended information
3415  //
3416 
3417  geometryEx->DiskSize = deviceExtension->PartitionLength;
3418 
3419  //
3420  // update information field.
3421  //
3422 
3423  realIrp->IoStatus.Information = FIELD_OFFSET(DISK_GEOMETRY_EX, Data);
3424  break;
3425  }
3426 
3429 
3430  PREAD_CAPACITY_DATA readCapacityBuffer = srb->DataBuffer;
3431  ULONG lastSector;
3432  ULONG bps;
3433  ULONG lastBit;
3434  ULONG tmp;
3435 
3436  //
3437  // Swizzle bytes from Read Capacity and translate into
3438  // the necessary geometry information in the device extension.
3439  //
3440 
3441  tmp = readCapacityBuffer->BytesPerBlock;
3442  ((PFOUR_BYTE)&bps)->Byte0 = ((PFOUR_BYTE)&tmp)->Byte3;
3443  ((PFOUR_BYTE)&bps)->Byte1 = ((PFOUR_BYTE)&tmp)->Byte2;
3444  ((PFOUR_BYTE)&bps)->Byte2 = ((PFOUR_BYTE)&tmp)->Byte1;
3445  ((PFOUR_BYTE)&bps)->Byte3 = ((PFOUR_BYTE)&tmp)->Byte0;
3446 
3447  //
3448  // Insure that bps is a power of 2.
3449  // This corrects a problem with the HP 4020i CDR where it
3450  // returns an incorrect number for bytes per sector.
3451  //
3452 
3453  if (!bps) {
3454  bps = 2048;
3455  } else {
3456  lastBit = (ULONG) -1;
3457  while (bps) {
3458  lastBit++;
3459  bps = bps >> 1;
3460  }
3461 
3462  bps = 1 << lastBit;
3463  }
3464  deviceExtension->DiskGeometry->Geometry.BytesPerSector = bps;
3465 
3466  DebugPrint((2,
3467  "CdRomDeviceControlCompletion: Calculated bps %#x\n",
3468  deviceExtension->DiskGeometry->Geometry.BytesPerSector));
3469 
3470  //
3471  // Copy last sector in reverse byte order.
3472  //
3473 
3474  tmp = readCapacityBuffer->LogicalBlockAddress;
3475  ((PFOUR_BYTE)&lastSector)->Byte0 = ((PFOUR_BYTE)&tmp)->Byte3;
3476  ((PFOUR_BYTE)&lastSector)->Byte1 = ((PFOUR_BYTE)&tmp)->Byte2;
3477  ((PFOUR_BYTE)&lastSector)->Byte2 = ((PFOUR_BYTE)&tmp)->Byte1;
3478  ((PFOUR_BYTE)&lastSector)->Byte3 = ((PFOUR_BYTE)&tmp)->Byte0;
3479 
3480  //
3481  // Calculate sector to byte shift.
3482  //
3483 
3484  WHICH_BIT(bps, deviceExtension->SectorShift);
3485 
3486  DebugPrint((2,"SCSI ScsiClassReadDriveCapacity: Sector size is %d\n",
3487  deviceExtension->DiskGeometry->Geometry.BytesPerSector));
3488 
3489  DebugPrint((2,"SCSI ScsiClassReadDriveCapacity: Number of Sectors is %d\n",
3490  lastSector + 1));
3491 
3492  //
3493  // Calculate media capacity in bytes.
3494  //
3495 
3496  deviceExtension->PartitionLength.QuadPart = (LONGLONG)(lastSector + 1);
3497 
3498  //
3499  // Calculate number of cylinders.
3500  //
3501 
3502  deviceExtension->DiskGeometry->Geometry.Cylinders.QuadPart = (LONGLONG)((lastSector + 1)/(32 * 64));
3503 
3504  deviceExtension->PartitionLength.QuadPart =
3505  (deviceExtension->PartitionLength.QuadPart << deviceExtension->SectorShift);
3506 
3507  if (DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) {
3508 
3509  //
3510  // This device supports removable media.
3511  //
3512 
3513  deviceExtension->DiskGeometry->Geometry.MediaType = RemovableMedia;
3514 
3515  } else {
3516 
3517  //
3518  // Assume media type is fixed disk.
3519  //
3520 
3521  deviceExtension->DiskGeometry->Geometry.MediaType = FixedMedia;
3522  }
3523 
3524  //
3525  // Assume sectors per track are 32;
3526  //
3527 
3528  deviceExtension->DiskGeometry->Geometry.SectorsPerTrack = 32;
3529 
3530  //
3531  // Assume tracks per cylinder (number of heads) is 64.
3532  //
3533 
3534  deviceExtension->DiskGeometry->Geometry.TracksPerCylinder = 64;
3535 
3536  //
3537  // Copy the device extension's geometry info into the user buffer.
3538  //
3539 
3540  RtlMoveMemory(realIrp->AssociatedIrp.SystemBuffer,
3541  deviceExtension->DiskGeometry,
3542  sizeof(DISK_GEOMETRY));
3543 
3544  //
3545  // update information field.
3546  //
3547 
3548  realIrp->IoStatus.Information = sizeof(DISK_GEOMETRY);
3549  break;
3550  }
3551 
3553 
3554  if((realIrpStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_CDROM_CHECK_VERIFY) &&
3555  (realIrpStack->Parameters.DeviceIoControl.OutputBufferLength)) {
3556 
3557  *((PULONG)realIrp->AssociatedIrp.SystemBuffer) =
3558  physicalExtension->MediaChangeCount;
3559  realIrp->IoStatus.Information = sizeof(ULONG);
3560  } else {
3561  realIrp->IoStatus.Information = 0;
3562  }
3563 
3564  DebugPrint((2, "CdRomDeviceControlCompletion: [%lx] completing CHECK_VERIFY buddy irp %lx\n", realIrp, Irp));
3565  break;
3566 
3568  case IOCTL_CDROM_READ_TOC: {
3569 
3570  PCDROM_TOC toc = srb->DataBuffer;
3571 
3572  //
3573  // Copy the device extension's geometry info into the user buffer.
3574  //
3575 
3576  RtlMoveMemory(realIrp->AssociatedIrp.SystemBuffer,
3577  toc,
3578  srb->DataTransferLength);
3579 
3580  //
3581  // update information field.
3582  //
3583 
3584  realIrp->IoStatus.Information = srb->DataTransferLength;
3585  break;
3586  }
3587 
3589 
3590  PLAY_ACTIVE(deviceExtension) = TRUE;
3591 
3592  break;
3593 
3595 
3596  PSUB_Q_CHANNEL_DATA userChannelData = realIrp->AssociatedIrp.SystemBuffer;
3597 #if DBG
3598  PCDROM_SUB_Q_DATA_FORMAT inputBuffer = realIrp->AssociatedIrp.SystemBuffer;
3599 #endif
3600  PSUB_Q_CHANNEL_DATA subQPtr = srb->DataBuffer;
3601 
3602 #if DBG
3603  switch( inputBuffer->Format ) {
3604 
3606  DebugPrint((2,"CdRomDeviceControlCompletion: Audio Status is %u\n", subQPtr->CurrentPosition.Header.AudioStatus ));
3607  DebugPrint((2,"CdRomDeviceControlCompletion: ADR = 0x%x\n", subQPtr->CurrentPosition.ADR ));
3608  DebugPrint((2,"CdRomDeviceControlCompletion: Control = 0x%x\n", subQPtr->CurrentPosition.Control ));
3609  DebugPrint((2,"CdRomDeviceControlCompletion: Track = %u\n", subQPtr->CurrentPosition.TrackNumber ));
3610  DebugPrint((2,"CdRomDeviceControlCompletion: Index = %u\n", subQPtr->CurrentPosition.IndexNumber ));
3611  DebugPrint((2,"CdRomDeviceControlCompletion: Absolute Address = %x\n", *((PULONG)subQPtr->CurrentPosition.AbsoluteAddress) ));
3612  DebugPrint((2,"CdRomDeviceControlCompletion: Relative Address = %x\n", *((PULONG)subQPtr->CurrentPosition.TrackRelativeAddress) ));
3613  break;
3614 
3616  DebugPrint((2,"CdRomDeviceControlCompletion: Audio Status is %u\n", subQPtr->MediaCatalog.Header.AudioStatus ));
3617  DebugPrint((2,"CdRomDeviceControlCompletion: Mcval is %u\n", subQPtr->MediaCatalog.Mcval ));
3618  break;
3619 
3621  DebugPrint((2,"CdRomDeviceControlCompletion: Audio Status is %u\n", subQPtr->TrackIsrc.Header.AudioStatus ));
3622  DebugPrint((2,"CdRomDeviceControlCompletion: Tcval is %u\n", subQPtr->TrackIsrc.Tcval ));
3623  break;
3624 
3625  }
3626 #endif
3627 
3628  //
3629  // Update the play active status.
3630  //
3631 
3633 
3634  PLAY_ACTIVE(deviceExtension) = TRUE;
3635 
3636  } else {
3637 
3638  PLAY_ACTIVE(deviceExtension) = FALSE;
3639 
3640  }
3641 
3642  //
3643  // Check if output buffer is large enough to contain
3644  // the data.
3645  //
3646 
3647  if (realIrpStack->Parameters.DeviceIoControl.OutputBufferLength <
3648  srb->DataTransferLength) {
3649 
3650  srb->DataTransferLength =
3651  realIrpStack->Parameters.DeviceIoControl.OutputBufferLength;
3652  }
3653 
3654  //
3655  // Copy our buffer into users.
3656  //
3657 
3658  RtlMoveMemory(userChannelData,
3659  subQPtr,
3660  srb->DataTransferLength);
3661 
3662  realIrp->IoStatus.Information = srb->DataTransferLength;
3663  break;
3664  }
3665 
3667 
3668  PLAY_ACTIVE(deviceExtension) = FALSE;
3669  realIrp->IoStatus.Information = 0;
3670  break;
3671 
3673 
3674  realIrp->IoStatus.Information = 0;
3675  break;
3676 
3678 
3679  realIrp->IoStatus.Information = 0;
3680  break;
3681 
3683 
3684  PLAY_ACTIVE(deviceExtension) = FALSE;
3685 
3686  realIrp->IoStatus.Information = 0;
3687  break;
3688 
3689  case IOCTL_CDROM_GET_CONTROL: {
3690 
3691  PCDROM_AUDIO_CONTROL audioControl = srb->DataBuffer;
3692  PAUDIO_OUTPUT audioOutput;
3693  ULONG bytesTransferred;
3694 
3695  audioOutput = ScsiClassFindModePage((PCHAR)audioControl,
3696  srb->DataTransferLength,
3698  use6Byte);
3699  //
3700  // Verify the page is as big as expected.
3701  //
3702 
3703  bytesTransferred = (PCHAR) audioOutput - (PCHAR) audioControl +
3704  sizeof(AUDIO_OUTPUT);
3705 
3706  if (audioOutput != NULL &&
3707  srb->DataTransferLength >= bytesTransferred) {
3708 
3709  audioControl->LbaFormat = audioOutput->LbaFormat;
3710 
3711  audioControl->LogicalBlocksPerSecond =
3712  (audioOutput->LogicalBlocksPerSecond[0] << (UCHAR)8) |
3713  audioOutput->LogicalBlocksPerSecond[1];
3714 
3715  realIrp->IoStatus.Information = sizeof(CDROM_AUDIO_CONTROL);
3716 
3717  } else {
3718  realIrp->IoStatus.Information = 0;
3720  }
3721  break;
3722  }
3723 
3724  case IOCTL_CDROM_GET_VOLUME: {
3725 
3726  PAUDIO_OUTPUT audioOutput;
3727  PVOLUME_CONTROL volumeControl = srb->DataBuffer;
3728  ULONG i,bytesTransferred;
3729 
3730  audioOutput = ScsiClassFindModePage((PCHAR)volumeControl,
3731  srb->DataTransferLength,
3733  use6Byte);
3734 
3735  //
3736  // Verify the page is as big as expected.
3737  //
3738 
3739  bytesTransferred = (PCHAR) audioOutput - (PCHAR) volumeControl +
3740  sizeof(AUDIO_OUTPUT);
3741 
3742  if (audioOutput != NULL &&
3743  srb->DataTransferLength >= bytesTransferred) {
3744 
3745  for (i=0; i<4; i++) {
3746  volumeControl->PortVolume[i] =
3747  audioOutput->PortOutput[i].Volume;
3748  }
3749 
3750  //
3751  // Set bytes transferred in IRP.
3752  //
3753 
3754  realIrp->IoStatus.Information = sizeof(VOLUME_CONTROL);
3755 
3756  } else {
3757  realIrp->IoStatus.Information = 0;
3759  }
3760 
3761  break;
3762  }
3763 
3765 
3766  realIrp->IoStatus.Information = sizeof(VOLUME_CONTROL);
3767  break;
3768 
3769  default:
3770 
3771  ASSERT(FALSE);
3772  realIrp->IoStatus.Information = 0;
3774 
3775  } // end switch()
3776  }
3777 
3778  //
3779  // Deallocate srb and sense buffer.
3780  //
3781 
3782  if (srb) {
3783  if (srb->DataBuffer) {
3784  ExFreePool(srb->DataBuffer);
3785  }
3786  if (srb->SenseInfoBuffer) {
3788  }
3789  ExFreePool(srb);
3790  }
3791 
3792  if (realIrp->PendingReturned) {
3793  IoMarkIrpPending(realIrp);
3794  }
3795 
3796  if (Irp->MdlAddress) {
3797  IoFreeMdl(Irp->MdlAddress);
3798  }
3799 
3800  IoFreeIrp(Irp);
3801 
3802  //
3803  // Set status in completing IRP.
3804  //
3805 
3806  realIrp->IoStatus.Status = status;
3807 
3808  //
3809  // Set the hard error if necessary.
3810  //
3811 
3813 
3814  //
3815  // Store DeviceObject for filesystem, and clear
3816  // in IoStatus.Information field.
3817  //
3818 
3819  DebugPrint((1, "CdRomDeviceCompletion - Setting Hard Error on realIrp %lx\n",
3820  realIrp));
3822  realIrp->IoStatus.Information = 0;
3823  }
3824 
3826 
3828 
3830 }
3831 
3832 NTSTATUS
3833 NTAPI
3836  IN PIRP Irp,
3837  IN PVOID Context
3838  )
3839 {
3840  PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
3842  PCDROM_DATA cdData = (PCDROM_DATA)(deviceExtension + 1);
3843  BOOLEAN use6Byte = cdData->XAFlags & XA_USE_6_BYTE;
3844  PIO_STACK_LOCATION realIrpStack;
3845  PIO_STACK_LOCATION realIrpNextStack;
3847  PIRP realIrp = NULL;
3848  NTSTATUS status;
3849  BOOLEAN retry;
3850 
3851  //
3852  // Extract the 'real' irp from the irpstack.
3853  //
3854 
3855  realIrp = (PIRP) irpStack->Parameters.Others.Argument2;
3856  realIrpStack = IoGetCurrentIrpStackLocation(realIrp);
3857  realIrpNextStack = IoGetNextIrpStackLocation(realIrp);
3858 
3859  //
3860  // Check SRB status for success of completing request.
3861  //
3862 
3863  if (SRB_STATUS(srb->SrbStatus) != SRB_STATUS_SUCCESS) {
3864 
3865  DebugPrint((2,
3866  "CdRomSetVolumeIntermediateCompletion: Irp %lx, Srb %lx Real Irp\n",
3867  Irp,
3868  srb,
3869  realIrp));
3870 
3871  //
3872  // Release the queue if it is frozen.
3873  //
3874 
3875  if (srb->SrbStatus & SRB_STATUS_QUEUE_FROZEN) {
3877  }
3878 
3879 
3881  srb,
3882  irpStack->MajorFunction,
3883  irpStack->Parameters.DeviceIoControl.IoControlCode,
3884  MAXIMUM_RETRIES - ((ULONG_PTR)realIrpNextStack->Parameters.Others.Argument1),
3885  &status);
3886 
3887  if (status == STATUS_DATA_OVERRUN) {
3889  retry = FALSE;
3890  }
3891 
3892  //
3893  // If the status is verified required and the this request
3894  // should bypass verify required then retry the request.
3895  //
3896 
3897  if (realIrpStack->Flags & SL_OVERRIDE_VERIFY_VOLUME &&
3899 
3901  retry = TRUE;
3902  }
3903 
3904  if (retry && (realIrpNextStack->Parameters.Others.Argument1 = (PVOID)((ULONG_PTR)realIrpNextStack->Parameters.Others.Argument1-1))) {
3905 
3906  if (((ULONG_PTR)realIrpNextStack->Parameters.Others.Argument1)) {
3907 
3908  //
3909  // Retry request.
3910  //
3911 
3912  DebugPrint((1, "Retry request %lx - Calling StartIo\n", Irp));
3913 
3914 
3916  ExFreePool(srb->DataBuffer);
3917  ExFreePool(srb);
3918  if (Irp->MdlAddress) {
3919  IoFreeMdl(Irp->MdlAddress);
3920  }
3921 
3922  IoFreeIrp(Irp);
3923 
3924  //
3925  // Call StartIo directly since IoStartNextPacket hasn't been called,
3926  // the serialisation is still intact.
3927  //
3928  ScsiCdRomStartIo(DeviceObject, realIrp);
3930 
3931  }
3932 
3933  //
3934  // Exhausted retries. Fall through and complete the request with the appropriate status.
3935  //
3936 
3937  }
3938  } else {
3939 
3940  //
3941  // Set status for successful request.
3942  //
3943 
3945  }
3946 
3947  if (NT_SUCCESS(status)) {
3948 
3949  PAUDIO_OUTPUT audioInput = NULL;
3950  PAUDIO_OUTPUT audioOutput;
3951  PVOLUME_CONTROL volumeControl = realIrp->AssociatedIrp.SystemBuffer;
3952  ULONG i,bytesTransferred,headerLength;
3953  PVOID dataBuffer;
3954  PCDB cdb;
3955 
3956  audioInput = ScsiClassFindModePage((PCHAR)srb->DataBuffer,
3957  srb->DataTransferLength,
3959  use6Byte);
3960 
3961  //
3962  // Check to make sure the mode sense data is valid before we go on
3963  //
3964 
3965  if(audioInput == NULL) {
3966 
3967  DebugPrint((1, "Mode Sense Page %d not found\n",
3969 
3970  realIrp->IoStatus.Information = 0;
3971  realIrp->IoStatus.Status = STATUS_IO_DEVICE_ERROR;
3974  ExFreePool(srb);
3975  IoFreeMdl(Irp->MdlAddress);
3976  IoFreeIrp(Irp);
3978  }
3979 
3980  if (use6Byte) {
3981  headerLength = sizeof(MODE_PARAMETER_HEADER);
3982  } else {
3983  headerLength = sizeof(MODE_PARAMETER_HEADER10);
3984  }
3985 
3986  bytesTransferred = sizeof(AUDIO_OUTPUT) + headerLength;
3987 
3988  //
3989  // Allocate a new buffer for the mode select.
3990  //
3991 
3992  dataBuffer = ExAllocatePool(NonPagedPoolCacheAligned, bytesTransferred);
3993 
3994  if (!dataBuffer) {
3995  realIrp->IoStatus.Information = 0;
3996  realIrp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
3999  ExFreePool(srb);
4000  IoFreeMdl(Irp->MdlAddress);
4001  IoFreeIrp(Irp);
4003  }
4004 
4005  RtlZeroMemory(dataBuffer, bytesTransferred);
4006 
4007  //
4008  // Rebuild the data buffer to include the user requested values.
4009  //
4010 
4011  audioOutput = (PAUDIO_OUTPUT) ((PCHAR) dataBuffer + headerLength);
4012 
4013  for (i=0; i<4; i++) {
4014  audioOutput->PortOutput[i].Volume =
4015  volumeControl->PortVolume[i];
4016  audioOutput->PortOutput[i].ChannelSelection =
4017  audioInput->PortOutput[i].ChannelSelection;
4018  }
4019 
4020  audioOutput->CodePage = CDROM_AUDIO_CONTROL_PAGE;
4021  audioOutput->ParameterLength = sizeof(AUDIO_OUTPUT) - 2;
4022  audioOutput->Immediate = MODE_SELECT_IMMEDIATE;
4023 
4024  //
4025  // Free the old data buffer, mdl.
4026  //
4027 
4028  ExFreePool(srb->DataBuffer);
4029  IoFreeMdl(Irp->MdlAddress);
4030 
4031  //
4032  // rebuild the srb.
4033  //
4034 
4035  cdb = (PCDB)srb->Cdb;
4037 
4038  srb->SrbStatus = srb->ScsiStatus = 0;
4039  srb->SrbFlags = deviceExtension->SrbFlags;
4041  srb->DataTransferLength = bytesTransferred;
4042 
4043  if (use6Byte) {
4044 
4045  cdb->MODE_SELECT.OperationCode = SCSIOP_MODE_SELECT;
4046  cdb->MODE_SELECT.ParameterListLength = (UCHAR) bytesTransferred;
4047  cdb->MODE_SELECT.PFBit = 1;
4048  srb->CdbLength = 6;
4049  } else {
4050 
4051  cdb->MODE_SELECT10.OperationCode = SCSIOP_MODE_SELECT10;
4052  cdb->MODE_SELECT10.ParameterListLength[0] = (UCHAR) (bytesTransferred >> 8);
4053  cdb->MODE_SELECT10.ParameterListLength[1] = (UCHAR) (bytesTransferred & 0xFF);
4054  cdb->MODE_SELECT10.PFBit = 1;
4055  srb->CdbLength = 10;
4056  }
4057 
4058  //
4059  // Prepare the MDL
4060  //
4061 
4062  Irp->MdlAddress = IoAllocateMdl(dataBuffer,
4063  bytesTransferred,
4064  FALSE,
4065  FALSE,
4066  (PIRP) NULL);
4067 
4068  if (!Irp->MdlAddress) {
4069  realIrp->IoStatus.Information = 0;
4070  realIrp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
4073  ExFreePool(srb);
4074  ExFreePool(dataBuffer);
4075  IoFreeIrp(Irp);
4077 
4078  }
4079 
4080  MmBuildMdlForNonPagedPool(Irp->MdlAddress);
4081  srb->DataBuffer = dataBuffer;
4082 
4083  irpStack = IoGetNextIrpStackLocation(Irp);
4085  irpStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_SCSI_EXECUTE_IN;
4086  irpStack->Parameters.Scsi.Srb = srb;
4087 
4088  //
4089  // reset the irp completion.
4090  //
4091 
4094  srb,
4095  TRUE,
4096  TRUE,
4097  TRUE);
4098  //
4099  // Call the port driver.
4100  //
4101 
4102  IoCallDriver(deviceExtension->PortDeviceObject, Irp);
4103 
4105  }
4106 
4107  //
4108  // Deallocate srb and sense buffer.
4109  //
4110 
4111  if (srb) {
4112  if (srb->DataBuffer) {
4113  ExFreePool(srb->DataBuffer);
4114  }
4115  if (srb->SenseInfoBuffer) {
4117  }
4118  ExFreePool(srb);
4119  }
4120 
4121  if (Irp->PendingReturned) {
4123  }
4124 
4125  if (realIrp->PendingReturned) {
4126  IoMarkIrpPending(realIrp);
4127  }
4128 
4129  if (Irp->MdlAddress) {
4130  IoFreeMdl(Irp->MdlAddress);
4131  }
4132 
4133  IoFreeIrp(Irp);
4134 
4135  //
4136  // Set status in completing IRP.
4137  //
4138 
4139  realIrp->IoStatus.Status = status;
4140 
4141  //
4142  // Set the hard error if necessary.
4143  //
4144 
4146 
4147  //
4148  // Store DeviceObject for filesystem, and clear
4149  // in IoStatus.Information field.
4150  //
4151 
4153  realIrp->IoStatus.Information = 0;
4154  }
4155 
4157 
4159 
4161 }
4162 
4163 
4164 NTSTATUS
4165 NTAPI
4168  IN PIRP Irp,
4169  IN PVOID Context
4170  )
4171 {
4172  PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
4174  PCDROM_DATA cdData = (PCDROM_DATA)(deviceExtension + 1);
4175  PIO_STACK_LOCATION realIrpStack;
4176  PIO_STACK_LOCATION realIrpNextStack;
4178  PIRP realIrp = NULL;
4179  NTSTATUS status;
4180  BOOLEAN retry;
4181 
4182  //
4183  // Extract the 'real' irp from the irpstack.
4184  //
4185 
4186  realIrp = (PIRP) irpStack->Parameters.Others.Argument2;
4187  realIrpStack = IoGetCurrentIrpStackLocation(realIrp);
4188  realIrpNextStack = IoGetNextIrpStackLocation(realIrp);
4189 
4190  //
4191  // Check SRB status for success of completing request.
4192  //
4193 
4194  if (SRB_STATUS(srb->SrbStatus) != SRB_STATUS_SUCCESS) {
4195 
4196  DebugPrint((2,
4197  "CdRomSetVolumeIntermediateCompletion: Irp %lx, Srb %lx Real Irp\n",
4198  Irp,
4199  srb,
4200  realIrp));
4201 
4202  //
4203  // Release the queue if it is frozen.
4204  //
4205 
4206  if (srb->SrbStatus & SRB_STATUS_QUEUE_FROZEN) {
4208  }
4209 
4210 
4212  srb,
4213  irpStack->MajorFunction,
4214  irpStack->Parameters.DeviceIoControl.IoControlCode,
4215  MAXIMUM_RETRIES - ((ULONG_PTR)realIrpNextStack->Parameters.Others.Argument1),
4216  &status);
4217 
4218  //
4219  // If the status is verified required and the this request
4220  // should bypass verify required then retry the request.
4221  //
4222 
4223  if (realIrpStack->Flags & SL_OVERRIDE_VERIFY_VOLUME &&
4225 
4227  retry = TRUE;
4228  }
4229 
4230  if (retry && (realIrpNextStack->Parameters.Others.Argument1 = (PVOID)((ULONG_PTR)realIrpNextStack->Parameters.Others.Argument1-1))) {
4231 
4232  if (((ULONG_PTR)realIrpNextStack->Parameters.Others.Argument1)) {
4233 
4234  //
4235  // Retry request.
4236  //
4237 
4238  DebugPrint((1, "Retry request %lx - Calling StartIo\n", Irp));
4239 
4240 
4242  ExFreePool(srb->DataBuffer);
4243  ExFreePool(srb);
4244  if (Irp->MdlAddress) {
4245  IoFreeMdl(Irp->MdlAddress);
4246  }
4247 
4248  IoFreeIrp(Irp);
4249 
4250  //
4251  // Call StartIo directly since IoStartNextPacket hasn't been called,
4252  // the serialisation is still intact.
4253  //
4254 
4255  ScsiCdRomStartIo(DeviceObject, realIrp);
4257 
4258  }
4259 
4260  //
4261  // Exhausted retries. Fall through and complete the request with the appropriate status.
4262  //
4263  }
4264  } else {
4265 
4266  //
4267  // Set status for successful request.
4268  //
4269 
4271  }
4272 
4273  if (NT_SUCCESS(status)) {
4274 
4275  ULONG sectorSize, startingSector, transferByteCount;
4276  PCDB cdb;
4277 
4278  //
4279  // Update device ext. to show which mode we are currently using.
4280  //
4281 
4282  sectorSize = cdData->u1.BlockDescriptor.BlockLength[0] << 16;
4283  sectorSize |= (cdData->u1.BlockDescriptor.BlockLength[1] << 8);
4284  sectorSize |= (cdData->u1.BlockDescriptor.BlockLength[2]);
4285 
4286  cdData->RawAccess = (sectorSize == RAW_SECTOR_SIZE) ? TRUE : FALSE;
4287 
4288  //
4289  // Free the old data buffer, mdl.
4290  //
4291 
4292  ExFreePool(srb->DataBuffer);
4293  IoFreeMdl(Irp->MdlAddress);
4294  IoFreeIrp(Irp);
4295 
4296  //
4297  // rebuild the srb.
4298  //
4299 
4300  cdb = (PCDB)srb->Cdb;
4302 
4303 
4304  if (cdData->RawAccess) {
4305 
4306  PRAW_READ_INFO rawReadInfo =
4307  (PRAW_READ_INFO)realIrpStack->Parameters.DeviceIoControl.Type3InputBuffer;
4308 
4309  ULONG maximumTransferLength;
4310  ULONG transferPages;
4311 
4312  //
4313  // Calculate starting offset.
4314  //
4315 
4316  startingSector = (ULONG)(rawReadInfo->DiskOffset.QuadPart >> deviceExtension->SectorShift);
4317  transferByteCount = rawReadInfo->SectorCount * RAW_SECTOR_SIZE;
4318  maximumTransferLength = deviceExtension->PortCapabilities->MaximumTransferLength;
4319  transferPages = ADDRESS_AND_SIZE_TO_SPAN_PAGES(MmGetMdlVirtualAddress(realIrp->MdlAddress),
4320  transferByteCount);
4321 
4322  //
4323  // Determine if request is within limits imposed by miniport.
4324  // If the request is larger than the miniport's capabilities, split it.
4325  //
4326 
4327  if (transferByteCount > maximumTransferLength ||
4328  transferPages > deviceExtension->PortCapabilities->MaximumPhysicalPages) {
4329 
4330  realIrp->IoStatus.Information = 0;
4331  realIrp->IoStatus.Status = STATUS_INVALID_PARAMETER;
4333 
4335  ExFreePool(srb);
4336 
4338 
4340  }
4341 
4342  srb->OriginalRequest = realIrp;
4343  srb->SrbFlags = deviceExtension->SrbFlags;
4345  srb->DataTransferLength = transferByteCount;
4346  srb->TimeOutValue = deviceExtension->TimeOutValue;
4347  srb->CdbLength = 10;
4348  srb->DataBuffer = MmGetMdlVirtualAddress(realIrp->MdlAddress);
4349 
4350  if (rawReadInfo->TrackMode == CDDA) {
4351  if (cdData->XAFlags & PLEXTOR_CDDA) {
4352 
4353  srb->CdbLength = 12;
4354 
4355  cdb->PLXTR_READ_CDDA.LogicalUnitNumber = deviceExtension->Lun;
4356  cdb->PLXTR_READ_CDDA.LogicalBlockByte3 = (UCHAR) (startingSector & 0xFF);
4357  cdb->PLXTR_READ_CDDA.LogicalBlockByte2 = (UCHAR) ((startingSector >> 8) & 0xFF);
4358  cdb->PLXTR_READ_CDDA.LogicalBlockByte1 = (UCHAR) ((startingSector >> 16) & 0xFF);
4359  cdb->PLXTR_READ_CDDA.LogicalBlockByte0 = (UCHAR) ((startingSector >> 24) & 0xFF);
4360 
4361  cdb->PLXTR_READ_CDDA.TransferBlockByte3 = (UCHAR) (rawReadInfo->SectorCount & 0xFF);
4362  cdb->PLXTR_READ_CDDA.TransferBlockByte2 = (UCHAR) (rawReadInfo->SectorCount >> 8);
4363  cdb->PLXTR_READ_CDDA.TransferBlockByte1 = 0;
4364  cdb->PLXTR_READ_CDDA.TransferBlockByte0 = 0;
4365 
4366  cdb->PLXTR_READ_CDDA.SubCode = 0;
4367  cdb->PLXTR_READ_CDDA.OperationCode = 0xD8;
4368 
4369  } else if (cdData->XAFlags & NEC_CDDA) {
4370 
4371  cdb->NEC_READ_CDDA.LogicalBlockByte3 = (UCHAR) (startingSector & 0xFF);
4372  cdb->NEC_READ_CDDA.LogicalBlockByte2 = (UCHAR) ((startingSector >> 8) & 0xFF);
4373  cdb->NEC_READ_CDDA.LogicalBlockByte1 = (UCHAR) ((startingSector >> 16) & 0xFF);
4374  cdb->NEC_READ_CDDA.LogicalBlockByte0 = (UCHAR) ((startingSector >> 24) & 0xFF);
4375 
4376  cdb->NEC_READ_CDDA.TransferBlockByte1 = (UCHAR) (rawReadInfo->SectorCount & 0xFF);
4377  cdb->NEC_READ_CDDA.TransferBlockByte0 = (UCHAR) (rawReadInfo->SectorCount >> 8);
4378 
4379  cdb->NEC_READ_CDDA.OperationCode = 0xD4;
4380  }
4381  } else {
4382  cdb->CDB10.LogicalUnitNumber = deviceExtension->Lun;
4383 
4384  cdb->CDB10.TransferBlocksMsb = (UCHAR) (rawReadInfo->SectorCount >> 8);
4385  cdb->CDB10.TransferBlocksLsb = (UCHAR) (rawReadInfo->SectorCount & 0xFF);
4386 
4387  cdb->CDB10.LogicalBlockByte3 = (UCHAR) (startingSector & 0xFF);
4388  cdb->CDB10.LogicalBlockByte2 = (UCHAR) ((startingSector >> 8) & 0xFF);
4389  cdb->CDB10.LogicalBlockByte1 = (UCHAR) ((startingSector >> 16) & 0xFF);
4390  cdb->CDB10.LogicalBlockByte0 = (UCHAR) ((startingSector >> 24) & 0xFF);
4391 
4392  cdb->CDB10.OperationCode = SCSIOP_READ;
4393  }
4394 
4395  srb->SrbStatus = srb->ScsiStatus = 0;
4396 
4397 
4398  irpStack = IoGetNextIrpStackLocation(realIrp);
4399  irpStack->MajorFunction = IRP_MJ_SCSI;
4400  irpStack->Parameters.Scsi.Srb = srb;
4401 
4402  if (!(irpStack->Parameters.Others.Argument1)) {
4403 
4404  //
4405  // Only jam this in if it doesn't exist. The completion routines can
4406  // call StartIo directly in the case of retries and resetting it will
4407  // cause infinite loops.
4408  //
4409 
4410  irpStack->Parameters.Others.Argument1 = (PVOID) MAXIMUM_RETRIES;
4411  }
4412 
4413  //
4414  // Set up IoCompletion routine address.
4415  //
4416 
4417  IoSetCompletionRoutine(realIrp,
4419  srb,
4420  TRUE,
4421  TRUE,
4422  TRUE);
4423  } else {
4424 
4425  ULONG maximumTransferLength = deviceExtension->PortCapabilities->MaximumTransferLength;
4426  ULONG transferPages = ADDRESS_AND_SIZE_TO_SPAN_PAGES(MmGetMdlVirtualAddress(realIrp->MdlAddress),
4427  realIrpStack->Parameters.Read.Length);
4428  //
4429  // Back to cooked sectors. Build and send a normal read.
4430  // The real work for setting offsets and checking for splitrequests was
4431  // done in startio
4432  //
4433 
4434  if ((realIrpStack->Parameters.Read.Length > maximumTransferLength) ||
4435  (transferPages > deviceExtension->PortCapabilities->MaximumPhysicalPages)) {
4436 
4437  //
4438  // Request needs to be split. Completion of each portion of the request will
4439  // fire off the next portion. The final request will signal Io to send a new request.
4440  //
4441 
4442  ScsiClassSplitRequest(DeviceObject, realIrp, maximumTransferLength);
4444 
4445  } else {
4446 
4447  //
4448  // Build SRB and CDB for this IRP.
4449  //
4450 
4452 
4453  }
4454  }
4455 
4456  //
4457  // Call the port driver.
4458  //
4459 
4460  IoCallDriver(deviceExtension->PortDeviceObject, realIrp);
4461 
4463  }
4464 
4465  //
4466  // Update device Extension flags to indicate that XA isn't supported.
4467  //
4468 
4469  cdData->XAFlags |= XA_NOT_SUPPORTED;
4470 
4471  //
4472  // Deallocate srb and sense buffer.
4473  //
4474 
4475  if (srb) {
4476  if (srb->DataBuffer) {
4477  ExFreePool(srb->DataBuffer);
4478  }
4479  if (srb->SenseInfoBuffer) {
4481  }
4482  ExFreePool(srb);
4483  }
4484 
4485  if (Irp->PendingReturned) {
4487  }
4488 
4489  if (realIrp->PendingReturned) {
4490  IoMarkIrpPending(realIrp);
4491  }
4492 
4493  if (Irp->MdlAddress) {
4494  IoFreeMdl(Irp->MdlAddress);
4495  }
4496 
4497  IoFreeIrp(Irp);
4498 
4499  //
4500  // Set status in completing IRP.
4501  //
4502 
4503  realIrp->IoStatus.Status = status;
4504 
4505  //
4506  // Set the hard error if necessary.
4507  //
4508 
4510 
4511  //
4512  // Store DeviceObject for filesystem, and clear
4513  // in IoStatus.Information field.
4514  //
4515 
4517  realIrp->IoStatus.Information = 0;
4518  }
4519 
4521 
4523 
4525 }
4526 
4527 NTSTATUS
4528 NTAPI
4531  IN PIRP Irp,
4532  IN PVOID Context
4533  )
4534 
4535 /*++
4536 
4537 Routine Description:
4538 
4539  This routine executes when the port driver has completed a request.
4540  It looks at the SRB status in the completing SRB and if not success
4541  it checks for valid request sense buffer information. If valid, the
4542  info is used to update status with more precise message of type of
4543  error. This routine deallocates the SRB.
4544 
4545 Arguments:
4546 
4547  DeviceObject - Supplies the device object which represents the logical
4548  unit.
4549 
4550  Irp - Supplies the Irp which has completed.
4551 
4552  Context - Supplies a pointer to the SRB.
4553 
4554 Return Value:
4555 
4556  NT status
4557 
4558 --*/
4559 
4560 {
4564  NTSTATUS status;
4565  BOOLEAN retry;
4566 
4567  //
4568  // Check SRB status for success of completing request.
4569  //
4570 
4571  if (SRB_STATUS(srb->SrbStatus) != SRB_STATUS_SUCCESS) {
4572 
4573  DebugPrint((2,"ScsiClassIoComplete: IRP %lx, SRB %lx\n", Irp, srb));
4574 
4575  //
4576  // Release the queue if it is frozen.
4577  //
4578 
4579  if (srb->SrbStatus & SRB_STATUS_QUEUE_FROZEN) {
4581  }
4582 
4584  DeviceObject,
4585  srb,
4586  irpStack->MajorFunction,
4587  irpStack->MajorFunction == IRP_MJ_DEVICE_CONTROL ? irpStack->Parameters.DeviceIoControl.IoControlCode : 0,
4588  MAXIMUM_RETRIES - ((ULONG_PTR)irpNextStack->Parameters.Others.Argument1),
4589  &status);
4590 
4591  //
4592  // If the status is verified required and the this request
4593  // should bypass verify required then retry the request.
4594  //
4595 
4596  if (irpStack->Flags & SL_OVERRIDE_VERIFY_VOLUME &&
4598 
4600  retry = TRUE;
4601  }
4602 
4603  if (retry && (irpNextStack->Parameters.Others.Argument1 = (PVOID)((ULONG_PTR)irpNextStack->Parameters.Others.Argument1-1))) {
4604 
4605  if (((ULONG_PTR)irpNextStack->Parameters.Others.Argument1)) {
4606 
4607  //
4608  // Retry request.
4609  //
4610 
4611  DebugPrint((1, "CdRomXACompletion: Retry request %lx - Calling StartIo\n", Irp));
4612 
4613 
4615  ExFreePool(srb->DataBuffer);
4616  ExFreePool(srb);
4617 
4618  //
4619  // Call StartIo directly since IoStartNextPacket hasn't been called,
4620  // the serialisation is still intact.
4621  //
4622 
4625 
4626  }
4627 
4628  //
4629  // Exhausted retries. Fall through and complete the request with the appropriate status.
4630  //
4631  }
4632  } else {
4633 
4634  //
4635  // Set status for successful request.
4636  //
4637 
4639 
4640  } // end if (SRB_STATUS(srb->SrbStatus) ...
4641 
4642  //
4643  // Return SRB to nonpaged pool.
4644  //
4645 
4646  ExFreePool(srb);
4647 
4648  //
4649  // Set status in completing IRP.
4650  //
4651 
4652  Irp->IoStatus.Status = status;
4653 
4654  //
4655  // Set the hard error if necessary.
4656  //
4657 
4659 
4660  //
4661  // Store DeviceObject for filesystem, and clear
4662  // in IoStatus.Information field.
4663  //
4664 
4666  Irp->IoStatus.Information = 0;
4667  }
4668 
4669  //
4670  // If pending has be returned for this irp then mark the current stack as
4671  // pending.
4672  //
4673 
4674  if (Irp->PendingReturned) {
4676  }
4677 
4678  //IoCompleteRequest(Irp, IO_DISK_INCREMENT);
4680 
4681  return status;
4682 }
4683 
4684 NTSTATUS
4685 NTAPI
4688  IN PIRP Irp
4689  )
4690 
4691 /*++
4692 
4693 Routine Description:
4694 
4695  This is the NT device control handler for CDROMs.
4696 
4697 Arguments:
4698 
4699  DeviceObject - for this CDROM
4700 
4701  Irp - IO Request packet
4702 
4703 Return Value:
4704 
4705  NTSTATUS
4706 
4707 --*/
4708 
4709 {
4711  PIO_STACK_LOCATION nextStack;
4712  PKEVENT deviceControlEvent;
4713  PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
4714  PCDROM_DATA cdData = (PCDROM_DATA)(deviceExtension+1);
4715  SCSI_REQUEST_BLOCK srb;
4716  NTSTATUS status;
4717  KIRQL irql;
4718 
4719  ULONG ioctlCode;
4720  ULONG baseCode;
4721  ULONG functionCode;
4722 
4723 RetryControl:
4724 
4725  //
4726  // Zero the SRB on stack.
4727  //
4728 
4729  RtlZeroMemory(&srb, sizeof(SCSI_REQUEST_BLOCK));
4730 
4731  Irp->IoStatus.Information = 0;
4732 
4733  //
4734  // if this is a class driver ioctl then we need to change the base code
4735  // to IOCTL_CDROM_BASE so that the switch statement can handle it.
4736  //
4737  // WARNING - currently the scsi class ioctl function codes are between
4738  // 0x200 & 0x300. this routine depends on that fact
4739  //
4740 
4741  ioctlCode = irpStack->Parameters.DeviceIoControl.IoControlCode;
4742  baseCode = ioctlCode >> 16;
4743  functionCode = (ioctlCode & (~0xffffc003)) >> 2;
4744 
4745  DebugPrint((1, "CdRomDeviceControl: Ioctl Code = %#08lx, Base Code = %#lx,"
4746  " Function Code = %#lx\n",
4747  ioctlCode,
4748  baseCode,
4749  functionCode
4750  ));
4751 
4752  if((functionCode >= 0x200) && (functionCode <= 0x300)) {
4753 
4754  ioctlCode = (ioctlCode & 0x0000ffff) | CTL_CODE(IOCTL_CDROM_BASE, 0, 0, 0);
4755 
4756  DebugPrint((1, "CdRomDeviceControl: Class Code - new ioctl code is %#08lx\n",
4757  ioctlCode));
4758 
4759  irpStack->Parameters.DeviceIoControl.IoControlCode = ioctlCode;
4760 
4761  }
4762 
4763  switch (ioctlCode) {
4764 
4765  case IOCTL_CDROM_RAW_READ: {
4766 
4767  LARGE_INTEGER startingOffset;
4768  ULONG transferBytes;
4769  PRAW_READ_INFO rawReadInfo = (PRAW_READ_INFO)irpStack->Parameters.DeviceIoControl.Type3InputBuffer;
4770  PUCHAR userData = (PUCHAR)Irp->AssociatedIrp.SystemBuffer;
4771 
4772  //
4773  // Ensure that XA reads are supported.
4774  //
4775 
4776  if (cdData->XAFlags & XA_NOT_SUPPORTED) {
4777 
4778  DebugPrint((1,
4779  "CdRomDeviceControl: XA Reads not supported. Flags (%x)\n",
4780  cdData->XAFlags));
4781 
4783  break;
4784  }
4785 
4786  //
4787  // Check that ending sector is on disc and buffers are there and of
4788  // correct size.
4789  //
4790 
4791  if (rawReadInfo == NULL) {
4792 
4793  //
4794  // Called from user space. Validate the buffers.
4795  //
4796 
4797  rawReadInfo = (PRAW_READ_INFO)userData;
4798  irpStack->Parameters.DeviceIoControl.Type3InputBuffer = (PVOID)userData;
4799 
4800  if (rawReadInfo == NULL) {
4801 
4802  DebugPrint((1,"CdRomDeviceControl: Invalid I/O parameters for XA Read (No extent info\n"));
4803 
4804  Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
4805 
4807  return STATUS_INVALID_PARAMETER;
4808  }
4809 
4810  if (irpStack->Parameters.DeviceIoControl.InputBufferLength != sizeof(RAW_READ_INFO)) {
4811 
4812  DebugPrint((1,"CdRomDeviceControl: Invalid I/O parameters for XA Read (Invalid info buffer\n"));
4813 
4814  Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
4815 
4817  return STATUS_INVALID_PARAMETER;
4818  }
4819  }
4820 
4821  startingOffset.QuadPart = rawReadInfo->DiskOffset.QuadPart;
4822  transferBytes = rawReadInfo->SectorCount * RAW_SECTOR_SIZE;
4823 
4824  if (irpStack->Parameters.DeviceIoControl.OutputBufferLength < transferBytes) {
4825 
4826  DebugPrint((1,"CdRomDeviceControl: Invalid I/O parameters for XA Read (Bad buffer size)\n"));
4827 
4828  //
4829  // Fail request with status of invalid parameters.
4830  //
4831 
4832  Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
4833 
4835  return STATUS_INVALID_PARAMETER;
4836  }
4837 
4838  if ((startingOffset.QuadPart + transferBytes) > deviceExtension->PartitionLength.QuadPart) {
4839 
4840  DebugPrint((1,"CdRomDeviceControl: Invalid I/O parameters for XA Read (Request Out of Bounds)\n"));
4841 
4842  //
4843  // Fail request with status of invalid parameters.
4844  //
4845 
4847  break;
4848  }
4849 
4852 
4853  return STATUS_PENDING;
4854  }
4855 
4858 
4859  DebugPrint((2,"CdRomDeviceControl: Get drive geometry\n"));
4860 
4861  if ( irpStack->Parameters.DeviceIoControl.OutputBufferLength <
4862  sizeof( DISK_GEOMETRY ) ) {
4863 
4865  break;
4866  }
4867 
4870 
4871  return STATUS_PENDING;
4872  }
4873 
4876 
4877  DebugPrint((2,"CdRomDeviceControl: Get drive geometry ex\n"));
4878 
4879  if ( irpStack->Parameters.DeviceIoControl.OutputBufferLength <
4880  sizeof( DISK_GEOMETRY_EX ) ) {
4881 
4883  break;
4884  }
4885 
4888 
4889  return STATUS_PENDING;
4890  }
4891 
4893 
4894  DebugPrint((2,"CdRomDeviceControl: Get length info\n"));
4895 
4896  if ( irpStack->Parameters.DeviceIoControl.OutputBufferLength <
4897  sizeof( GET_LENGTH_INFORMATION ) ) {
4898 
4900  break;
4901  }
4902 
4905 
4906  return STATUS_PENDING;
4907  }
4908 
4910  case IOCTL_CDROM_READ_TOC: {
4911 
4912  //
4913  // If the cd is playing music then reject this request.
4914  //
4915 
4917  Irp->IoStatus.Status = STATUS_DEVICE_BUSY;
4919  return STATUS_DEVICE_BUSY;
4920  }
4921 
4924 
4925  return STATUS_PENDING;
4926  }
4927 
4929 
4930  //
4931  // Play Audio MSF
4932  //
4933 
4934  DebugPrint((2,"CdRomDeviceControl: Play audio MSF\n"));
4935 
4936  if (irpStack->Parameters.DeviceIoControl.InputBufferLength <
4937  sizeof(CDROM_PLAY_AUDIO_MSF)) {
4938 
4939  //
4940  // Indicate unsuccessful status.
4941  //
4942 
4944  break;
4945  }
4946 
4949 
4950  return STATUS_PENDING;
4951  }
4952 
4954 
4955 
4956  //
4957  // Seek Audio MSF
4958  //
4959 
4960  DebugPrint((2,"CdRomDeviceControl: Seek audio MSF\n"));
4961 
4962  if (irpStack->Parameters.DeviceIoControl.InputBufferLength <
4963  sizeof(CDROM_SEEK_AUDIO_MSF)) {
4964 
4965  //
4966  // Indicate unsuccessful status.
4967  //
4968 
4970  break;
4971  } else {
4974 
4975  return STATUS_PENDING;
4976 
4977  }
4978  }
4979 
4980  case IOCTL_CDROM_PAUSE_AUDIO: {
4981 
4982  //
4983  // Pause audio
4984  //
4985 
4986  DebugPrint((2, "CdRomDeviceControl: Pause audio\n"));
4987 
4990 
4991  return STATUS_PENDING;
4992 
4993  break;
4994  }
4995 
4996  case IOCTL_CDROM_RESUME_AUDIO: {
4997 
4998  //
4999  // Resume audio
5000  //
5001 
5002  DebugPrint((2, "CdRomDeviceControl: Resume audio\n"));
5003 
5006 
5007  return STATUS_PENDING;
5008  }
5009 
5011 
5012  if(irpStack->Parameters.DeviceIoControl.InputBufferLength <
5013  sizeof(CDROM_SUB_Q_DATA_FORMAT)) {
5014 
5016  Irp->IoStatus.Information = 0;
5017  break;
5018  }
5019 
5022 
5023  return STATUS_PENDING;
5024  }
5025 
5026  case IOCTL_CDROM_GET_CONTROL: {
5027 
5028  DebugPrint((2, "CdRomDeviceControl: Get audio control\n"));
5029 
5030  //
5031  // Verify user buffer is large enough for the data.
5032  //
5033 
5034  if (irpStack->Parameters.DeviceIoControl.OutputBufferLength <
5035  sizeof(CDROM_AUDIO_CONTROL)) {
5036 
5037  //
5038  // Indicate unsuccessful status and no data transferred.
5039  //
5040 
5042  Irp->IoStatus.Information = 0;
5043  break;
5044 
5045  } else {
5046 
5049 
5050  return STATUS_PENDING;
5051  }
5052  }
5053 
5054  case IOCTL_CDROM_GET_VOLUME: {
5055 
5056  DebugPrint((2, "CdRomDeviceControl: Get volume control\n"));
5057 
5058  //
5059  // Verify user buffer is large enough for data.
5060  //
5061 
5062  if (irpStack->Parameters.DeviceIoControl.OutputBufferLength <
5063  sizeof(VOLUME_CONTROL)) {
5064 
5065  //
5066  // Indicate unsuccessful status and no data transferred.
5067  //
5068 
5070  Irp->IoStatus.Information = 0;
5071  break;
5072 
5073  } else {
5076 
5077  return STATUS_PENDING;
5078  }
5079  }
5080 
5081  case IOCTL_CDROM_SET_VOLUME: {
5082 
5083  DebugPrint((2, "CdRomDeviceControl: Set volume control\n"));
5084 
5085  if (irpStack->Parameters.DeviceIoControl.InputBufferLength <
5086  sizeof(VOLUME_CONTROL)) {
5087 
5088  //
5089  // Indicate unsuccessful status.
5090  //
5091 
5093  break;
5094  } else {
5095 
5098 
5099  return STATUS_PENDING;
5100  }
5101  }
5102 
5103  case IOCTL_CDROM_STOP_AUDIO: {
5104 
5105  //
5106  // Stop play.
5107  //
5108 
5109  DebugPrint((2, "CdRomDeviceControl: Stop audio\n"));
5110 
5113 
5114  return STATUS_PENDING;
5115  }
5116 
5117  case IOCTL_CDROM_CHECK_VERIFY: {
5118  DebugPrint((1, "CdRomDeviceControl: [%lx] Check Verify\n", Irp));
5120 
5121  if((irpStack->Parameters.DeviceIoControl.OutputBufferLength) &&
5122  (irpStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(ULONG))) {
5123 
5124  DebugPrint((1, "CdRomDeviceControl: Check Verify: media count "
5125  "buffer too small\n"));
5126 
5128  break;
5129  }
5130 
5132 
5133  return STATUS_PENDING;
5134  }
5135 
5136  default: {
5137 
5138  //
5139  // allocate an event and stuff it into our stack location.
5140  //
5141 
5142  deviceControlEvent = ExAllocatePool(NonPagedPool, sizeof(KEVENT));
5143 
5144  if(!deviceControlEvent) {
5145 
5147 
5148  } else {
5149 
5150  PIO_STACK_LOCATION currentStack;
5151 
5152  KeInitializeEvent(deviceControlEvent, NotificationEvent, FALSE);
5153 
5154  currentStack = IoGetCurrentIrpStackLocation(Irp);
5155  nextStack = IoGetNextIrpStackLocation(Irp);
5156 
5157  //
5158  // Copy the stack down a notch
5159  //
5160 
5161  *nextStack = *currentStack;
5162 
5164  Irp,
5166  deviceControlEvent,
5167  TRUE,
5168  TRUE,
5169  TRUE
5170  );
5171 
5173 
5174  Irp->IoStatus.Status = STATUS_SUCCESS;
5175  Irp->IoStatus.Information = 0;
5176 
5177  //
5178  // Override volume verifies on this stack location so that we
5179  // will be forced through the synchronization. Once this location
5180  // goes away we get the old value back
5181  //
5182 
5183  nextStack->Flags |= SL_OVERRIDE_VERIFY_VOLUME;
5184 
5186 
5188 
5189  //
5190  // Wait for CdRomClassIoctlCompletion to set the event. This
5191  // ensures serialization remains intact for these unhandled device
5192  // controls.
5193  //
5194 
5196  deviceControlEvent,
5197  Suspended,
5198  KernelMode,
5199  FALSE,
5200  NULL);
5201 
5202  ExFreePool(deviceControlEvent);
5203 
5204  DebugPrint((2, "CdRomDeviceControl: irp %#08lx synchronized\n", Irp));
5205 
5206  //
5207  // If an error occured then propagate that back up - we are no longer
5208  // guaranteed synchronization and the upper layers will have to
5209  // retry.
5210  //
5211  // If no error occured, call down to the class driver directly
5212  // then start up the next request.
5213  //
5214 
5215  if(Irp->IoStatus.Status == STATUS_SUCCESS) {
5216 
5218 
5220 
5222 
5223  KeLowerIrql(irql);
5224  }
5225  }
5226 
5227  return status;
5228  }
5229 
5230  } // end switch()
5231 
5232  if (status == STATUS_VERIFY_REQUIRED) {
5233 
5234  //
5235  // If the status is verified required and this request
5236  // should bypass verify required then retry the request.
5237  //
5238 
5239  if (irpStack->Flags & SL_OVERRIDE_VERIFY_VOLUME) {
5240 
5242  goto RetryControl;
5243 
5244  }
5245  }
5246 
5248 
5250 
5251  }
5252 
5253  //
5254  // Update IRP with completion status.
5255  //
5256 
5257  Irp->IoStatus.Status = status;
5258 
5259  //
5260  // Complete the request.
5261  //
5262 
5264  DebugPrint((2, "CdRomDeviceControl: Status is %lx\n", status));
5265  return status;
5266 
5267 } // end ScsiCdRomDeviceControl()
5268 
5269 VOID
5270 NTAPI
5273  PINQUIRYDATA InquiryData,
5274  PIO_SCSI_CAPABILITIES PortCapabilities
5275  )
5276 
5277 /*++
5278 
5279 Routine Description:
5280 
5281  This function checks to see if an SCSI logical unit requires an special
5282  initialization or error processing.
5283 
5284 Arguments:
5285 
5286  DeviceObject - Supplies the device object to be tested.
5287 
5288  InquiryData - Supplies the inquiry data returned by the device of interest.
5289 
5290  PortCapabilities - Supplies the capabilities of the device object.
5291 
5292 Return Value:
5293 
5294  None.
5295 
5296 --*/
5297 
5298 {
5299  PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
5300  PCDROM_DATA cdData = (PCDROM_DATA)(deviceExtension+1);
5301 
5302  //
5303  // Look for a Hitachi CDR-1750. Read-ahead must be disabled in order
5304  // to get this cdrom drive to work on scsi adapters that use PIO.
5305  //
5306 
5307  if ((strncmp((PCHAR)InquiryData->VendorId, "HITACHI CDR-1750S", strlen("HITACHI CDR-1750S")) == 0 ||
5308  strncmp((PCHAR)InquiryData->VendorId, "HITACHI CDR-3650/1650S", strlen("HITACHI CDR-3650/1650S")) == 0)
5309  && PortCapabilities->AdapterUsesPio) {
5310 
5311  DebugPrint((1, "CdRom ScanForSpecial: Found Hitachi CDR-1750S.\n"));
5312 
5313  //
5314  // Setup an error handler to reinitialize the cd rom after it is reset.
5315  //
5316 
5317  deviceExtension->ClassError = HitachProcessError;
5318 
5319  } else if (( RtlCompareMemory( InquiryData->VendorId,"FUJITSU", 7 ) == 7 ) &&
5320  (( RtlCompareMemory( InquiryData->ProductId,"FMCD-101", 8 ) == 8 ) ||
5321  ( RtlCompareMemory( InquiryData->ProductId,"FMCD-102", 8 ) == 8 ))) {
5322 
5323  //
5324  // When Read command is issued to FMCD-101 or FMCD-102 and there is a music
5325  // cd in it. It takes longer time than SCSI_CDROM_TIMEOUT before returning
5326  // error status.
5327  //
5328 
5329  deviceExtension->TimeOutValue = 20;
5330 
5331  } else if (( RtlCompareMemory( InquiryData->VendorId,"TOSHIBA", 7) == 7) &&
5332  (( RtlCompareMemory( InquiryData->ProductId,"CD-ROM XM-34", 12) == 12))) {
5333 
5334  SCSI_REQUEST_BLOCK srb;
5335  PCDB cdb;
5336  ULONG length;
5337  PUCHAR buffer;
5338  NTSTATUS status;
5339 
5340  //
5341  // Set the density code and the error handler.
5342  //
5343 
5345 
5346  RtlZeroMemory(&srb, sizeof(SCSI_REQUEST_BLOCK));
5347 
5348  //
5349  // Build the MODE SENSE CDB.
5350  //
5351 
5352  srb.CdbLength = 6;
5353  cdb = (PCDB)srb.Cdb;
5354 
5355  //
5356  // Set timeout value from device extension.
5357  //
5358 
5359  srb.TimeOutValue = deviceExtension->TimeOutValue;
5360 
5361  cdb->MODE_SENSE.OperationCode = SCSIOP_MODE_SENSE;
5362  cdb->MODE_SENSE.PageCode = 0x1;
5363  cdb->MODE_SENSE.AllocationLength = (UCHAR)length;
5364 
5366  if (!buffer) {
5367  return;
5368  }
5369 
5371  &srb,
5372  buffer,
5373  length,
5374  FALSE);
5375 
5376  ((PERROR_RECOVERY_DATA)buffer)->BlockDescriptor.DensityCode = 0x83;
5377  ((PERROR_RECOVERY_DATA)buffer)->Header.ModeDataLength = 0x0;
5378 
5379  RtlCopyMemory(&cdData->u1.Header, buffer, sizeof(ERROR_RECOVERY_DATA));
5380 
5381  RtlZeroMemory(&srb, sizeof(SCSI_REQUEST_BLOCK));
5382 
5383  //
5384  // Build the MODE SENSE CDB.
5385  //
5386 
5387  srb.CdbLength = 6;
5388  cdb = (PCDB)srb.Cdb;
5389 
5390  //
5391  // Set timeout value from device extension.
5392  //
5393 
5394  srb.TimeOutValue = deviceExtension->TimeOutValue;
5395 
5396  cdb->MODE_SELECT.OperationCode = SCSIOP_MODE_SELECT;
5397  cdb->MODE_SELECT.PFBit = 1;
5398  cdb->MODE_SELECT.ParameterListLength = (UCHAR)length;
5399 
5401  &srb,
5402  buffer,
5403  length,
5404  TRUE);
5405 
5406  if (!NT_SUCCESS(status)) {
5407  DebugPrint((1,
5408  "Cdrom.ScanForSpecial: Setting density code on Toshiba failed [%x]\n",
5409  status));
5410  }
5411 
5412  deviceExtension->ClassError = ToshibaProcessError;
5413 
5414  ExFreePool(buffer);
5415 
5416  }
5417 
5418  //
5419  // Determine special CD-DA requirements.
5420  //
5421 
5422  if (RtlCompareMemory( InquiryData->VendorId,"PLEXTOR",7) == 7) {
5423  cdData->XAFlags |= PLEXTOR_CDDA;
5424  } else if (RtlCompareMemory ( InquiryData->VendorId,"NEC",3) == 3) {
5425  cdData->XAFlags |= NEC_CDDA;
5426  }
5427 
5428  return;
5429 }
5430 
5431 VOID
5432 NTAPI
5436  NTSTATUS *Status,
5437  BOOLEAN *Retry
5438  )
5439 /*++
5440 
5441 Routine Description:
5442 
5443  This routine checks the type of error. If the error indicates CD-ROM the
5444  CD-ROM needs to be reinitialized then a Mode sense command is sent to the
5445  device. This command disables read-ahead for the device.
5446 
5447 Arguments:
5448 
5449  DeviceObject - Supplies a pointer to the device object.
5450 
5451  Srb - Supplies a pointer to the failing Srb.
5452 
5453  Status - Not used.
5454 
5455  Retry - Not used.
5456 
5457 Return Value:
5458 
5459  None.
5460 
5461 --*/
5462 
5463 {
5464  PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
5465  PSENSE_DATA senseBuffer = Srb->SenseInfoBuffer;
5466  LARGE_INTEGER largeInt;
5467  PUCHAR modePage;
5468  PIO_STACK_LOCATION irpStack;
5469  PIRP irp;
5470  PSCSI_REQUEST_BLOCK srb;
5472  PCDB cdb;
5473  ULONG alignment;
5474 
5477 
5478  largeInt.QuadPart = (LONGLONG) 1;
5479 
5480  //
5481  // Check the status. The initialization command only needs to be sent
5482  // if UNIT ATTENTION is returned.
5483  //
5484 
5485  if (!(Srb->SrbStatus & SRB_STATUS_AUTOSENSE_VALID)) {
5486 
5487  //
5488  // The drive does not require reinitialization.
5489  //
5490 
5491  return;
5492  }
5493 
5494  //
5495  // Found a bad HITACHI cd-rom. These devices do not work with PIO
5496  // adapters when read-ahead is enabled. Read-ahead is disabled by
5497  // a mode select command. The mode select page code is zero and the
5498  // length is 6 bytes. All of the other bytes should be zero.
5499  //
5500 
5501 
5502  if ((senseBuffer->SenseKey & 0xf) == SCSI_SENSE_UNIT_ATTENTION) {
5503 
5504  DebugPrint((1, "HitachiProcessError: Reinitializing the CD-ROM.\n"));
5505 
5506  //
5507  // Send the special mode select command to disable read-ahead
5508  // on the CD-ROM reader.
5509  //
5510 
5511  alignment = DeviceObject->AlignmentRequirement ?
5513 
5515  NonPagedPool,
5516  sizeof(COMPLETION_CONTEXT) + HITACHI_MODE_DATA_SIZE + alignment
5517  );
5518 
5519  if (context == NULL) {
5520 
5521  //
5522  // If there is not enough memory to fulfill this request,
5523  // simply return. A subsequent retry will fail and another
5524  // chance to start the unit.
5525  //
5526 
5527  return;
5528  }
5529 
5530  context->DeviceObject = DeviceObject;
5531  srb = &context->Srb;
5532 
5534 
5535  //
5536  // Write length to SRB.
5537  //
5538 
5540 
5541  //
5542  // Set up SCSI bus address.
5543  //
5544 
5545  srb->PathId = deviceExtension->PathId;
5546  srb->TargetId = deviceExtension->TargetId;
5547  srb->Lun = deviceExtension->Lun;
5548 
5550  srb->TimeOutValue = deviceExtension->TimeOutValue;
5551 
5552  //
5553  // Set the transfer length.
5554  //
5555 
5558 
5559  //
5560  // The data buffer must be aligned.
5561  //
5562 
5563  srb->DataBuffer = (PVOID) (((ULONG_PTR) (context + 1) + (alignment - 1)) &