3.2.4 Setting Up Access to User Buffers

Most NT device and all intermediate drivers set a bit in the DeviceObject->Flags, shown in Figure 3.2, by ORing the Flags either with DO_BUFFERED_IO or with DO_DIRECT_IO in each device object they create. NT drivers must use one of the following three ways to access user buffers for data transfers:

·If an NT driver services an interactive (slow) device and/or usually transfers relatively small chunks of data at a time, it should set up its device object(s) requesting buffered I/O. Using buffered I/O for small, interactive transfers improves overall physical memory usage, because the NT Memory Manager need not lock down a full physical page for each transfer, as it does for NT drivers that request direct I/O.

Generally, NT video, keyboard, mouse, serial, and parallel drivers request buffered I/O.

Any NT intermediate driver layered above such a device driver must set up its DeviceObject->Flags to match that of the next-lower-level driver.

·If an NT driver services a device that can transfer large chunks of data at a time, it should set up its device object(s) requesting direct I/O. Using direct I/O for large transfers improves a driver's performance both by reducing its interrupt overhead and by eliminating the memory allocation and copying operations inherent in buffered I/O.

Generally, NT mass-storage device drivers request direct I/O for transfer requests, including lowest-level drivers that use DMA or PIO, as well as any intermediate drivers chained above them.

Even drivers that request direct I/O use buffered I/O to satisfy certain IRPs. In particular, the system-defined, device-type-specific I/O control codes for IRP_MJ_DEVICE_CONTROL requests that require data transfers are buffered, whether a driver has ORed its device objects' Flags with DO_DIRECT_IO or not.

Any NT intermediate driver layered above such a device driver must set up its DeviceObject->Flags to match that of the next-lower driver.

·A driver writer can choose to set up device object(s) requesting neither direct nor buffered I/O if and only if the driver will always be called in the context of the original, user-mode thread that requests an I/O operation. Such a driver must be a highest-level NT driver.

The following subsections describe how ORing device objects' Flags with DO_BUFFERED_IO, DO_DIRECT_IO, or neither affects data transfer requests sent to NT drivers, including how the data can be stored in physical memory and how a driver can access that memory.