ENTERPRISE

Windows 7 : Programming Multiple I/O Queues and Programming I/O - Handling Requests from a Parallel Queue

7/17/2014 4:40:37 AM

KMDF delivers I/O requests from a parallel queue by calling the appropriate callback function that the driver registered for the queue. For example, the PCIDRV sample configures its parallel device I/O control queue, which accepts only WdfRequestTypeDeviceControl requests, with an EvtIoDeviceControl callback.

The driver’s actions in the callback depend on the type of I/O that is required to satisfy the request. If the request required DMA, the driver should retrieve a pointer to the device context area and then set up the DMA transaction.

For I/O requests that do not involve DMA, a driver takes the following steps:

1.
Gets the parameters for the I/O request.

2.
Parses the parameters.

3.
Performs the requested I/O or manually requeues the request for later processing.

1. Code to Handle I/O Requests

The following code shows how the PCIDRV sample handles certain device I/O control requests. The PciDrvEvtIoControl function is the driver’s EvtIoDeviceControl callback for one of its parallel queues and appears in the pcidrv\sys\Pcidrv.c source file.

VOID
PciDrvEvtIoDeviceControl (
IN WDFQUEUE Queue,
IN WDFREQUEST Request,
IN size_t OutputBufferLength,
IN size_t InputBufferLength,
IN ULONG IoControlCode
)
{
NTSTATUS status = STATUS_SUCCESS;
PFDO_DATA fdoData = NULL;
WDFDEVICE hDevice;
WDF_REQUEST_PARAMETERS params;

UNREFERENCED_PARAMETER (OutputBufferLength);
UNREFERENCED_PARAMETER (InputBufferLength);


hDevice = WdfIoQueueGetDevice (Queue);
fdoData = FdoGetData (hDevice);

WDF_REQUEST_PARAMETERS_INIT (&params);

WdfRequestGetParameters (
Request,
&params
);
switch (IoControlCode)
{
case IOCTL_NDISPROT_QUERY_OID_VALUE:
ASSERT ((IoControlCode * 0x3) ==
METHOD_BUFFERED);
NICHandleQueryOldRequest (
Queue,
Request,
&params
);
break;

// code omitted
// ... . .
//
case IOCTL_NDISPROT_INDICATE_STAUS:
status = WdfRequestForwardToIoQueue (Request,
fdoData->PendingIoctlQueue);
if (!NT_SUCCESS (status))
{
WdfRequestcomplete (Request, status);
break;
}
break;

default:
ASSERTMSG (FALSE, "Invalid IOCTL request\n");
WdfRequestComplete (Request,
STATUS_INVALID_DEVICE_REQUEST);
break;
}
return;
}


The driver requires access to its device object context area, so it starts by calling WdfIoQueueGetDevice, which returns a handle to the device object that is associated with the I/O queue. It then passes the returned handle to FdoGetData, the accessor function for its device context area, which returns a pointer to the context area.

Next, the driver retrieves the parameters that were passed with the I/O request. KMDF defines the WDF_REQUEST_PARAMETERS structure for this purpose. The driver initializes the structure by calling WDF_REQUEST_PARAMETERS_INIT and then passes it to the WdfRequestParameters method. This method fills in the requested parameters. The driver must retrieve the parameters from the request structure before it performs the I/O.

The driver’s action depends on the I/O control code that was specified in the request. For most control codes, the driver calls a device-specific function to handle the request. If the control code is valid, the driver performs the requested action. If the control code is not valid, the driver completes the request by calling WdfRequestComplete with the handle to the request and the status STATUS_INVALID_DEVICE_REQUEST.

In response to the two control codes shown in the code, the driver takes two different actions. If the control code is IOCTL_NDISPROT_QUERY_OID_VALUE, the driver performs buffered I/O. If the control code is IOCTL_NDISPROT_INDICATE_STATUS, the driver forwards the request to a different I/O queue. The next two sections describe these actions.

2. Performing Buffered I/O

The WDFREQUEST object contains pointers to the input and output buffers for the I/O request. The driver can obtain these pointers by calling WdfRequestRetrieveOutputBuffer and WdfRequestRetrieveInputBuffer.

For METHOD_BUFFERED requests, however, the input and output buffers are the same, so both of these methods return the same pointer. Therefore, when performing buffered I/O, a driver must read all input data from the buffer before writing any output data to the buffer.

The NICHandleQueryOidRequest function, defined in the pcidrv\sys\hw\Nic_req.c file, gets the input and output buffers from the WDFREQUEST object and retrieves the requested information. Most of this function performs device-specific tasks, so this section describes only the KMDF-specific actions.

The sample retrieves the buffer by calling WdfRequestRetrieveOutputBuffer, as follows:

status = WdfRequestRetrieveOutputBuffer (Request,
sizeof (NDISPROT_QUERY_OID),
&DataBuffer,
&BufferLength
);

