Most audio device drivers are interrupt-driven. For example, a waveform output device interrupts when the device needs another data block. A MIDI input device interrupts when the device receives a MIDI event at its input port. Driver code accessed during an interrupt service routine must adhere to the guidelines discussed in the following sections.
Note
Audio and video compression and decompression drivers are not typically accessed during interrupts.
Any code segments or data segments a driver accesses at interrupt time must be fixed segments. For best overall system performance, you should minimize the amount of code and data in fixed segments. To minimize the amount of fixed code, isolate all interrupt-time code in a few source modules and put this code into a single fixed-code segment. Unless your driver has a large amount of data not accessed at interrupt time, use a single fixed-data segment.
The data segment _TEXT is used as a safety measure. The compiler places code for which you do not specify a segment in the _TEXT segment. This way, any code that is missed will be placed into a single segment, preventing possible problems at interrupt time. If you use fixed segments, you should check your segmentation to ensure that only code that is required to be FIXED goes into the FIXED code segment.
The Bravado video-capture driver is a medium-model DLL, using a single data segment and multiple code segments. The following example fragment is from the module-definition file for the Bravado device driver:
CODE MOVEABLE DISCARDABLE LOADONCALL DATA FIXED SINGLE PRELOAD SEGMENTS _TEXT FIXED PRELOAD INIT MOVEABLE DISCARDABLE PRELOAD VCAP MOVEABLE DISCARDABLE PRELOAD
This example fixes the data segment and the code segment named _TEXT. All other code segments are moveable.
You can allocate either local memory or global memory for use at interrupt time.
To allocate local memory for use at interrupt time, follow these steps:
1 Use LocalAlloc with the LMEM_FIXED flag to get a handle to the memory block. (This assumes fixed data segments.)
2 Pass this handle to LocalLock to get a near pointer to the memory block.
Any global memory a driver uses at interrupt time must be page-locked. To allocate and page-lock global memory, follow these steps:
1 Use GlobalAlloc with the GMEM_MOVEABLE and GMEM_SHARE flags to get a handle to the memory block.
2 Pass this handle to GlobalLock to get a far pointer to the memory block.
3 Pass the high-order word of the far pointer to GlobalPageLock to page-lock the memory block.
The only Windows functions a driver can call at interrupt time are: