Re: For PDO: How to forward request to next lower driver stack automatically in KMDF? by Eliyas
Eliyas
Tue Jun 05 12:48:04 CDT 2007
Instead of exchanging callback pointers between the PDO and parent FDO, you
can use IoTarget to forward the request from PDO to parent FDO. Currently
there isn't a sample in the WDK that shows how to do this but we have used
this scheme in couple of our MS drivers. In the future version of framework,
we might allow you to transfer request from the child PDO queue directly to
the parent FDO queue without using IoTarget.
So here are the steps on how to forward reqeust from PDO to parent FDO:
You do the steps 1-3 in the routine that creates the child PDO.
1) Get the wdm deviceobject pointer from the parent FDO.
PDEVICE_OBJECT parentWdmDeviceObject;
parentWdmDeviceObject =
WdfDeviceWdmGetDeviceObject(WdfPdoGetParent(hChild));
2) Increas the stack size of the PDO to account for the stack size of parent
FDO.
WdfDeviceWdmGetDeviceObject(hChild)->StackSize +=
parentWdmDeviceObject->StackSize;
3) Create an IoTarget and open the taget by using the deviceobject pointer
of parentWdmDeviceObject.
status = WdfIoTargetCreate(hChild,
WDF_NO_OBJECT_ATTRIBUTES,
&pdoData->IoTargetForParentFdo);
if (!NT_SUCCESS (status)) {
goto Cleanup;
}
WDF_IO_TARGET_OPEN_PARAMS_INIT_EXISTING_DEVICE(&openParams,
parentWdmDeviceObject );
status = WdfIoTargetOpen(pdoData->IoTargetForParentFdo, &openParams);
if (!NT_SUCCESS (status)) {
goto Cleanup;
}
4) Use this iotarget to forward request. You can either forward in a
fire-and-forget manner or forward it with a completion routine. The
following routine shows how to forward reqeust from a default I/O handler of
PDO.
VOID
PdoEvtIoDefault(
IN WDFQUEUE Queue,
IN WDFREQUEST Request
)
{
NTSTATUS status;
BOOLEAN ret;
WDF_REQUEST_SEND_OPTIONS options;
PPDO_DEVICE_DATA pdoData;
WDFDEVICE device;
device = WdfIoQueueGetDevice(Queue);
pdoData = PdoGetData(device);
#ifdef FIRE_AND_FORGET
WDF_REQUEST_SEND_OPTIONS_INIT(&options,
WDF_REQUEST_SEND_OPTION_SEND_AND_FORGET);
ret = WdfRequestSend(Request,
pdoData->IoTargetForParentFdo,
&options);
#else
WdfRequestFormatRequestUsingCurrentType(Request);
WdfRequestSetCompletionRoutine(Request,
PdoRequestCompletionRoutine,
WDF_NO_CONTEXT);
ret = WdfRequestSend (Request, pdoData->IoTargetForParentFdo,
WDF_NO_SEND_OPTIONS);
#endif
if (ret == FALSE) {
status = WdfRequestGetStatus (Request);
KdPrint(("WdfRequestSend failed: 0x%x\n", status));
WdfRequestComplete(Request, status);
}
return;
}
VOID
PdoRequestCompletionRoutine(
IN WDFREQUEST Request,
IN WDFIOTARGET Target,
PWDF_REQUEST_COMPLETION_PARAMS CompletionParams,
IN WDFCONTEXT Context
)
{
UNREFERENCED_PARAMETER(Target);
UNREFERENCED_PARAMETER(Context);
WdfRequestComplete(Request, CompletionParams->IoStatus.Status);
return;
}
-Eliyas