As its name suggests, a StartIo routine in an NT device driver is responsible for starting an I/O operation on the physical device.
When an NT device driver’s StartIo routine is called, it can assume that the target device represented by the input device object is not busy. Either one of that device driver’s Dispatch routines has just called IoStartPacket and the IRP was not inserted into the device queue associated with the target device object, or the driver’s DpcForIsr routine is completing another request and has just called IoStartNextPacket.
Before the StartIo routine in a highest-level NT device driver is called, that driver’s Dispatch routine must have probed and locked down the user buffer, if necessary, to set up valid mapped buffer addresses in the IRP queued to its StartIo routine. Such a highest-level device driver that sets up its device objects for direct I/O (or for neither buffered nor direct I/O) cannot defer locking down a user buffer to the driver’s StartIo routine because every StartIo routine is called in an arbitrary thread context at IRQL DISPATCH_LEVEL.
Any buffer memory to be accessed by an NT driver’s StartIo routine must be locked down or allocated from resident, system-space memory and must be accessible in an arbitrary thread context.
NT drivers that set up their device objects for buffered I/O can rely on the I/O Manager to pass valid buffers in all IRPs sent to such a driver. Lower-level NT drivers that set up device objects for direct I/O can rely on the highest-level NT driver in their chain to pass valid buffers in all IRPs sent through any intermediate drivers to the underlying device driver.
In general, any NT device driver’s StartIo routine is responsible for calling IoGetCurrentIrpStackLocation with the input IRP and then doing whatever request-specific processing is necessary to start the I/O operation on its device, which can include the following:
For example, if a device driver maintains an InterruptExpected Boolean about the current transfer operation, its StartIo routine might set this variable to TRUE. If the driver maintains a time-out counter for the current operation, its StartIo routine might set up this value, or the StartIo routine might queue the driver’s CustomTimerDpc routine.
Note that if this state information or any other resource is shared with other driver routines, the state area or resource must be protected by a spin lock. If the StartIo routine shares state or resources with other nonISR routines, it must acquire the spin lock that protects the state or resource before accessing it. If the StartIo routine shares state with the driver’s ISR, StartIo must call KeSynchronizeExecution with a driver-supplied SynchCritSection routine that sets up the state.
For more information about CustomTimerDpc routines, see Chapter 14. For more information about the ISR and SynchCritSection routines, see Chapters 8 and 10, respectively. For more information about using spin locks, see Chapter 16.
For more information about logging I/O errors, see Chapter 16.
For example, a disk driver might need to calculate the starting sector and/or byte offset to the physical disk address for a transfer operation, and whether the requested length of the transfer will cross a particular sector boundary or exceed the transfer capacity of its physical device.
For more information about handling removable media, see Chapter 16.
The StartIo routine of such a device driver also can be responsible for calling KeFlushIoBuffers and, if the driver uses packet-based DMA, for calling IoAllocateAdapterChannel with the driver’s AdapterControl routine.
For more information about AdapterControl routines, see Chapter 11. For more information about maintaining cache coherency during DMA operations, see also Chapter 16.
For read requests, the device driver’s StartIo routine can be responsible for calling KeFlushIoBuffers before PIO operations begin. For more information about maintaining cache coherency during PIO, see also Chapter 16.
For more information about ControllerControl routines, see Chapter 11.
For more information about Cancel routines, see Chapter 12.