Audio (AC97/HDA)
AC97 and Intel HDA are the two audio device families a kernel is most likely to find emulated under QEMU, and despite being separate standards from different eras, both are built around the same core idea: a circular buffer the controller drains continuously via DMA, so a driver supplies audio data in bulk ahead of time rather than being interrupted once per individual sample the way a naive design might work.
The circular buffer model
Section titled “The circular buffer model”A driver allocates a buffer, fills it with audio samples, and hands the controller its physical address and length; the controller then reads through that buffer continuously via DMA, wrapping back to the start once it reaches the end, and raises an interrupt at points the driver configured in advance (commonly when the buffer is half-consumed, and again when it wraps) rather than once per sample.
struct audio_buffer_descriptor { uint32_t buffer_addr; // physical address of sample data uint16_t sample_count; uint16_t flags; // interrupt-on-completion, etc.};This is what makes continuous playback possible without an impractical interrupt rate: at a typical 48,000 Hz sample rate, interrupting once per sample would mean 48,000 interrupts per second just for one audio stream, while interrupting only when a buffer region needs refilling, commonly a few dozen times per second, leaves the driver ample time between interrupts to prepare the next chunk of audio without an audible gap ever developing in the output.
Mixer versus bus master registers
Section titled “Mixer versus bus master registers”Both AC97 and HDA controllers split their register space into two functionally distinct groups. Mixer registers control the audio signal path itself: master volume, per-channel volume, sample rate, and input/output routing, values a driver sets once during initialization and adjusts only in response to explicit volume or format changes, not on any fixed schedule. Bus master registers control the DMA engine that actually moves samples between the circular buffer and the audio codec: the buffer’s physical address, its length, a control bit to start or stop the transfer, and status bits reporting how far through the buffer the controller currently is.
// mixer: set master volume (AC97 example)mixer_write(AC97_MASTER_VOLUME, (attenuation_left << 8) | attenuation_right);
// bus master: point the controller at the buffer and start itbm_write32(BDBAR, buffer_descriptor_phys_addr);bm_write8(CIV_LVI, last_valid_index);bm_write8(CONTROL, RUN_BIT);Keeping the two separate is deliberate on the hardware’s part: a driver adjusting volume mid-playback touches only mixer registers, with no effect on the DMA transfer already in progress, and a driver that only ever wants to change format or volume never needs to touch the bus-master side at all.
Why AC97 is the simpler starting point
Section titled “Why AC97 is the simpler starting point”AC97 predates HDA and has a considerably smaller, more directly memory-mapped register set with less negotiation required before playback can begin: a driver maps the mixer and bus-master BARs through PCI the same way any other PCI device is discovered, sets a handful of mixer registers, and points the bus-master registers at a prepared buffer descriptor list, with comparatively little else standing between mapping the device and hearing sound. HDA, the modern standard actually shipped in current hardware, uses a considerably more elaborate model built around codecs discovered and configured through a command/response verb protocol sent over its own internal ring buffers, closer in spirit to a small bus of its own than to a flat register file, which makes a minimal working HDA driver a larger undertaking despite HDA and AC97 sharing the same underlying circular-buffer DMA idea at their core. A hobby kernel targeting audio for the first time commonly starts with AC97 specifically because QEMU emulates it faithfully and its register model requires the least amount of protocol before the first sound plays, even though HDA is what any current physical machine actually exposes.
Implementation notes
Section titled “Implementation notes”The buffer descriptor list itself (an array of buffer address/length pairs rather than a single buffer, on both AC97 and HDA) exists so the controller can be kept continuously fed without the driver needing to reprogram the DMA engine on every single interrupt: the driver refills whichever descriptor entry the controller just finished with while the controller is already consuming a different entry further ahead in the list, the same double-buffering discipline that prevents an audible gap or glitch from a refill that arrives a moment too late. Paging is directly relevant here the same way it is for any DMA-capable device: the buffer descriptors and the sample buffers they point at both need physically contiguous, properly mapped memory the controller can reach without any translation the DMA engine itself doesn’t perform.
References
Section titled “References”- ^ Intel, AC’97 Component Specification: the register-level specification for the mixer and bus-master model described above.
- ^ Intel, High Definition Audio Specification: the codec/verb-based model HDA replaces AC97’s flatter register set with.
See also
Section titled “See also”- PCI: device discovery and BAR mapping for either controller family.
- Paging & Virtual Memory: the physically contiguous buffers both the mixer’s DMA engine and this article’s descriptor lists depend on.