Non-Contiguous Buffers
Prev | Chapter 11. Buffer and Memory Management | Next

## Non-Contiguous Buffers

If your hardware supports the page table as in emu10k1 or the buffer descriptors as in via82xx, you can use the scatter-gather (SG) DMA. ALSA provides an interface for handling SG-buffers. The API is provided in `<sound/pcm.h>`.

For creating the SG-buffer handler, call `snd_pcm_lib_preallocate_pages()` or `snd_pcm_lib_preallocate_pages_for_all()` with `SNDRV_DMA_TYPE_DEV_SG` in the PCM constructor like other PCI pre-allocator. You need to pass `snd_dma_pci_data(pci)`, where pci is the struct pci_dev pointer of the chip as well. The struct snd_sg_buf instance is created as substream->dma_private. You can cast the pointer like:

      struct snd_sg_buf *sgbuf = (struct snd_sg_buf *)substream->dma_private;

Then call `snd_pcm_lib_malloc_pages()` in the `hw_params` callback as well as in the case of normal PCI buffer. The SG-buffer handler will allocate the non-contiguous kernel pages of the given size and map them onto the virtually contiguous memory. The virtual pointer is addressed in runtime->dma_area. The physical address (runtime->dma_addr) is set to zero, because the buffer is physically non-contiguous. The physical address table is set up in sgbuf->table. You can get the physical address at a certain offset via `snd_pcm_sgbuf_get_addr()`.

When a SG-handler is used, you need to set `snd_pcm_sgbuf_ops_page` as the `page` callback. (See page callback section.)

To release the data, call `snd_pcm_lib_free_pages()` in the `hw_free` callback as usual.

Prev | Up | Next
External Hardware Buffers | Home | Vmalloc'ed Buffers