some notes:
-
- this will freeze the queue for the current LUN, not the current
target. very important distinction here. scsiport doesn’t do anything
to track targets except as part of the bus address of the LUNs.
the code below looks okay from a quick scan, but obviously something’s
wrong with it so that “is this all correct” question is tough to answer

at the point that you crashed, ESI contains the pointer to the SRB
scsiport is processing. If you log all SRB pointers as they enter and
leave your driver you should be able to compare ESI against that log to
find out which SRB it is. Simply dumping the SRB probably won’t help
since it’s very likely been reused as a new SRB (or some other memory
allocation) by that point.
-p
-----Original Message-----
From: Joe Moriarty [mailto:xxxxx@east.sun.com]
Sent: Friday, October 25, 2002 9:11 AM
To: NT Developers Interest List
Subject: [ntdev] RE: Virtual SCSI miniport question
Peter,
I am 100% sure you are correct. The only problem I have now is
determining which SRB I am completing twice. I have checked each and
everyone of the requests to make sure everything is correct. The only
question I have now is if I am handling the case when passing the
request down to a lower level driver.
So here is the sequence of events.
- SRB_FUNCTION_EXECUTE_SCSI requests comes in to my StartIo.
- I notify a worker thread to pass the request down to the lower level
driver. pointer to the SRB is passed to the worker thread.
- I do the following before returning from my StartIo routine.
//Adapter ready for next request.
ScsiPortNotification(NextRequest, pAdapterExt, NULL);
I do not mark the current SRB I was working on in my StartIo as
completed, busy, etc. My guess was that this would freeze
the queue for this particular target ID. I verified this in the
debugger.
- Worker thread starts up and passes the SRB down to the lower level
driver and waits on completion.
- Upon completion of the SRB I create the following IRP to pass to the
SCSIPORT driver. The code is below.
PPDO_SCSI_MINIPORT_EXTENSION pPdoScsiMiniportExt;
PEMDISK_CONTROLLER_EXTENSION pEmDiskCntrlExt;
PDEVICE_EXT_HDR pPdoDevExtHdr;
PSCSI_REQUEST_BLOCK pCurrentSrb;
KEVENT kEvent;
IO_SRB_CONTROL_STRUCTURE IoCntrlStrct;
PIRP pIrp;
LARGE_INTEGER liStartingOffset;
IO_STATUS_BLOCK IoStatusBlock;
SCSI_REQUEST_BLOCK Srb;
PIO_STACK_LOCATION pIrpSp;
NTSTATUS Status = STATUS_INSUFFICIENT_RESOURCES;
pPdoScsiMiniportExt =
(PPDO_SCSI_MINIPORT_EXTENSION)pAdapterExt->pPdoScsiMiniport;
pEmDiskCntrlExt =
pPdoScsiMiniportExt->PdoDskCntrlComExt.DeviceDataExt.pEmDiskCntrlExt;
pPdoDevExtHdr =
&pPdoScsiMiniportExt->PdoDskCntrlComExt.DeviceDataExt.DeviceExtHdr;
pCurrentSrb = pAdapterExt->pCurrentSrb;
KeInitializeEvent(&kEvent, NotificationEvent, FALSE);
//
// Setup Data structure
//
RtlZeroMemory(&IoCntrlStrct, sizeof(IO_SRB_CONTROL_STRUCTURE));
IoCntrlStrct.IoSrbCntrl.HeaderLength = sizeof(SRB_IO_CONTROL);
strcpy(IoCntrlStrct.IoSrbCntrl.Signature, VER_INTERNALNAME_STR);
IoCntrlStrct.IoSrbCntrl.Timeout = FOUR_SECONDS;
IoCntrlStrct.IoSrbCntrl.ControlCode = DIO_SUNPCI_INTERMEDIATE_IO;
IoCntrlStrct.IoSrbCntrl.Length = sizeof(PSCSI_REQUEST_BLOCK);
IoCntrlStrct.pCurSrb = pCurrentSrb;
liStartingOffset.QuadPart = 1;// SCSIPORT does this, no idea why…
pIrp = IoBuildSynchronousFsdRequest(IRP_MJ_SCSI,
(PDEVICE_OBJECT)pAdapterExt->pScsiPortDevObj,
&IoCntrlStrct,
sizeof(IO_SRB_CONTROL_STRUCTURE),
&liStartingOffset, &kEvent,
&IoStatusBlock);
if(pIrp)
{
//
// Setup Irp Request Data
//
RtlZeroMemory(&Srb, sizeof(SCSI_REQUEST_BLOCK));
Srb.PathId = pCurrentSrb->PathId;
Srb.TargetId = pCurrentSrb->TargetId;
Srb.Lun = pCurrentSrb->Lun;
Srb.Function = SRB_FUNCTION_IO_CONTROL;
Srb.Length = sizeof(SCSI_REQUEST_BLOCK);
Srb.SrbFlags = SRB_FLAGS_DATA_IN | SRB_FLAGS_NO_QUEUE_FREEZE |
SRB_FLAGS_BYPASS_FROZEN_QUEUE;
Srb.DataBuffer = &IoCntrlStrct;
Srb.DataTransferLength = sizeof(IO_SRB_CONTROL_STRUCTURE);
pIrpSp = IoGetNextIrpStackLocation(pIrp);
pIrpSp->MajorFunction = IRP_MJ_SCSI;
pIrpSp->MinorFunction = 1;
pIrpSp->Parameters.Scsi.Srb = &Srb;
IoCallDriver((PDEVICE_OBJECT)pAdapterExt->pScsiPortDevObj, pIrp);
KeWaitForSingleObject(&kEvent, Executive, KernelMode, FALSE,
NULL);
Status = IoStatusBlock.Status;
}
6) My StartIo routine is hit with the above IRP. I figure out that the
IRP came from my worker thread trying to complete the SRB he was working
on. I complete the request for the worker thread. I then complete the
request for worker thread IRP he sent to complete the SRB. Below is the
code that does this.
pSrbIoCntrl = (PSRB_IO_CONTROL)pSrb->DataBuffer;
if(RtlCompareMemory(pSrbIoCntrl->Signature, VER_INTERNALNAME_STR,
sizeof(pSrbIoCntrl->Signature)) ==
sizeof(pSrbIoCntrl->Signature))
{
switch(pSrbIoCntrl->ControlCode)
{
case DIO_SUNPCI_INTERMEDIATE_IO:
{
PIO_SRB_CONTROL_STRUCTURE pIoSrbCntrlStrct;
pIoSrbCntrlStrct =
(PIO_SRB_CONTROL_STRUCTURE)pSrb->DataBuffer;
pCompletedSrb = pIoSrbCntrlStrct->pCurSrb;
if(pCompletedSrb)
{
// Complete the original SRB request.
ScsiPortNotification(RequestComplete, pAdapterExt,
pCompletedSrb);
}
// Set the status for the Intermediate SRB
pSrb->ScsiStatus = SCSISTAT_GOOD;
pSrb->SrbStatus = SRB_STATUS_SUCCESS;
// Complete the Intermediate SRB request.
ScsiPortNotification(RequestComplete, pAdapterExt, pSrb);
break;
}
Is this all correct?
Joe
-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com]On Behalf Of Peter Wieland
Sent: Thursday, October 24, 2002 2:43 PM
To: NT Developers Interest List
Subject: [ntdev] RE: Virtual SCSI miniport question
SpGetInterruptState takes all the data squirreled away while the
miniport was running inside the ‘interupt spinlock’ (in your case it’s
just a normal spinlock and we synch at DPC level) and makes it safely
accessible by the completion DPC. If it’s faulting in that routine
it’s likely that something squirreled away is no longer valid - for
example you might have completed an SRB which had already been
completed earlier.
given that the SrbStatus is a one byte field at offset 3 in the SRB,
that SpGetInterruptState checks the SRB statuses while processing
them, and that the faulting address below is attempting to read a one
byte value at offset 3 from esi, I’d suspect that’s the case.
-p
-----Original Message-----
From: Joe Moriarty [mailto:xxxxx@east.sun.com]
Sent: Thursday, October 24, 2002 10:28 AM
To: NT Developers Interest List
Subject: [ntdev] Virtual SCSI miniport question
I have a virtual SCSI miniport driver that works fine except for when
the user issues a SHUTDOWN/RESET under Win2K. I get to the “Windows
is shutting down …” and then boom. The dump is below. It doesn’t
happen all the time. I would say that in 50% of the shutdowns this
will occur. The question I have is why is the SCSIPORT driver trying
to acquire the interrupt state from the HBA? I have set the
HwInterrupt routine to NULL in my DriverEntry routine. BTW, this is a
PNP virtual SCSI miniport. The system thinks it’s on a ISA bus. I
have created a bus driver that enumerates a virtual SCSI miniport
device. The SCSIPORT driver loads on top of this stack and then calls
my virtual SCSI miniport driver.
Thanks In Advance,
Joe
**********************************************************************
**
****
***
*
*
* Bugcheck Analysis
*
*
*
************************************************************************
****
***
DRIVER_IRQL_NOT_LESS_OR_EQUAL (d1)
An attempt was made to access a pagable (or completely invalid)
address at an interrupt request level (IRQL) that is too high. This
is usually caused by drivers using improper addresses. If kernel
debugger is available get stack backtrace.
Arguments:
Arg1: 00000003, memory referenced
Arg2: 00000002, IRQL
Arg3: 00000000, value 0 = read operation, 1 = write operation
Arg4: bff3a6a6, address which referenced memory
Debugging Details:
READ_ADDRESS: 00000003 Unknown
CURRENT_IRQL: 2
FAULTING_IP:
SCSIPORT!SpGetInterruptState+6e
bff3a6a6 8a5603 mov dl,[esi+0x3]
DEFAULT_BUCKET_ID: DRIVER_FAULT
BUGCHECK_STR: D1
LAST_CONTROL_TRANSFER: from 8042bcb9 to 80452e70
STACK_TEXT:
f441fb0c 8042bcb9 00000003 f441fb54 00000003
nt!RtlpBreakWithStatusInstruction f441fb3c 8042c068 00000003 00000003
bff3a6a6 nt!KiBugCheckDebugBreak+0x31 f441fec4 80464b1f 00000000
00000003 00000002 nt!KeBugCheckEx+0x37b f441fec4 bff3a6a6 00000000
00000003 00000002 nt!KiTrap0E+0x27c f441ff5c bff3b636 f441ffd0
818881e4 818880e8 SCSIPORT!SpGetInterruptState+0x6e f441ff70 bff39971
818880e8 bff3a638 f441ffd0 SCSIPORT!SpSynchronizeExecution+0x1e
f441ffe0 80460bd4 818880a4 81888030 00000000
SCSIPORT!ScsiPortCompletionDpc+0x3b
f441fff4 80403a82 f4473b9c 00000000 00000000 nt!KiRetireDpcList+0x30
FOLLOWUP_IP:
SCSIPORT!SpGetInterruptState+6e
bff3a6a6 8a5603 mov dl,[esi+0x3]
FOLLOWUP_NAME: MachineOwner
SYMBOL_NAME: SCSIPORT!SpGetInterruptState+6e
MODULE_NAME: SCSIPORT
IMAGE_NAME: SCSIPORT
STACK_COMMAND: kb
BUCKET_ID: 0xD1_SCSIPORT!SpGetInterruptState+6e
Followup: MachineOwner
You are currently subscribed to ntdev as: xxxxx@microsoft.com To
unsubscribe send a blank email to %%email.unsub%%
You are currently subscribed to ntdev as: xxxxx@east.sun.com To
unsubscribe send a blank email to %%email.unsub%%
You are currently subscribed to ntdev as: xxxxx@microsoft.com To
unsubscribe send a blank email to %%email.unsub%%