📄 cdrom.c
字号:
}
//
// Save the device descriptors
//
fdoExtension->AdapterDescriptor = NULL;
fdoExtension->DeviceDescriptor = NULL;
//
// Clear the SrbFlags and disable synchronous transfers
//
fdoExtension->SrbFlags = SRB_FLAGS_DISABLE_SYNCH_TRANSFER;
//
// Finally, attach to the PDO
//
fdoExtension->LowerPdo = PhysicalDeviceObject;
fdoExtension->CommonExtension.LowerDeviceObject =
IoAttachDeviceToDeviceStack(deviceObject, PhysicalDeviceObject);
if(fdoExtension->CommonExtension.LowerDeviceObject == NULL) {
//
// Uh - oh, we couldn't attach
// cleanup and return
//
status = STATUS_UNSUCCESSFUL;
goto CreateCdRomDeviceObjectExit;
}
//
// CdRom uses an extra stack location for synchronizing it's start io
// routine
//
deviceObject->StackSize++;
//
// cdData is used a few times below
//
cdData = fdoExtension->CommonExtension.DriverData;
//
// For NTMS to be able to easily determine drives-drv. letter matches.
//
status = CdRomCreateWellKnownName( deviceObject );
if (!NT_SUCCESS(status)) {
TraceLog((CdromDebugWarning,
"CdromCreateDeviceObjects: unable to create symbolic "
"link for device %wZ\n", &fdoExtension->CommonExtension.DeviceName));
TraceLog((CdromDebugWarning,
"CdromCreateDeviceObjects: (non-fatal error)\n"));
}
ClassUpdateInformationInRegistry(deviceObject, "CdRom",
fdoExtension->DeviceNumber, NULL, 0);
//
// from above IoGetAttachedDeviceReference
//
ObDereferenceObject(lowerDevice);
//
// need to init timerlist here in case a remove occurs
// without a start, since we check the list is empty on remove.
//
cdData->DelayedRetryIrp = NULL;
cdData->DelayedRetryInterval = 0;
//
// need this to be initialized for RPC Phase 1 drives (rpc0)
//
KeInitializeMutex(&cdData->Rpc0RegionMutex, 0);
//
// The device is initialized properly - mark it as such.
//
CLEAR_FLAG(deviceObject->Flags, DO_DEVICE_INITIALIZING);
return(STATUS_SUCCESS);
CreateCdRomDeviceObjectExit:
//
// Release the device since an error occured.
//
// ClassClaimDevice(PortDeviceObject,
// LunInfo,
// TRUE,
// NULL);
//
// from above IoGetAttachedDeviceReference
//
ObDereferenceObject(lowerDevice);
if (deviceObject != NULL) {
IoDeleteDevice(deviceObject);
}
return status;
} // end CreateCdRomDeviceObject()
NTSTATUS
CdRomInitDevice(
IN PDEVICE_OBJECT Fdo
)
/*++
Routine Description:
This routine will complete the cd-rom initialization. This includes
allocating sense info buffers and srb s-lists, reading drive capacity
and setting up Media Change Notification (autorun).
This routine will not clean up allocate resources if it fails - that
is left for device stop/removal
Arguments:
Fdo - a pointer to the functional device object for this device
Return Value:
status
--*/
{
PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = Fdo->DeviceExtension;
PCOMMON_DEVICE_EXTENSION commonExtension = Fdo->DeviceExtension;
PCLASS_DRIVER_EXTENSION driverExtension = ClassGetDriverExtension(
Fdo->DriverObject);
PVOID senseData = NULL;
ULONG timeOut;
PCDROM_DATA cddata = (PCDROM_DATA)(commonExtension->DriverData);
BOOLEAN changerDevice;
BOOLEAN isMmcDevice = FALSE;
ULONG bps;
ULONG lastBit;
NTSTATUS status;
PAGED_CODE();
//
// Build the lookaside list for srb's for the physical disk. Should only
// need a couple.
//
ClassInitializeSrbLookasideList(&(fdoExtension->CommonExtension),
CDROM_SRB_LIST_SIZE);
//
// Allocate request sense buffer.
//
senseData = ExAllocatePoolWithTag(NonPagedPoolCacheAligned,
SENSE_BUFFER_SIZE,
CDROM_TAG_SENSE_INFO);
if (senseData == NULL) {
//
// The buffer cannot be allocated.
//
status = STATUS_INSUFFICIENT_RESOURCES;
goto CdRomInitDeviceExit;
}
//
// Set the sense data pointer in the device extension.
//
fdoExtension->SenseData = senseData;
//
// CDROMs are not partitionable so starting offset is 0.
//
commonExtension->StartingOffset.LowPart = 0;
commonExtension->StartingOffset.HighPart = 0;
//
// Set timeout value in seconds.
//
timeOut = ClassQueryTimeOutRegistryValue(Fdo);
if ((timeOut != 0) && (timeOut <= 30 * 60)) { // 30 minutes
fdoExtension->TimeOutValue = timeOut;
} else {
fdoExtension->TimeOutValue = SCSI_CDROM_TIMEOUT;
}
//
// Set up media change support defaults.
//
KeInitializeSpinLock(&cddata->DelayedRetrySpinLock);
cddata->DelayedRetryIrp = NULL;
cddata->DelayedRetryInterval = 0;
cddata->Mmc.WriteAllowed = FALSE;
//
// Scan for controllers that require special processing.
//
ScanForSpecial(Fdo);
//
// Determine if the drive is MMC-Capable
//
CdRomIsDeviceMmcDevice(Fdo, &isMmcDevice);
if (!isMmcDevice) {
SET_FLAG(Fdo->Characteristics, FILE_READ_ONLY_DEVICE);
} else {
//
// the drive supports at least a subset of MMC commands
// (and therefore supports READ_CD, etc...)
//
cddata->Mmc.IsMmc = TRUE;
//
// allocate a buffer for all the capabilities and such
//
status = CdRomAllocateMmcResources(Fdo);
if (!NT_SUCCESS(status)) {
goto CdRomInitDeviceExit;
}
//
// if the drive supports target defect management and sector-addressable
// writes, then we should allow writes to the media.
//
if (CdRomFindFeaturePage(cddata->Mmc.CapabilitiesBuffer,
cddata->Mmc.CapabilitiesBufferSize,
FeatureDefectManagement) &&
CdRomFindFeaturePage(cddata->Mmc.CapabilitiesBuffer,
cddata->Mmc.CapabilitiesBufferSize,
FeatureRandomWritable)) {
//
// the drive is target defect managed, and supports random writes
// on sector-aligment. allow writes to occur by setting the error
// handler to point to a private media change detection handler.
//
KdPrintEx((DPFLTR_CDROM_ID, CdromDebugFeatures,
"Found a WRITE capable device: %p\n", Fdo));
//
// the write specific pages have been found --
// set the error handler and set it to require an update!
//
cddata->Mmc.UpdateState = CdromMmcUpdateRequired;
cddata->ErrorHandler = CdRomMmcErrorHandler;
}
//
// ISSUE-2000/4/4-henrygab - mmc-compliant compliant drives should
// be initialized based upon reported
// capabilities, such as CSS, Analogue Audio,
// READ_CD capabilities, and (possibly) even
// drive capacity information.
//
TraceLog((CdromDebugWarning,
"Defaulting to READ_CD because device %p is MMC compliant\n",
Fdo));
SET_FLAG(fdoExtension->DeviceFlags, DEV_SAFE_START_UNIT);
SET_FLAG(cddata->XAFlags, XA_USE_READ_CD);
}
//
// Set the default geometry for the cdrom to match what NT 4 used.
// Classpnp will use these values to compute the cylinder count rather
// than using it's NT 5.0 defaults.
//
fdoExtension->DiskGeometry.TracksPerCylinder = 0x40;
fdoExtension->DiskGeometry.SectorsPerTrack = 0x20;
//
// Do READ CAPACITY. This SCSI command returns the last sector address
// on the device and the bytes per sector. These are used to calculate
// the drive capacity in bytes.
//
// NOTE: This should be change to send the Srb synchronously, then
// call CdRomInterpretReadCapacity() to properly setup the defaults.
//
status = ClassReadDriveCapacity(Fdo);
bps = fdoExtension->DiskGeometry.BytesPerSector;
if (!NT_SUCCESS(status) || !bps) {
TraceLog((CdromDebugWarning,
"CdRomStartDevice: Can't read capacity for device %wZ\n",
&(fdoExtension->CommonExtension.DeviceName)));
//
// Set disk geometry to default values (per ISO 9660).
//
bps = 2048;
fdoExtension->SectorShift = 11;
commonExtension->PartitionLength.QuadPart = (LONGLONG)(0x7fffffff);
} else {
//
// Insure that bytes per sector is a power of 2
// This corrects a problem with the HP 4020i CDR where it
// returns an incorrect number for bytes per sector.
//
lastBit = (ULONG) -1;
while (bps) {
lastBit++;
bps = bps >> 1;
}
bps = 1 << lastBit;
}
fdoExtension->DiskGeometry.BytesPerSector = bps;
TraceLog((CdromDebugTrace, "CdRomInitDevice: Calc'd bps = %x\n", bps));
ClassInitializeMediaChangeDetection(fdoExtension, "CdRom");
//
// test for audio read capabilities
//
TraceLog((CdromDebugWarning,
"Detecting XA_READ capabilities\n"));
if (CdRomGetDeviceType(Fdo) == FILE_DEVICE_DVD) {
TraceLog((CdromDebugWarning,
"CdRomInitDevice: DVD Devices require START_UNIT\n"));
//
// all DVD devices must support the READ_CD command
//
TraceLog((CdromDebugWarning,
"CdRomDetermineRawReadCapabilities: DVD devices "
"support READ_CD command for FDO %p\n", Fdo));
SET_FLAG(fdoExtension->DeviceFlags, DEV_SAFE_START_UNIT);
SET_FLAG(cddata->XAFlags, XA_USE_READ_CD);
status = STATUS_SUCCESS;
} else if ((fdoExtension->DeviceDescriptor->BusType != BusTypeScsi) &&
(fdoExtension->DeviceDescriptor->BusType != BusTypeAta) &&
(fdoExtension->DeviceDescriptor->BusType != BusTypeAtapi) &&
(fdoExtension->DeviceDescriptor->BusType != BusTypeUnknown)
) {
//
// devices on the newer busses must support READ_CD command
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -