I’m writting a virtual miniport driver. When I need to handle Read10 and Write10 command, I build a new irp and send it to a physical scsi controller. Here is part of my code for Read10:
{
// Make srb
PSCSI_REQUEST_BLOCK newSrb = NULL;
PSENSE_DATA pSenseData = NULL;
PCDB pCdb10 = NULL;
newSrb = (PSCSI_REQUEST_BLOCK)ExAllocatePoolWithTag(NonPagedPool, sizeof(SCSI_REQUEST_BLOCK),0x12345678);
if (newSrb == NULL)
{
if (newSrb->SenseInfoBuffer && newSrb->SenseInfoBuffer != pSenseData)
{
ExFreePool(newSrb->SenseInfoBuffer);
}
if (newSrb != NULL)
{
ExFreePool(newSrb);
}
if (pSenseData != NULL)
{
ExFreePool(pSenseData);
}
SetSrbSenseCode(newSrb,NO_MEDIA_IN_DEVICE);
return TRUE;
}
pSenseData = (PSENSE_DATA)ExAllocatePoolWithTag(NonPagedPool, sizeof(SENSE_DATA),0x12345678);
if (pSenseData == NULL)
{
if (newSrb->SenseInfoBuffer && newSrb->SenseInfoBuffer != pSenseData)
{
ExFreePool(newSrb->SenseInfoBuffer);
}
if (newSrb != NULL)
{
ExFreePool(newSrb);
}
if (pSenseData != NULL)
{
ExFreePool(pSenseData);
}
SetSrbSenseCode(newSrb,NO_MEDIA_IN_DEVICE);
return TRUE;
}
RtlZeroMemory(newSrb, sizeof(SCSI_REQUEST_BLOCK));
RtlZeroMemory(pSenseData, sizeof(SENSE_DATA));
newSrb->Length = sizeof (SCSI_REQUEST_BLOCK);
newSrb->Function = SRB_FUNCTION_EXECUTE_SCSI;
newSrb->PathId = 0;
newSrb->TargetId = 2;
newSrb->Lun = 0;
newSrb->ScsiStatus = newSrb->SrbStatus = 0;
newSrb->NextSrb = NULL;
newSrb->LinkTimeoutValue = -1;
newSrb->QueueAction = SRB_SIMPLE_TAG_REQUEST;
newSrb->SenseInfoBuffer = pSenseData;
newSrb->SenseInfoBufferLength = sizeof(SENSE_DATA);
newSrb->DataBuffer = (PVOID)pSrb->DataBuffer;
newSrb->DataTransferLength = ulLen*512;
newSrb->QueueSortKey = ulStart;
if (1)
{
// READ
newSrb->SrbFlags |= SRB_FLAGS_DATA_IN;
newSrb->SrbFlags |= SRB_FLAGS_ADAPTER_CACHE_ENABLE;
}
else
{
// WRITE
newSrb->SrbFlags |= SRB_FLAGS_DATA_OUT;
}
newSrb->SrbFlags |= SRB_FLAGS_DISABLE_AUTOSENSE;
newSrb->CdbLength = 0x0A; //CDB10
pCdb10 = (PCDB)newSrb->Cdb;
if (1)
{
pCdb10->CDB10.OperationCode = SCSIOP_READ;
}
else
{
pCdb10->CDB10.OperationCode = SCSIOP_WRITE;
}
pCdb10->CDB10.LogicalBlockByte0 = (UCHAR)(ulStart >> 0x18);
pCdb10->CDB10.LogicalBlockByte1 = (UCHAR)(ulStart >> 0x10);
pCdb10->CDB10.LogicalBlockByte2 = (UCHAR)(ulStart >> 0x8);
pCdb10->CDB10.LogicalBlockByte3 = (UCHAR)(ulStart);
pCdb10->CDB10.TransferBlocksLsb = (UCHAR)(ulLen >> 0x8);
pCdb10->CDB10.TransferBlocksMsb = (UCHAR)(ulLen);
#if 0
NTSTATUS status = STATUS_SUCCESS;
if (doOnceFlag == 0)
{
UNICODE_STRING mpUnicodeName;
RtlInitUnicodeString(&mpUnicodeName, L"\Device\Scsi\symmpi1Port2Path0Target2Lun0");
status = IoGetDeviceObjectPointer(
&mpUnicodeName,
GENERIC_READ|GENERIC_WRITE,
&SCSIFileObject,
&SCSIDeviceObject
);
if (NT_SUCCESS(status))
{
InterlockedIncrement(&doOnceFlag);
ObDereferenceObject(SCSIFileObject);
}
}
#endif
//if (NT_SUCCESS(status))
MakeAsynchronousRequest2((PDEVICE_OBJECT)g_pstrSCSIfdo,pSrb->DataBuffer,ulLen*512,1,newSrb);
}