3 * Copyright (C) 2001, 2002 ReactOS Team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 * COPYRIGHT: See COPYING in the top level directory
22 * PROJECT: ReactOS kernel
23 * FILE: services/storage/cdrom/cdrom.c
24 * PURPOSE: cdrom class driver
25 * PROGRAMMER: Eric Kohl (ekohl@rz-online.de)
30 * - Add io timer routine for autorun support.
31 * - Add cdaudio support (cd player).
34 /* INCLUDES *****************************************************************/
36 #include <ddk/ntddk.h>
38 #include <ddk/class2.h>
39 #include <ddk/ntddscsi.h>
44 #define VERSION "0.0.1"
47 #define SCSI_CDROM_TIMEOUT 10 /* Default timeout: 10 seconds */
50 typedef struct _ERROR_RECOVERY_DATA6
52 MODE_PARAMETER_HEADER Header;
53 MODE_PARAMETER_BLOCK BlockDescriptor;
54 MODE_READ_RECOVERY_PAGE ReadRecoveryPage;
55 } ERROR_RECOVERY_DATA6, *PERROR_RECOVERY_DATA6;
58 typedef struct _ERROR_RECOVERY_DATA10
60 MODE_PARAMETER_HEADER10 Header;
61 MODE_PARAMETER_BLOCK BlockDescriptor;
62 MODE_READ_RECOVERY_PAGE ReadRecoveryPage;
63 } ERROR_RECOVERY_DATA10, *PERROR_RECOVERY_DATA10;
66 typedef struct _CDROM_DATA
74 ERROR_RECOVERY_DATA6 Data6;
75 ERROR_RECOVERY_DATA10 Data10;
78 } CDROM_DATA, *PCDROM_DATA;
80 /* CDROM_DATA.XaFlags */
81 #define XA_USE_6_BYTE 0x0001
82 #define XA_USE_10_BYTE 0x0002
83 #define XA_USE_READ_CD 0x0004
84 #define XA_NOT_SUPPORTED 0x0008
88 CdromClassFindDevices(IN PDRIVER_OBJECT DriverObject,
89 IN PUNICODE_STRING RegistryPath,
90 IN PCLASS_INIT_DATA InitializationData,
91 IN PDEVICE_OBJECT PortDeviceObject,
95 CdromClassCheckDevice(IN PINQUIRYDATA InquiryData);
98 CdromClassCheckReadWrite(IN PDEVICE_OBJECT DeviceObject,
102 CdromClassCreateMediaChangeEvent(IN PDEVICE_EXTENSION DeviceExtension,
103 IN ULONG DeviceNumber);
106 CdromClassCreateDeviceObject(IN PDRIVER_OBJECT DriverObject,
107 IN PUNICODE_STRING RegistryPath,
108 IN PDEVICE_OBJECT PortDeviceObject,
110 IN ULONG DeviceNumber,
111 IN PIO_SCSI_CAPABILITIES Capabilities,
112 IN PSCSI_INQUIRY_DATA InquiryData,
113 IN PCLASS_INIT_DATA InitializationData);
117 CdromClassDeviceControl(IN PDEVICE_OBJECT DeviceObject,
121 CdromClassStartIo (IN PDEVICE_OBJECT DeviceObject,
125 CdromTimerRoutine(IN PDEVICE_OBJECT DeviceObject,
129 /* FUNCTIONS ****************************************************************/
131 /**********************************************************************
136 * This function initializes the driver, locates and claims
137 * hardware resources, and creates various NT objects needed
138 * to process I/O requests.
145 * System allocated Driver Object for this driver
147 * Name of registry driver service key
154 DriverEntry(IN PDRIVER_OBJECT DriverObject,
155 IN PUNICODE_STRING RegistryPath)
157 CLASS_INIT_DATA InitData;
159 DPRINT("CD-ROM Class Driver %s\n",
161 DPRINT("RegistryPath '%wZ'\n",
164 InitData.InitializationDataSize = sizeof(CLASS_INIT_DATA);
165 InitData.DeviceExtensionSize = sizeof(DEVICE_EXTENSION) + sizeof(CDROM_DATA);
166 InitData.DeviceType = FILE_DEVICE_CD_ROM;
167 InitData.DeviceCharacteristics = FILE_REMOVABLE_MEDIA | FILE_READ_ONLY_DEVICE;
169 InitData.ClassError = NULL;
170 InitData.ClassReadWriteVerification = CdromClassCheckReadWrite;
171 InitData.ClassFindDeviceCallBack = CdromClassCheckDevice;
172 InitData.ClassFindDevices = CdromClassFindDevices;
173 InitData.ClassDeviceControl = CdromClassDeviceControl;
174 InitData.ClassShutdownFlush = NULL;
175 InitData.ClassCreateClose = NULL;
176 InitData.ClassStartIo = CdromClassStartIo;
178 return(ScsiClassInitialize(DriverObject,
184 /**********************************************************************
186 * CdromClassFindDevices
189 * This function searches for device that are attached to the
197 * System allocated Driver Object for this driver
199 * Name of registry driver service key.
201 * Pointer to the main initialization data
203 * Scsi port device object
208 * TRUE: At least one disk drive was found
209 * FALSE: No disk drive found
213 CdromClassFindDevices(IN PDRIVER_OBJECT DriverObject,
214 IN PUNICODE_STRING RegistryPath,
215 IN PCLASS_INIT_DATA InitializationData,
216 IN PDEVICE_OBJECT PortDeviceObject,
219 PCONFIGURATION_INFORMATION ConfigInfo;
220 PIO_SCSI_CAPABILITIES PortCapabilities;
221 PSCSI_ADAPTER_BUS_INFO AdapterBusInfo;
222 PSCSI_INQUIRY_DATA UnitInfo;
223 PINQUIRYDATA InquiryData;
230 DPRINT("CdromClassFindDevices() called.\n");
232 /* Get port capabilities */
233 Status = ScsiClassGetCapabilities(PortDeviceObject,
235 if (!NT_SUCCESS(Status))
237 DPRINT1("ScsiClassGetCapabilities() failed! (Status 0x%lX)\n", Status);
241 DPRINT("PortCapabilities: %p\n", PortCapabilities);
242 DPRINT("MaximumTransferLength: %lu\n", PortCapabilities->MaximumTransferLength);
243 DPRINT("MaximumPhysicalPages: %lu\n", PortCapabilities->MaximumPhysicalPages);
245 /* Get inquiry data */
246 Status = ScsiClassGetInquiryData(PortDeviceObject,
247 (PSCSI_ADAPTER_BUS_INFO *)&Buffer);
248 if (!NT_SUCCESS(Status))
250 DPRINT1("ScsiClassGetInquiryData() failed! (Status 0x%lX)\n", Status);
254 /* Check whether there are unclaimed devices */
255 AdapterBusInfo = (PSCSI_ADAPTER_BUS_INFO)Buffer;
256 DeviceCount = ScsiClassFindUnclaimedDevices(InitializationData,
258 if (DeviceCount == 0)
260 DPRINT("No unclaimed devices!\n");
264 DPRINT("Found %lu unclaimed devices!\n", DeviceCount);
266 ConfigInfo = IoGetConfigurationInformation();
267 DPRINT("Number of SCSI ports: %lu\n", ConfigInfo->ScsiPortCount);
269 /* Search each bus of this adapter */
270 for (Bus = 0; Bus < (ULONG)AdapterBusInfo->NumberOfBuses; Bus++)
272 DPRINT("Searching bus %lu\n", Bus);
274 UnitInfo = (PSCSI_INQUIRY_DATA)(Buffer + AdapterBusInfo->BusData[Bus].InquiryDataOffset);
276 while (AdapterBusInfo->BusData[Bus].InquiryDataOffset)
278 InquiryData = (PINQUIRYDATA)UnitInfo->InquiryData;
280 if ((InquiryData->DeviceType == READ_ONLY_DIRECT_ACCESS_DEVICE) &&
281 (InquiryData->DeviceTypeQualifier == 0) &&
282 (UnitInfo->DeviceClaimed == FALSE))
284 DPRINT("Vendor: '%.24s'\n",
285 InquiryData->VendorId);
287 /* Create device objects for disk */
288 Status = CdromClassCreateDeviceObject(DriverObject,
292 ConfigInfo->CdRomCount,
296 if (NT_SUCCESS(Status))
298 ConfigInfo->CdRomCount++;
303 if (UnitInfo->NextInquiryDataOffset == 0)
306 UnitInfo = (PSCSI_INQUIRY_DATA)(Buffer + UnitInfo->NextInquiryDataOffset);
312 DPRINT("CdromClassFindDevices() done\n");
318 /**********************************************************************
320 * CdromClassCheckDevice
323 * This function checks the InquiryData for the correct device
324 * type and qualifier.
331 * Pointer to the inquiry data for the device in question.
334 * TRUE: A disk device was found.
339 CdromClassCheckDevice(IN PINQUIRYDATA InquiryData)
341 return((InquiryData->DeviceType == READ_ONLY_DIRECT_ACCESS_DEVICE) &&
342 (InquiryData->DeviceTypeQualifier == 0));
346 /**********************************************************************
348 * CdromClassCheckReadWrite
351 * This function checks the given IRP for correct data.
358 * Pointer to the device.
363 * STATUS_SUCCESS: The IRP matches the requirements of the given device.
368 CdromClassCheckReadWrite(IN PDEVICE_OBJECT DeviceObject,
371 DPRINT("CdromClassCheckReadWrite() called\n");
373 return(STATUS_SUCCESS);
378 CdromClassCreateMediaChangeEvent(IN PDEVICE_EXTENSION DeviceExtension,
379 IN ULONG DeviceNumber)
381 WCHAR NameBuffer[MAX_PATH];
384 swprintf (NameBuffer,
385 L"\\Device\\MediaChangeEvent%lu",
387 RtlInitUnicodeString (&Name,
390 DeviceExtension->MediaChangeEvent =
391 IoCreateSynchronizationEvent (&Name,
392 &DeviceExtension->MediaChangeEventHandle);
394 KeClearEvent (DeviceExtension->MediaChangeEvent);
398 /**********************************************************************
400 * CdromClassCreateDeviceObject
403 * Create the raw device and any partition devices on this drive
410 * System allocated Driver Object for this driver.
412 * Name of registry driver service key.
425 CdromClassCreateDeviceObject(IN PDRIVER_OBJECT DriverObject,
426 IN PUNICODE_STRING RegistryPath,
427 IN PDEVICE_OBJECT PortDeviceObject,
429 IN ULONG DeviceNumber,
430 IN PIO_SCSI_CAPABILITIES Capabilities,
431 IN PSCSI_INQUIRY_DATA InquiryData,
432 IN PCLASS_INIT_DATA InitializationData)
434 PDEVICE_EXTENSION DiskDeviceExtension; /* defined in class2.h */
435 OBJECT_ATTRIBUTES ObjectAttributes;
436 UNICODE_STRING UnicodeDeviceDirName;
437 PDEVICE_OBJECT DiskDeviceObject;
438 SCSI_REQUEST_BLOCK Srb;
439 PCDROM_DATA CdromData;
447 DPRINT("CdromClassCreateDeviceObject() called\n");
449 /* Claim the cdrom device */
450 Status = ScsiClassClaimDevice(PortDeviceObject,
454 if (!NT_SUCCESS(Status))
456 DbgPrint("Could not claim cdrom device\n");
460 /* Create cdrom device */
462 "\\Device\\CdRom%lu",
465 Status = ScsiClassCreateDeviceObject(DriverObject,
470 if (!NT_SUCCESS(Status))
472 DPRINT1("ScsiClassCreateDeviceObject() failed (Status %x)\n", Status);
474 /* Release (unclaim) the disk */
475 ScsiClassClaimDevice(PortDeviceObject,
483 DiskDeviceObject->Flags |= DO_DIRECT_IO;
484 DiskDeviceObject->Characteristics |= FILE_REMOVABLE_MEDIA;
485 DiskDeviceObject->StackSize = (CCHAR)PortDeviceObject->StackSize + 1;
487 if (PortDeviceObject->AlignmentRequirement > DiskDeviceObject->AlignmentRequirement)
489 DiskDeviceObject->AlignmentRequirement = PortDeviceObject->AlignmentRequirement;
492 DiskDeviceExtension = DiskDeviceObject->DeviceExtension;
493 DiskDeviceExtension->LockCount = 0;
494 DiskDeviceExtension->DeviceNumber = DeviceNumber;
495 DiskDeviceExtension->PortDeviceObject = PortDeviceObject;
496 DiskDeviceExtension->PhysicalDevice = DiskDeviceObject;
497 DiskDeviceExtension->PortCapabilities = Capabilities;
498 DiskDeviceExtension->StartingOffset.QuadPart = 0;
499 DiskDeviceExtension->PortNumber = (UCHAR)PortNumber;
500 DiskDeviceExtension->PathId = InquiryData->PathId;
501 DiskDeviceExtension->TargetId = InquiryData->TargetId;
502 DiskDeviceExtension->Lun = InquiryData->Lun;
504 /* zero-out disk data */
505 CdromData = (PCDROM_DATA)(DiskDeviceExtension + 1);
506 RtlZeroMemory(CdromData,
509 DiskDeviceExtension->SenseData = ExAllocatePool(NonPagedPool,
511 if (DiskDeviceExtension->SenseData == NULL)
513 DPRINT1("Failed to allocate sense data buffer!\n");
515 IoDeleteDevice(DiskDeviceObject);
517 /* Release (unclaim) the disk */
518 ScsiClassClaimDevice(PortDeviceObject,
523 return(STATUS_INSUFFICIENT_RESOURCES);
526 /* Get timeout value */
527 DiskDeviceExtension->TimeOutValue =
528 ScsiClassQueryTimeOutRegistryValue(RegistryPath);
529 if (DiskDeviceExtension->TimeOutValue == 0)
530 DiskDeviceExtension->TimeOutValue = SCSI_CDROM_TIMEOUT;
532 /* Initialize lookaside list for SRBs */
533 ScsiClassInitializeSrbLookasideList(DiskDeviceExtension,
536 /* Get disk geometry */
537 DiskDeviceExtension->DiskGeometry = ExAllocatePool(NonPagedPool,
538 sizeof(DISK_GEOMETRY));
539 if (DiskDeviceExtension->DiskGeometry == NULL)
541 DPRINT1("Failed to allocate geometry buffer!\n");
543 ExDeleteNPagedLookasideList(&DiskDeviceExtension->SrbLookasideListHead);
545 IoDeleteDevice(DiskDeviceObject);
547 /* Release (unclaim) the disk */
548 ScsiClassClaimDevice(PortDeviceObject,
553 return(STATUS_INSUFFICIENT_RESOURCES);
556 /* Read the drive's capacity */
557 Status = ScsiClassReadDriveCapacity(DiskDeviceObject);
558 if (!NT_SUCCESS(Status) ||
559 DiskDeviceExtension->DiskGeometry->BytesPerSector == 0)
561 /* Set ISO9660 defaults */
562 DiskDeviceExtension->DiskGeometry->BytesPerSector = 2048;
563 DiskDeviceExtension->DiskGeometry->MediaType = RemovableMedia;
564 DiskDeviceExtension->SectorShift = 11;
565 DiskDeviceExtension->PartitionLength.QuadPart = (ULONGLONG)0x7fffffff;
569 /* Make sure the BytesPerSector value is a power of 2 */
570 // DiskDeviceExtension->DiskGeometry->BytesPerSector = 2048;
573 DPRINT("SectorSize: %lu\n", DiskDeviceExtension->DiskGeometry->BytesPerSector);
575 /* Initialize media change support */
576 CdromClassCreateMediaChangeEvent (DiskDeviceExtension,
578 if (DiskDeviceExtension->MediaChangeEvent != NULL)
580 DPRINT("Allocated media change event!\n");
582 /* FIXME: Allocate media change IRP and SRB */
585 /* Use 6 byte xa commands by default */
586 CdromData->XaFlags |= XA_USE_6_BYTE;
588 /* Read 'error recovery page' to get additional drive capabilities */
589 Length = sizeof(MODE_READ_RECOVERY_PAGE) +
590 MODE_BLOCK_DESC_LENGTH +
594 sizeof(SCSI_REQUEST_BLOCK));
596 Srb.TimeOutValue = DiskDeviceExtension->TimeOutValue;
599 Cdb->MODE_SENSE.OperationCode = SCSIOP_MODE_SENSE;
600 Cdb->MODE_SENSE.PageCode = 0x01;
601 Cdb->MODE_SENSE.AllocationLength = (UCHAR)Length;
603 Buffer = ExAllocatePool (NonPagedPool,
604 sizeof(MODE_READ_RECOVERY_PAGE) +
605 MODE_BLOCK_DESC_LENGTH + MODE_HEADER_LENGTH10);
608 DPRINT1("Allocating recovery page buffer failed!\n");
609 return STATUS_INSUFFICIENT_RESOURCES;
612 Status = ScsiClassSendSrbSynchronous (DiskDeviceObject,
617 if (!NT_SUCCESS (Status))
619 DPRINT("MODE_SENSE(6) failed\n");
621 /* Try the 10 byte version */
622 Length = sizeof(MODE_READ_RECOVERY_PAGE) +
623 MODE_BLOCK_DESC_LENGTH +
624 MODE_HEADER_LENGTH10;
627 sizeof(SCSI_REQUEST_BLOCK));
629 Srb.TimeOutValue = DiskDeviceExtension->TimeOutValue;
632 Cdb->MODE_SENSE10.OperationCode = SCSIOP_MODE_SENSE10;
633 Cdb->MODE_SENSE10.PageCode = 0x01;
634 Cdb->MODE_SENSE10.AllocationLength[0] = (UCHAR)(Length >> 8);
635 Cdb->MODE_SENSE10.AllocationLength[1] = (UCHAR)(Length && 0xFF);
637 Status = ScsiClassSendSrbSynchronous (DiskDeviceObject,
642 if (Status == STATUS_DATA_OVERRUN)
644 DPRINT1("Data overrun\n");
648 else if (NT_SUCCESS (Status))
650 DPRINT("Use 10 byte commands\n");
651 RtlCopyMemory (&CdromData->RecoveryData.Data10.Header,
653 sizeof (ERROR_RECOVERY_DATA10));
654 CdromData->RecoveryData.Data10.Header.ModeDataLength[0] = 0;
655 CdromData->RecoveryData.Data10.Header.ModeDataLength[1] = 0;
657 CdromData->XaFlags &= XA_USE_6_BYTE;
658 CdromData->XaFlags |= XA_USE_10_BYTE;
662 DPRINT("XA not supported\n");
663 CdromData->XaFlags |= XA_NOT_SUPPORTED;
668 DPRINT("Use 6 byte commands\n");
669 RtlCopyMemory (&CdromData->RecoveryData.Data6.Header,
671 sizeof (ERROR_RECOVERY_DATA6));
672 CdromData->RecoveryData.Data6.Header.ModeDataLength = 0;
676 /* Initialize device timer */
677 IoInitializeTimer(DiskDeviceObject,
680 IoStartTimer(DiskDeviceObject);
682 DPRINT("CdromClassCreateDeviceObjects() done\n");
684 return(STATUS_SUCCESS);
688 /**********************************************************************
690 * CdromClassReadTocEntry
703 CdromClassReadTocEntry (PDEVICE_OBJECT DeviceObject,
708 PDEVICE_EXTENSION DeviceExtension;
709 SCSI_REQUEST_BLOCK Srb;
712 DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
714 RtlZeroMemory(&Srb, sizeof(SCSI_REQUEST_BLOCK));
716 Srb.TimeOutValue = DeviceExtension->TimeOutValue;
719 Cdb->READ_TOC.OperationCode = SCSIOP_READ_TOC;
720 Cdb->READ_TOC.StartingTrack = TrackNo;
721 Cdb->READ_TOC.Format = 0;
722 Cdb->READ_TOC.AllocationLength[0] = Length >> 8;
723 Cdb->READ_TOC.AllocationLength[1] = Length & 0xff;
724 Cdb->READ_TOC.Msf = 1;
726 return(ScsiClassSendSrbSynchronous(DeviceObject,
735 CdromClassReadLastSession (PDEVICE_OBJECT DeviceObject,
740 PDEVICE_EXTENSION DeviceExtension;
741 SCSI_REQUEST_BLOCK Srb;
744 DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
746 RtlZeroMemory(&Srb, sizeof(SCSI_REQUEST_BLOCK));
748 Srb.TimeOutValue = DeviceExtension->TimeOutValue;
751 Cdb->READ_TOC.OperationCode = SCSIOP_READ_TOC;
752 Cdb->READ_TOC.StartingTrack = TrackNo;
753 Cdb->READ_TOC.Format = 1;
754 Cdb->READ_TOC.AllocationLength[0] = Length >> 8;
755 Cdb->READ_TOC.AllocationLength[1] = Length & 0xff;
756 Cdb->READ_TOC.Msf = 0;
758 return(ScsiClassSendSrbSynchronous(DeviceObject,
766 /**********************************************************************
768 * CdromClassDeviceControl
771 * Answer requests for device control calls
779 * Standard dispatch arguments
786 CdromClassDeviceControl(IN PDEVICE_OBJECT DeviceObject,
789 PDEVICE_EXTENSION DeviceExtension;
790 PIO_STACK_LOCATION IrpStack;
791 ULONG ControlCode, InputLength, OutputLength;
792 PCDROM_DATA CdromData;
796 DPRINT("CdromClassDeviceControl() called!\n");
798 Status = STATUS_INVALID_DEVICE_REQUEST;
800 IrpStack = IoGetCurrentIrpStackLocation(Irp);
801 ControlCode = IrpStack->Parameters.DeviceIoControl.IoControlCode;
802 InputLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength;
803 OutputLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength;
804 DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
805 CdromData = (PCDROM_DATA)(DeviceExtension + 1);
809 case IOCTL_CDROM_GET_DRIVE_GEOMETRY:
810 DPRINT("IOCTL_CDROM_GET_DRIVE_GEOMETRY\n");
811 if (IrpStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(DISK_GEOMETRY))
813 Status = STATUS_INVALID_PARAMETER;
817 PDISK_GEOMETRY Geometry;
819 if (DeviceExtension->DiskGeometry == NULL)
821 DPRINT("No cdrom geometry available!\n");
822 DeviceExtension->DiskGeometry = ExAllocatePool(NonPagedPool,
823 sizeof(DISK_GEOMETRY));
825 Status = ScsiClassReadDriveCapacity(DeviceObject);
826 if (NT_SUCCESS(Status))
828 Geometry = (PDISK_GEOMETRY)Irp->AssociatedIrp.SystemBuffer;
829 RtlMoveMemory(Geometry,
830 DeviceExtension->DiskGeometry,
831 sizeof(DISK_GEOMETRY));
833 Status = STATUS_SUCCESS;
834 Information = sizeof(DISK_GEOMETRY);
839 case IOCTL_CDROM_READ_TOC:
840 DPRINT("IOCTL_CDROM_READ_TOC\n");
841 if (IrpStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(CDROM_TOC))
843 Status = STATUS_INFO_LENGTH_MISMATCH;
847 PCDROM_TOC TocBuffer;
850 TocBuffer = Irp->AssociatedIrp.SystemBuffer;
852 /* First read the lead out */
853 Length = 4 + sizeof(TRACK_DATA);
854 Status = CdromClassReadTocEntry(DeviceObject,
858 if (NT_SUCCESS(Status))
860 if (TocBuffer->FirstTrack == 0xaa)
862 /* there is an empty cd */
863 Information = Length;
868 Length = 4 + sizeof(TRACK_DATA) * (TocBuffer->LastTrack - TocBuffer->FirstTrack + 2);
869 Status = CdromClassReadTocEntry(DeviceObject,
870 TocBuffer->FirstTrack,
872 if (NT_SUCCESS(Status))
874 Information = Length;
881 case IOCTL_CDROM_GET_LAST_SESSION:
882 DPRINT("IOCTL_CDROM_GET_LAST_SESSION\n");
883 if (IrpStack->Parameters.DeviceIoControl.OutputBufferLength < 4 + sizeof(TRACK_DATA))
885 Status = STATUS_INFO_LENGTH_MISMATCH;
889 PCDROM_TOC TocBuffer;
892 TocBuffer = Irp->AssociatedIrp.SystemBuffer;
893 Length = 4 + sizeof(TRACK_DATA);
894 Status = CdromClassReadLastSession(DeviceObject,
898 if (NT_SUCCESS(Status))
900 Information = Length;
906 /* Call the common device control function */
907 return(ScsiClassDeviceControl(DeviceObject, Irp));
910 /* Verify the device if the user caused the error */
911 if (!NT_SUCCESS(Status) && IoIsErrorUserInduced(Status))
913 IoSetHardErrorOrVerifyDevice(Irp, DeviceObject);
916 Irp->IoStatus.Status = Status;
917 Irp->IoStatus.Information = Information;
918 IoCompleteRequest(Irp,
921 return(STATUS_SUCCESS);
925 /**********************************************************************
930 * Starts IRP processing.
938 * Standard dispatch arguments
944 CdromClassStartIo (IN PDEVICE_OBJECT DeviceObject,
947 PDEVICE_EXTENSION DeviceExtension;
948 PIO_STACK_LOCATION IrpStack;
949 ULONG MaximumTransferLength;
952 DPRINT("CdromClassStartIo() called!\n");
954 DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
955 IrpStack = IoGetCurrentIrpStackLocation (Irp);
957 MaximumTransferLength = DeviceExtension->PortCapabilities->MaximumTransferLength;
959 if (IrpStack->MajorFunction == IRP_MJ_READ)
961 DPRINT(" IRP_MJ_READ\n");
964 ADDRESS_AND_SIZE_TO_SPAN_PAGES (MmGetMdlVirtualAddress(Irp->MdlAddress),
965 IrpStack->Parameters.Read.Length);
967 /* Check transfer size */
968 if ((IrpStack->Parameters.Read.Length > MaximumTransferLength) ||
969 (TransferPages > DeviceExtension->PortCapabilities->MaximumPhysicalPages))
971 /* Transfer size is too large - split it */
973 DeviceExtension->PortCapabilities->MaximumPhysicalPages - 1;
975 /* Adjust transfer size */
976 if (MaximumTransferLength > TransferPages * PAGE_SIZE)
977 MaximumTransferLength = TransferPages * PAGE_SIZE;
979 if (MaximumTransferLength == 0)
980 MaximumTransferLength = PAGE_SIZE;
982 /* Split the transfer */
983 ScsiClassSplitRequest (DeviceObject,
985 MaximumTransferLength);
991 ScsiClassBuildRequest (DeviceObject,
995 else if (IrpStack->MajorFunction == IRP_MJ_DEVICE_CONTROL)
997 DPRINT1(" IRP_MJ_IRP_MJ_DEVICE_CONTROL\n");
1001 switch (IrpStack->Parameters.DeviceIoControl.IoControlCode)
1005 IoCompleteRequest (Irp,
1012 /* Call the SCSI port driver */
1013 IoCallDriver (DeviceExtension->PortDeviceObject,
1019 CdromTimerRoutine(PDEVICE_OBJECT DeviceObject,
1022 DPRINT("CdromTimerRoutine() called\n");