Windows
 

Windows 7 : Programming Drivers for the Kernel Mode Driver Framework (part 7)

11/30/2013 8:26:27 PM

4.5. Default I/O Queue

The SimpleToaster driver uses a default I/O queue, for which KMDF handles power management. The default queue receives all I/O requests for which the driver does not specifically configure another queue. In this case, the default queue receives all read, write, and device I/O control requests that are targeted at the Simple Toaster driver. Default queues do not receive create requests.

The driver configures the queue by using the WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE function, which sets initial values in a configuration structure for the queue:

WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE (&ioEvents,
WdfIoQueueDispatchParallel);

The function takes two parameters: a pointer to a WDF_IO_QUEUE_CONFIG structure (ioEvents) and an enumerator of the WDF_IO_QUEUE_DISPATCH_TYPE, which indicates how to dispatch requests from the queue. By specifying WdfIoQueueDispatchParallel, the driver indicates that KMDF should dispatch I/O requests from the queue as soon as they arrive and that the driver can handle multiple requests in parallel.

After configuring the queue, the driver registers its callbacks for I/O events. The Simple Toaster supports only read, write, and device I/O control requests, so it sets callbacks for only these three events in the ioEvents configuration structure. It then calls WdfIoQueueCreate to create the WDFQUEUE object, as the following code shows:

ioEvents.EvtIoRead = ToasterEvtIoRead;
ioEvents.EvtIoWrite = ToasterEvtIoWrite;
ioEvents.EvtIoDeviceControl = ToasterEvtIoDeviceControl;

status = WdfIoQueueCreate (
hDevice,
&ioEvents,
WDF_NO_OBJECT_ATTRIBUTES,
&queue // pointer to default queue
);

When the driver calls WdfIoQueueCreate, it passes a handle to the WDFDEVICE object (hDevice) and a pointer to the ioEvents configuration structure. The driver accepts the default attributes for the queue, so it passes WDF_NO_OBJECT_ATTRIBUTES. The method returns a handle to the queue at &queue. By default, KMDF places all read, write, and device I/O requests targeted at the device into this queue.

4.6. Handling I/O Request: EvtIoRead, EvtIoWrite, EvtIoDeviceControl

A driver can include one or more of the following I/O callback functions to handle the I/O requests that are dispatched from its queues:

  • EvtIoRead

  • EvtIoWrite

  • EvtIoDeviceControl

  • EvtIoInternalDeviceControl

  • EvtIoDefault

For each queue, the driver registers one or more such callbacks. When an I/O request arrives, KMDF invokes the callback that is registered for that type of request, if one exists. For example, when a read request arrives, KMDF dispatches it to the EvtIoRead callback. Write requests are dispatched to the EvtIoWrite callback, and so forth. KMDF calls the EvtIoDefault callback when a request arrives for which the driver has not registered another callback. (In some cases, EvtIoDefault is also called to handle create request.)

KMDF queues and dispatches only the request for which the driver configures a queue. If KMDF receives any other I/O requests targeted at the Simple Toaster driver, it fails the requests with STATUS_INVALID_DEVICE_REQUEST.

As the preceding section mentions, the Simple Toaster driver handles only read, write, and device I/O control requests, so it includes only the EvtIoRead, EvtIoWrite, and EvtIoDeviceControl callback functions.

When KMDF invokes these callbacks, it passes a handle to the WDFQUEUE object, a handle to the WDFREQUEST object that represents the I/O request, and one or more additional parameters that provide details about the request. The additional parameters vary depending on the specific callback.

If the driver supports buffered or direct I/O, it can use either the buffer passed by the originator of the request or a WDFMEMORY object that represents that buffer. Using a WDFMEMORY object is simpler and requires less code because the framework handles all validation and addressing issues. For example, the handle to the WDFMEMORY object contains the size of the buffer, thus ensuring that buffer overruns does not occur. The Simple Toaster driver uses this technique.

To get a handle to the WDFMEMORY object, the driver calls WdfRequestRetrieveOutputMemory for a read request and WdfRequestRetrieveInputMemory for a write request. Each of these methods creates a WDFMEMORY object that represents the corresponding buffer and is associated with the WDFREQUEST object.

To handle a read request, the driver then gets the data from its device and uses WdfMemoryCopyFromBuffer to copy the data from its internal buffer into the WDFMEMORY object that is associated with the request.

To handle a write request, the driver has three options:

  • Calling WdfMemoryCopyToBuffer to copy data from the WDFREQUEST object to the driver’s internal buffer, from which the driver can write to the device.

  • Getting the buffer pointer from the request by calling WdfRequestRetrieveInputBuffer, which also returns the number of bytes to write.

  • Getting the buffer pointer and the number of bytes to write by calling WdfMemoryGetBuffer.

For most write requests, drivers should use WdfMemoryCopyToBuffer to copy data supplied in the I/O request (and now stored in the associated WDFMEMORY object) to the driver’s output buffer. This function copies the data and returns an error if a buffer overflow occurs. Use the WdfRequestRetrieveInputBuffer and WdfMemoryGetBuffer methods only if you require the buffer pointer so that you can cast it to a structure, which might be necessary when handling a device I/O control request.

Initially, the names WdfMemoryCopyFromBuffer and WdfMemoryCopyToBuffer might appear somewhat confusing. Remember that the word “Memory” in the name means that the function acts on a WDFMEMORY object and copies data to or from a program buffer into that object. Thus, WdfMemoryCopyFromBuffer copies data from the driver’s internal buffer into a WDFMEMORY object, so it is used for read requests. WdfMemoryCopyToBuffer copies data to the driver’s internal buffer, so it is used for write requests.

When the driver has satisfied the I/O request, it calls WdfRequestCompleteWithInformation, which completes the underlying I/O request with the specified status and passes the number of bytes read or written.

The Simple Toaster sample’s EvtIoRead, EvtIoWrite, and EvtIoDeviceControl callbacks are essentially stubs. Although the ToasterEvtIoRead function calls WdfRequestRetrieveOutputMemory to get the output buffer and the ToasterEvtIoWrite function calls WdfRequestRetrieveInputMemory to get the input buffer, neither function reads, writes, or returns any data. Therefore, none of these I/O event callbacks is reproduced here.

 
Others
 
- Windows 7 : Programming Drivers for the Kernel Mode Driver Framework (part 6) - Device Object and Device Context Area, Device Interface
- Windows 7 : Programming Drivers for the Kernel Mode Driver Framework (part 5) - Creating the Device Object, Device Interface
- Windows 7 : Programming Drivers for the Kernel Mode Driver Framework (part 4) - Creating a WDF Driver Object: DriverEntry
- Windows 7 : Programming Drivers for the Kernel Mode Driver Framework (part 3) - KMDF Driver Structure and Concepts - Object Context Area
- Windows 7 : Programming Drivers for the Kernel Mode Driver Framework (part 2) - KMDF Driver Structure and Concepts - Object Creation
- Windows 7 : Programming Drivers for the Kernel Mode Driver Framework (part 1)
- Windows Server 2008 : Creating and Running a PowerShell Script - Testing for the Existence of a File, Creating Output as HTML
- Windows Server 2008 : Creating and Running a PowerShell Script - Running PowerShell Scripts, Logging Processes with a get-process Script
- Windows Server 2008 : Creating and Running a PowerShell Script - Creating and Modifying the Global PowerShell Profile
- Windows Server 2008 : Creating and Running a PowerShell Script - Creating a PowerShell Profile
- Windows Server 2008 : Creating and Running a PowerShell Script - Setting the Security Context
- Windows 8 : Cloud Connections - Office 2013
- Windows 8 : Cloud Connections - SkyDrive (part 3) - To access SkyDrive from a browser
- Windows 8 : Cloud Connections - SkyDrive (part 2) - To open SkyDrive inside Windows Explorer
- Windows 8 : Cloud Connections - SkyDrive (part 1) - To add a file to the tile-based SkyDrive app
- Windows 8 : Cloud Connections - Windows Essentials (part 2) - To install Windows Essentials
- Windows 8 : Cloud Connections - Windows Essentials (part 1)
- Windows 8 : Cloud Connections - Windows Live
- Windows 8 : Cloud Connections - Microsoft Account (part 2) - To enable a roaming profile
- Windows 8 : Cloud Connections - Microsoft Account (part 1) - To convert a local account to a Microsoft account
 
 
Most View
 
- Exchange Server 2013 : Exchange Clients - Why Does Client Choice Matter?
- Windows 8 : Sharing and Securing with User Accounts - Creating and Managing User Accounts (part 4) - Changing a user account type , Password-protecting an account
- Microsoft Lync Server 2013 : Installing the Director Role (part 1) - Prerequisites
- Microsoft Project 2010 : Setting Up Project for Your Use - Defining Calendars (part 2) - Setting Project and Resources Calendar
- Microsoft Exchange Server 2013 : Designing a Successful Exchange Storage Solution - A Brief History of Exchange Storage
- Sharepoint 2013 : Customizing a SharePoint Site - Change the Home Page of a Site
- Microsoft Excel 2010 : Working with Graphics - Inserting a Diagram,Inserting an Object
- Microsoft Word 2010 : Creating an Outline (part 3) - Building an Outline - Expanding and Collapsing Parts of an Outline , Reorganizing an Outline
- SQL Server 2012 : Delivering A SQL Server Health Check (part 10)
- Microsoft Visio 2013 : A Visual Orientation to a Visual Product - Panning and zooming in Visio
 
 
Top 10
 
- Microsoft LynServer 2013 : Dependent Services and SQL - Office Web Apps Server
- Microsoft LynServer 2013 : Dependent Services and SQL - Network Dependencies (part 2) - Defining Network Sites
- Microsoft LynServer 2013 : Dependent Services and SQL - Network Dependencies (part 1) - Supporting Lync Phone Edition with DHCP
- SQL Server 2012 : Performance Monitor Overview (part 5) - Remotely Running PerfMon
- SQL Server 2012 : Performance Monitor Overview (part 4) - Working with Data Collector Sets
- SQL Server 2012 : Performance Monitor Overview (part 3) - Getting Started with PerfMon - Monitoring Real-Time Server Activity, Starting Out with Data Collector Sets
- SQL Server 2012 : Performance Monitor Overview (part 2) - New PerfMon Counters for SQL Server 2012
- SQL Server 2012 : Performance Monitor Overview (part 1) - Reliability and Performance Monitor
- SQL Server 2012 : Knowing Tempdb - Configuration Best Practices (part 2) - Tempdb Initial Sizing and Autogrowth , Configuring Multiple Tempdb Data Files
- SQL Server 2012 : Knowing Tempdb - Configuration Best Practices (part 1) - Tempdb File Placement