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
)
396 DeviceExtension
->MediaChangeEvent
=
397 IoCreateSynchronizationEvent (NULL
,
398 &DeviceExtension
->MediaChangeEventHandle
);
400 KeClearEvent (DeviceExtension
->MediaChangeEvent
);
404 /**********************************************************************
406 * CdromClassCreateDeviceObject
409 * Create the raw device and any partition devices on this drive
416 * System allocated Driver Object for this driver.
418 * Name of registry driver service key.
431 CdromClassCreateDeviceObject(IN PDRIVER_OBJECT DriverObject
,
432 IN PUNICODE_STRING RegistryPath
,
433 IN PDEVICE_OBJECT PortDeviceObject
,
435 IN ULONG DeviceNumber
,
436 IN PIO_SCSI_CAPABILITIES Capabilities
,
437 IN PSCSI_INQUIRY_DATA InquiryData
,
438 IN PCLASS_INIT_DATA InitializationData
)
440 PDEVICE_EXTENSION DiskDeviceExtension
; /* defined in class2.h */
441 PDEVICE_OBJECT DiskDeviceObject
;
442 PCDROM_DATA CdromData
;
444 SCSI_REQUEST_BLOCK Srb
;
450 DPRINT("CdromClassCreateDeviceObject() called\n");
452 /* Claim the cdrom device */
453 Status
= ScsiClassClaimDevice(PortDeviceObject
,
457 if (!NT_SUCCESS(Status
))
459 DbgPrint("Could not claim cdrom device\n");
463 /* Create cdrom device */
465 "\\Device\\CdRom%lu",
468 Status
= ScsiClassCreateDeviceObject(DriverObject
,
473 if (!NT_SUCCESS(Status
))
475 DPRINT1("ScsiClassCreateDeviceObject() failed (Status %x)\n", Status
);
477 /* Release (unclaim) the disk */
478 ScsiClassClaimDevice(PortDeviceObject
,
486 DiskDeviceObject
->Flags
|= DO_DIRECT_IO
;
487 DiskDeviceObject
->Characteristics
|= FILE_REMOVABLE_MEDIA
;
488 DiskDeviceObject
->StackSize
= (CCHAR
)PortDeviceObject
->StackSize
+ 1;
490 if (PortDeviceObject
->AlignmentRequirement
> DiskDeviceObject
->AlignmentRequirement
)
492 DiskDeviceObject
->AlignmentRequirement
= PortDeviceObject
->AlignmentRequirement
;
495 DiskDeviceExtension
= DiskDeviceObject
->DeviceExtension
;
496 DiskDeviceExtension
->LockCount
= 0;
497 DiskDeviceExtension
->DeviceNumber
= DeviceNumber
;
498 DiskDeviceExtension
->DeviceObject
= DiskDeviceObject
;
499 DiskDeviceExtension
->PortDeviceObject
= PortDeviceObject
;
500 DiskDeviceExtension
->PhysicalDevice
= DiskDeviceObject
;
501 DiskDeviceExtension
->PortCapabilities
= Capabilities
;
502 DiskDeviceExtension
->StartingOffset
.QuadPart
= 0;
503 DiskDeviceExtension
->PortNumber
= (UCHAR
)PortNumber
;
504 DiskDeviceExtension
->PathId
= InquiryData
->PathId
;
505 DiskDeviceExtension
->TargetId
= InquiryData
->TargetId
;
506 DiskDeviceExtension
->Lun
= InquiryData
->Lun
;
508 /* zero-out disk data */
509 CdromData
= (PCDROM_DATA
)(DiskDeviceExtension
+ 1);
510 RtlZeroMemory(CdromData
,
513 DiskDeviceExtension
->SenseData
= ExAllocatePool(NonPagedPool
,
515 if (DiskDeviceExtension
->SenseData
== NULL
)
517 DPRINT1("Failed to allocate sense data buffer!\n");
519 IoDeleteDevice(DiskDeviceObject
);
521 /* Release (unclaim) the disk */
522 ScsiClassClaimDevice(PortDeviceObject
,
527 return(STATUS_INSUFFICIENT_RESOURCES
);
530 /* Get timeout value */
531 DiskDeviceExtension
->TimeOutValue
=
532 ScsiClassQueryTimeOutRegistryValue(RegistryPath
);
533 if (DiskDeviceExtension
->TimeOutValue
== 0)
534 DiskDeviceExtension
->TimeOutValue
= SCSI_CDROM_TIMEOUT
;
536 /* Initialize lookaside list for SRBs */
537 ScsiClassInitializeSrbLookasideList(DiskDeviceExtension
,
540 /* Get disk geometry */
541 DiskDeviceExtension
->DiskGeometry
= ExAllocatePool(NonPagedPool
,
542 sizeof(DISK_GEOMETRY
));
543 if (DiskDeviceExtension
->DiskGeometry
== NULL
)
545 DPRINT1("Failed to allocate geometry buffer!\n");
547 ExDeleteNPagedLookasideList(&DiskDeviceExtension
->SrbLookasideListHead
);
549 IoDeleteDevice(DiskDeviceObject
);
551 /* Release (unclaim) the disk */
552 ScsiClassClaimDevice(PortDeviceObject
,
557 return(STATUS_INSUFFICIENT_RESOURCES
);
560 /* Read the drive's capacity */
561 Status
= ScsiClassReadDriveCapacity(DiskDeviceObject
);
562 if (!NT_SUCCESS(Status
) ||
563 DiskDeviceExtension
->DiskGeometry
->BytesPerSector
== 0)
565 /* Set ISO9660 defaults */
566 DiskDeviceExtension
->DiskGeometry
->BytesPerSector
= 2048;
567 DiskDeviceExtension
->DiskGeometry
->MediaType
= RemovableMedia
;
568 DiskDeviceExtension
->SectorShift
= 11;
569 DiskDeviceExtension
->PartitionLength
.QuadPart
= (ULONGLONG
)0x7fffffff;
573 /* Make sure the BytesPerSector value is a power of 2 */
574 // DiskDeviceExtension->DiskGeometry->BytesPerSector = 2048;
577 DPRINT("SectorSize: %lu\n", DiskDeviceExtension
->DiskGeometry
->BytesPerSector
);
579 /* Initialize media change support */
580 CdromClassCreateMediaChangeEvent (DiskDeviceExtension
,
582 if (DiskDeviceExtension
->MediaChangeEvent
!= NULL
)
584 DPRINT("Allocated media change event!\n");
586 /* FIXME: Allocate media change IRP and SRB */
589 /* Use 6 byte xa commands by default */
590 CdromData
->XaFlags
|= XA_USE_6_BYTE
;
592 /* Read 'error recovery page' to get additional drive capabilities */
593 Length
= sizeof(MODE_READ_RECOVERY_PAGE
) + MODE_HEADER_LENGTH
;
596 sizeof(SCSI_REQUEST_BLOCK
));
598 Srb
.TimeOutValue
= DiskDeviceExtension
->TimeOutValue
;
601 Cdb
->MODE_SENSE
.OperationCode
= SCSIOP_MODE_SENSE
;
602 Cdb
->MODE_SENSE
.PageCode
= 0x01;
603 Cdb
->MODE_SENSE
.AllocationLength
= (UCHAR
)Length
;
605 Buffer
= ExAllocatePool (NonPagedPool
,
606 max(sizeof(ERROR_RECOVERY_DATA6
),
607 max(sizeof(ERROR_RECOVERY_DATA10
),
608 max(sizeof(MODE_CAPABILITIES_DATA6
),
609 sizeof(MODE_CAPABILITIES_DATA10
)))));
612 DPRINT1("Allocating recovery page buffer failed!\n");
613 return STATUS_INSUFFICIENT_RESOURCES
;
616 Status
= ScsiClassSendSrbSynchronous (DiskDeviceObject
,
622 if (!NT_SUCCESS (Status
))
624 DPRINT("MODE_SENSE(6) failed\n");
626 /* Try the 10 byte version */
627 Length
= sizeof(MODE_READ_RECOVERY_PAGE
) + MODE_HEADER_LENGTH10
;
630 sizeof(SCSI_REQUEST_BLOCK
));
632 Srb
.TimeOutValue
= DiskDeviceExtension
->TimeOutValue
;
635 Cdb
->MODE_SENSE10
.OperationCode
= SCSIOP_MODE_SENSE10
;
636 Cdb
->MODE_SENSE10
.PageCode
= 0x01;
637 Cdb
->MODE_SENSE10
.AllocationLength
[0] = (UCHAR
)(Length
>> 8);
638 Cdb
->MODE_SENSE10
.AllocationLength
[1] = (UCHAR
)(Length
& 0xFF);
640 Status
= ScsiClassSendSrbSynchronous (DiskDeviceObject
,
646 if (Status
== STATUS_DATA_OVERRUN
)
648 DPRINT1("Data overrun\n");
652 else if (NT_SUCCESS (Status
))
654 DPRINT("Use 10 byte commands\n");
655 CdromData
->XaFlags
&= XA_USE_6_BYTE
;
656 CdromData
->XaFlags
|= XA_USE_10_BYTE
;
660 DPRINT("XA not supported\n");
661 CdromData
->XaFlags
|= XA_NOT_SUPPORTED
;
666 DPRINT("Use 6 byte commands\n");
669 /* Read 'capabilities & mechanical status page' to get additional drive capabilities */
670 Length
= sizeof(MODE_READ_RECOVERY_PAGE
) + MODE_HEADER_LENGTH
;
672 if (!(CdromData
->XaFlags
& XA_NOT_SUPPORTED
))
674 RtlZeroMemory (&Srb
, sizeof(SCSI_REQUEST_BLOCK
));
675 Srb
.TimeOutValue
= DiskDeviceExtension
->TimeOutValue
;
678 if (CdromData
->XaFlags
& XA_USE_10_BYTE
)
680 /* Try the 10 byte version */
681 Length
= sizeof(MODE_CAPABILITIES_PAGE2
) + MODE_HEADER_LENGTH10
;
684 Cdb
->MODE_SENSE10
.OperationCode
= SCSIOP_MODE_SENSE10
;
685 Cdb
->MODE_SENSE10
.PageCode
= 0x2a;
686 Cdb
->MODE_SENSE10
.AllocationLength
[0] = (UCHAR
)(Length
>> 8);
687 Cdb
->MODE_SENSE10
.AllocationLength
[1] = (UCHAR
)(Length
& 0xFF);
691 Length
= sizeof(MODE_CAPABILITIES_PAGE2
) + MODE_HEADER_LENGTH
;
694 Cdb
->MODE_SENSE
.OperationCode
= SCSIOP_MODE_SENSE
;
695 Cdb
->MODE_SENSE
.PageCode
= 0x2a;
696 Cdb
->MODE_SENSE
.AllocationLength
= (UCHAR
)Length
;
698 Status
= ScsiClassSendSrbSynchronous (DiskDeviceObject
,
703 if (NT_SUCCESS (Status
))
706 PMODE_CAPABILITIES_PAGE2 CapabilitiesData
;
707 if (CdromData
->XaFlags
& XA_USE_10_BYTE
)
709 CapabilitiesData
= (PMODE_CAPABILITIES_PAGE2
)(Buffer
+ sizeof(MODE_PARAMETER_HEADER10
));
713 CapabilitiesData
= (PMODE_CAPABILITIES_PAGE2
)(Buffer
+ sizeof(MODE_PARAMETER_HEADER
));
716 DbgPrint("Capabilities for '%s':\n", NameBuffer
);
717 if (CapabilitiesData
->Reserved2
[0] & 0x20)
719 DbgPrint(" Drive supports reading of DVD-RAM discs\n");
721 if (CapabilitiesData
->Reserved2
[0] & 0x10)
723 DbgPrint(" Drive supports reading of DVD-R discs\n");
725 if (CapabilitiesData
->Reserved2
[0] & 0x08)
727 DbgPrint(" Drive supports reading of DVD-ROM discs\n");
729 if (CapabilitiesData
->Reserved2
[0] & 0x04)
731 DbgPrint(" Drive supports reading CD-R discs with addressing method 2\n");
733 if (CapabilitiesData
->Reserved2
[0] & 0x02)
735 DbgPrint(" Drive can read from CD-R/W (CD-E) discs (orange book, part III)\n");
737 if (CapabilitiesData
->Reserved2
[0] & 0x01)
739 DbgPrint(" Drive supports read from CD-R discs (orange book, part II)\n");
741 DPRINT("CapabilitiesData.Reserved2[1] %x\n", CapabilitiesData
->Reserved2
[1]);
742 if (CapabilitiesData
->Reserved2
[1] & 0x01)
744 DbgPrint(" Drive can write to CD-R discs (orange book, part II)\n");
746 if (CapabilitiesData
->Reserved2
[1] & 0x02)
748 DbgPrint(" Drive can write to CD-R/W (CD-E) discs (orange book, part III)\n");
750 if (CapabilitiesData
->Reserved2
[1] & 0x04)
752 DbgPrint(" Drive can fake writes\n");
754 if (CapabilitiesData
->Reserved2
[1] & 0x10)
756 DbgPrint(" Drive can write DVD-R discs\n");
758 if (CapabilitiesData
->Reserved2
[1] & 0x20)
760 DbgPrint(" Drive can write DVD-RAM discs\n");
762 DPRINT("CapabilitiesData.Capabilities[0] %x\n", CapabilitiesData
->Capabilities
[0]);
763 if (CapabilitiesData
->Capabilities
[0] & 0x01)
765 DbgPrint(" Drive supports audio play operations\n");
767 if (CapabilitiesData
->Capabilities
[0] & 0x02)
769 DbgPrint(" Drive can deliver a composite audio/video data stream\n");
771 if (CapabilitiesData
->Capabilities
[0] & 0x04)
773 DbgPrint(" Drive supports digital output on port 1\n");
775 if (CapabilitiesData
->Capabilities
[0] & 0x08)
777 DbgPrint(" Drive supports digital output on port 2\n");
779 if (CapabilitiesData
->Capabilities
[0] & 0x10)
781 DbgPrint(" Drive can read mode 2, form 1 (XA) data\n");
783 if (CapabilitiesData
->Capabilities
[0] & 0x20)
785 DbgPrint(" Drive can read mode 2, form 2 data\n");
787 if (CapabilitiesData
->Capabilities
[0] & 0x40)
789 DbgPrint(" Drive can read multisession discs\n");
791 DPRINT("CapabilitiesData.Capabilities[1] %x\n", CapabilitiesData
->Capabilities
[1]);
792 if (CapabilitiesData
->Capabilities
[1] & 0x01)
794 DbgPrint(" Drive can read Red Book audio data\n");
796 if (CapabilitiesData
->Capabilities
[1] & 0x02)
798 DbgPrint(" Drive can continue a read cdda operation from a loss of streaming\n");
800 if (CapabilitiesData
->Capabilities
[1] & 0x04)
802 DbgPrint(" Subchannel reads can return combined R-W information\n");
804 if (CapabilitiesData
->Capabilities
[1] & 0x08)
806 DbgPrint(" R-W data will be returned deinterleaved and error corrected\n");
808 if (CapabilitiesData
->Capabilities
[1] & 0x10)
810 DbgPrint(" Drive supports C2 error pointers\n");
812 if (CapabilitiesData
->Capabilities
[1] & 0x20)
814 DbgPrint(" Drive can return International Standard Recording Code info\n");
816 if (CapabilitiesData
->Capabilities
[1] & 0x40)
818 DbgPrint(" Drive can return Media Catalog Number (UPC) info\n");
820 DPRINT("CapabilitiesData.Capabilities[2] %x\n", CapabilitiesData
->Capabilities
[2]);
821 if (CapabilitiesData
->Capabilities
[2] & 0x01)
823 DbgPrint(" Drive can lock the door\n");
825 if (CapabilitiesData
->Capabilities
[2] & 0x02)
827 DbgPrint(" The door is locked\n");
829 if (CapabilitiesData
->Capabilities
[2] & 0x04)
832 if (CapabilitiesData
->Capabilities
[2] & 0x08)
834 DbgPrint(" Drive can eject a disc or changer cartridge\n");
836 if (CapabilitiesData
->Capabilities
[2] & 0x10)
838 DbgPrint(" Drive supports C2 error pointers\n");
840 switch (CapabilitiesData
->Capabilities
[2] >> 5)
843 DbgPrint(" Drive use a caddy type loading mechanism\n");
846 DbgPrint(" Drive use a tray type loading mechanism\n");
849 DbgPrint(" Drive use a pop-up type loading mechanism\n");
852 DbgPrint(" Drive is a changer with individually changeable discs\n");
855 DbgPrint(" Drive is a changer with cartridge mechanism\n");
858 DPRINT("CapabilitiesData.Capabilities[3] %x\n", CapabilitiesData
->Capabilities
[3]);
859 if (CapabilitiesData
->Capabilities
[3] & 0x01)
861 DbgPrint(" Audio level for each channel can be controlled independently\n");
863 if (CapabilitiesData
->Capabilities
[3] & 0x02)
865 DbgPrint(" Audio for each channel can be muted independently\n");
867 if (CapabilitiesData
->Capabilities
[3] & 0x04)
869 DbgPrint(" Changer can report exact contents of slots\n");
871 if (CapabilitiesData
->Capabilities
[3] & 0x08)
873 DbgPrint(" Drive supports software slot selection\n");
875 DbgPrint(" Maximum speed is %d kB/s\n",
876 (CapabilitiesData
->MaximumSpeedSupported
[0] << 8)
877 | CapabilitiesData
->MaximumSpeedSupported
[1]);
878 DbgPrint(" Current speed is %d kB/s\n",
879 (CapabilitiesData
->CurrentSpeed
[0] << 8)
880 | CapabilitiesData
->CurrentSpeed
[1]);
881 DbgPrint(" Number of discrete volume levels is %d\n",
882 (CapabilitiesData
->Reserved3
<< 8)
883 | CapabilitiesData
->NumberVolumeLevels
);
884 DbgPrint(" Buffer size is %d kB\n",
885 (CapabilitiesData
->BufferSize
[0] << 8)
886 | CapabilitiesData
->BufferSize
[1]);
891 DPRINT("XA not supported\n");
892 CdromData
->XaFlags
|= XA_NOT_SUPPORTED
;
900 /* Initialize device timer */
901 IoInitializeTimer(DiskDeviceObject
,
904 IoStartTimer(DiskDeviceObject
);
906 DPRINT("CdromClassCreateDeviceObjects() done\n");
908 return(STATUS_SUCCESS
);
912 /**********************************************************************
914 * CdromClassReadTocEntry
926 CdromClassReadTocEntry (PDEVICE_OBJECT DeviceObject
,
931 PDEVICE_EXTENSION DeviceExtension
;
932 SCSI_REQUEST_BLOCK Srb
;
935 DeviceExtension
= (PDEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
937 RtlZeroMemory(&Srb
, sizeof(SCSI_REQUEST_BLOCK
));
939 Srb
.TimeOutValue
= DeviceExtension
->TimeOutValue
;
942 Cdb
->READ_TOC
.OperationCode
= SCSIOP_READ_TOC
;
943 Cdb
->READ_TOC
.StartingTrack
= TrackNo
;
944 Cdb
->READ_TOC
.Format
= 0;
945 Cdb
->READ_TOC
.AllocationLength
[0] = Length
>> 8;
946 Cdb
->READ_TOC
.AllocationLength
[1] = Length
& 0xff;
947 Cdb
->READ_TOC
.Msf
= 1;
949 return(ScsiClassSendSrbSynchronous(DeviceObject
,
958 CdromClassReadLastSession (PDEVICE_OBJECT DeviceObject
,
963 PDEVICE_EXTENSION DeviceExtension
;
964 SCSI_REQUEST_BLOCK Srb
;
967 DeviceExtension
= (PDEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
969 RtlZeroMemory(&Srb
, sizeof(SCSI_REQUEST_BLOCK
));
971 Srb
.TimeOutValue
= DeviceExtension
->TimeOutValue
;
974 Cdb
->READ_TOC
.OperationCode
= SCSIOP_READ_TOC
;
975 Cdb
->READ_TOC
.StartingTrack
= TrackNo
;
976 Cdb
->READ_TOC
.Format
= 1;
977 Cdb
->READ_TOC
.AllocationLength
[0] = Length
>> 8;
978 Cdb
->READ_TOC
.AllocationLength
[1] = Length
& 0xff;
979 Cdb
->READ_TOC
.Msf
= 0;
981 return(ScsiClassSendSrbSynchronous(DeviceObject
,
989 /**********************************************************************
991 * CdromClassDeviceControl
994 * Answer requests for device control calls
1002 * Standard dispatch arguments
1009 CdromClassDeviceControl(IN PDEVICE_OBJECT DeviceObject
,
1012 PDEVICE_EXTENSION DeviceExtension
;
1013 PIO_STACK_LOCATION IrpStack
;
1014 ULONG ControlCode
, InputLength
, OutputLength
;
1015 PCDROM_DATA CdromData
;
1019 DPRINT("CdromClassDeviceControl() called!\n");
1021 Status
= STATUS_INVALID_DEVICE_REQUEST
;
1023 IrpStack
= IoGetCurrentIrpStackLocation(Irp
);
1024 ControlCode
= IrpStack
->Parameters
.DeviceIoControl
.IoControlCode
;
1025 InputLength
= IrpStack
->Parameters
.DeviceIoControl
.InputBufferLength
;
1026 OutputLength
= IrpStack
->Parameters
.DeviceIoControl
.OutputBufferLength
;
1027 DeviceExtension
= (PDEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
1028 CdromData
= (PCDROM_DATA
)(DeviceExtension
+ 1);
1030 switch (ControlCode
)
1032 case IOCTL_CDROM_GET_DRIVE_GEOMETRY
:
1033 DPRINT ("CdromClassDeviceControl: IOCTL_CDROM_GET_DRIVE_GEOMETRY\n");
1034 if (IrpStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(DISK_GEOMETRY
))
1036 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1039 IoMarkIrpPending (Irp
);
1040 IoStartPacket (DeviceObject
,
1044 return STATUS_PENDING
;
1046 case IOCTL_CDROM_CHECK_VERIFY
:
1047 DPRINT ("CdromClassDeviceControl: IOCTL_CDROM_CHECK_VERIFY\n");
1048 if (OutputLength
!= 0 && OutputLength
< sizeof (ULONG
))
1050 DPRINT1("Buffer too small\n");
1051 Status
= STATUS_BUFFER_TOO_SMALL
;
1054 IoMarkIrpPending (Irp
);
1055 IoStartPacket (DeviceObject
,
1059 return STATUS_PENDING
;
1061 case IOCTL_CDROM_READ_TOC
:
1062 DPRINT("IOCTL_CDROM_READ_TOC\n");
1063 if (IrpStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(CDROM_TOC
))
1065 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1069 PCDROM_TOC TocBuffer
;
1072 TocBuffer
= Irp
->AssociatedIrp
.SystemBuffer
;
1074 /* First read the lead out */
1075 Length
= 4 + sizeof(TRACK_DATA
);
1076 Status
= CdromClassReadTocEntry(DeviceObject
,
1080 if (NT_SUCCESS(Status
))
1082 if (TocBuffer
->FirstTrack
== 0xaa)
1084 /* there is an empty cd */
1085 Information
= Length
;
1090 Length
= 4 + sizeof(TRACK_DATA
) * (TocBuffer
->LastTrack
- TocBuffer
->FirstTrack
+ 2);
1091 Status
= CdromClassReadTocEntry(DeviceObject
,
1092 TocBuffer
->FirstTrack
,
1094 if (NT_SUCCESS(Status
))
1096 Information
= Length
;
1103 case IOCTL_CDROM_GET_LAST_SESSION
:
1104 DPRINT("IOCTL_CDROM_GET_LAST_SESSION\n");
1105 if (IrpStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< 4 + sizeof(TRACK_DATA
))
1107 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1111 PCDROM_TOC TocBuffer
;
1114 TocBuffer
= Irp
->AssociatedIrp
.SystemBuffer
;
1115 Length
= 4 + sizeof(TRACK_DATA
);
1116 Status
= CdromClassReadLastSession(DeviceObject
,
1120 if (NT_SUCCESS(Status
))
1122 Information
= Length
;
1128 /* Call the common device control function */
1129 return(ScsiClassDeviceControl(DeviceObject
, Irp
));
1132 /* Verify the device if the user caused the error */
1133 if (!NT_SUCCESS(Status
) && IoIsErrorUserInduced(Status
))
1135 IoSetHardErrorOrVerifyDevice(Irp
, DeviceObject
);
1138 Irp
->IoStatus
.Status
= Status
;
1139 Irp
->IoStatus
.Information
= Information
;
1140 IoCompleteRequest(Irp
,
1147 /**********************************************************************
1152 * Starts IRP processing.
1160 * Standard dispatch arguments
1166 CdromClassStartIo (IN PDEVICE_OBJECT DeviceObject
,
1169 PDEVICE_EXTENSION DeviceExtension
;
1170 PIO_STACK_LOCATION IrpStack
;
1171 PIO_STACK_LOCATION SubIrpStack
;
1172 ULONG MaximumTransferLength
;
1173 ULONG TransferPages
;
1174 PSCSI_REQUEST_BLOCK Srb
;
1180 DPRINT("CdromClassStartIo() called!\n");
1182 IoMarkIrpPending (Irp
);
1184 DeviceExtension
= (PDEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
1185 IrpStack
= IoGetCurrentIrpStackLocation (Irp
);
1187 MaximumTransferLength
= DeviceExtension
->PortCapabilities
->MaximumTransferLength
;
1189 if (DeviceObject
->Flags
& DO_VERIFY_VOLUME
)
1191 if (!(IrpStack
->Flags
& SL_OVERRIDE_VERIFY_VOLUME
))
1193 DPRINT1 ("Verify required\n");
1195 if (Irp
->Tail
.Overlay
.Thread
)
1197 IoSetHardErrorOrVerifyDevice (Irp
,
1200 Irp
->IoStatus
.Status
= STATUS_VERIFY_REQUIRED
;
1202 /* FIXME: Update drive capacity */
1203 IoCompleteRequest (Irp
,
1205 IoStartNextPacket (DeviceObject
,
1211 if (IrpStack
->MajorFunction
== IRP_MJ_READ
)
1213 DPRINT ("CdromClassStartIo: IRP_MJ_READ\n");
1216 ADDRESS_AND_SIZE_TO_SPAN_PAGES (MmGetMdlVirtualAddress(Irp
->MdlAddress
),
1217 IrpStack
->Parameters
.Read
.Length
);
1219 /* Check transfer size */
1220 if ((IrpStack
->Parameters
.Read
.Length
> MaximumTransferLength
) ||
1221 (TransferPages
> DeviceExtension
->PortCapabilities
->MaximumPhysicalPages
))
1223 /* Transfer size is too large - split it */
1225 DeviceExtension
->PortCapabilities
->MaximumPhysicalPages
- 1;
1227 /* Adjust transfer size */
1228 if (MaximumTransferLength
> TransferPages
* PAGE_SIZE
)
1229 MaximumTransferLength
= TransferPages
* PAGE_SIZE
;
1231 if (MaximumTransferLength
== 0)
1232 MaximumTransferLength
= PAGE_SIZE
;
1234 /* Split the transfer */
1235 ScsiClassSplitRequest (DeviceObject
,
1237 MaximumTransferLength
);
1243 ScsiClassBuildRequest (DeviceObject
,
1247 else if (IrpStack
->MajorFunction
== IRP_MJ_DEVICE_CONTROL
)
1249 DPRINT ("CdromClassStartIo: IRP_MJ_IRP_MJ_DEVICE_CONTROL\n");
1251 /* Allocate an IRP for sending requests to the port driver */
1252 SubIrp
= IoAllocateIrp ((CCHAR
)(DeviceObject
->StackSize
+ 1),
1256 Irp
->IoStatus
.Information
= 0;
1257 Irp
->IoStatus
.Status
= STATUS_INSUFFICIENT_RESOURCES
;
1258 IoCompleteRequest (Irp
,
1260 IoStartNextPacket (DeviceObject
,
1265 /* Allocate an SRB */
1266 Srb
= ExAllocatePool (NonPagedPool
,
1267 sizeof (SCSI_REQUEST_BLOCK
));
1271 Irp
->IoStatus
.Information
= 0;
1272 Irp
->IoStatus
.Status
= STATUS_INSUFFICIENT_RESOURCES
;
1273 IoCompleteRequest (Irp
,
1275 IoStartNextPacket (DeviceObject
,
1280 /* Allocte a sense buffer */
1281 SenseBuffer
= ExAllocatePool (NonPagedPoolCacheAligned
,
1283 if (SenseBuffer
== NULL
)
1287 Irp
->IoStatus
.Information
= 0;
1288 Irp
->IoStatus
.Status
= STATUS_INSUFFICIENT_RESOURCES
;
1289 IoCompleteRequest (Irp
,
1291 IoStartNextPacket (DeviceObject
,
1296 /* Initialize the IRP */
1297 IoSetNextIrpStackLocation (SubIrp
);
1298 SubIrp
->IoStatus
.Information
= 0;
1299 SubIrp
->IoStatus
.Status
= STATUS_SUCCESS
;
1301 SubIrp
->UserBuffer
= NULL
;
1303 SubIrpStack
= IoGetCurrentIrpStackLocation (SubIrp
);
1304 SubIrpStack
->DeviceObject
= DeviceExtension
->DeviceObject
;
1305 SubIrpStack
->Parameters
.Others
.Argument2
= (PVOID
)Irp
;
1307 /* Initialize next stack location */
1308 SubIrpStack
= IoGetNextIrpStackLocation (SubIrp
);
1309 SubIrpStack
->MajorFunction
= IRP_MJ_SCSI
;
1310 SubIrpStack
->Parameters
.DeviceIoControl
.IoControlCode
= IOCTL_SCSI_EXECUTE_IN
;
1311 SubIrpStack
->Parameters
.Scsi
.Srb
= Srb
;
1313 /* Initialize the SRB */
1315 sizeof (SCSI_REQUEST_BLOCK
));
1316 Srb
->Length
= sizeof (SCSI_REQUEST_BLOCK
);
1317 Srb
->PathId
= DeviceExtension
->PathId
;
1318 Srb
->TargetId
= DeviceExtension
->TargetId
;
1319 Srb
->Lun
= DeviceExtension
->Lun
;
1320 Srb
->Function
= SRB_FUNCTION_EXECUTE_SCSI
;
1321 Srb
->SrbStatus
= SRB_STATUS_SUCCESS
;
1322 Srb
->ScsiStatus
= 0;
1324 Srb
->OriginalRequest
= SubIrp
;
1325 Srb
->SenseInfoBuffer
= SenseBuffer
;
1326 Srb
->SenseInfoBufferLength
= SENSE_BUFFER_SIZE
;
1328 /* Initialize the CDB */
1329 Cdb
= (PCDB
)Srb
->Cdb
;
1331 /* Set the completion routine */
1332 IoSetCompletionRoutine (SubIrp
,
1333 CdromDeviceControlCompletion
,
1339 switch (IrpStack
->Parameters
.DeviceIoControl
.IoControlCode
)
1341 case IOCTL_CDROM_GET_DRIVE_GEOMETRY
:
1342 DPRINT ("CdromClassStartIo: IOCTL_CDROM_GET_DRIVE_GEOMETRY\n");
1343 Srb
->DataTransferLength
= sizeof(READ_CAPACITY_DATA
);
1344 Srb
->CdbLength
= 10;
1345 Srb
->TimeOutValue
= DeviceExtension
->TimeOutValue
;
1346 Srb
->SrbFlags
= SRB_FLAGS_DISABLE_SYNCH_TRANSFER
| SRB_FLAGS_DATA_IN
;
1347 Cdb
->CDB10
.OperationCode
= SCSIOP_READ_CAPACITY
;
1349 /* Allocate data buffer */
1350 DataBuffer
= ExAllocatePool (NonPagedPoolCacheAligned
,
1351 sizeof(READ_CAPACITY_DATA
));
1352 if (DataBuffer
== NULL
)
1354 Irp
->IoStatus
.Information
= 0;
1355 Irp
->IoStatus
.Status
= STATUS_INSUFFICIENT_RESOURCES
;
1356 IoCompleteRequest (Irp
,
1358 ExFreePool (SenseBuffer
);
1361 IoStartNextPacket (DeviceObject
,
1366 /* Allocate an MDL for the data buffer */
1367 SubIrp
->MdlAddress
= IoAllocateMdl (DataBuffer
,
1368 sizeof(READ_CAPACITY_DATA
),
1372 if (SubIrp
->MdlAddress
== NULL
)
1374 Irp
->IoStatus
.Information
= 0;
1375 Irp
->IoStatus
.Status
= STATUS_INSUFFICIENT_RESOURCES
;
1376 IoCompleteRequest (Irp
,
1378 ExFreePool (DataBuffer
);
1379 ExFreePool (SenseBuffer
);
1382 IoStartNextPacket (DeviceObject
,
1387 MmBuildMdlForNonPagedPool (SubIrp
->MdlAddress
);
1388 Srb
->DataBuffer
= DataBuffer
;
1390 IoCallDriver (DeviceExtension
->PortDeviceObject
,
1394 case IOCTL_CDROM_CHECK_VERIFY
:
1395 DPRINT ("CdromClassStartIo: IOCTL_CDROM_CHECK_VERIFY\n");
1397 Srb
->TimeOutValue
= DeviceExtension
->TimeOutValue
* 2;
1398 Srb
->SrbFlags
= SRB_FLAGS_NO_DATA_TRANSFER
;
1399 Cdb
->CDB6GENERIC
.OperationCode
= SCSIOP_TEST_UNIT_READY
;
1401 IoCallDriver (DeviceExtension
->PortDeviceObject
,
1406 IoCompleteRequest (Irp
,
1412 /* Call the SCSI port driver */
1413 IoCallDriver (DeviceExtension
->PortDeviceObject
,
1419 CdromDeviceControlCompletion (IN PDEVICE_OBJECT DeviceObject
,
1423 PDEVICE_EXTENSION DeviceExtension
;
1424 PDEVICE_EXTENSION PhysicalExtension
;
1425 PIO_STACK_LOCATION IrpStack
;
1426 PIO_STACK_LOCATION OrigCurrentIrpStack
;
1427 PIO_STACK_LOCATION OrigNextIrpStack
;
1428 PSCSI_REQUEST_BLOCK Srb
;
1433 DPRINT ("CdromDeviceControlCompletion() called\n");
1435 DeviceExtension
= (PDEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
1436 PhysicalExtension
= (PDEVICE_EXTENSION
)DeviceExtension
->PhysicalDevice
->DeviceExtension
;
1437 Srb
= (PSCSI_REQUEST_BLOCK
) Context
;
1439 IrpStack
= IoGetCurrentIrpStackLocation (Irp
);
1441 /* Get the original IRP */
1442 OrigIrp
= (PIRP
)IrpStack
->Parameters
.Others
.Argument2
;
1443 OrigCurrentIrpStack
= IoGetCurrentIrpStackLocation (OrigIrp
);
1444 OrigNextIrpStack
= IoGetNextIrpStackLocation (OrigIrp
);
1446 if (SRB_STATUS(Srb
->SrbStatus
) == SRB_STATUS_SUCCESS
)
1448 Status
= STATUS_SUCCESS
;
1452 DPRINT ("SrbStatus %lx\n", Srb
->SrbStatus
);
1454 /* Interpret sense info */
1455 Retry
= ScsiClassInterpretSenseInfo (DeviceObject
,
1457 IrpStack
->MajorFunction
,
1458 IrpStack
->Parameters
.DeviceIoControl
.IoControlCode
,
1459 MAXIMUM_RETRIES
- (ULONG
)OrigNextIrpStack
->Parameters
.Others
.Argument1
,
1461 DPRINT ("Retry %u\n", Retry
);
1463 if (Retry
== TRUE
&&
1464 (ULONG
)OrigNextIrpStack
->Parameters
.Others
.Argument1
> 0)
1466 DPRINT1 ("Try again (Retry count %lu)\n",
1467 (ULONG
)OrigNextIrpStack
->Parameters
.Others
.Argument1
);
1469 (ULONG
)OrigNextIrpStack
->Parameters
.Others
.Argument1
--;
1471 /* Release 'old' buffers */
1472 ExFreePool (Srb
->SenseInfoBuffer
);
1473 if (Srb
->DataBuffer
)
1474 ExFreePool(Srb
->DataBuffer
);
1477 if (Irp
->MdlAddress
!= NULL
)
1478 IoFreeMdl(Irp
->MdlAddress
);
1482 /* Call the StartIo routine again */
1483 CdromClassStartIo (DeviceObject
,
1486 return STATUS_MORE_PROCESSING_REQUIRED
;
1489 DPRINT ("Status %lx\n", Status
);
1492 if (NT_SUCCESS (Status
))
1494 switch (OrigCurrentIrpStack
->Parameters
.DeviceIoControl
.IoControlCode
)
1496 case IOCTL_CDROM_GET_DRIVE_GEOMETRY
:
1498 PREAD_CAPACITY_DATA CapacityBuffer
;
1502 DPRINT ("CdromClassControlCompletion: IOCTL_CDROM_GET_DRIVE_GEOMETRY\n");
1504 CapacityBuffer
= (PREAD_CAPACITY_DATA
)Srb
->DataBuffer
;
1505 SectorSize
= (((PUCHAR
)&CapacityBuffer
->BytesPerBlock
)[0] << 24) |
1506 (((PUCHAR
)&CapacityBuffer
->BytesPerBlock
)[1] << 16) |
1507 (((PUCHAR
)&CapacityBuffer
->BytesPerBlock
)[2] << 8) |
1508 ((PUCHAR
)&CapacityBuffer
->BytesPerBlock
)[3];
1510 LastSector
= (((PUCHAR
)&CapacityBuffer
->LogicalBlockAddress
)[0] << 24) |
1511 (((PUCHAR
)&CapacityBuffer
->LogicalBlockAddress
)[1] << 16) |
1512 (((PUCHAR
)&CapacityBuffer
->LogicalBlockAddress
)[2] << 8) |
1513 ((PUCHAR
)&CapacityBuffer
->LogicalBlockAddress
)[3];
1515 if (SectorSize
== 0)
1517 DeviceExtension
->DiskGeometry
->BytesPerSector
= SectorSize
;
1519 DeviceExtension
->PartitionLength
.QuadPart
= (LONGLONG
)(LastSector
+ 1);
1520 WHICH_BIT(DeviceExtension
->DiskGeometry
->BytesPerSector
,
1521 DeviceExtension
->SectorShift
);
1522 DeviceExtension
->PartitionLength
.QuadPart
=
1523 (DeviceExtension
->PartitionLength
.QuadPart
<< DeviceExtension
->SectorShift
);
1525 if (DeviceObject
->Characteristics
& FILE_REMOVABLE_MEDIA
)
1527 DeviceExtension
->DiskGeometry
->MediaType
= RemovableMedia
;
1531 DeviceExtension
->DiskGeometry
->MediaType
= FixedMedia
;
1533 DeviceExtension
->DiskGeometry
->Cylinders
.QuadPart
=
1534 (LONGLONG
)((LastSector
+ 1)/(32 * 64));
1535 DeviceExtension
->DiskGeometry
->SectorsPerTrack
= 32;
1536 DeviceExtension
->DiskGeometry
->TracksPerCylinder
= 64;
1538 RtlCopyMemory (OrigIrp
->AssociatedIrp
.SystemBuffer
,
1539 DeviceExtension
->DiskGeometry
,
1540 sizeof(DISK_GEOMETRY
));
1541 OrigIrp
->IoStatus
.Information
= sizeof(DISK_GEOMETRY
);
1545 case IOCTL_CDROM_CHECK_VERIFY
:
1546 DPRINT ("CdromDeviceControlCompletion: IOCTL_CDROM_CHECK_VERIFY\n");
1547 if (OrigCurrentIrpStack
->Parameters
.DeviceIoControl
.OutputBufferLength
!= 0)
1549 /* Return the media change counter */
1550 *((PULONG
)(OrigIrp
->AssociatedIrp
.SystemBuffer
)) =
1551 PhysicalExtension
->MediaChangeCount
;
1552 OrigIrp
->IoStatus
.Information
= sizeof(ULONG
);
1556 OrigIrp
->IoStatus
.Information
= 0;
1561 OrigIrp
->IoStatus
.Information
= 0;
1562 Status
= STATUS_INVALID_DEVICE_REQUEST
;
1567 /* Release the SRB and associated buffers */
1570 DPRINT("Srb %p\n", Srb
);
1572 if (Srb
->DataBuffer
!= NULL
)
1573 ExFreePool (Srb
->DataBuffer
);
1575 if (Srb
->SenseInfoBuffer
!= NULL
)
1576 ExFreePool (Srb
->SenseInfoBuffer
);
1581 if (OrigIrp
->PendingReturned
)
1583 IoMarkIrpPending (OrigIrp
);
1586 /* Release the MDL */
1587 if (Irp
->MdlAddress
!= NULL
)
1589 IoFreeMdl (Irp
->MdlAddress
);
1592 /* Release the sub irp */
1595 /* Set io status information */
1596 OrigIrp
->IoStatus
.Status
= Status
;
1597 if (!NT_SUCCESS(Status
) && IoIsErrorUserInduced (Status
))
1599 IoSetHardErrorOrVerifyDevice (OrigIrp
,
1601 OrigIrp
->IoStatus
.Information
= 0;
1604 /* Complete the original IRP */
1605 IoCompleteRequest (OrigIrp
,
1607 IoStartNextPacket (DeviceObject
,
1610 DPRINT ("CdromDeviceControlCompletion() done\n");
1612 return STATUS_MORE_PROCESSING_REQUIRED
;
1617 CdromTimerRoutine(IN PDEVICE_OBJECT DeviceObject
,
1620 PIO_WORKITEM WorkItem
;
1622 DPRINT ("CdromTimerRoutine() called\n");
1623 WorkItem
= IoAllocateWorkItem(DeviceObject
);
1629 IoQueueWorkItem(WorkItem
,
1637 CdromWorkItem(IN PDEVICE_OBJECT DeviceObject
,
1642 IO_STATUS_BLOCK IoStatus
;
1645 DPRINT("CdromWorkItem() called\n");
1647 IoFreeWorkItem((PIO_WORKITEM
) Context
);
1649 KeInitializeEvent(&Event
,
1653 Irp
= IoBuildDeviceIoControlRequest(IOCTL_CDROM_CHECK_VERIFY
,
1664 DPRINT("IoBuildDeviceIoControlRequest failed\n");
1668 Status
= IoCallDriver(DeviceObject
, Irp
);
1669 DPRINT("Status: %x\n", Status
);
1671 if (Status
== STATUS_PENDING
)
1673 KeWaitForSingleObject(&Event
,