Virtual SCSI Miniport IOCTL problem

Hi,

I am developing a virtual scsi miniport. Where i need to send an IOCTL to my
miniport from a workitem with an SRB to be marked complete. For this I plan
to create an SRB with its databuffer pointer pointing to my old SRB which is
to be completed. Then I create an IRP with this new SRB. And send it to my
miniport dev obj.

The code below is sending a char buffer instead of SRB for testing purpose:

#define SCSIOP_COMPLETE_SRB 0xFE

NTSTATUS SendSRBCompletionIRP(IN PWORKITEM_FOR_DEFERRED_IO
WorkItemToBeCompleted)
{
PSCSI_REQUEST_BLOCK FakeSrb = NULL;
PIRP pIrp = NULL;
PIO_STACK_LOCATION pIoStackLocation = NULL;
PKEVENT Event = NULL;
IO_STATUS_BLOCK IoStatus = {};
NTSTATUS ntStatus = NULL;
char * Buffer = NULL;
FakeSrb = (PSCSI_REQUEST_BLOCK)ExAllocatePoolWithTag(NonPagedPool,
sizeof(SCSI_REQUEST_BLOCK), ‘brsF’);
if(!FakeSrb)
{
NBDDbgPrint(“SendSRBCompletionIRP:: Error Allocating the Fake SRB!”);
NBDASSERT(0);
return STATUS_MEMORY_NOT_ALLOCATED;
}

Event = (PKEVENT) ExAllocatePoolWithTag(NonPagedPool,
sizeof(KEVENT), ‘tnve’);
if(!Event)
{
NBDDbgPrint(“SendSRBCompletionIRP:: Error Allocating Event Memory!”);
NBDASSERT(0);
ExFreePoolWithTag(FakeSrb, ‘brsF’);
return STATUS_MEMORY_NOT_ALLOCATED;
}

Buffer = (char *)ExAllocatePoolWithTag(NonPagedPool,
sizeof(“Charan”+1), ‘ffub’);
if(!Buffer)
{
NBDDbgPrint(“SendSRBCompletionIRP:: Buffer Allocation Failed!”);
NBDASSERT(0);
ExFreePoolWithTag(Event, ‘tnve’);
ExFreePoolWithTag(FakeSrb, ‘brsF’);
return STATUS_MEMORY_NOT_ALLOCATED;
}
RtlCopyBytes((PVOID)Buffer, (PVOID)“Charan\0”, 7);
// SCSI address of the other virtual target used for completion
// or real target that pScsiRequestBlock was initiated to.
// Depends of the flags we’ll set in SRB.
FakeSrb->PathId = WorkItemToBeCompleted->srb->PathId;
FakeSrb->TargetId = WorkItemToBeCompleted->srb->TargetId;
FakeSrb->Lun = WorkItemToBeCompleted->srb->Lun;
FakeSrb->DataBuffer = (PVOID) WorkItemToBeCompleted->srb;
// other SRB fields set here
FakeSrb->Length = SCSI_REQUEST_BLOCK_SIZE;
FakeSrb->QueueAction = WorkItemToBeCompleted->srb->QueueAction;
FakeSrb->SrbFlags = WorkItemToBeCompleted->srb->SrbFlags |
SRB_FLAGS_BYPASS_FROZEN_QUEUE;
CDB &cdb = *(CDB *)FakeSrb->Cdb;
cdb.CDB10.OperationCode = SCSIOP_COMPLETE_SRB;

pIrp = IoBuildDeviceIoControlRequest(IOCTL_SCSI_MINIPORT,

WorkItemToBeCompleted->DeviceExtension->pMiniportDevObj,
FakeSrb,
sizeof(SCSI_REQUEST_BLOCK),
NULL, 0, FALSE,
Event,
&IoStatus);
if(!pIrp)
{
NBDDbgPrint(“SendSRBCompletionIRP:: Error Allocating IRP!”);
NBDASSERT(0);
ExFreePoolWithTag(Buffer, ‘ffub’);
ExFreePoolWithTag(Event, ‘tnve’);
ExFreePoolWithTag(FakeSrb, ‘brsF’);
return STATUS_MEMORY_NOT_ALLOCATED;
}

pIoStackLocation = IoGetNextIrpStackLocation( pIrp );
pIoStackLocation->Parameters.Scsi.Srb = FakeSrb;
pIoStackLocation->MajorFunction = IRP_MJ_SCSI;

KeClearEvent(Event);
ntStatus = IoCallDriver(WorkItemToBeCompleted->DeviceExtension->pMiniportDevObj,
pIrp);
if(STATUS_PENDING == (ntStatus))
KeWaitForSingleObject(Event, Executive, KernelMode, TRUE, NULL);

if(NT_SUCCESS(ntStatus))
ntStatus = IoStatus.Status;

ExFreePoolWithTag(Buffer, ‘ffub’);
ExFreePoolWithTag(Event, ‘tnve’);
ExFreePoolWithTag(FakeSrb, ‘brsF’);
return ntStatus;
}

But the problem here is that IoCallDriver returns *STATUS_REVISION_MISMATCH
(0xC0000059)*.

The StartIO code is as follows:

{
if(Srb->Function == SRB_FUNCTION_EXECUTE_SCSI)
StartCDB(DeviceExtension, Srb);
else if(Srb->Function == SRB_FUNCTION_IO_CONTROL)
{
NBDDbgPrint(“HwScsiStartIo: Miniport IOCtl received:
Databuffer is :: %s\n”, “%s”, Srb->DataBuffer);
ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
}
else
CompleteSRB(DeviceExtension, Srb, (UCHAR)SRB_STATUS_BAD_FUNCTION);
}

Also in StartCDB Function I handle the Operation code
SCSIOP_COMPLETE_SRBas follows:

case SCSIOP_COMPLETE_SRB:
{
NBDDbgPrint(“SCSIOP_COMPLETE_SRB: Miniport IOCtl
received: Databuffer is :: %s\n”, “%s”, Srb->DataBuffer);
DbgBreakPoint();
break;
}

But none of the messages is printed and i get *STATUS_REVISION_MISMATCH* in
IoCallDriver.

Can you please help me find solution to this problem or tell me where am I
going wrong in above code?

Thanks and Regards,

Charansing D Deore
Sr. Software Developer,
CalSoft Pvt Ltd.
Baner Road, Pune-411045
Office: +91 20 40792900 Ext: 3055
Cell: +91 9850960550

Hi Guys,

I found a bug in my earlier code. And it was that I had forgotten to
initialize the even before calling IoCallDriver. Now IoCallDriver doesnot
return *STATUS_REVISION_MISMATCH*, Instead It results in a bugcheck
PAGE_FAULT_IN_NONPAGED_AREA (50). The stack trace is as follows:

