Sound Blaster DMA: The IRQ Dance
SET BLASTER=A220 I5 D1
For any PC gamer in the early 90s, configuring a game meant running SETUP.EXE and manually selecting three magic numbers: Base Address (220), IRQ (5), and DMA (1).
If you got them wrong, the game would hang, or worse—you’d get sound effects but no music (or vice versa).
But why was this necessary? Unlike modern plug-and-play USB audio, the Creative Labs Sound Blaster relied on a direct, low-level conversation with the motherboard’s Direct Memory Access (DMA) controller.
The 8237 DMA Controller
The Intel 8237 was a support chip on the PC motherboard. Its job was simple but vital: copy bytes from RAM to an I/O device (or vice versa) without bothering the CPU. This was essential for audio. If the CPU had to manually move every byte of sound data to the card 11,000 times a second, it would have no time to run the game logic.
Channel 1 (D1) was the standard 8-bit channel used by the Sound Blaster.
The Sequence of Playback
Playing a digital sound effect (PCM) involved a complex coordination dance:
- Allocate Buffer: The programmer reserves a chunk of conventional memory (must be within the first 1MB of RAM, and cannot cross a 64KB physical page boundary—a notorious bug/limitation of the 8237).
- Fill Buffer: Copy the audio data (e.g., “I’m sorry, Dave”) into this buffer.
- Program the DMA: Tell the 8237 chip: “Look at address X. I need you to transfer Y bytes. Do it in Single Cycle mode.”
- Wake the Blaster: Send a command to the Sound Blaster’s DSP (Digital Signal Processor) via port
0x22C. Command0x14means “8-bit Output”. Then send the length of the sound.
Once triggered, the DMA controller starts spoon-feeding bytes to the Sound Blaster. The Sound Blaster converts them to analog audio. The CPU is free to do other things.
Code Snippet: Programming the DMA
This is what the low-level code looked like to set up Channel 1.
void setup_dma(unsigned int buffer_offset, unsigned int length) {
length--; // DMA count is always len-1
outp(0x0A, 0x05); // Mask DMA channel 1 (Disable it temporarily)
outp(0x0C, 0x00); // Clear byte pointer flip-flop
// Set Mode: Single Mode, Increment, Read transfer, Channel 1
outp(0x0B, 0x49);
// Write the Page Register (Upper 4 bits of 20-bit address)
// Assumes buffer is in first 64k segment for simplicity
outp(0x83, 0x00);
// Write Offset (Lower 16 bits) - Low Byte then High Byte
outp(0x02, buffer_offset & 0xFF);
outp(0x02, (buffer_offset >> 8) & 0xFF);
// Write Count - Low Byte then High Byte
outp(0x03, length & 0xFF);
outp(0x03, (length >> 8) & 0xFF);
outp(0x0A, 0x01); // Unmask DMA channel 1 (Enable it)
}
The Interrupt (IRQ)
What happens when the sound finishes? The Sound Blaster pulls the IRQ line (usually IRQ 5 or 7). This signals the Programmable Interrupt Controller (PIC) to pause the CPU and jump to a specific function in your code: the Interrupt Service Routine (ISR).
In the ISR, you had to:
- Acknowledge the interrupt (read port
0x22Eon SB Pro/16). - Tell the PIC you are done (send
0x20to port0x20). - Decide what to do next (stop playback, or load the next chunk of audio).
Ping-Pong Buffering
To play continuous music (like a long background track), developers used Double Buffering (or Ping-Pong buffering). They would allocate a buffer twice the size of the update chunk.
- DMA plays the first half.
- When it hits the halfway mark, it fires an interrupt.
- The CPU quickly fills the first half with new data while the DMA continues playing the second half.
- When the end is reached, another interrupt fires, and the CPU fills the second half.
This circular loop created the illusion of an infinite audio stream. If the game froze or crashed, the loop would stop updating, resulting in the infamous “machine gun” stutter where the last 1KB of audio repeated forever: rat-a-tat-tat-tat.
IRQ 7 vs IRQ 5
Originally, the Sound Blaster used IRQ 7. But IRQ 7 was also used by the LPT1 (Printer) port. If you tried to print a document while playing Wolfenstein 3D, the machine would often lock up. Later cards moved to IRQ 5 (which was freed up by the XT hard drive controller), becoming the new standard.