Usually, the StartIo routine in an NT device driver must synchronize access to any memory or device registers it shares with the driver’s ISR by calling KeSynchronizeExecution with a driver-supplied SynchCritSection routine.
In other words, a device driver’s StartIo routine generally causes the SynchCritSection routine to actually program the physical device for I/O at DIRQL. For more information about SynchCritSection routines, see Chapter 10.
The StartIo routine must do any preprocessing necessary for the request, such as calculating an initial partial-transfer range and saving any state information about the original request for other driver routines, before it calls KeSynchronizeExecution with a SynchCritSection routine that programs the device.
If a device driver uses DMA, its StartIo routine usually calls IoAllocateAdapterChannel with a driver-supplied AdapterControl routine. In these circumstances, the StartIo routine postpones the responsibility for programming the physical device to the AdapterControl routine. It, in turn, can call KeSynchronizeExecution to have a driver-supplied SynchCritSection routine program the device for a DMA transfer.
For more information about how driver routines share resources with an ISR or share resources among routines other than the ISR in a multiprocessor-safe way, see the section on using spin locks in Chapter 16. For more information about using DMA, see Chapter 3 or, for AdapterControl routines, see Chapter 11.