f8902770 804f780d 00000003 85858599 00000000
nt!RtlpBreakWithStatusInstruction
f89027bc 804f83fa 00000003 00000000 c042c2c0 nt!KiBugCheckDebugBreak+0x19
f8902b9c 804f8925 00000050 85858599 00000000 nt!KeBugCheck2+0x574
f8902bbc 8051bf07 00000050 85858599 00000000 nt!KeBugCheckEx+0x1b
f8902c1c 8053f6ec 00000000 85858599 00000000 nt!MmAccessFault+0x8e7
f8902c1c bad8dbb1 00000000 85858599 00000000 nt!KiTrap0E+0xcc
f8902cc4 bad8b469 828daa30 82f92fd8 829b4738
SCSIPORT!ScsiPortFdoDispatch+0x11d
f8902cd8 804eddf9 828daa30 82f92f20 806d02e8
SCSIPORT!ScsiPortGlobalDispatch+0x1d
f8902ce8 8064b5a8 832dafd0 8055a238 82b5cb30 nt!IopfCallDriver+0x31
f8902d0c f8839b9a 8298f1b4 832dafd0 832dafd0 nt!IovCallDriver+0xa0
f8902d48 f88396e2 832dafd0 82966658 00000000
SCSI_NBD!SendSRBCompletionIRP+0x34a
[e:\p-networks\cvsrepository\scsi_nbd\scsi_nbd\deferredworkitems.cpp @ 416]
f8902d74 80533dd0 832dafd0 00000000 82b5cb30
SCSI_NBD!DeferredWorkerThreadToWriteToDisk+0x152
[e:\p-networks\cvsrepository\scsi_nbd\scsi_nbd\deferredworkitems.cpp @ 251]
f8902dac 805c4a28 832dafd0 00000000 00000000 nt!ExpWorkerThread+0x100
f8902ddc 80540fa2 80533cd0 00000002 00000000 nt!PspSystemThreadStartup+0x34
00000000 00000000 00000000 00000000 00000000 nt!KiThreadStartup+0x16

Note: My miniport driver’s name is SCSI_NBD.

Seems I have again messed up something in my code. Any pointers?

Thanks and Regards,

Charansing D Deore
Sr. Software Developer,
CalSoft Pvt Ltd.
Baner Road, Pune-411045
Office: +91 20 40792900 Ext: 3055
Cell: +91 9850960550

On Thu, Dec 18, 2008 at 11:52 AM, Charansing Rajput wrote:

> Hi,
>
> I am developing a virtual scsi miniport. Where i need to send an IOCTL to
> my miniport from a workitem with an SRB to be marked complete. For this I
> plan to create an SRB with its databuffer pointer pointing to my old SRB
> which is to be completed. Then I create an IRP with this new SRB. And send
> it to my miniport dev obj.
>
> The code below is sending a char buffer instead of SRB for testing purpose:
>
> #define SCSIOP_COMPLETE_SRB 0xFE
>
> NTSTATUS SendSRBCompletionIRP(IN PWORKITEM_FOR_DEFERRED_IO WorkItemToBeCompleted)
> {
> PSCSI_REQUEST_BLOCK FakeSrb = NULL;
>
> PIRP pIrp = NULL;
> PIO_STACK_LOCATION pIoStackLocation = NULL;
>
> PKEVENT Event = NULL;
> IO_STATUS_BLOCK IoStatus = {};
>
> NTSTATUS ntStatus = NULL;
> char * Buffer = NULL;
>
> FakeSrb = (PSCSI_REQUEST_BLOCK)ExAllocatePoolWithTag(NonPagedPool, sizeof(SCSI_REQUEST_BLOCK), ‘brsF’);
>
> if(!FakeSrb)
> {
> NBDDbgPrint(“SendSRBCompletionIRP:: Error Allocating the Fake SRB!”);
>
> NBDASSERT(0);
> return STATUS_MEMORY_NOT_ALLOCATED;
>
> }
>
> Event = (PKEVENT) ExAllocatePoolWithTag(NonPagedPool, sizeof(KEVENT), ‘tnve’);
>
> if(!Event)
> {
> NBDDbgPrint(“SendSRBCompletionIRP:: Error Allocating Event Memory!”);
>
> NBDASSERT(0);
> ExFreePoolWithTag(FakeSrb, ‘brsF’);
>
> return STATUS_MEMORY_NOT_ALLOCATED;
> }
>
> Buffer = (char *)ExAllocatePoolWithTag(NonPagedPool, sizeof(“Charan”+1), ‘ffub’);
>
> if(!Buffer)
> {
> NBDDbgPrint(“SendSRBCompletionIRP:: Buffer Allocation Failed!”);
>
> NBDASSERT(0);
> ExFreePoolWithTag(Event, ‘tnve’);
>
> ExFreePoolWithTag(FakeSrb, ‘brsF’);
>
> return STATUS_MEMORY_NOT_ALLOCATED;
> }
> RtlCopyBytes((PVOID)Buffer, (PVOID)“Charan\0”, 7);
>
> // SCSI address of the other virtual target used for completion
> // or real target that pScsiRequestBlock was initiated to.
>
> // Depends of the flags we’ll set in SRB.
> FakeSrb->PathId = WorkItemToBeCompleted->srb->PathId;
>
> FakeSrb->TargetId = WorkItemToBeCompleted->srb->TargetId;
> FakeSrb->Lun = WorkItemToBeCompleted->srb->Lun;
>
> FakeSrb->DataBuffer = (PVOID) WorkItemToBeCompleted->srb;
> // other SRB fields set here
>
> FakeSrb->Length = SCSI_REQUEST_BLOCK_SIZE;
> FakeSrb->QueueAction = WorkItemToBeCompleted->srb->QueueAction;
>
> FakeSrb->SrbFlags = WorkItemToBeCompleted->srb->SrbFlags | SRB_FLAGS_BYPASS_FROZEN_QUEUE;
>
> CDB &cdb = *(CDB *)FakeSrb->Cdb;
> cdb.CDB10.OperationCode = SCSIOP_COMPLETE_SRB;
>
>
> pIrp = IoBuildDeviceIoControlRequest(IOCTL_SCSI_MINIPORT,
> WorkItemToBeCompleted->DeviceExtension->pMiniportDevObj,
>
> FakeSrb,
> sizeof(SCSI_REQUEST_BLOCK),
>
> NULL, 0, FALSE,
>
> Event,
> &IoStatus);
> if(!pIrp)
>
> {
> NBDDbgPrint(“SendSRBCompletionIRP:: Error Allocating IRP!”);
>
> NBDASSERT(0);
> ExFreePoolWithTag(Buffer, ‘ffub’);
>
> ExFreePoolWithTag(Event, ‘tnve’);
>
> ExFreePoolWithTag(FakeSrb, ‘brsF’);
>
> return STATUS_MEMORY_NOT_ALLOCATED;
> }
>
> pIoStackLocation = IoGetNextIrpStackLocation( pIrp );
>
> pIoStackLocation->Parameters.Scsi.Srb = FakeSrb;
> pIoStackLocation->MajorFunction = IRP_MJ_SCSI;
>
> KeInitializeEvent(Event, SynchronizationEvent, FALSE); /I had forgotten this in previous code/
>
> ntStatus = IoCallDriver(WorkItemToBeCompleted->DeviceExtension->pMiniportDevObj, pIrp);
> if(STATUS_PENDING == (ntStatus))
> KeWaitForSingleObject(Event, Executive, KernelMode, TRUE, NULL);
>
> if(NT_SUCCESS(ntStatus))
> ntStatus = IoStatus.Status;
>
> ExFreePoolWithTag(Buffer, ‘ffub’);
> ExFreePoolWithTag(Event, ‘tnve’);
> ExFreePoolWithTag(FakeSrb, ‘brsF’);
> return ntStatus;
> }
>
>
> But the problem here is that IoCallDriver returns STATUS_REVISION_MISMATCH
> (0xC0000059)
.
>
> The StartIO code is as follows:
>
> {
> if(Srb->Function == SRB_FUNCTION_EXECUTE_SCSI)
> StartCDB(DeviceExtension, Srb);
> else if(Srb->Function == SRB_FUNCTION_IO_CONTROL)
> {
> NBDDbgPrint(“HwScsiStartIo: Miniport IOCtl received: Databuffer is :: %s\n”, “%s”, Srb->DataBuffer);
> ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
> }
> else
> CompleteSRB(DeviceExtension, Srb, (UCHAR)SRB_STATUS_BAD_FUNCTION);
> }
>
>
> Also in StartCDB Function I handle the Operation code SCSIOP_COMPLETE_SRBas follows:
>
> case SCSIOP_COMPLETE_SRB:
> {
> NBDDbgPrint(“SCSIOP_COMPLETE_SRB: Miniport IOCtl received: Databuffer is :: %s\n”, “%s”, Srb->DataBuffer); DbgBreakPoint();
> break;
> }
>
> But none of the messages is printed and i get STATUS_REVISION_MISMATCHin IoCallDriver.
>
> Can you please help me find solution to this problem or tell me where am I
> going wrong in above code?
>
>
> Thanks and Regards,
> ----------------------------------------------------------------
> Charansing D Deore
> Sr. Software Developer,
> CalSoft Pvt Ltd.
> Baner Road, Pune-411045
> Office: +91 20 40792900 Ext: 3055
> Cell: +91 9850960550
>