if (!NT_SUCCESS (status))
{
WdfRequestcomplete (Request, status);
return;
}

The input parameters to WdfRequestRetrieveOutputBuffer are the handle to the request object and the minimum required size for the buffer. The method returns a pointer to the buffer and a pointer to its length. If the length is smaller than the minimum required or if some other error occurs, WdfRequestRetrieveOutputBuffer returns a failure status and the driver immediately completes the request with that status.

The driver then performs device-specific queries for the requested information and writes the returned data into the output buffer. If the buffer is too small to hold the data, the driver sets status to STATUS_BUFFER_TOO_SMALL.

Next, the driver updates the buffer length to include the number of bytes of data, the size of the structure that holds it, and any padding bytes that are required to align the structure correctly. The driver performs this calculation even if the buffer is too small, so that it can return the buffer length that would be required to successfully complete the request. Finally, the driver completes the request by calling WdfRequestCompleteWithInformation with the handle to the request, the previously set status value, and the calculated buffer length, as follows:

//
// Adjust the size to include the structure.
//
ulInfoLen += FIELD_OFFSET (NDISPROT_QUERY_OID, Data);

WdfRequestCompleteWithInformation (Request,
Status, ulInfoLen);
Other  
  •  Windows 7 : Programming Multiple I/O Queues and Programming I/O - Creating and Configuring the Queues (part 2)
  •  Windows 7 : Programming Multiple I/O Queues and Programming I/O - Creating and Configuring the Queues (part 1)
  •  Microsoft Exchange Server 2010 : Managing Mailbox and public Folder Databases (part 2) - Moving Databases
  •  Microsoft Exchange Server 2010 : Managing Mailbox and public Folder Databases (part 1) - Mounting and Dismounting Databases
  •  Microsoft Exchange Server 2010 : Using Public Folder Databases (part 4) - Configuring Public Folder Referrals, Recovering Deleted Items from Public Folder Databases
  •  Microsoft Exchange Server 2010 : Using Public Folder Databases (part 3) - Configuring Public Folder Replication
  •  Microsoft Exchange Server 2010 : Using Public Folder Databases (part 2) - Setting Public Folder Database Limits
  •  Microsoft Exchange Server 2010 : Using Public Folder Databases (part 1) - Creating Public Folder Databases
  •  Microsoft Exchange Server 2010 : Working with Active Mailbox Databases (part 3) - Recovering Deleted Mailboxes , Recovering Deleted Items from Mailbox Databases
  •  Microsoft Exchange Server 2010 : Working with Active Mailbox Databases (part 2) - Setting Mailbox Database Limits and Deletion retention
  •  
    Top 10
    Extending LINQ to Objects : Writing a Single Element Operator (part 2) - Building the RandomElement Operator
    Extending LINQ to Objects : Writing a Single Element Operator (part 1) - Building Our Own Last Operator
    3 Tips for Maintaining Your Cell Phone Battery (part 2) - Discharge Smart, Use Smart
    3 Tips for Maintaining Your Cell Phone Battery (part 1) - Charge Smart
    OPEL MERIVA : Making a grand entrance
    FORD MONDEO 2.0 ECOBOOST : Modern Mondeo
    BMW 650i COUPE : Sexy retooling of BMW's 6-series
    BMW 120d; M135i - Finely tuned
    PHP Tutorials : Storing Images in MySQL with PHP (part 2) - Creating the HTML, Inserting the Image into MySQL
    PHP Tutorials : Storing Images in MySQL with PHP (part 1) - Why store binary files in MySQL using PHP?
    REVIEW
    - First look: Apple Watch

    - 3 Tips for Maintaining Your Cell Phone Battery (part 1)

    - 3 Tips for Maintaining Your Cell Phone Battery (part 2)
    VIDEO TUTORIAL
    - How to create your first Swimlane Diagram or Cross-Functional Flowchart Diagram by using Microsoft Visio 2010 (Part 1)

    - How to create your first Swimlane Diagram or Cross-Functional Flowchart Diagram by using Microsoft Visio 2010 (Part 2)

    - How to create your first Swimlane Diagram or Cross-Functional Flowchart Diagram by using Microsoft Visio 2010 (Part 3)
    Popular Tags
    Microsoft Access Microsoft Excel Microsoft OneNote Microsoft PowerPoint Microsoft Project Microsoft Visio Microsoft Word Active Directory Biztalk Exchange Server Microsoft LynC Server Microsoft Dynamic Sharepoint Sql Server Windows Server 2008 Windows Server 2012 Windows 7 Windows 8 Adobe Indesign Adobe Flash Professional Dreamweaver Adobe Illustrator Adobe After Effects Adobe Photoshop Adobe Fireworks Adobe Flash Catalyst Corel Painter X CorelDRAW X5 CorelDraw 10 QuarkXPress 8 windows Phone 7 windows Phone 8 BlackBerry Android Ipad Iphone iOS