NT: Questions about port drivers

Hi!All,
I am writing a virtual port driver for Windows2000. But I meet the
following troubles:
1 When system will send major function of IRP_MJ_PNP accompanied with minor
function of IRP_MN_DEVICE_USAGE_NOTIFICATION to port driver. Why does system
send IRP_MN_DEVICE_USAGE_NOTIFICATION to port driver?

2 According to sample of Disk Class driver from DDK, disk driver will send
SRB(SCSI_REQUEST_BLOCK) to port driver. “DataBuffer” is a member of SRB. Can
port driver access the memory which “DataBuffer” points to directly?

Any idea is welcome!!! Thank you in advance!!!

The system sends IRP_MN_DEVICE_USAGE_NOTIFICATION to a PDO the port driver
enumerates when a paging, hibernation, or crash dump file is allocated for
this PDO. E.g. in the Power applet in Control Panel; when you select the
check box “enable hibernation” a IRP_MN_DEVICE_USAGE_NOTIFICATION Irp gets
sent to the PDO (usually representing the boot disk) with
DeviceUsageTypeHibernation.

The usual answer . . . It depends. It turns out I’m in the middle of
developing a Port driver and am trying to understand this issue myself. So,
what I’m going to say I “believe” is correct.

-If you are accessing Srb->DataBuffer through a DMA adapter object and its
respective functions you need to use Srb->DataBuffer as the starting point
of a current transfer, passing this VA to GetScatterGather list of
AllocateAdapterChannel.

If you’re not using DMA (and it sounds like you’re not) Srb->DataBuffer may
not be a valid address (in your thread context.) So you need to call
MmGetSystemAddressForMdlSafe(…).

-Now comes the complicated part. . . ClassPnp will split up a request if it
is to big for your adapter to handle. It offsets subsequent requests by
incrementing Srb->DataBuffer. To calculate the offset you need to subtract
the start of the MDL from Srb->DataBuffer:

BufferOffset =
(ULONG)Srb->DataBuffer -
(ULONG)MmGetMdlVirtualAddress(Irp->MdlAddress);

Then you need to get a system address and add the offset to it:

Srb->DataBuffer =
MmGetSystemAddressForMdlSafe(
Irp->MdlAddress,
HighPagePriority
);
Srb->DataBuffer += BufferOffset;

Confused yet: Wait there’s more…

-If the Srb that comes in is a retry, the class driver sends down the same
Irp/Srb that it did in the original request. The means that you no longer
can do the following calculation:

BufferOffset =
(ULONG)Srb->DataBuffer -
(ULONG)MmGetMdlVirtualAddress(Irp->MdlAddress);

Since Srb->DataBuffer has been mapped into system space it no longer
represents an offset into the MDL. Note (I found this out yesterday). To
work around this I look at the return value from
MmGetSystemAddressForMdlSafe. If it is the same as Srb->DataBuffer I know I
don’t need to calculate an offset. If it is different, I calculate an
offset:

//
// If we’re doing a data transfer and there’s an MDL . . .
//
if ( (Srb->SrbFlags & SRB_FLAGS_DATA_IN || Srb->SrbFlags &
SRB_FLAGS_DATA_OUT) &&
(Irp->MdlAddress != NULL) )
{
PVOID TempBuffer;

//
// Save original DataBuffer since we’re going to replace it
// tape drives need to have the original DataBuffer intact
// In the Dpc we’ll move it back before calling IoCompleteRequest.
//
FDODevExt->PrevSrbDataBuffer = Srb->DataBuffer;

//
// Most times BufferOffset will be NULL, but after a
ClassSplitRequest(…)
// the Srb->DataBuffer gets incremented past the start of the
MDL.
// So, we need to use an offset to calculate the databuffer for
this request.
//
BufferOffset =
(ULONG)FDODevExt->PrevSrbDataBuffer -
(ULONG)MmGetMdlVirtualAddress(Irp->MdlAddress);

//
// get a valid system address for the databuffer becuase
// the original address may not be valid in this thread context.
//
TempBuffer =
MmGetSystemAddressForMdlSafe(
Irp->MdlAddress,
HighPagePriority
);

// Test MmGetSystemAddressForMdlSafe call
if (TempBuffer == NULL)
{
ScsiDebugPrint(0, “Call to MmGetSystemAddressForMdlSafe returned
NULL.\n”);
ASSERT(FALSE);

Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
goto STARTIO_RETURN;
}

//
// If Irp->MdlAddress was already mapped TempBuffer ==
Srb->DataBuffer,
// Since, Srb->DataBuffer has already been incremented we don’t
need to
//
if (TempBuffer != Srb->DataBuffer)
{
// Now increment the buffer by the offset calculated above
Srb->DataBuffer = TempBuffer;
(ULONG)Srb->DataBuffer += BufferOffset;
}

ASSERT(MmIsAddressValid(Srb->DataBuffer));
}

If anyone has a better solution, let me know.

Daniel Nemiroff
Intel Corporation
System Software Engineering
(916) 356-5723

-----Original Message-----
From: GuJiang [mailto:xxxxx@psh.com.cn]
Sent: Thursday, June 29, 2000 10:23 PM
To: NT Developers Interest List
Subject: [ntdev] NT: Questions about port drivers

Hi!All,
I am writing a virtual port driver for Windows2000. But I meet the
following troubles:
1 When system will send major function of IRP_MJ_PNP accompanied with minor
function of IRP_MN_DEVICE_USAGE_NOTIFICATION to port driver. Why does system
send IRP_MN_DEVICE_USAGE_NOTIFICATION to port driver?

2 According to sample of Disk Class driver from DDK, disk driver will send
SRB(SCSI_REQUEST_BLOCK) to port driver. “DataBuffer” is a member of SRB. Can
port driver access the memory which “DataBuffer” points to directly?

Any idea is welcome!!! Thank you in advance!!!


You are currently subscribed to ntdev as: xxxxx@intel.com
To unsubscribe send a blank email to $subst(‘Email.Unsub’)