Is this “virtual” mini-port on top of a SCSIPORT minport? If so, you do realize that you are walking down a path that many have trod and never returned? “Virtual” SCSI miniports are like the Yeti, or Nessie, or UFO’s. They make great stories but don’t exist. The biggest problem is that you are stuck with polling at a 10 ms rate since you cannot hang a request on the DPC queue since you do not h ave access to the device object needed to hang a DPC. You’re restricted to SCSIPORT functions to do not have access to that object.


The personal opinion of
Gary G. Little

“Charansing Rajput” wrote in message news:xxxxx@ntdev…
Hi,

I am developing a virtual scsi miniport. Where i need to send an IOCTL to my miniport from a workitem with an SRB to be marked complete. For this I plan to create an SRB with its databuffer pointer pointing to my old SRB which is to be completed. Then I create an IRP with this new SRB. And send it to my miniport dev obj.

The code below is sending a char buffer instead of SRB for testing purpose:

#define SCSIOP_COMPLETE_SRB 0xFENTSTATUS SendSRBCompletionIRP(IN PWORKITEM_FOR_DEFERRED_IO WorkItemToBeCompleted){ PSCSI_REQUEST_BLOCK FakeSrb = NULL;
PIRP pIrp = NULL; PIO_STACK_LOCATION pIoStackLocation = NULL;
PKEVENT Event = NULL; IO_STATUS_BLOCK IoStatus = {};
NTSTATUS ntStatus = NULL; char * Buffer = NULL;
FakeSrb = (PSCSI_REQUEST_BLOCK)ExAllocatePoolWithTag(NonPagedPool, sizeof(SCSI_REQUEST_BLOCK), ‘brsF’);
if(!FakeSrb) { NBDDbgPrint(“SendSRBCompletionIRP:: Error Allocating the Fake SRB!”);
NBDASSERT(0); return STATUS_MEMORY_NOT_ALLOCATED;
} Event = (PKEVENT) ExAllocatePoolWithTag(NonPagedPool, sizeof(KEVENT), ‘tnve’);
if(!Event) { NBDDbgPrint(“SendSRBCompletionIRP:: Error Allocating Event Memory!”);
NBDASSERT(0); ExFreePoolWithTag(FakeSrb, ‘brsF’);
return STATUS_MEMORY_NOT_ALLOCATED; } Buffer = (char *)ExAllocatePoolWithTag(NonPagedPool, sizeof(“Charan”+1), ‘ffub’);
if(!Buffer) { NBDDbgPrint(“SendSRBCompletionIRP:: Buffer Allocation Failed!”);
NBDASSERT(0); ExFreePoolWithTag(Event, ‘tnve’);
ExFreePoolWithTag(FakeSrb, ‘brsF’);
return STATUS_MEMORY_NOT_ALLOCATED; } RtlCopyBytes((PVOID)Buffer, (PVOID)“Charan\0”, 7);
// SCSI address of the other virtual target used for completion // or real target that pScsiRequestBlock was initiated to.
// Depends of the flags we’ll set in SRB. FakeSrb->PathId = WorkItemToBeCompleted->srb->PathId;
FakeSrb->TargetId = WorkItemToBeCompleted->srb->TargetId; FakeSrb->Lun = WorkItemToBeCompleted->srb->Lun;
FakeSrb->DataBuffer = (PVOID) WorkItemToBeCompleted->srb; // other SRB fields set here
FakeSrb->Length = SCSI_REQUEST_BLOCK_SIZE; FakeSrb->QueueAction = WorkItemToBeCompleted->srb->QueueAction;
FakeSrb->SrbFlags = WorkItemToBeCompleted->srb->SrbFlags | SRB_FLAGS_BYPASS_FROZEN_QUEUE;
CDB &cdb = *(CDB *)FakeSrb->Cdb; cdb.CDB10.OperationCode = SCSIOP_COMPLETE_SRB;
pIrp = IoBuildDeviceIoControlRequest(IOCTL_SCSI_MINIPORT, WorkItemToBeCompleted->DeviceExtension->pMiniportDevObj,
FakeSrb, sizeof(SCSI_REQUEST_BLOCK),
NULL, 0, FALSE,
Event, &IoStatus); if(!pIrp)
{ NBDDbgPrint(“SendSRBCompletionIRP:: Error Allocating IRP!”);
NBDASSERT(0); ExFreePoolWithTag(Buffer, ‘ffub’);
ExFreePoolWithTag(Event, ‘tnve’);
ExFreePoolWithTag(FakeSrb, ‘brsF’);
return STATUS_MEMORY_NOT_ALLOCATED; } pIoStackLocation = IoGetNextIrpStackLocation( pIrp );
pIoStackLocation->Parameters.Scsi.Srb = FakeSrb; pIoStackLocation->MajorFunction = IRP_MJ_SCSI;
KeClearEvent(Event); ntStatus = IoCallDriver(WorkItemToBeCompleted->DeviceExtension->pMiniportDevObj, pIrp);
if(STATUS_PENDING == (ntStatus)) KeWaitForSingleObject(Event, Executive, KernelMode, TRUE, NULL);
if(NT_SUCCESS(ntStatus)) ntStatus = IoStatus.Status;
ExFreePoolWithTag(Buffer, ‘ffub’);
ExFreePoolWithTag(Event, ‘tnve’);
ExFreePoolWithTag(FakeSrb, ‘brsF’);
return ntStatus;}
But the problem here is that IoCallDriver returns STATUS_REVISION_MISMATCH (0xC0000059).

