📄 cdrom.c
字号:
deviceExtension->PhysicalDevice = deviceObject;
//
// Initialize lock count to zero. The lock count is used to
// disable the ejection mechanism when media is mounted.
//
deviceExtension->LockCount = 0;
//
// Save system cdrom number
//
deviceExtension->DeviceNumber = *DeviceCount;
//
// Copy port device object to device extension.
//
deviceExtension->PortDeviceObject = PortDeviceObject;
//
// Set the alignment requirements for the device based on the
// host adapter requirements
//
if (PortDeviceObject->AlignmentRequirement > deviceObject->AlignmentRequirement) {
deviceObject->AlignmentRequirement = PortDeviceObject->AlignmentRequirement;
}
//
// Save address of port driver capabilities.
//
deviceExtension->PortCapabilities = PortCapabilities;
//
// Clear SRB flags.
//
deviceExtension->SrbFlags = 0;
deviceExtension->SrbFlags |= SRB_FLAGS_DISABLE_SYNCH_TRANSFER;
//
// Allocate request sense buffer.
//
senseData = ExAllocatePool(NonPagedPoolCacheAligned, SENSE_BUFFER_SIZE);
if (senseData == NULL) {
//
// The buffer cannot be allocated.
//
status = STATUS_INSUFFICIENT_RESOURCES;
goto CreateCdRomDeviceObjectExit;
}
//
// Set the sense data pointer in the device extension.
//
deviceExtension->SenseData = senseData;
//
// CDROMs are not partitionable so starting offset is 0.
//
deviceExtension->StartingOffset.LowPart = 0;
deviceExtension->StartingOffset.HighPart = 0;
//
// Path/TargetId/LUN describes a device location on the SCSI bus.
// This information comes from the LunInfo buffer.
//
deviceExtension->PortNumber = (UCHAR)PortNumber;
deviceExtension->PathId = LunInfo->PathId;
deviceExtension->TargetId = LunInfo->TargetId;
deviceExtension->Lun = LunInfo->Lun;
//
// Set timeout value in seconds.
//
timeOut = ScsiClassQueryTimeOutRegistryValue(RegistryPath);
if (timeOut) {
deviceExtension->TimeOutValue = timeOut;
} else {
deviceExtension->TimeOutValue = SCSI_CDROM_TIMEOUT;
}
//
// Build the lookaside list for srb's for the physical disk. Should only
// need a couple.
//
ScsiClassInitializeSrbLookasideList(deviceExtension,
CDROM_SRB_LIST_SIZE);
srbListInitialized = TRUE;
//
// Back pointer to device object.
//
deviceExtension->DeviceObject = deviceObject;
//
// Allocate buffer for drive geometry.
//
deviceExtension->DiskGeometry =
ExAllocatePool(NonPagedPool, sizeof(DISK_GEOMETRY));
if (deviceExtension->DiskGeometry == NULL) {
status = STATUS_INSUFFICIENT_RESOURCES;
goto CreateCdRomDeviceObjectExit;
}
//
// Set up media change support defaults.
//
cddata = (PCDROM_DATA)(deviceExtension + 1);
KeInitializeSpinLock(&cddata->FormSpinLock);
KeInitializeSpinLock(&cddata->TimerIrpSpinLock);
InitializeListHead(&cddata->TimerIrpList);
cddata->MediaChangeCountDown = MEDIA_CHANGE_DEFAULT_TIME;
cddata->MediaChangeSupported = FALSE;
cddata->MediaChange = FALSE;
//
// Assume that there is initially no media in the device
// only notify upper layers if there is something there
//
deviceExtension->MediaChangeNoMedia = TRUE;
cddata->MediaChangeIrp = NULL;
#ifdef DBG
cddata->MediaChangeIrpTimeInUse = 0;
cddata->MediaChangeIrpLost = FALSE;
#endif
//
// Scan for Scsi controllers that require special processing.
//
ScanForSpecial(deviceObject,
(PINQUIRYDATA) LunInfo->InquiryData,
PortCapabilities);
//
// 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.
//
status = ScsiClassReadDriveCapacity(deviceObject);
bps = deviceExtension->DiskGeometry->BytesPerSector;
if (!NT_SUCCESS(status) || !bps) {
DebugPrint((1,
"CreateCdRomDeviceObjects: Can't read capacity for device %s\n",
ntNameBuffer));
//
// Set disk geometry to default values (per ISO 9660).
//
bps = 2048;
deviceExtension->SectorShift = 11;
deviceExtension->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;
}
deviceExtension->DiskGeometry->BytesPerSector = bps;
DebugPrint((2, "CreateCdRomDeviceObject: Calc'd bps = %x\n", bps));
//
// Check to see if this is some sort of changer device
//
changerDevice = FALSE;
//
// Search for devices that have special requirements for media
// change support.
//
if (deviceExtension->Lun > 0) {
changerDevice = TRUE;
}
if (!changerDevice) {
changerDevice = IsThisASanyo(deviceObject, deviceExtension->PathId,
deviceExtension->TargetId);
}
if (!changerDevice) {
ULONG tmp;
changerDevice = IsThisAnAtapiChanger(deviceObject, &tmp);
}
if (!changerDevice) {
changerDevice = IsThisAMultiLunDevice(deviceObject, PortDeviceObject);
}
//
// If it is a changer device, increment the timeout to take platter-swapping
// time into account
//
if(changerDevice) {
deviceExtension->TimeOutValue += SCSI_CHANGER_BONUS_TIMEOUT;
}
//
// Create the media change named event. If this succeeds then continue
// initializing the media change support data items.
//
CdRomCreateNamedEvent(deviceExtension,*DeviceCount);
if (deviceExtension->MediaChangeEvent) {
//
// If this is not a changer, get an IRP for the timer request
// and initialize the timer.
//
if (!changerDevice) {
//
// Not a changer device - continue with media change initialization.
// Determine if the user actually wants media change events.
//
if (CdRomCheckRegistryForMediaChangeValue(RegistryPath, *DeviceCount)) {
PIO_STACK_LOCATION irpStack;
PSCSI_REQUEST_BLOCK srb;
PIRP irp;
//
// User wants it - preallocate IRP and SRB.
//
irp = IoAllocateIrp((CCHAR)(deviceObject->StackSize+1),
FALSE);
if (irp) {
PVOID buffer;
srb = ExAllocatePool(NonPagedPool, sizeof(SCSI_REQUEST_BLOCK));
buffer = ExAllocatePool(NonPagedPoolCacheAligned, SENSE_BUFFER_SIZE);
if (srb && buffer) {
PCDB cdb;
//
// All resources have been allocated set up the IRP.
//
IoSetNextIrpStackLocation(irp);
irpStack = IoGetCurrentIrpStackLocation(irp);
irpStack->DeviceObject = deviceObject;
irpStack = IoGetNextIrpStackLocation(irp);
cddata->MediaChangeIrp = irp;
irpStack->Parameters.Scsi.Srb = srb;
//
// Initialize the SRB
//
RtlZeroMemory(srb, sizeof(SCSI_REQUEST_BLOCK));
srb->CdbLength = 6;
srb->TimeOutValue = deviceExtension->TimeOutValue * 2;
srb->QueueTag = SP_UNTAGGED;
srb->QueueAction = SRB_SIMPLE_TAG_REQUEST;
srb->Length = SCSI_REQUEST_BLOCK_SIZE;
srb->PathId = deviceExtension->PathId;
srb->TargetId = deviceExtension->TargetId;
srb->Lun = deviceExtension->Lun;
srb->Function = SRB_FUNCTION_EXECUTE_SCSI;
//
// Initialize and set up the sense information buffer
//
RtlZeroMemory(buffer, SENSE_BUFFER_SIZE);
srb->SenseInfoBuffer = buffer;
srb->SenseInfoBufferLength = SENSE_BUFFER_SIZE;
//
// Initialize the CDB
//
cdb = (PCDB)&srb->Cdb[0];
cdb->CDB6GENERIC.OperationCode = SCSIOP_TEST_UNIT_READY;
cdb->CDB6GENERIC.LogicalUnitNumber = deviceExtension->Lun;
//
// It is ok to support media change events on this device.
//
cddata->MediaChangeSupported = TRUE;
cddata->MediaChange = TRUE;
} else {
if (srb) {
ExFreePool(srb);
}
if (buffer) {
ExFreePool(buffer);
}
IoFreeIrp(irp);
}
}
} else {
deviceExtension->MediaChangeEvent = NULL;
}
} else {
deviceExtension->MediaChangeEvent = NULL;
}
}
//
// Assume use of 6-byte mode sense/select for now.
//
cddata->XAFlags |= XA_USE_6_BYTE;
//
// Build and issue mode sense with Read error recovery page. This will be used to change
// block size in case of any raw reads (Mode 2, Form 2).
//
length = (sizeof(MODE_READ_RECOVERY_PAGE) + MODE_BLOCK_DESC_LENGTH + MODE_HEADER_LENGTH);
RtlZeroMemory(&srb, sizeof(SCSI_REQUEST_BLOCK));
srb.CdbLength = 6;
cdb = (PCDB)srb.Cdb;
//
// Set timeout value from device extension.
//
srb.TimeOutValue = deviceExtension->TimeOutValue;
//
// Build the MODE SENSE CDB. The data returned will be kept in the device extension
// and used to set block size.
//
cdb->MODE_SENSE.OperationCode = SCSIOP_MODE_SENSE;
cdb->MODE_SENSE.PageCode = 0x1;
cdb->MODE_SENSE.AllocationLength = (UCHAR)length;
buffer = ExAllocatePool(NonPagedPoolCacheAligned, (sizeof(MODE_READ_RECOVERY_PAGE) + MODE_BLOCK_DESC_LENGTH + MODE_HEADER_LENGTH10));
if (!buffer) {
status = STATUS_INSUFFICIENT_RESOURCES;
goto CreateCdRomDeviceObjectExit;
}
status = ScsiClassSendSrbSynchronous(deviceObject,
&srb,
buffer,
length,
FALSE);
if (!NT_SUCCESS(status)) {
//
// May be Atapi, try 10-byte.
//
length = (sizeof(MODE_READ_RECOVERY_PAGE) + MODE_BLOCK_DESC_LENGTH + MODE_HEADER_LENGTH10);
RtlZeroMemory(&srb, sizeof(SCSI_REQUEST_BLOCK));
//
// Build the MODE SENSE CDB.
//
srb.CdbLength = 10;
cdb = (PCDB)srb.Cdb;
//
// Set timeout value from device extension.
//
srb.TimeOutValue = deviceExtension->TimeOutValue;
cdb->MODE_SENSE10.OperationCode = SCSIOP_MODE_SENSE10;
cdb->MODE_SENSE10.PageCode = 0x1;
cdb->MODE_SENSE10.AllocationLength[0] = (UCHAR)(length >> 8);
cdb->MODE_SENSE10.AllocationLength[1] = (UCHAR)(length & 0xFF);
status = ScsiClassSendSrbSynchronous(deviceObject,
&srb,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -