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>
40 #include <ntos/minmax.h>
45 #define VERSION "0.0.1"
48 #define SCSI_CDROM_TIMEOUT 10 /* Default timeout: 10 seconds */
51 typedef struct _ERROR_RECOVERY_DATA6
53 MODE_PARAMETER_HEADER Header
;
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_READ_RECOVERY_PAGE ReadRecoveryPage
;
62 } ERROR_RECOVERY_DATA10
, *PERROR_RECOVERY_DATA10
;
64 typedef struct _MODE_CAPABILITIES_DATA6
66 MODE_PARAMETER_HEADER Header
;
67 MODE_CAPABILITIES_PAGE2 CababilitiesPage
;
68 } MODE_CAPABILITIES_DATA6
, *PMODE_CAPABILITIES_DATA6
;
70 typedef struct _MODE_CAPABILITIES_DATA10
72 MODE_PARAMETER_HEADER10 Header
;
73 MODE_CAPABILITIES_PAGE2 CababilitiesPage
;
74 } MODE_CAPABILITIES_DATA10
, *PMODE_CAPABILITIES_DATA10
;
76 typedef struct _CDROM_DATA
82 } CDROM_DATA
, *PCDROM_DATA
;
84 /* CDROM_DATA.XaFlags */
85 #define XA_USE_6_BYTE 0x0001
86 #define XA_USE_10_BYTE 0x0002
87 #define XA_USE_READ_CD 0x0004
88 #define XA_NOT_SUPPORTED 0x0008
92 CdromClassFindDevices(IN PDRIVER_OBJECT DriverObject
,
93 IN PUNICODE_STRING RegistryPath
,
94 IN PCLASS_INIT_DATA InitializationData
,
95 IN PDEVICE_OBJECT PortDeviceObject
,
99 CdromClassCheckDevice(IN PINQUIRYDATA InquiryData
);
102 CdromClassCheckReadWrite(IN PDEVICE_OBJECT DeviceObject
,
106 CdromClassCreateMediaChangeEvent(IN PDEVICE_EXTENSION DeviceExtension
,
107 IN ULONG DeviceNumber
);
110 CdromClassCreateDeviceObject(IN PDRIVER_OBJECT DriverObject
,
111 IN PUNICODE_STRING RegistryPath
,
112 IN PDEVICE_OBJECT PortDeviceObject
,
114 IN ULONG DeviceNumber
,
115 IN PIO_SCSI_CAPABILITIES Capabilities
,
116 IN PSCSI_INQUIRY_DATA InquiryData
,
117 IN PCLASS_INIT_DATA InitializationData
);
121 CdromClassDeviceControl(IN PDEVICE_OBJECT DeviceObject
,
125 CdromClassStartIo (IN PDEVICE_OBJECT DeviceObject
,
129 CdromDeviceControlCompletion (IN PDEVICE_OBJECT DeviceObject
,
134 CdromTimerRoutine(IN PDEVICE_OBJECT DeviceObject
,
138 CdromWorkItem(IN PDEVICE_OBJECT DeviceObject
,
142 /* FUNCTIONS ****************************************************************/
144 /**********************************************************************
149 * This function initializes the driver, locates and claims
150 * hardware resources, and creates various NT objects needed
151 * to process I/O requests.
158 * System allocated Driver Object for this driver
160 * Name of registry driver service key
167 DriverEntry(IN PDRIVER_OBJECT DriverObject
,
168 IN PUNICODE_STRING RegistryPath
)
170 CLASS_INIT_DATA InitData
;
172 DPRINT("CD-ROM Class Driver %s\n",
174 DPRINT("RegistryPath '%wZ'\n",
177 InitData
.InitializationDataSize
= sizeof(CLASS_INIT_DATA
);
178 InitData
.DeviceExtensionSize
= sizeof(DEVICE_EXTENSION
) + sizeof(CDROM_DATA
);
179 InitData
.DeviceType
= FILE_DEVICE_CD_ROM
;
180 InitData
.DeviceCharacteristics
= FILE_REMOVABLE_MEDIA
| FILE_READ_ONLY_DEVICE
;
182 InitData
.ClassError
= NULL
;
183 InitData
.ClassReadWriteVerification
= CdromClassCheckReadWrite
;
184 InitData
.ClassFindDeviceCallBack
= CdromClassCheckDevice
;
185 InitData
.ClassFindDevices
= CdromClassFindDevices
;
186 InitData
.ClassDeviceControl
= CdromClassDeviceControl
;
187 InitData
.ClassShutdownFlush
= NULL
;
188 InitData
.ClassCreateClose
= NULL
;
189 InitData
.ClassStartIo
= CdromClassStartIo
;
191 return(ScsiClassInitialize(DriverObject
,
197 /**********************************************************************
199 * CdromClassFindDevices
202 * This function searches for device that are attached to the
210 * System allocated Driver Object for this driver
212 * Name of registry driver service key.
214 * Pointer to the main initialization data
216 * Scsi port device object
221 * TRUE: At least one disk drive was found
222 * FALSE: No disk drive found
226 CdromClassFindDevices(IN PDRIVER_OBJECT DriverObject
,
227 IN PUNICODE_STRING RegistryPath
,
228 IN PCLASS_INIT_DATA InitializationData
,
229 IN PDEVICE_OBJECT PortDeviceObject
,
232 PCONFIGURATION_INFORMATION ConfigInfo
;
233 PIO_SCSI_CAPABILITIES PortCapabilities
;
234 PSCSI_ADAPTER_BUS_INFO AdapterBusInfo
;
235 PSCSI_INQUIRY_DATA UnitInfo
;
236 PINQUIRYDATA InquiryData
;
240 BOOLEAN FoundDevice
= FALSE
;
243 DPRINT("CdromClassFindDevices() called.\n");
245 /* Get port capabilities */
246 Status
= ScsiClassGetCapabilities(PortDeviceObject
,
248 if (!NT_SUCCESS(Status
))
250 DPRINT1("ScsiClassGetCapabilities() failed! (Status 0x%lX)\n", Status
);
254 DPRINT("PortCapabilities: %p\n", PortCapabilities
);
255 DPRINT("MaximumTransferLength: %lu\n", PortCapabilities
->MaximumTransferLength
);
256 DPRINT("MaximumPhysicalPages: %lu\n", PortCapabilities
->MaximumPhysicalPages
);
258 /* Get inquiry data */
259 Status
= ScsiClassGetInquiryData(PortDeviceObject
,
260 (PSCSI_ADAPTER_BUS_INFO
*)&Buffer
);
261 if (!NT_SUCCESS(Status
))
263 DPRINT1("ScsiClassGetInquiryData() failed! (Status 0x%lX)\n", Status
);
267 /* Check whether there are unclaimed devices */
268 AdapterBusInfo
= (PSCSI_ADAPTER_BUS_INFO
)Buffer
;
269 DeviceCount
= ScsiClassFindUnclaimedDevices(InitializationData
,
271 if (DeviceCount
== 0)
273 DPRINT("No unclaimed devices!\n");
277 DPRINT("Found %lu unclaimed devices!\n", DeviceCount
);
279 ConfigInfo
= IoGetConfigurationInformation();
280 DPRINT("Number of SCSI ports: %lu\n", ConfigInfo
->ScsiPortCount
);
282 /* Search each bus of this adapter */
283 for (Bus
= 0; Bus
< (ULONG
)AdapterBusInfo
->NumberOfBuses
; Bus
++)
285 DPRINT("Searching bus %lu\n", Bus
);
287 UnitInfo
= (PSCSI_INQUIRY_DATA
)(Buffer
+ AdapterBusInfo
->BusData
[Bus
].InquiryDataOffset
);
289 while (AdapterBusInfo
->BusData
[Bus
].InquiryDataOffset
)
291 InquiryData
= (PINQUIRYDATA
)UnitInfo
->InquiryData
;
293 if ((InquiryData
->DeviceType
== READ_ONLY_DIRECT_ACCESS_DEVICE
) &&
294 (InquiryData
->DeviceTypeQualifier
== 0) &&
295 (UnitInfo
->DeviceClaimed
== FALSE
))
297 DPRINT("Vendor: '%.24s'\n",
298 InquiryData
->VendorId
);
300 /* Create device objects for disk */
301 Status
= CdromClassCreateDeviceObject(DriverObject
,
305 ConfigInfo
->CdRomCount
,
309 if (NT_SUCCESS(Status
))
311 ConfigInfo
->CdRomCount
++;
316 if (UnitInfo
->NextInquiryDataOffset
== 0)
319 UnitInfo
= (PSCSI_INQUIRY_DATA
)(Buffer
+ UnitInfo
->NextInquiryDataOffset
);
325 DPRINT("CdromClassFindDevices() done\n");
331 /**********************************************************************
333 * CdromClassCheckDevice
336 * This function checks the InquiryData for the correct device
337 * type and qualifier.
344 * Pointer to the inquiry data for the device in question.
347 * TRUE: A disk device was found.
352 CdromClassCheckDevice(IN PINQUIRYDATA InquiryData
)
354 return((InquiryData
->DeviceType
== READ_ONLY_DIRECT_ACCESS_DEVICE
) &&
355 (InquiryData
->DeviceTypeQualifier
== 0));
359 /**********************************************************************
361 * CdromClassCheckReadWrite
364 * This function checks the given IRP for correct data.
371 * Pointer to the device.
376 * STATUS_SUCCESS: The IRP matches the requirements of the given device.
381 CdromClassCheckReadWrite(IN PDEVICE_OBJECT DeviceObject
,
384 DPRINT("CdromClassCheckReadWrite() called\n");
386 return(STATUS_SUCCESS
);
391 CdromClassCreateMediaChangeEvent(IN PDEVICE_EXTENSION DeviceExtension
,
392 IN ULONG DeviceNumber
)
394 WCHAR NameBuffer
[MAX_PATH
];
397 swprintf (NameBuffer
,
398 L
"\\Device\\MediaChangeEvent%lu",
400 RtlInitUnicodeString (&Name
,
403 DeviceExtension
->MediaChangeEvent
=
404 IoCreateSynchronizationEvent (&Name
,
405 &DeviceExtension
->MediaChangeEventHandle
);
407 KeClearEvent (DeviceExtension
->MediaChangeEvent
);
411 /**********************************************************************
413 * CdromClassCreateDeviceObject
416 * Create the raw device and any partition devices on this drive
423 * System allocated Driver Object for this driver.
425 * Name of registry driver service key.
438 CdromClassCreateDeviceObject(IN PDRIVER_OBJECT DriverObject
,
439 IN PUNICODE_STRING RegistryPath
,
440 IN PDEVICE_OBJECT PortDeviceObject
,
442 IN ULONG DeviceNumber
,
443 IN PIO_SCSI_CAPABILITIES Capabilities
,
444 IN PSCSI_INQUIRY_DATA InquiryData
,
445 IN PCLASS_INIT_DATA InitializationData
)
447 PDEVICE_EXTENSION DiskDeviceExtension
; /* defined in class2.h */
448 PDEVICE_OBJECT DiskDeviceObject
;
449 PCDROM_DATA CdromData
;
451 SCSI_REQUEST_BLOCK Srb
;
457 DPRINT("CdromClassCreateDeviceObject() called\n");
459 /* Claim the cdrom device */
460 Status
= ScsiClassClaimDevice(PortDeviceObject
,
464 if (!NT_SUCCESS(Status
))
466 DbgPrint("Could not claim cdrom device\n");
470 /* Create cdrom device */
472 "\\Device\\CdRom%lu",
475 Status
= ScsiClassCreateDeviceObject(DriverObject
,
480 if (!NT_SUCCESS(Status
))
482 DPRINT1("ScsiClassCreateDeviceObject() failed (Status %x)\n", Status
);
484 /* Release (unclaim) the disk */
485 ScsiClassClaimDevice(PortDeviceObject
,
493 DiskDeviceObject
->Flags
|= DO_DIRECT_IO
;
494 DiskDeviceObject
->Characteristics
|= FILE_REMOVABLE_MEDIA
;
495 DiskDeviceObject
->StackSize
= (CCHAR
)PortDeviceObject
->StackSize
+ 1;
497 if (PortDeviceObject
->AlignmentRequirement
> DiskDeviceObject
->AlignmentRequirement
)
499 DiskDeviceObject
->AlignmentRequirement
= PortDeviceObject
->AlignmentRequirement
;
502 DiskDeviceExtension
= DiskDeviceObject
->DeviceExtension
;
503 DiskDeviceExtension
->LockCount
= 0;
504 DiskDeviceExtension
->DeviceNumber
= DeviceNumber
;
505 DiskDeviceExtension
->DeviceObject
= DiskDeviceObject
;
506 DiskDeviceExtension
->PortDeviceObject
= PortDeviceObject
;
507 DiskDeviceExtension
->PhysicalDevice
= DiskDeviceObject
;
508 DiskDeviceExtension
->PortCapabilities
= Capabilities
;
509 DiskDeviceExtension
->StartingOffset
.QuadPart
= 0;
510 DiskDeviceExtension
->PortNumber
= (UCHAR
)PortNumber
;
511 DiskDeviceExtension
->PathId
= InquiryData
->PathId
;
512 DiskDeviceExtension
->TargetId
= InquiryData
->TargetId
;
513 DiskDeviceExtension
->Lun
= InquiryData
->Lun
;
515 /* zero-out disk data */
516 CdromData
= (PCDROM_DATA
)(DiskDeviceExtension
+ 1);
517 RtlZeroMemory(CdromData
,
520 DiskDeviceExtension
->SenseData
= ExAllocatePool(NonPagedPool
,
522 if (DiskDeviceExtension
->SenseData
== NULL
)
524 DPRINT1("Failed to allocate sense data buffer!\n");
526 IoDeleteDevice(DiskDeviceObject
);
528 /* Release (unclaim) the disk */
529 ScsiClassClaimDevice(PortDeviceObject
,
534 return(STATUS_INSUFFICIENT_RESOURCES
);
537 /* Get timeout value */
538 DiskDeviceExtension
->TimeOutValue
=
539 ScsiClassQueryTimeOutRegistryValue(RegistryPath
);
540 if (DiskDeviceExtension
->TimeOutValue
== 0)
541 DiskDeviceExtension
->TimeOutValue
= SCSI_CDROM_TIMEOUT
;
543 /* Initialize lookaside list for SRBs */
544 ScsiClassInitializeSrbLookasideList(DiskDeviceExtension
,
547 /* Get disk geometry */
548 DiskDeviceExtension
->DiskGeometry
= ExAllocatePool(NonPagedPool
,
549 sizeof(DISK_GEOMETRY
));
550 if (DiskDeviceExtension
->DiskGeometry
== NULL
)
552 DPRINT1("Failed to allocate geometry buffer!\n");
554 ExDeleteNPagedLookasideList(&DiskDeviceExtension
->SrbLookasideListHead
);
556 IoDeleteDevice(DiskDeviceObject
);
558 /* Release (unclaim) the disk */
559 ScsiClassClaimDevice(PortDeviceObject
,
564 return(STATUS_INSUFFICIENT_RESOURCES
);
567 /* Read the drive's capacity */
568 Status
= ScsiClassReadDriveCapacity(DiskDeviceObject
);
569 if (!NT_SUCCESS(Status
) ||
570 DiskDeviceExtension
->DiskGeometry
->BytesPerSector
== 0)
572 /* Set ISO9660 defaults */
573 DiskDeviceExtension
->DiskGeometry
->BytesPerSector
= 2048;
574 DiskDeviceExtension
->DiskGeometry
->MediaType
= RemovableMedia
;
575 DiskDeviceExtension
->SectorShift
= 11;
576 DiskDeviceExtension
->PartitionLength
.QuadPart
= (ULONGLONG
)0x7fffffff;
580 /* Make sure the BytesPerSector value is a power of 2 */
581 // DiskDeviceExtension->DiskGeometry->BytesPerSector = 2048;
584 DPRINT("SectorSize: %lu\n", DiskDeviceExtension
->DiskGeometry
->BytesPerSector
);
586 /* Initialize media change support */
587 CdromClassCreateMediaChangeEvent (DiskDeviceExtension
,
589 if (DiskDeviceExtension
->MediaChangeEvent
!= NULL
)
591 DPRINT("Allocated media change event!\n");
593 /* FIXME: Allocate media change IRP and SRB */
596 /* Use 6 byte xa commands by default */
597 CdromData
->XaFlags
|= XA_USE_6_BYTE
;
599 /* Read 'error recovery page' to get additional drive capabilities */
600 Length
= sizeof(MODE_READ_RECOVERY_PAGE
) + MODE_HEADER_LENGTH
;
603 sizeof(SCSI_REQUEST_BLOCK
));
605 Srb
.TimeOutValue
= DiskDeviceExtension
->TimeOutValue
;
608 Cdb
->MODE_SENSE
.OperationCode
= SCSIOP_MODE_SENSE
;
609 Cdb
->MODE_SENSE
.PageCode
= 0x01;
610 Cdb
->MODE_SENSE
.AllocationLength
= (UCHAR
)Length
;
612 Buffer
= ExAllocatePool (NonPagedPool
,
613 max(sizeof(ERROR_RECOVERY_DATA6
),
614 max(sizeof(ERROR_RECOVERY_DATA10
),
615 max(sizeof(MODE_CAPABILITIES_DATA6
),
616 sizeof(MODE_CAPABILITIES_DATA10
)))));
619 DPRINT1("Allocating recovery page buffer failed!\n");
620 return STATUS_INSUFFICIENT_RESOURCES
;
623 Status
= ScsiClassSendSrbSynchronous (DiskDeviceObject
,
629 if (!NT_SUCCESS (Status
))
631 DPRINT("MODE_SENSE(6) failed\n");
633 /* Try the 10 byte version */
634 Length
= sizeof(MODE_READ_RECOVERY_PAGE
) + MODE_HEADER_LENGTH10
;
637 sizeof(SCSI_REQUEST_BLOCK
));
639 Srb
.TimeOutValue
= DiskDeviceExtension
->TimeOutValue
;
642 Cdb
->MODE_SENSE10
.OperationCode
= SCSIOP_MODE_SENSE10
;
643 Cdb
->MODE_SENSE10
.PageCode
= 0x01;
644 Cdb
->MODE_SENSE10
.AllocationLength
[0] = (UCHAR
)(Length
>> 8);
645 Cdb
->MODE_SENSE10
.AllocationLength
[1] = (UCHAR
)(Length
& 0xFF);
647 Status
= ScsiClassSendSrbSynchronous (DiskDeviceObject
,
653 if (Status
== STATUS_DATA_OVERRUN
)
655 DPRINT1("Data overrun\n");
659 else if (NT_SUCCESS (Status
))
661 DPRINT("Use 10 byte commands\n");
662 CdromData
->XaFlags
&= XA_USE_6_BYTE
;
663 CdromData
->XaFlags
|= XA_USE_10_BYTE
;
667 DPRINT("XA not supported\n");
668 CdromData
->XaFlags
|= XA_NOT_SUPPORTED
;
673 DPRINT("Use 6 byte commands\n");
676 /* Read 'capabilities & mechanical status page' to get additional drive capabilities */
677 Length
= sizeof(MODE_READ_RECOVERY_PAGE
) + MODE_HEADER_LENGTH
;
679 if (!(CdromData
->XaFlags
& XA_NOT_SUPPORTED
))
681 RtlZeroMemory (&Srb
, sizeof(SCSI_REQUEST_BLOCK
));
682 Srb
.TimeOutValue
= DiskDeviceExtension
->TimeOutValue
;
685 if (CdromData
->XaFlags
& XA_USE_10_BYTE
)
687 /* Try the 10 byte version */
688 Length
= sizeof(MODE_CAPABILITIES_PAGE2
) + MODE_HEADER_LENGTH10
;
691 Cdb
->MODE_SENSE10
.OperationCode
= SCSIOP_MODE_SENSE10
;
692 Cdb
->MODE_SENSE10
.PageCode
= 0x2a;
693 Cdb
->MODE_SENSE10
.AllocationLength
[0] = (UCHAR
)(Length
>> 8);
694 Cdb
->MODE_SENSE10
.AllocationLength
[1] = (UCHAR
)(Length
& 0xFF);
698 Length
= sizeof(MODE_CAPABILITIES_PAGE2
) + MODE_HEADER_LENGTH
;
701 Cdb
->MODE_SENSE
.OperationCode
= SCSIOP_MODE_SENSE
;
702 Cdb
->MODE_SENSE
.PageCode
= 0x2a;
703 Cdb
->MODE_SENSE
.AllocationLength
= (UCHAR
)Length
;
705 Status
= ScsiClassSendSrbSynchronous (DiskDeviceObject
,
710 if (NT_SUCCESS (Status
))
713 PMODE_CAPABILITIES_PAGE2 CapabilitiesData
;
714 if (CdromData
->XaFlags
& XA_USE_10_BYTE
)
716 CapabilitiesData
= (PMODE_CAPABILITIES_PAGE2
)(Buffer
+ sizeof(MODE_PARAMETER_HEADER10
));
720 CapabilitiesData
= (PMODE_CAPABILITIES_PAGE2
)(Buffer
+ sizeof(MODE_PARAMETER_HEADER
));
723 DbgPrint("Capabilities for '%s':\n", NameBuffer
);
724 if (CapabilitiesData
->Reserved2
[0] & 0x20)
726 DbgPrint(" Drive supports reading of DVD-RAM discs\n");
728 if (CapabilitiesData
->Reserved2
[0] & 0x10)
730 DbgPrint(" Drive supports reading of DVD-R discs\n");
732 if (CapabilitiesData
->Reserved2
[0] & 0x08)
734 DbgPrint(" Drive supports reading of DVD-ROM discs\n");
736 if (CapabilitiesData
->Reserved2
[0] & 0x04)
738 DbgPrint(" Drive supports reading CD-R discs with addressing method 2\n");
740 if (CapabilitiesData
->Reserved2
[0] & 0x02)
742 DbgPrint(" Drive can read from CD-R/W (CD-E) discs (orange book, part III)\n");
744 if (CapabilitiesData
->Reserved2
[0] & 0x01)
746 DbgPrint(" Drive supports read from CD-R discs (orange book, part II)\n");
748 DPRINT("CapabilitiesData.Reserved2[1] %x\n", CapabilitiesData
->Reserved2
[1]);
749 if (CapabilitiesData
->Reserved2
[1] & 0x01)
751 DbgPrint(" Drive can write to CD-R discs (orange book, part II)\n");
753 if (CapabilitiesData
->Reserved2
[1] & 0x02)
755 DbgPrint(" Drive can write to CD-R/W (CD-E) discs (orange book, part III)\n");
757 if (CapabilitiesData
->Reserved2
[1] & 0x04)
759 DbgPrint(" Drive can fake writes\n");
761 if (CapabilitiesData
->Reserved2
[1] & 0x10)
763 DbgPrint(" Drive can write DVD-R discs\n");
765 if (CapabilitiesData
->Reserved2
[1] & 0x20)
767 DbgPrint(" Drive can write DVD-RAM discs\n");
769 DPRINT("CapabilitiesData.Capabilities[0] %x\n", CapabilitiesData
->Capabilities
[0]);
770 if (CapabilitiesData
->Capabilities
[0] & 0x01)
772 DbgPrint(" Drive supports audio play operations\n");
774 if (CapabilitiesData
->Capabilities
[0] & 0x02)
776 DbgPrint(" Drive can deliver a composite audio/video data stream\n");
778 if (CapabilitiesData
->Capabilities
[0] & 0x04)
780 DbgPrint(" Drive supports digital output on port 1\n");
782 if (CapabilitiesData
->Capabilities
[0] & 0x08)
784 DbgPrint(" Drive supports digital output on port 2\n");
786 if (CapabilitiesData
->Capabilities
[0] & 0x10)
788 DbgPrint(" Drive can read mode 2, form 1 (XA) data\n");
790 if (CapabilitiesData
->Capabilities
[0] & 0x20)
792 DbgPrint(" Drive can read mode 2, form 2 data\n");
794 if (CapabilitiesData
->Capabilities
[0] & 0x40)
796 DbgPrint(" Drive can read multisession discs\n");
798 DPRINT("CapabilitiesData.Capabilities[1] %x\n", CapabilitiesData
->Capabilities
[1]);
799 if (CapabilitiesData
->Capabilities
[1] & 0x01)
801 DbgPrint(" Drive can read Red Book audio data\n");
803 if (CapabilitiesData
->Capabilities
[1] & 0x02)
805 DbgPrint(" Drive can continue a read cdda operation from a loss of streaming\n");
807 if (CapabilitiesData
->Capabilities
[1] & 0x04)
809 DbgPrint(" Subchannel reads can return combined R-W information\n");
811 if (CapabilitiesData
->Capabilities
[1] & 0x08)
813 DbgPrint(" R-W data will be returned deinterleaved and error corrected\n");
815 if (CapabilitiesData
->Capabilities
[1] & 0x10)
817 DbgPrint(" Drive supports C2 error pointers\n");
819 if (CapabilitiesData
->Capabilities
[1] & 0x20)
821 DbgPrint(" Drive can return International Standard Recording Code info\n");
823 if (CapabilitiesData
->Capabilities
[1] & 0x40)
825 DbgPrint(" Drive can return Media Catalog Number (UPC) info\n");
827 DPRINT("CapabilitiesData.Capabilities[2] %x\n", CapabilitiesData
->Capabilities
[2]);
828 if (CapabilitiesData
->Capabilities
[2] & 0x01)
830 DbgPrint(" Drive can lock the door\n");
832 if (CapabilitiesData
->Capabilities
[2] & 0x02)
834 DbgPrint(" The door is locked\n");
836 if (CapabilitiesData
->Capabilities
[2] & 0x04)
839 if (CapabilitiesData
->Capabilities
[2] & 0x08)
841 DbgPrint(" Drive can eject a disc or changer cartridge\n");
843 if (CapabilitiesData
->Capabilities
[2] & 0x10)
845 DbgPrint(" Drive supports C2 error pointers\n");
847 switch (CapabilitiesData
->Capabilities
[2] >> 5)
850 DbgPrint(" Drive use a caddy type loading mechanism\n");
853 DbgPrint(" Drive use a tray type loading mechanism\n");
856 DbgPrint(" Drive use a pop-up type loading mechanism\n");
859 DbgPrint(" Drive is a changer with individually changeable discs\n");
862 DbgPrint(" Drive is a changer with cartridge mechanism\n");
865 DPRINT("CapabilitiesData.Capabilities[3] %x\n", CapabilitiesData
->Capabilities
[3]);
866 if (CapabilitiesData
->Capabilities
[3] & 0x01)
868 DbgPrint(" Audio level for each channel can be controlled independently\n");
870 if (CapabilitiesData
->Capabilities
[3] & 0x02)
872 DbgPrint(" Audio for each channel can be muted independently\n");
874 if (CapabilitiesData
->Capabilities
[3] & 0x04)
876 DbgPrint(" Changer can report exact contents of slots\n");
878 if (CapabilitiesData
->Capabilities
[3] & 0x08)
880 DbgPrint(" Drive supports software slot selection\n");
882 DbgPrint(" Maximum speed is %d kB/s\n",
883 (CapabilitiesData
->MaximumSpeedSupported
[0] << 8)
884 | CapabilitiesData
->MaximumSpeedSupported
[1]);
885 DbgPrint(" Current speed is %d kB/s\n",
886 (CapabilitiesData
->CurrentSpeed
[0] << 8)
887 | CapabilitiesData
->CurrentSpeed
[1]);
888 DbgPrint(" Number of discrete volume levels is %d\n",
889 (CapabilitiesData
->Reserved3
<< 8)
890 | CapabilitiesData
->NumberVolumeLevels
);
891 DbgPrint(" Buffer size is %d kB\n",
892 (CapabilitiesData
->BufferSize
[0] << 8)
893 | CapabilitiesData
->BufferSize
[1]);
898 DPRINT("XA not supported\n");
899 CdromData
->XaFlags
|= XA_NOT_SUPPORTED
;
907 /* Initialize device timer */
908 IoInitializeTimer(DiskDeviceObject
,
911 IoStartTimer(DiskDeviceObject
);
913 DPRINT("CdromClassCreateDeviceObjects() done\n");
915 return(STATUS_SUCCESS
);
919 /**********************************************************************
921 * CdromClassReadTocEntry
933 CdromClassReadTocEntry (PDEVICE_OBJECT DeviceObject
,
938 PDEVICE_EXTENSION DeviceExtension
;
939 SCSI_REQUEST_BLOCK Srb
;
942 DeviceExtension
= (PDEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
944 RtlZeroMemory(&Srb
, sizeof(SCSI_REQUEST_BLOCK
));
946 Srb
.TimeOutValue
= DeviceExtension
->TimeOutValue
;
949 Cdb
->READ_TOC
.OperationCode
= SCSIOP_READ_TOC
;
950 Cdb
->READ_TOC
.StartingTrack
= TrackNo
;
951 Cdb
->READ_TOC
.Format
= 0;
952 Cdb
->READ_TOC
.AllocationLength
[0] = Length
>> 8;
953 Cdb
->READ_TOC
.AllocationLength
[1] = Length
& 0xff;
954 Cdb
->READ_TOC
.Msf
= 1;
956 return(ScsiClassSendSrbSynchronous(DeviceObject
,
965 CdromClassReadLastSession (PDEVICE_OBJECT DeviceObject
,
970 PDEVICE_EXTENSION DeviceExtension
;
971 SCSI_REQUEST_BLOCK Srb
;
974 DeviceExtension
= (PDEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
976 RtlZeroMemory(&Srb
, sizeof(SCSI_REQUEST_BLOCK
));
978 Srb
.TimeOutValue
= DeviceExtension
->TimeOutValue
;
981 Cdb
->READ_TOC
.OperationCode
= SCSIOP_READ_TOC
;
982 Cdb
->READ_TOC
.StartingTrack
= TrackNo
;
983 Cdb
->READ_TOC
.Format
= 1;
984 Cdb
->READ_TOC
.AllocationLength
[0] = Length
>> 8;
985 Cdb
->READ_TOC
.AllocationLength
[1] = Length
& 0xff;
986 Cdb
->READ_TOC
.Msf
= 0;
988 return(ScsiClassSendSrbSynchronous(DeviceObject
,
996 /**********************************************************************
998 * CdromClassDeviceControl
1001 * Answer requests for device control calls
1009 * Standard dispatch arguments
1016 CdromClassDeviceControl(IN PDEVICE_OBJECT DeviceObject
,
1019 PDEVICE_EXTENSION DeviceExtension
;
1020 PIO_STACK_LOCATION IrpStack
;
1021 ULONG ControlCode
, InputLength
, OutputLength
;
1022 PCDROM_DATA CdromData
;
1026 DPRINT("CdromClassDeviceControl() called!\n");
1028 Status
= STATUS_INVALID_DEVICE_REQUEST
;
1030 IrpStack
= IoGetCurrentIrpStackLocation(Irp
);
1031 ControlCode
= IrpStack
->Parameters
.DeviceIoControl
.IoControlCode
;
1032 InputLength
= IrpStack
->Parameters
.DeviceIoControl
.InputBufferLength
;
1033 OutputLength
= IrpStack
->Parameters
.DeviceIoControl
.OutputBufferLength
;
1034 DeviceExtension
= (PDEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
1035 CdromData
= (PCDROM_DATA
)(DeviceExtension
+ 1);
1037 switch (ControlCode
)
1039 case IOCTL_CDROM_GET_DRIVE_GEOMETRY
:
1040 DPRINT ("CdromClassDeviceControl: IOCTL_CDROM_GET_DRIVE_GEOMETRY\n");
1041 if (IrpStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(DISK_GEOMETRY
))
1043 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1046 IoMarkIrpPending (Irp
);
1047 IoStartPacket (DeviceObject
,
1051 return STATUS_PENDING
;
1053 case IOCTL_CDROM_CHECK_VERIFY
:
1054 DPRINT ("CdromClassDeviceControl: IOCTL_CDROM_CHECK_VERIFY\n");
1055 if (OutputLength
!= 0 && OutputLength
< sizeof (ULONG
))
1057 DPRINT1("Buffer too small\n");
1058 Status
= STATUS_BUFFER_TOO_SMALL
;
1061 IoMarkIrpPending (Irp
);
1062 IoStartPacket (DeviceObject
,
1066 return STATUS_PENDING
;
1068 case IOCTL_CDROM_READ_TOC
:
1069 DPRINT("IOCTL_CDROM_READ_TOC\n");
1070 if (IrpStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(CDROM_TOC
))
1072 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1076 PCDROM_TOC TocBuffer
;
1079 TocBuffer
= Irp
->AssociatedIrp
.SystemBuffer
;
1081 /* First read the lead out */
1082 Length
= 4 + sizeof(TRACK_DATA
);
1083 Status
= CdromClassReadTocEntry(DeviceObject
,
1087 if (NT_SUCCESS(Status
))
1089 if (TocBuffer
->FirstTrack
== 0xaa)
1091 /* there is an empty cd */
1092 Information
= Length
;
1097 Length
= 4 + sizeof(TRACK_DATA
) * (TocBuffer
->LastTrack
- TocBuffer
->FirstTrack
+ 2);
1098 Status
= CdromClassReadTocEntry(DeviceObject
,
1099 TocBuffer
->FirstTrack
,
1101 if (NT_SUCCESS(Status
))
1103 Information
= Length
;
1110 case IOCTL_CDROM_GET_LAST_SESSION
:
1111 DPRINT("IOCTL_CDROM_GET_LAST_SESSION\n");
1112 if (IrpStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< 4 + sizeof(TRACK_DATA
))
1114 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1118 PCDROM_TOC TocBuffer
;
1121 TocBuffer
= Irp
->AssociatedIrp
.SystemBuffer
;
1122 Length
= 4 + sizeof(TRACK_DATA
);
1123 Status
= CdromClassReadLastSession(DeviceObject
,
1127 if (NT_SUCCESS(Status
))
1129 Information
= Length
;
1135 /* Call the common device control function */
1136 return(ScsiClassDeviceControl(DeviceObject
, Irp
));
1139 /* Verify the device if the user caused the error */
1140 if (!NT_SUCCESS(Status
) && IoIsErrorUserInduced(Status
))
1142 IoSetHardErrorOrVerifyDevice(Irp
, DeviceObject
);
1145 Irp
->IoStatus
.Status
= Status
;
1146 Irp
->IoStatus
.Information
= Information
;
1147 IoCompleteRequest(Irp
,
1154 /**********************************************************************
1159 * Starts IRP processing.
1167 * Standard dispatch arguments
1173 CdromClassStartIo (IN PDEVICE_OBJECT DeviceObject
,
1176 PDEVICE_EXTENSION DeviceExtension
;
1177 PIO_STACK_LOCATION IrpStack
;
1178 PIO_STACK_LOCATION SubIrpStack
;
1179 ULONG MaximumTransferLength
;
1180 ULONG TransferPages
;
1181 PSCSI_REQUEST_BLOCK Srb
;
1187 DPRINT("CdromClassStartIo() called!\n");
1189 IoMarkIrpPending (Irp
);
1191 DeviceExtension
= (PDEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
1192 IrpStack
= IoGetCurrentIrpStackLocation (Irp
);
1194 MaximumTransferLength
= DeviceExtension
->PortCapabilities
->MaximumTransferLength
;
1196 if (DeviceObject
->Flags
& DO_VERIFY_VOLUME
)
1198 if (!(IrpStack
->Flags
& SL_OVERRIDE_VERIFY_VOLUME
))
1200 DPRINT1 ("Verify required\n");
1202 if (Irp
->Tail
.Overlay
.Thread
)
1204 IoSetHardErrorOrVerifyDevice (Irp
,
1207 Irp
->IoStatus
.Status
= STATUS_VERIFY_REQUIRED
;
1209 /* FIXME: Update drive capacity */
1210 IoCompleteRequest (Irp
,
1212 IoStartNextPacket (DeviceObject
,
1218 if (IrpStack
->MajorFunction
== IRP_MJ_READ
)
1220 DPRINT ("CdromClassStartIo: IRP_MJ_READ\n");
1223 ADDRESS_AND_SIZE_TO_SPAN_PAGES (MmGetMdlVirtualAddress(Irp
->MdlAddress
),
1224 IrpStack
->Parameters
.Read
.Length
);
1226 /* Check transfer size */
1227 if ((IrpStack
->Parameters
.Read
.Length
> MaximumTransferLength
) ||
1228 (TransferPages
> DeviceExtension
->PortCapabilities
->MaximumPhysicalPages
))
1230 /* Transfer size is too large - split it */
1232 DeviceExtension
->PortCapabilities
->MaximumPhysicalPages
- 1;
1234 /* Adjust transfer size */
1235 if (MaximumTransferLength
> TransferPages
* PAGE_SIZE
)
1236 MaximumTransferLength
= TransferPages
* PAGE_SIZE
;
1238 if (MaximumTransferLength
== 0)
1239 MaximumTransferLength
= PAGE_SIZE
;
1241 /* Split the transfer */
1242 ScsiClassSplitRequest (DeviceObject
,
1244 MaximumTransferLength
);
1250 ScsiClassBuildRequest (DeviceObject
,
1254 else if (IrpStack
->MajorFunction
== IRP_MJ_DEVICE_CONTROL
)
1256 DPRINT ("CdromClassStartIo: IRP_MJ_IRP_MJ_DEVICE_CONTROL\n");
1258 /* Allocate an IRP for sending requests to the port driver */
1259 SubIrp
= IoAllocateIrp ((CCHAR
)(DeviceObject
->StackSize
+ 1),
1263 Irp
->IoStatus
.Information
= 0;
1264 Irp
->IoStatus
.Status
= STATUS_INSUFFICIENT_RESOURCES
;
1265 IoCompleteRequest (Irp
,
1267 IoStartNextPacket (DeviceObject
,
1272 /* Allocate an SRB */
1273 Srb
= ExAllocatePool (NonPagedPool
,
1274 sizeof (SCSI_REQUEST_BLOCK
));
1278 Irp
->IoStatus
.Information
= 0;
1279 Irp
->IoStatus
.Status
= STATUS_INSUFFICIENT_RESOURCES
;
1280 IoCompleteRequest (Irp
,
1282 IoStartNextPacket (DeviceObject
,
1287 /* Allocte a sense buffer */
1288 SenseBuffer
= ExAllocatePool (NonPagedPoolCacheAligned
,
1290 if (SenseBuffer
== NULL
)
1294 Irp
->IoStatus
.Information
= 0;
1295 Irp
->IoStatus
.Status
= STATUS_INSUFFICIENT_RESOURCES
;
1296 IoCompleteRequest (Irp
,
1298 IoStartNextPacket (DeviceObject
,
1303 /* Initialize the IRP */
1304 IoSetNextIrpStackLocation (SubIrp
);
1305 SubIrp
->IoStatus
.Information
= 0;
1306 SubIrp
->IoStatus
.Status
= STATUS_SUCCESS
;
1308 SubIrp
->UserBuffer
= NULL
;
1310 SubIrpStack
= IoGetCurrentIrpStackLocation (SubIrp
);
1311 SubIrpStack
->DeviceObject
= DeviceExtension
->DeviceObject
;
1312 SubIrpStack
->Parameters
.Others
.Argument2
= (PVOID
)Irp
;
1314 /* Initialize next stack location */
1315 SubIrpStack
= IoGetNextIrpStackLocation (SubIrp
);
1316 SubIrpStack
->MajorFunction
= IRP_MJ_SCSI
;
1317 SubIrpStack
->Parameters
.DeviceIoControl
.IoControlCode
= IOCTL_SCSI_EXECUTE_IN
;
1318 SubIrpStack
->Parameters
.Scsi
.Srb
= Srb
;
1320 /* Initialize the SRB */
1322 sizeof (SCSI_REQUEST_BLOCK
));
1323 Srb
->Length
= sizeof (SCSI_REQUEST_BLOCK
);
1324 Srb
->PathId
= DeviceExtension
->PathId
;
1325 Srb
->TargetId
= DeviceExtension
->TargetId
;
1326 Srb
->Lun
= DeviceExtension
->Lun
;
1327 Srb
->Function
= SRB_FUNCTION_EXECUTE_SCSI
;
1328 Srb
->SrbStatus
= SRB_STATUS_SUCCESS
;
1329 Srb
->ScsiStatus
= 0;
1331 Srb
->OriginalRequest
= SubIrp
;
1332 Srb
->SenseInfoBuffer
= SenseBuffer
;
1333 Srb
->SenseInfoBufferLength
= SENSE_BUFFER_SIZE
;
1335 /* Initialize the CDB */
1336 Cdb
= (PCDB
)Srb
->Cdb
;
1338 /* Set the completion routine */
1339 IoSetCompletionRoutine (SubIrp
,
1340 CdromDeviceControlCompletion
,
1346 switch (IrpStack
->Parameters
.DeviceIoControl
.IoControlCode
)
1348 case IOCTL_CDROM_GET_DRIVE_GEOMETRY
:
1349 DPRINT ("CdromClassStartIo: IOCTL_CDROM_GET_DRIVE_GEOMETRY\n");
1350 Srb
->DataTransferLength
= sizeof(READ_CAPACITY_DATA
);
1351 Srb
->CdbLength
= 10;
1352 Srb
->TimeOutValue
= DeviceExtension
->TimeOutValue
;
1353 Srb
->SrbFlags
= SRB_FLAGS_DISABLE_SYNCH_TRANSFER
| SRB_FLAGS_DATA_IN
;
1354 Cdb
->CDB10
.OperationCode
= SCSIOP_READ_CAPACITY
;
1356 /* Allocate data buffer */
1357 DataBuffer
= ExAllocatePool (NonPagedPoolCacheAligned
,
1358 sizeof(READ_CAPACITY_DATA
));
1359 if (DataBuffer
== NULL
)
1361 Irp
->IoStatus
.Information
= 0;
1362 Irp
->IoStatus
.Status
= STATUS_INSUFFICIENT_RESOURCES
;
1363 IoCompleteRequest (Irp
,
1365 ExFreePool (SenseBuffer
);
1368 IoStartNextPacket (DeviceObject
,
1373 /* Allocate an MDL for the data buffer */
1374 SubIrp
->MdlAddress
= IoAllocateMdl (DataBuffer
,
1375 sizeof(READ_CAPACITY_DATA
),
1379 if (SubIrp
->MdlAddress
== NULL
)
1381 Irp
->IoStatus
.Information
= 0;
1382 Irp
->IoStatus
.Status
= STATUS_INSUFFICIENT_RESOURCES
;
1383 IoCompleteRequest (Irp
,
1385 ExFreePool (DataBuffer
);
1386 ExFreePool (SenseBuffer
);
1389 IoStartNextPacket (DeviceObject
,
1394 MmBuildMdlForNonPagedPool (SubIrp
->MdlAddress
);
1395 Srb
->DataBuffer
= DataBuffer
;
1397 IoCallDriver (DeviceExtension
->PortDeviceObject
,
1401 case IOCTL_CDROM_CHECK_VERIFY
:
1402 DPRINT ("CdromClassStartIo: IOCTL_CDROM_CHECK_VERIFY\n");
1404 Srb
->TimeOutValue
= DeviceExtension
->TimeOutValue
* 2;
1405 Srb
->SrbFlags
= SRB_FLAGS_NO_DATA_TRANSFER
;
1406 Cdb
->CDB6GENERIC
.OperationCode
= SCSIOP_TEST_UNIT_READY
;
1408 IoCallDriver (DeviceExtension
->PortDeviceObject
,
1413 IoCompleteRequest (Irp
,
1419 /* Call the SCSI port driver */
1420 IoCallDriver (DeviceExtension
->PortDeviceObject
,
1426 CdromDeviceControlCompletion (IN PDEVICE_OBJECT DeviceObject
,
1430 PDEVICE_EXTENSION DeviceExtension
;
1431 PDEVICE_EXTENSION PhysicalExtension
;
1432 PIO_STACK_LOCATION IrpStack
;
1433 PIO_STACK_LOCATION OrigCurrentIrpStack
;
1434 PIO_STACK_LOCATION OrigNextIrpStack
;
1435 PSCSI_REQUEST_BLOCK Srb
;
1440 DPRINT ("CdromDeviceControlCompletion() called\n");
1442 DeviceExtension
= (PDEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
1443 PhysicalExtension
= (PDEVICE_EXTENSION
)DeviceExtension
->PhysicalDevice
->DeviceExtension
;
1444 Srb
= (PSCSI_REQUEST_BLOCK
) Context
;
1446 IrpStack
= IoGetCurrentIrpStackLocation (Irp
);
1448 /* Get the original IRP */
1449 OrigIrp
= (PIRP
)IrpStack
->Parameters
.Others
.Argument2
;
1450 OrigCurrentIrpStack
= IoGetCurrentIrpStackLocation (OrigIrp
);
1451 OrigNextIrpStack
= IoGetNextIrpStackLocation (OrigIrp
);
1453 if (SRB_STATUS(Srb
->SrbStatus
) == SRB_STATUS_SUCCESS
)
1455 Status
= STATUS_SUCCESS
;
1459 DPRINT ("SrbStatus %lx\n", Srb
->SrbStatus
);
1461 /* Interpret sense info */
1462 Retry
= ScsiClassInterpretSenseInfo (DeviceObject
,
1464 IrpStack
->MajorFunction
,
1465 IrpStack
->Parameters
.DeviceIoControl
.IoControlCode
,
1466 MAXIMUM_RETRIES
- (ULONG
)OrigNextIrpStack
->Parameters
.Others
.Argument1
,
1468 DPRINT ("Retry %u\n", Retry
);
1470 if (Retry
== TRUE
&&
1471 (ULONG
)OrigNextIrpStack
->Parameters
.Others
.Argument1
> 0)
1473 DPRINT1 ("Try again (Retry count %lu)\n",
1474 (ULONG
)OrigNextIrpStack
->Parameters
.Others
.Argument1
);
1476 (ULONG
)OrigNextIrpStack
->Parameters
.Others
.Argument1
--;
1478 /* Release 'old' buffers */
1479 ExFreePool (Srb
->SenseInfoBuffer
);
1480 if (Srb
->DataBuffer
)
1481 ExFreePool(Srb
->DataBuffer
);
1484 if (Irp
->MdlAddress
!= NULL
)
1485 IoFreeMdl(Irp
->MdlAddress
);
1489 /* Call the StartIo routine again */
1490 CdromClassStartIo (DeviceObject
,
1493 return STATUS_MORE_PROCESSING_REQUIRED
;
1496 DPRINT ("Status %lx\n", Status
);
1499 if (NT_SUCCESS (Status
))
1501 switch (OrigCurrentIrpStack
->Parameters
.DeviceIoControl
.IoControlCode
)
1503 case IOCTL_CDROM_GET_DRIVE_GEOMETRY
:
1505 PREAD_CAPACITY_DATA CapacityBuffer
;
1509 DPRINT ("CdromClassControlCompletion: IOCTL_CDROM_GET_DRIVE_GEOMETRY\n");
1511 CapacityBuffer
= (PREAD_CAPACITY_DATA
)Srb
->DataBuffer
;
1512 SectorSize
= (((PUCHAR
)&CapacityBuffer
->BytesPerBlock
)[0] << 24) |
1513 (((PUCHAR
)&CapacityBuffer
->BytesPerBlock
)[1] << 16) |
1514 (((PUCHAR
)&CapacityBuffer
->BytesPerBlock
)[2] << 8) |
1515 ((PUCHAR
)&CapacityBuffer
->BytesPerBlock
)[3];
1517 LastSector
= (((PUCHAR
)&CapacityBuffer
->LogicalBlockAddress
)[0] << 24) |
1518 (((PUCHAR
)&CapacityBuffer
->LogicalBlockAddress
)[1] << 16) |
1519 (((PUCHAR
)&CapacityBuffer
->LogicalBlockAddress
)[2] << 8) |
1520 ((PUCHAR
)&CapacityBuffer
->LogicalBlockAddress
)[3];
1522 if (SectorSize
== 0)
1524 DeviceExtension
->DiskGeometry
->BytesPerSector
= SectorSize
;
1526 DeviceExtension
->PartitionLength
.QuadPart
= (LONGLONG
)(LastSector
+ 1);
1527 WHICH_BIT(DeviceExtension
->DiskGeometry
->BytesPerSector
,
1528 DeviceExtension
->SectorShift
);
1529 DeviceExtension
->PartitionLength
.QuadPart
=
1530 (DeviceExtension
->PartitionLength
.QuadPart
<< DeviceExtension
->SectorShift
);
1532 if (DeviceObject
->Characteristics
& FILE_REMOVABLE_MEDIA
)
1534 DeviceExtension
->DiskGeometry
->MediaType
= RemovableMedia
;
1538 DeviceExtension
->DiskGeometry
->MediaType
= FixedMedia
;
1540 DeviceExtension
->DiskGeometry
->Cylinders
.QuadPart
=
1541 (LONGLONG
)((LastSector
+ 1)/(32 * 64));
1542 DeviceExtension
->DiskGeometry
->SectorsPerTrack
= 32;
1543 DeviceExtension
->DiskGeometry
->TracksPerCylinder
= 64;
1545 RtlCopyMemory (OrigIrp
->AssociatedIrp
.SystemBuffer
,
1546 DeviceExtension
->DiskGeometry
,
1547 sizeof(DISK_GEOMETRY
));
1548 OrigIrp
->IoStatus
.Information
= sizeof(DISK_GEOMETRY
);
1552 case IOCTL_CDROM_CHECK_VERIFY
:
1553 DPRINT ("CdromDeviceControlCompletion: IOCTL_CDROM_CHECK_VERIFY\n");
1554 if (OrigCurrentIrpStack
->Parameters
.DeviceIoControl
.OutputBufferLength
!= 0)
1556 /* Return the media change counter */
1557 *((PULONG
)(OrigIrp
->AssociatedIrp
.SystemBuffer
)) =
1558 PhysicalExtension
->MediaChangeCount
;
1559 OrigIrp
->IoStatus
.Information
= sizeof(ULONG
);
1563 OrigIrp
->IoStatus
.Information
= 0;
1568 OrigIrp
->IoStatus
.Information
= 0;
1569 Status
= STATUS_INVALID_DEVICE_REQUEST
;
1574 /* Release the SRB and associated buffers */
1577 DPRINT("Srb %p\n", Srb
);
1579 if (Srb
->DataBuffer
!= NULL
)
1580 ExFreePool (Srb
->DataBuffer
);
1582 if (Srb
->SenseInfoBuffer
!= NULL
)
1583 ExFreePool (Srb
->SenseInfoBuffer
);
1588 if (OrigIrp
->PendingReturned
)
1590 IoMarkIrpPending (OrigIrp
);
1593 /* Release the MDL */
1594 if (Irp
->MdlAddress
!= NULL
)
1596 IoFreeMdl (Irp
->MdlAddress
);
1599 /* Release the sub irp */
1602 /* Set io status information */
1603 OrigIrp
->IoStatus
.Status
= Status
;
1604 if (!NT_SUCCESS(Status
) && IoIsErrorUserInduced (Status
))
1606 IoSetHardErrorOrVerifyDevice (OrigIrp
,
1608 OrigIrp
->IoStatus
.Information
= 0;
1611 /* Complete the original IRP */
1612 IoCompleteRequest (OrigIrp
,
1614 IoStartNextPacket (DeviceObject
,
1617 DPRINT ("CdromDeviceControlCompletion() done\n");
1619 return STATUS_MORE_PROCESSING_REQUIRED
;
1624 CdromTimerRoutine(IN PDEVICE_OBJECT DeviceObject
,
1627 PIO_WORKITEM WorkItem
;
1629 DPRINT ("CdromTimerRoutine() called\n");
1630 WorkItem
= IoAllocateWorkItem(DeviceObject
);
1636 IoQueueWorkItem(WorkItem
,
1644 CdromWorkItem(IN PDEVICE_OBJECT DeviceObject
,
1649 IO_STATUS_BLOCK IoStatus
;
1652 DPRINT("CdromWorkItem() called\n");
1654 IoFreeWorkItem((PIO_WORKITEM
) Context
);
1656 KeInitializeEvent(&Event
,
1660 Irp
= IoBuildDeviceIoControlRequest(IOCTL_CDROM_CHECK_VERIFY
,
1671 DPRINT("IoBuildDeviceIoControlRequest failed\n");
1675 Status
= IoCallDriver(DeviceObject
, Irp
);
1676 DPRINT("Status: %x\n", Status
);
1678 if (Status
== STATUS_PENDING
)
1680 KeWaitForSingleObject(&Event
,