The StartIO code is as follows:

{ if(Srb->Function == SRB_FUNCTION_EXECUTE_SCSI)
StartCDB(DeviceExtension, Srb); else if(Srb->Function == SRB_FUNCTION_IO_CONTROL)
{ NBDDbgPrint(“HwScsiStartIo: Miniport IOCtl received: Databuffer is :: %s\n”, “%s”, Srb->DataBuffer);
ScsiPortNotification(RequestComplete, DeviceExtension, Srb); } else
CompleteSRB(DeviceExtension, Srb, (UCHAR)SRB_STATUS_BAD_FUNCTION);}
Also in StartCDB Function I handle the Operation code SCSIOP_COMPLETE_SRB as follows:

case SCSIOP_COMPLETE_SRB: {
NBDDbgPrint(“SCSIOP_COMPLETE_SRB: Miniport IOCtl received: Databuffer is :: %s\n”, “%s”, Srb->DataBuffer); DbgBreakPoint();
break; }But none of the messages is printed and i get STATUS_REVISION_MISMATCH in IoCallDriver.

Can you please help me find solution to this problem or tell me where am I going wrong in above code?

Thanks and Regards,
----------------------------------------------------------------
Charansing D Deore
Sr. Software Developer,
CalSoft Pvt Ltd.
Baner Road, Pune-411045
Office: +91 20 40792900 Ext: 3055
Cell: +91 9850960550

>

Is this “virtual” mini-port on top of a SCSIPORT minport? If so, you
do
realize that you are walking down a path that many have trod and never
returned? “Virtual” SCSI miniports are like the Yeti, or Nessie, or
UFO’s.
They make great stories but don’t exist. The biggest problem is that
you
are stuck with polling at a 10 ms rate since you cannot hang a request
on
the DPC queue since you do not h ave access to the device object
needed to
hang a DPC. You’re restricted to SCSIPORT functions to do not have
access
to that object.

The trick I have used to get around this is to issue ‘int x’
instructions from outside the scsiport context to get back into the
scsiport context, having previously bound the scsiport adapter to ‘made
up’ interrupt. Performance isn’t ideal obviously but it sure beats 10ms
polling!

James

This virtual miniport is just like a normal scsi miniport, just that it
doesnt cater any real hardware but it serves the IO from TCP/IP network.

Virtual miniports unlike UFOs do exist. The welknown examples are emBoot’s
netboot scsi miniport which has network backbone, perisoft’s miniFile which
can have network of FileSystem backbone, Nero’s ImageDrive which also has
FileSystem backbone and many other virtual SCSI CD/DVD drive software’s
which have filesystem backbone.

And Yes, I do have device object for my miniport.

Thanks and Regards,

Charansing D Deore
Sr. Software Developer,
CalSoft Pvt Ltd.
Baner Road, Pune-411045
Office: +91 20 40792900 Ext: 3055
Cell: +91 9850960550

On Thu, Dec 18, 2008 at 10:23 PM, Gary G. Little
wrote:

> Is this “virtual” mini-port on top of a SCSIPORT minport? If so, you do
> realize that you are walking down a path that many have trod and never
> returned? “Virtual” SCSI miniports are like the Yeti, or Nessie, or UFO’s.
> They make great stories but don’t exist. The biggest problem is that you are
> stuck with polling at a 10 ms rate since you cannot hang a request on the
> DPC queue since you do not h ave access to the device object needed to hang
> a DPC. You’re restricted to SCSIPORT functions to do not have access to that
> object.
>
> –
> The personal opinion of
> Gary G. Little
>
> “Charansing Rajput” wrote in message
> news:xxxxx@ntdev…
>
> Hi,
>
> I am developing a virtual scsi miniport. Where i need to send an IOCTL to
> my miniport from a workitem with an SRB to be marked complete. For this I
> plan to create an SRB with its databuffer pointer pointing to my old SRB
> which is to be completed. Then I create an IRP with this new SRB. And send
> it to my miniport dev obj.
>
> The code below is sending a char buffer instead of SRB for testing purpose:
>
> #define SCSIOP_COMPLETE_SRB 0xFE
>
> NTSTATUS SendSRBCompletionIRP(IN PWORKITEM_FOR_DEFERRED_IO WorkItemToBeCompleted)
> {
> PSCSI_REQUEST_BLOCK FakeSrb = NULL;
> PIRP pIrp = NULL;
> PIO_STACK_LOCATION pIoStackLocation = NULL;
> PKEVENT Event = NULL;
> IO_STATUS_BLOCK IoStatus = {};
> NTSTATUS ntStatus = NULL;
> char * Buffer = NULL;
> FakeSrb = (PSCSI_REQUEST_BLOCK)ExAllocatePoolWithTag(NonPagedPool, sizeof(SCSI_REQUEST_BLOCK), ‘brsF’);
> if(!FakeSrb)
> {
> NBDDbgPrint(“SendSRBCompletionIRP:: Error Allocating the Fake SRB!”);
> NBDASSERT(0);
> return STATUS_MEMORY_NOT_ALLOCATED;
> }
>
> Event = (PKEVENT) ExAllocatePoolWithTag(NonPagedPool, sizeof(KEVENT), ‘tnve’);
> if(!Event)
> {
> NBDDbgPrint(“SendSRBCompletionIRP:: Error Allocating Event Memory!”);
> NBDASSERT(0);
> ExFreePoolWithTag(FakeSrb, ‘brsF’);
> return STATUS_MEMORY_NOT_ALLOCATED;
> }
>
> Buffer = (char *)ExAllocatePoolWithTag(NonPagedPool, sizeof(“Charan”+1), ‘ffub’);
> if(!Buffer)
> {
> NBDDbgPrint(“SendSRBCompletionIRP:: Buffer Allocation Failed!”);
> NBDASSERT(0);
> ExFreePoolWithTag(Event, ‘tnve’);
> ExFreePoolWithTag(FakeSrb, ‘brsF’);
> return STATUS_MEMORY_NOT_ALLOCATED;
> }
> RtlCopyBytes((PVOID)Buffer, (PVOID)“Charan\0”, 7);
> // SCSI address of the other virtual target used for completion
> // or real target that pScsiRequestBlock was initiated to.
> // Depends of the flags we’ll set in SRB.
> FakeSrb->PathId = WorkItemToBeCompleted->srb->PathId;
> FakeSrb->TargetId = WorkItemToBeCompleted->srb->TargetId;
> FakeSrb->Lun = WorkItemToBeCompleted->srb->Lun;
> FakeSrb->DataBuffer = (PVOID) WorkItemToBeCompleted->srb;
> // other SRB fields set here
> FakeSrb->Length = SCSI_REQUEST_BLOCK_SIZE;
> FakeSrb->QueueAction = WorkItemToBeCompleted->srb->QueueAction;
> FakeSrb->SrbFlags = WorkItemToBeCompleted->srb->SrbFlags | SRB_FLAGS_BYPASS_FROZEN_QUEUE;
> CDB &cdb = *(CDB *)FakeSrb->Cdb;
> cdb.CDB10.OperationCode = SCSIOP_COMPLETE_SRB;
>
> pIrp = IoBuildDeviceIoControlRequest(IOCTL_SCSI_MINIPORT,
> WorkItemToBeCompleted->DeviceExtension->pMiniportDevObj,
> FakeSrb,
> sizeof(SCSI_REQUEST_BLOCK),
> NULL, 0, FALSE,
> Event,
> &IoStatus);
> if(!pIrp)
> {
> NBDDbgPrint(“SendSRBCompletionIRP:: Error Allocating IRP!”);
> NBDASSERT(0);
> ExFreePoolWithTag(Buffer, ‘ffub’);
> ExFreePoolWithTag(Event, ‘tnve’);
> ExFreePoolWithTag(FakeSrb, ‘brsF’);
> return STATUS_MEMORY_NOT_ALLOCATED;
> }
>
> pIoStackLocation = IoGetNextIrpStackLocation( pIrp );
> pIoStackLocation->Parameters.Scsi.Srb = FakeSrb;
> pIoStackLocation->MajorFunction = IRP_MJ_SCSI;
>
> KeClearEvent(Event);
>
> ntStatus = IoCallDriver(WorkItemToBeCompleted->DeviceExtension->pMiniportDevObj, pIrp);
> if(STATUS_PENDING == (ntStatus))
> KeWaitForSingleObject(Event, Executive, KernelMode, TRUE, NULL);
>
> if(NT_SUCCESS(ntStatus))
> ntStatus = IoStatus.Status;
>
> ExFreePoolWithTag(Buffer, ‘ffub’);
> ExFreePoolWithTag(Event, ‘tnve’);
> ExFreePoolWithTag(FakeSrb, ‘brsF’);
> return ntStatus;
> }
>
>
> But the problem here is that IoCallDriver returns STATUS_REVISION_MISMATCH
> (0xC0000059)
.
>
> The StartIO code is as follows:
>
> {
> if(Srb->Function == SRB_FUNCTION_EXECUTE_SCSI)
> StartCDB(DeviceExtension, Srb);
> else if(Srb->Function == SRB_FUNCTION_IO_CONTROL)
> {
> NBDDbgPrint(“HwScsiStartIo: Miniport IOCtl received: Databuffer is :: %s\n”, “%s”, Srb->DataBuffer);
> ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
> }
> else
> CompleteSRB(DeviceExtension, Srb, (UCHAR)SRB_STATUS_BAD_FUNCTION);
> }
>
>
> Also in StartCDB Function I handle the Operation code SCSIOP_COMPLETE_SRBas follows:
>
> case SCSIOP_COMPLETE_SRB:
> {
> NBDDbgPrint(“SCSIOP_COMPLETE_SRB: Miniport IOCtl received: Databuffer is :: %s\n”, “%s”, Srb->DataBuffer); DbgBreakPoint();
> break;
> }
>
> But none of the messages is printed and i get STATUS_REVISION_MISMATCHin IoCallDriver.
>
> Can you please help me find solution to this problem or tell me where am I
> going wrong in above code?
>
>
> Thanks and Regards,
> ----------------------------------------------------------------
> Charansing D Deore
> Sr. Software Developer,
> CalSoft Pvt Ltd.
> Baner Road, Pune-411045
> Office: +91 20 40792900 Ext: 3055
> Cell: +91 9850960550
>
>
> —
> NTDEV is sponsored by OSR
>
> For our schedule of WDF, WDM, debugging and other seminars visit:
> http://www.osr.com/seminars
>
> To unsubscribe, visit the List Server section of OSR Online at
> http://www.osronline.com/page.cfm?name=ListServer
>

Hi James,

Thanks for replying. Could you please elaborate more on this solution?

Which interrupt should I issue?
How do I make sure that SCSIPORT gets this interrupt and it promptly
delivers it to my miniport’s interrupt handler that I registered in
HW_INITIALIZATION_DATA? As you know I just need to get back into
scsiport
context to mark the SRBs complete.

Thanks and Regards,

Charansing D Deore
Sr. Software Developer,
CalSoft Pvt Ltd.
Baner Road, Pune-411045
Office: +91 20 40792900 Ext: 3055
Cell: +91 9850960550

On Fri, Dec 19, 2008 at 2:16 AM, James Harper > wrote:

> >
> > Is this “virtual” mini-port on top of a SCSIPORT minport? If so, you
> do
> > realize that you are walking down a path that many have trod and never
> > returned? “Virtual” SCSI miniports are like the Yeti, or Nessie, or
> UFO’s.
> > They make great stories but don’t exist. The biggest problem is that
> you
> > are stuck with polling at a 10 ms rate since you cannot hang a request
> on
> > the DPC queue since you do not h ave access to the device object
> needed to
> > hang a DPC. You’re restricted to SCSIPORT functions to do not have
> access
> > to that object.
> >
>
> The trick I have used to get around this is to issue ‘int x’
> instructions from outside the scsiport context to get back into the
> scsiport context, having previously bound the scsiport adapter to ‘made
> up’ interrupt. Performance isn’t ideal obviously but it sure beats 10ms
> polling!
>
> James
>
> —
> NTDEV is sponsored by OSR
>
> For our schedule of WDF, WDM, debugging and other seminars visit:
> http://www.osr.com/seminars
>
> To unsubscribe, visit the List Server section of OSR Online at
> http://www.osronline.com/page.cfm?name=ListServer
>

> Hi James,

Thanks for replying. Could you please elaborate more on this solution?

Which interrupt should I issue?
How do I make sure that SCSIPORT gets this interrupt and it promptly
delivers it to my miniport’s interrupt handler that I registered in
HW_INITIALIZATION_DATA? As you know I just need to get back into
scsiport
context to mark the SRBs complete.

I had the advantage that my virtual scsiport device was enumerated by a
bus driver, so I just put an interrupt into the resource requirements
list. You may be able to use IoReportResourceForDetection to get an
interrupt in the resources of your StartDevice routine. You may well
already be doing something similar as scsiport requires at least 1 i/o
or memory access range.

Once you get the interrupt allocated to you, connect it like you would
with a real scsiport driver, and use the Vector in the translated
resources as the parameter to the ‘int x’ instruction (this may take a
bit of extra work as I don’t know that scsiport gives you the vector -
might need a filter to get it). Unfortunately the ‘int x’ instruction
can only take a literal as a parameter, so you need a great big case or
if statement with inline asm statements in it to make it work. For
amd64, you obviously need an external asm as you are not allowed to use
inline asm.

One thing to also watch out for is that calling an ‘int x’ instruction
like this bypasses a few assumptions Windows makes about the state of
things. If you call ‘int x’ from a DIRQL higher than the one you are
calling, strange things will happen. Likewise be careful calling it when
interrupts are disabled. Neither of those should be an issue if you call
it from PASSIVE_LEVEL or DISPATCH_LEVEL.

I ended up abandoning this method as under Xen I found a better way of
doing things - with this method I had to service the interrupt from xen,
schedule a dpc, then do the ‘int x’ instruction which would go to the
interrupt of my virtual device (so I didn’t violate IRQ priorities), and
for ndis the device would schedule another dpc. Way too much overhead.
It may work for what you want though. I’m sure that someone on the list
will speak up if there are some fatal flaws with this method…

The code I am presenting here comes from a GPL’d project (written by
me), so ummm… maybe learn from it rather than copying it verbatim :wink:

(I tried attaching these but the list won’t allow it - hope I’m not
breaking protocol by sending code inline… it’s only a few kb)

This is the code for the .h file:

"
#if defined(X86)

#define SWINT(x) if (intno == x) { __asm { int x } return; }

static __inline VOID
sw_interrupt(UCHAR intno)
{
SWINT(0x10) SWINT(0x11) SWINT(0x12) SWINT(0x13) SWINT(0x14)
SWINT(0x15) SWINT(0x16) SWINT(0x17)
SWINT(0x18) SWINT(0x19) SWINT(0x1A) SWINT(0x1B) SWINT(0x1C)
SWINT(0x1D) SWINT(0x1E) SWINT(0x1F)
SWINT(0x20) SWINT(0x21) SWINT(0x22) SWINT(0x23) SWINT(0x24)
SWINT(0x25) SWINT(0x26) SWINT(0x27)
SWINT(0x28) SWINT(0x29) SWINT(0x2A) SWINT(0x2B) SWINT(0x2C)
SWINT(0x2D) SWINT(0x2E) SWINT(0x2F)
SWINT(0x30) SWINT(0x31) SWINT(0x32) SWINT(0x33) SWINT(0x34)
SWINT(0x35) SWINT(0x36) SWINT(0x37)
SWINT(0x38) SWINT(0x39) SWINT(0x3A) SWINT(0x3B) SWINT(0x3C)
SWINT(0x3D) SWINT(0x3E) SWINT(0x3F)
SWINT(0x40) SWINT(0x41) SWINT(0x42) SWINT(0x43) SWINT(0x44)
SWINT(0x45) SWINT(0x46) SWINT(0x47)
SWINT(0x48) SWINT(0x49) SWINT(0x4A) SWINT(0x4B) SWINT(0x4C)
SWINT(0x4D) SWINT(0x4E) SWINT(0x4F)
SWINT(0x50) SWINT(0x51) SWINT(0x52) SWINT(0x53) SWINT(0x54)
SWINT(0x55) SWINT(0x56) SWINT(0x57)
SWINT(0x58) SWINT(0x59) SWINT(0x5A) SWINT(0x5B) SWINT(0x5C)
SWINT(0x5D) SWINT(0x5E) SWINT(0x5F)
SWINT(0x60) SWINT(0x61) SWINT(0x62) SWINT(0x63) SWINT(0x64)
SWINT(0x65) SWINT(0x66) SWINT(0x67)
SWINT(0x68) SWINT(0x69) SWINT(0x6A) SWINT(0x6B) SWINT(0x6C)
SWINT(0x6D) SWINT(0x6E) SWINT(0x6F)
SWINT(0x70) SWINT(0x71) SWINT(0x72) SWINT(0x73) SWINT(0x74)
SWINT(0x75) SWINT(0x76) SWINT(0x77)
SWINT(0x78) SWINT(0x79) SWINT(0x7A) SWINT(0x7B) SWINT(0x7C)
SWINT(0x7D) SWINT(0x7E) SWINT(0x7F)
SWINT(0x80) SWINT(0x81) SWINT(0x82) SWINT(0x83) SWINT(0x84)
SWINT(0x85) SWINT(0x86) SWINT(0x87)
SWINT(0x88) SWINT(0x89) SWINT(0x8A) SWINT(0x8B) SWINT(0x8C)
SWINT(0x8D) SWINT(0x8E) SWINT(0x8F)
SWINT(0x90) SWINT(0x91) SWINT(0x92) SWINT(0x93) SWINT(0x94)
SWINT(0x95) SWINT(0x96) SWINT(0x97)
SWINT(0x98) SWINT(0x99) SWINT(0x9A) SWINT(0x9B) SWINT(0x9C)
SWINT(0x9D) SWINT(0x9E) SWINT(0x9F)
SWINT(0xA0) SWINT(0xA1) SWINT(0xA2) SWINT(0xA3) SWINT(0xA4)
SWINT(0xA5) SWINT(0xA6) SWINT(0xA7)
SWINT(0xA8) SWINT(0xA9) SWINT(0xAA) SWINT(0xAB) SWINT(0xAC)
SWINT(0xAD) SWINT(0xAE) SWINT(0xAF)
SWINT(0xB0) SWINT(0xB1) SWINT(0xB2) SWINT(0xB3) SWINT(0xB4)
SWINT(0xB5) SWINT(0xB6) SWINT(0xB7)
SWINT(0xB8) SWINT(0xB9) SWINT(0xBA) SWINT(0xBB) SWINT(0xBC)
SWINT(0xBD) SWINT(0xBE) SWINT(0xBF)
SWINT(0xC0) SWINT(0xC1) SWINT(0xC2) SWINT(0xC3) SWINT(0xC4)
SWINT(0xC5) SWINT(0xC6) SWINT(0xC7)
SWINT(0xC8) SWINT(0xC9) SWINT(0xCA) SWINT(0xCB) SWINT(0xCC)
SWINT(0xCD) SWINT(0xCE) SWINT(0xCF)
SWINT(0xD0) SWINT(0xD1) SWINT(0xD2) SWINT(0xD3) SWINT(0xD4)
SWINT(0xD5) SWINT(0xD6) SWINT(0xD7)
SWINT(0xD8) SWINT(0xD9) SWINT(0xDA) SWINT(0xDB) SWINT(0xDC)
SWINT(0xDD) SWINT(0xDE) SWINT(0xDF)
SWINT(0xE0) SWINT(0xE1) SWINT(0xE2) SWINT(0xE3) SWINT(0xE4)
SWINT(0xE5) SWINT(0xE6) SWINT(0xE7)
SWINT(0xE8) SWINT(0xE9) SWINT(0xEA) SWINT(0xEB) SWINT(0xEC)
SWINT(0xED) SWINT(0xEE) SWINT(0xEF)
SWINT(0xF0) SWINT(0xF1) SWINT(0xF2) SWINT(0xF3) SWINT(0xF4)
SWINT(0xF5) SWINT(0xF6) SWINT(0xF7)
SWINT(0xF8) SWINT(0xF9) SWINT(0xFA) SWINT(0xFB) SWINT(0xFC)
SWINT(0xFD) SWINT(0xFE) SWINT(0xFF)

/* not found - do something useful here */
}
#else
VOID _sw_interrupt(UCHAR);

static __inline VOID
sw_interrupt(UCHAR intno)
{
_sw_interrupt(intno);
}
#endif
"

And this is the .asm file:

"
.code
_sw_interrupt proc
shl rcx, 3
mov rax, jump_table
add rax, rcx
jmp qword ptr [rax]

I0:
int 0
ret
I1:
int 1
ret
I2:
int 2
ret
I3:
int 3
ret
I4:
int 4
ret
I5:
int 5
ret
I6:
int 6
ret
I7:
int 7
ret
I8:
int 8
ret
I9:
int 9
ret
I10:
int 10
ret
I11:
int 11
ret
I12:
int 12
ret
I13:
int 13
ret
I14:
int 14
ret
I15:
int 15
ret
I16:
int 16
ret
I17:
int 17
ret
I18:
int 18
ret
I19:
int 19
ret
I20:
int 20
ret
I21:
int 21
ret
I22:
int 22
ret
I23:
int 23
ret
I24:
int 24
ret
I25:
int 25
ret
I26:
int 26
ret
I27:
int 27
ret
I28:
int 28
ret
I29:
int 29
ret
I30:
int 30
ret
I31:
int 31
ret
I32:
int 32
ret
I33:
int 33
ret
I34:
int 34
ret
I35:
int 35
ret
I36:
int 36
ret
I37:
int 37
ret
I38:
int 38
ret
I39:
int 39
ret
I40:
int 40
ret
I41:
int 41
ret
I42:
int 42
ret
I43:
int 43
ret
I44:
int 44
ret
I45:
int 45
ret
I46:
int 46
ret
I47:
int 47
ret
I48:
int 48
ret
I49:
int 49
ret
I50:
int 50
ret
I51:
int 51
ret
I52:
int 52
ret
I53:
int 53
ret
I54:
int 54
ret
I55:
int 55
ret
I56:
int 56
ret
I57:
int 57
ret
I58:
int 58
ret
I59:
int 59
ret
I60:
int 60
ret
I61:
int 61
ret
I62:
int 62
ret
I63:
int 63
ret
I64:
int 64
ret
I65:
int 65
ret
I66:
int 66
ret
I67:
int 67
ret
I68:
int 68
ret
I69:
int 69
ret
I70:
int 70
ret
I71:
int 71
ret
I72:
int 72
ret
I73:
int 73
ret
I74:
int 74
ret
I75:
int 75
ret
I76:
int 76
ret
I77:
int 77
ret
I78:
int 78
ret
I79:
int 79
ret
I80:
int 80
ret
I81:
int 81
ret
I82:
int 82
ret
I83:
int 83
ret
I84:
int 84
ret
I85:
int 85
ret
I86:
int 86
ret
I87:
int 87
ret
I88:
int 88
ret
I89:
int 89
ret
I90:
int 90
ret
I91:
int 91
ret
I92:
int 92
ret
I93:
int 93
ret
I94:
int 94
ret
I95:
int 95
ret
I96:
int 96
ret
I97:
int 97
ret
I98:
int 98
ret
I99:
int 99
ret
I100:
int 100
ret
I101:
int 101
ret
I102:
int 102
ret
I103:
int 103
ret
I104:
int 104
ret
I105:
int 105
ret
I106:
int 106
ret
I107:
int 107
ret
I108:
int 108
ret
I109:
int 109
ret
I110:
int 110
ret
I111:
int 111
ret
I112:
int 112
ret
I113:
int 113
ret
I114:
int 114
ret
I115:
int 115
ret
I116:
int 116
ret
I117:
int 117
ret
I118:
int 118
ret
I119:
int 119
ret
I120:
int 120
ret
I121:
int 121
ret
I122:
int 122
ret
I123:
int 123
ret
I124:
int 124
ret
I125:
int 125
ret
I126:
int 126
ret
I127:
int 127
ret
I128:
int 128
ret
I129:
int 129
ret
I130:
int 130
ret
I131:
int 131
ret
I132:
int 132
ret
I133:
int 133
ret
I134:
int 134
ret
I135:
int 135
ret
I136:
int 136
ret
I137:
int 137
ret
I138:
int 138
ret
I139:
int 139
ret
I140:
int 140
ret
I141:
int 141
ret
I142:
int 142
ret
I143:
int 143
ret
I144:
int 144
ret
I145:
int 145
ret
I146:
int 146
ret
I147:
int 147
ret
I148:
int 148
ret
I149:
int 149
ret
I150:
int 150
ret
I151:
int 151
ret
I152:
int 152
ret
I153:
int 153
ret
I154:
int 154
ret
I155:
int 155
ret
I156:
int 156
ret
I157:
int 157
ret
I158:
int 158
ret
I159:
int 159
ret
I160:
int 160
ret
I161:
int 161
ret
I162:
int 162
ret
I163:
int 163
ret
I164:
int 164
ret
I165:
int 165
ret
I166:
int 166
ret
I167:
int 167
ret
I168:
int 168
ret
I169:
int 169
ret
I170:
int 170
ret
I171:
int 171
ret
I172:
int 172
ret
I173:
int 173
ret
I174:
int 174
ret
I175:
int 175
ret
I176:
int 176
ret
I177:
int 177
ret
I178:
int 178
ret
I179:
int 179
ret
I180:
int 180
ret
I181:
int 181
ret
I182:
int 182
ret
I183:
int 183
ret
I184:
int 184
ret
I185:
int 185
ret
I186:
int 186
ret
I187:
int 187
ret
I188:
int 188
ret
I189:
int 189
ret
I190:
int 190
ret
I191:
int 191
ret
I192:
int 192
ret
I193:
int 193
ret
I194:
int 194
ret
I195:
int 195
ret
I196:
int 196
ret
I197:
int 197
ret
I198:
int 198
ret
I199:
int 199
ret
I200:
int 200
ret
I201:
int 201
ret
I202:
int 202
ret
I203:
int 203
ret
I204:
int 204
ret
I205:
int 205
ret
I206:
int 206
ret
I207:
int 207
ret
I208:
int 208
ret
I209:
int 209
ret
I210:
int 210
ret
I211:
int 211
ret
I212:
int 212
ret
I213:
int 213
ret
I214:
int 214
ret
I215:
int 215
ret
I216:
int 216
ret
I217:
int 217
ret
I218:
int 218
ret
I219:
int 219
ret
I220:
int 220
ret
I221:
int 221
ret
I222:
int 222
ret
I223:
int 223
ret
I224:
int 224
ret
I225:
int 225
ret
I226:
int 226
ret
I227:
int 227
ret
I228:
int 228
ret
I229:
int 229
ret
I230:
int 230
ret
I231:
int 231
ret
I232:
int 232
ret
I233:
int 233
ret
I234:
int 234
ret
I235:
int 235
ret
I236:
int 236
ret
I237:
int 237
ret
I238:
int 238
ret
I239:
int 239
ret
I240:
int 240
ret
I241:
int 241
ret
I242:
int 242
ret
I243:
int 243
ret
I244:
int 244
ret
I245:
int 245
ret
I246:
int 246
ret
I247:
int 247
ret
I248:
int 248
ret
I249:
int 249
ret
I250:
int 250
ret
I251:
int 251
ret
I252:
int 252
ret
I253:
int 253
ret
I254:
int 254
ret
I255:
int 255
ret

.data
jump_table:
dq I0
dq I1
dq I2
dq I3
dq I4
dq I5
dq I6
dq I7
dq I8
dq I9
dq I10
dq I11
dq I12
dq I13
dq I14
dq I15
dq I16
dq I17
dq I18
dq I19
dq I20
dq I21
dq I22
dq I23
dq I24
dq I25
dq I26
dq I27
dq I28
dq I29
dq I30
dq I31
dq I32
dq I33
dq I34
dq I35
dq I36
dq I37
dq I38
dq I39
dq I40
dq I41
dq I42
dq I43
dq I44
dq I45
dq I46
dq I47
dq I48
dq I49
dq I50
dq I51
dq I52
dq I53
dq I54
dq I55
dq I56
dq I57
dq I58
dq I59
dq I60
dq I61
dq I62
dq I63
dq I64
dq I65
dq I66
dq I67
dq I68
dq I69
dq I70
dq I71
dq I72
dq I73
dq I74
dq I75
dq I76
dq I77
dq I78
dq I79
dq I80
dq I81
dq I82
dq I83
dq I84
dq I85
dq I86
dq I87
dq I88
dq I89
dq I90
dq I91
dq I92
dq I93
dq I94
dq I95
dq I96
dq I97
dq I98
dq I99
dq I100
dq I101
dq I102
dq I103
dq I104
dq I105
dq I106
dq I107
dq I108
dq I109
dq I110
dq I111
dq I112
dq I113
dq I114
dq I115
dq I116
dq I117
dq I118
dq I119
dq I120
dq I121
dq I122
dq I123
dq I124
dq I125
dq I126
dq I127
dq I128
dq I129
dq I130
dq I131
dq I132
dq I133
dq I134
dq I135
dq I136
dq I137
dq I138
dq I139
dq I140
dq I141
dq I142
dq I143
dq I144
dq I145
dq I146
dq I147
dq I148
dq I149
dq I150
dq I151
dq I152
dq I153
dq I154
dq I155
dq I156
dq I157
dq I158
dq I159
dq I160
dq I161
dq I162
dq I163
dq I164
dq I165
dq I166
dq I167
dq I168
dq I169
dq I170
dq I171
dq I172
dq I173
dq I174
dq I175
dq I176
dq I177
dq I178
dq I179
dq I180
dq I181
dq I182
dq I183
dq I184
dq I185
dq I186
dq I187
dq I188
dq I189
dq I190
dq I191
dq I192
dq I193
dq I194
dq I195
dq I196
dq I197
dq I198
dq I199
dq I200
dq I201
dq I202
dq I203
dq I204
dq I205
dq I206
dq I207
dq I208
dq I209
dq I210
dq I211
dq I212
dq I213
dq I214
dq I215
dq I216
dq I217
dq I218
dq I219
dq I220
dq I221
dq I222
dq I223
dq I224
dq I225
dq I226
dq I227
dq I228
dq I229
dq I230
dq I231
dq I232
dq I233
dq I234
dq I235
dq I236
dq I237
dq I238
dq I239
dq I240
dq I241
dq I242
dq I243
dq I244
dq I245
dq I246
dq I247
dq I248
dq I249
dq I250
dq I251
dq I252
dq I253
dq I254
dq I255
.code
_sw_interrupt endp
END
"

James

>One thing to also watch out for is that calling an ‘int x’ instruction

like this bypasses a few assumptions Windows makes about the state of
things.

Yes, for instance, HalBegin/EndSystemInterrupt will be called in the prolog/epilog of the ISR, thus pinging the APIC for the non-existing hardware interrupt.

Probably writing a full storage port - i.e. a PnP bus driver which will support all SRBs, all IOCTL_SCSI_xxx, all SCSIPORT’s naming and is also the power policy owner of its PDOs - is simpler then maintaining such “int x” hacks in the field.


Maxim S. Shatskih
Windows DDK MVP
xxxxx@storagecraft.com
http://www.storagecraft.com