📄 cdrom.c
字号:
// Build SRB and CDB for this IRP.
//
ScsiClassBuildRequest(DeviceObject, Irp);
}
} else if (currentIrpStack->MajorFunction == IRP_MJ_DEVICE_CONTROL) {
//
// Allocate an irp, srb and associated structures.
//
irp2 = IoAllocateIrp((CCHAR)(deviceExtension->DeviceObject->StackSize+1),
FALSE);
if (!irp2) {
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
IoCompleteRequest(Irp, IO_DISK_INCREMENT);
IoStartNextPacket(DeviceObject, FALSE);
DebugPrint((2, "ScsiCdRomStartIo: [%lx] bailing with status %lx at line %s\n", Irp, Irp->IoStatus.Status, __LINE__));
return;
}
srb = ExAllocatePool(NonPagedPool, sizeof(SCSI_REQUEST_BLOCK));
if (!srb) {
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
IoCompleteRequest(Irp, IO_DISK_INCREMENT);
IoFreeIrp(irp2);
IoStartNextPacket(DeviceObject, FALSE);
DebugPrint((2, "ScsiCdRomStartIo: [%lx] bailing with status %lx at line %s\n", Irp, Irp->IoStatus.Status, __LINE__));
return;
}
RtlZeroMemory(srb, sizeof(SCSI_REQUEST_BLOCK));
cdb = (PCDB)srb->Cdb;
//
// Allocate sense buffer.
//
senseBuffer = ExAllocatePool(NonPagedPoolCacheAligned, SENSE_BUFFER_SIZE);
if (!senseBuffer) {
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
IoCompleteRequest(Irp, IO_DISK_INCREMENT);
ExFreePool(srb);
IoFreeIrp(irp2);
IoStartNextPacket(DeviceObject, FALSE);
DebugPrint((2, "ScsiCdRomStartIo: [%lx] bailing with status %lx at line %s\n", Irp, Irp->IoStatus.Status, __LINE__));
return;
}
//
// Set up the irp.
//
IoSetNextIrpStackLocation(irp2);
irp2->IoStatus.Status = STATUS_SUCCESS;
irp2->IoStatus.Information = 0;
irp2->Flags = 0;
irp2->UserBuffer = NULL;
//
// Save the device object and irp in a private stack location.
//
irpStack = IoGetCurrentIrpStackLocation(irp2);
irpStack->DeviceObject = deviceExtension->DeviceObject;
irpStack->Parameters.Others.Argument2 = (PVOID) Irp;
//
// The retry count will be in the real Irp, as the retry logic will
// recreate our private irp.
//
if (!(nextIrpStack->Parameters.Others.Argument1)) {
//
// Only jam this in if it doesn't exist. The completion routines can
// call StartIo directly in the case of retries and resetting it will
// cause infinite loops.
//
nextIrpStack->Parameters.Others.Argument1 = (PVOID) MAXIMUM_RETRIES;
}
//
// Construct the IRP stack for the lower level driver.
//
irpStack = IoGetNextIrpStackLocation(irp2);
irpStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
irpStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_SCSI_EXECUTE_IN;
irpStack->Parameters.Scsi.Srb = srb;
IoSetCompletionRoutine(irp2,
CdRomDeviceControlCompletion,
srb,
TRUE,
TRUE,
TRUE);
//
// Setup those fields that are generic to all requests.
//
srb->Length = SCSI_REQUEST_BLOCK_SIZE;
srb->PathId = deviceExtension->PathId;
srb->TargetId = deviceExtension->TargetId;
srb->Lun = deviceExtension->Lun;
srb->Function = SRB_FUNCTION_EXECUTE_SCSI;
srb->Cdb[1] |= deviceExtension->Lun << 5;
srb->SrbStatus = srb->ScsiStatus = 0;
srb->NextSrb = 0;
srb->OriginalRequest = irp2;
srb->SenseInfoBufferLength = SENSE_BUFFER_SIZE;
srb->SenseInfoBuffer = senseBuffer;
switch (currentIrpStack->Parameters.DeviceIoControl.IoControlCode) {
case IOCTL_CDROM_RAW_READ: {
//
// Determine whether the drive is currently in raw or cooked mode,
// and which command to use to read the data.
//
if (!(cdData->XAFlags & XA_USE_READ_CD)) {
PRAW_READ_INFO rawReadInfo =
(PRAW_READ_INFO)currentIrpStack->Parameters.DeviceIoControl.Type3InputBuffer;
ULONG maximumTransferLength;
ULONG transferPages;
if (cdData->RawAccess) {
ULONG startingSector;
UCHAR min, sec, frame;
//
// Free the recently allocated irp, as we don't need it.
//
IoFreeIrp(irp2);
cdb = (PCDB)srb->Cdb;
RtlZeroMemory(cdb, 12);
//
// Calculate starting offset.
//
startingSector = (ULONG)(rawReadInfo->DiskOffset.QuadPart >> deviceExtension->SectorShift);
transferByteCount = rawReadInfo->SectorCount * RAW_SECTOR_SIZE;
maximumTransferLength = deviceExtension->PortCapabilities->MaximumTransferLength;
transferPages = ADDRESS_AND_SIZE_TO_SPAN_PAGES(MmGetMdlVirtualAddress(Irp->MdlAddress),
transferByteCount);
//
// Determine if request is within limits imposed by miniport.
//
if (transferByteCount > maximumTransferLength ||
transferPages > deviceExtension->PortCapabilities->MaximumPhysicalPages) {
//
// The claim is that this won't happen, and is backed up by
// ActiveMovie usage, which does unbuffered XA reads of 0x18000, yet
// we get only 4 sector requests.
//
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
IoCompleteRequest(Irp, IO_DISK_INCREMENT);
ExFreePool(senseBuffer);
ExFreePool(srb);
IoStartNextPacket(DeviceObject, FALSE);
return;
}
srb->OriginalRequest = Irp;
srb->SrbFlags = deviceExtension->SrbFlags;
srb->SrbFlags |= (SRB_FLAGS_DISABLE_SYNCH_TRANSFER | SRB_FLAGS_DATA_IN);
srb->DataTransferLength = transferByteCount;
srb->TimeOutValue = deviceExtension->TimeOutValue;
srb->CdbLength = 10;
srb->DataBuffer = MmGetMdlVirtualAddress(Irp->MdlAddress);
if (rawReadInfo->TrackMode == CDDA) {
if (cdData->XAFlags & PLEXTOR_CDDA) {
srb->CdbLength = 12;
cdb->PLXTR_READ_CDDA.LogicalUnitNumber = deviceExtension->Lun;
cdb->PLXTR_READ_CDDA.LogicalBlockByte3 = (UCHAR) (startingSector & 0xFF);
cdb->PLXTR_READ_CDDA.LogicalBlockByte2 = (UCHAR) ((startingSector >> 8) & 0xFF);
cdb->PLXTR_READ_CDDA.LogicalBlockByte1 = (UCHAR) ((startingSector >> 16) & 0xFF);
cdb->PLXTR_READ_CDDA.LogicalBlockByte0 = (UCHAR) ((startingSector >> 24) & 0xFF);
cdb->PLXTR_READ_CDDA.TransferBlockByte3 = (UCHAR) (rawReadInfo->SectorCount & 0xFF);
cdb->PLXTR_READ_CDDA.TransferBlockByte2 = (UCHAR) (rawReadInfo->SectorCount >> 8);
cdb->PLXTR_READ_CDDA.TransferBlockByte1 = 0;
cdb->PLXTR_READ_CDDA.TransferBlockByte0 = 0;
cdb->PLXTR_READ_CDDA.SubCode = 0;
cdb->PLXTR_READ_CDDA.OperationCode = 0xD8;
} else if (cdData->XAFlags & NEC_CDDA) {
cdb->NEC_READ_CDDA.LogicalBlockByte3 = (UCHAR) (startingSector & 0xFF);
cdb->NEC_READ_CDDA.LogicalBlockByte2 = (UCHAR) ((startingSector >> 8) & 0xFF);
cdb->NEC_READ_CDDA.LogicalBlockByte1 = (UCHAR) ((startingSector >> 16) & 0xFF);
cdb->NEC_READ_CDDA.LogicalBlockByte0 = (UCHAR) ((startingSector >> 24) & 0xFF);
cdb->NEC_READ_CDDA.TransferBlockByte1 = (UCHAR) (rawReadInfo->SectorCount & 0xFF);
cdb->NEC_READ_CDDA.TransferBlockByte0 = (UCHAR) (rawReadInfo->SectorCount >> 8);
cdb->NEC_READ_CDDA.OperationCode = 0xD4;
}
} else {
cdb->CDB10.LogicalUnitNumber = deviceExtension->Lun;
cdb->CDB10.TransferBlocksMsb = (UCHAR) (rawReadInfo->SectorCount >> 8);
cdb->CDB10.TransferBlocksLsb = (UCHAR) (rawReadInfo->SectorCount & 0xFF);
cdb->CDB10.LogicalBlockByte3 = (UCHAR) (startingSector & 0xFF);
cdb->CDB10.LogicalBlockByte2 = (UCHAR) ((startingSector >> 8) & 0xFF);
cdb->CDB10.LogicalBlockByte1 = (UCHAR) ((startingSector >> 16) & 0xFF);
cdb->CDB10.LogicalBlockByte0 = (UCHAR) ((startingSector >> 24) & 0xFF);
cdb->CDB10.OperationCode = SCSIOP_READ;
}
srb->SrbStatus = srb->ScsiStatus = 0;
nextIrpStack->MajorFunction = IRP_MJ_SCSI;
nextIrpStack->Parameters.Scsi.Srb = srb;
if (!(nextIrpStack->Parameters.Others.Argument1)) {
//
// Only jam this in if it doesn't exist. The completion routines can
// call StartIo directly in the case of retries and resetting it will
// cause infinite loops.
//
nextIrpStack->Parameters.Others.Argument1 = (PVOID) MAXIMUM_RETRIES;
}
//
// Set up IoCompletion routine address.
//
IoSetCompletionRoutine(Irp,
CdRomXACompletion,
srb,
TRUE,
TRUE,
TRUE);
IoCallDriver(deviceExtension->PortDeviceObject, Irp);
return;
} else {
transferByteCount = (use6Byte) ? sizeof(ERROR_RECOVERY_DATA) : sizeof(ERROR_RECOVERY_DATA10);
dataBuffer = ExAllocatePool(NonPagedPoolCacheAligned, transferByteCount );
if (!dataBuffer) {
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
IoCompleteRequest(Irp, IO_DISK_INCREMENT);
ExFreePool(senseBuffer);
ExFreePool(srb);
IoFreeIrp(irp2);
IoStartNextPacket(DeviceObject, FALSE);
return;
}
irp2->MdlAddress = IoAllocateMdl(dataBuffer,
transferByteCount,
FALSE,
FALSE,
(PIRP) NULL);
if (!irp2->MdlAddress) {
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
IoCompleteRequest(Irp, IO_DISK_INCREMENT);
ExFreePool(senseBuffer);
ExFreePool(srb);
ExFreePool(dataBuffer);
IoFreeIrp(irp2);
IoStartNextPacket(DeviceObject, FALSE);
return;
}
//
// Prepare the MDL
//
MmBuildMdlForNonPagedPool(irp2->MdlAddress);
srb->DataBuffer = dataBuffer;
//
// Set the new block size in the descriptor.
//
cdData->u1.BlockDescriptor.BlockLength[0] = (UCHAR)(RAW_SECTOR_SIZE >> 16) & 0xFF;
cdData->u1.BlockDescriptor.BlockLength[1] = (UCHAR)(RAW_SECTOR_SIZE >> 8) & 0xFF;
cdData->u1.BlockDescriptor.BlockLength[2] = (UCHAR)(RAW_SECTOR_SIZE & 0xFF);
//
// TODO: Set density code, based on operation
//
cdData->u1.BlockDescriptor.DensityCode = 0;
//
// Move error page into dataBuffer.
//
RtlCopyMemory(srb->DataBuffer, &cdData->u1.Header, transferByteCount);
//
// Build and send a mode select to switch into raw mode.
//
srb->SrbFlags = deviceExtension->SrbFlags;
srb->SrbFlags |= (SRB_FLAGS_DISABLE_SYNCH_TRANSFER | SRB_FLAGS_DATA_OUT);
srb->DataTransferLength = transferByteCount;
srb->TimeOutValue = deviceExtension->TimeOutValue * 2;
if (use6Byte) {
srb->CdbLength = 6;
cdb->MODE_SELECT.OperationCode = SCSIOP_MODE_SELECT;
cdb->MODE_SELECT.PFBit = 1;
cdb->MODE_SELECT.ParameterListLength = (UCHAR)transferByteCount;
} else {
srb->CdbLength = 10;
cdb->MODE_SELECT10.OperationCode = SCSIOP_MODE_SELECT10;
cdb->MODE_SELECT10.PFBit = 1;
cdb->MODE_SELECT10.ParameterListLength[0] = (UCHAR)(transferByteCount >> 8);
cdb->MODE_SELECT10.ParameterListLength[1] = (UCHAR)(transferByteCount & 0xFF);
}
//
// Update completion routine.
//
IoSetCompletionRoutine(irp2,
CdRomSwitchModeCompletion,
srb,
TRUE,
TRUE,
TRUE);
}
} else {
PRAW_READ_INFO rawReadInfo =
(PRAW_READ_INFO)currentIrpStack->Parameters.DeviceIoControl.Type3InputBuffer;
ULONG startingSector;
//
// Free the recently allocated irp, as we don't need it.
//
IoFreeIrp(irp2);
cdb = (PCDB)srb->Cdb;
RtlZeroMemory(cdb, 12);
//
// Calculate starting offset.
//
startingSector = (ULONG)(rawReadInfo->DiskOffset.QuadPart >> deviceExtension->SectorShift);
transferByteCount = rawReadInfo->SectorCount * RAW_SECTOR_SIZE;
srb->OriginalRequest = Irp;
srb->SrbFlags = deviceExtension->SrbFlags;
srb->SrbFlags |= (SRB_FLAGS_DISABLE_SYNCH_TRANSFER | SRB_FLAGS_DATA_IN);
srb->DataTransferLength = transferByteCount;
srb->TimeOutValue = deviceExtension->TimeOutValue;
srb->DataBuffer = MmGetMdlVirtualAddress(Irp->MdlAddress);
srb->CdbLength = 12;
srb->SrbStatus = srb->ScsiStatus = 0;
//
// Fill in CDB fields.
//
cdb = (PCDB)srb->Cdb;
cdb->READ_CD.TransferBlocks[2] = (UCHAR) (rawReadInfo->SectorCount & 0xFF);
cdb->READ_CD.TransferBlocks[1] = (UCHAR) (rawReadInfo->SectorCount >> 8 );
cdb->READ_CD.TransferBlocks[0] = (UCHAR) (rawReadInfo->SectorCount >> 16);
cdb->READ_CD.StartingLBA[3] = (UCHAR) (startingSector & 0
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -