7.2.5 Points to Consider in Implementing StartIo
Keep the following points in mind when implementing a StartIo routine:
·A StartIo routine must synchronize its access to a physical device and to any shared state information or resources that the driver maintains in the device extension with the driver’s other routines that access the same device, memory location, or resources.
If the StartIo routine shares the device or state with the ISR, it must call KeSynchronizeExecution with a driver-supplied SynchCritSection routine to program the device or to access the shared state. For more information about SynchCritSection routines, see Chapter 10.
If the StartIo routine shares state or resources with routines other than the ISR, it must protect the shared state or resources with a driver-initialized executive spin lock for which the driver provides the storage. For more information about using executive spin locks, see Chapter 16.
·If a monolithic NT device driver sets up a controller object in its DriverEntry routine, its StartIo routine can use the controller object to synchronize operations through a shared physical device with attached (similar) devices.
For more information about controller objects, see Chapter 3. For more information about such a driver’s ControllerControl routine, see Chapter 11.
·Unless a closely coupled higher-level driver pre-splits large DMA transfer requests for its underlying device driver, a DMA device driver’s StartIo routine must split up large transfer requests into partial-transfer ranges and the driver must carry out a sequence of partial-transfer device operations. Each partial transfer must be sized to suit the capabilities of the hardware: either the capabilities of the driver’s device or, for a slave DMA device, the capabilities of the system DMA controller, whichever has stricter constraints.
For more information about using system or busmaster DMA, see Chapter 3.
·The StartIo routine of a driver that uses DMA must synchronize transfers using an adapter object.
For more information about adapter objects, see Chapter 3.
·A StartIo routine is run at IRQL DISPATCH_LEVEL, which restricts the set of support routines it can call.
For example, a StartIo routine can neither access nor allocate pageable memory, and it cannot wait on a dispatcher object. On the other hand, a StartIo routine can acquire and release a driver-allocated executive spin lock with KeAcquireSpinLockAtDpcLevel and KeReleaseSpinLockFromDpcLevel, which run faster than KeAcquireSpinLock and KeReleaseSpinLock.
For more information about managing IRQLs and using spin locks, see Chapter 16.
·If the driver holds IRPs in a cancelable state, its StartIo routine must check whether the input IRP has already been cancelled before it begins any processing for that request on its device. For more information about managing cancelable IRPs, see also Chapter 12.