# HG changeset patch # User Paul Boddie # Date 1708472035 -3600 # Node ID 200859fe60d963f5c0f26d3ff027390e9878e87d # Parent b60c8cf438402842e13ef38bc4bb94aaa1c2dc0e Exposed DMA space creation as a separate function. diff -r b60c8cf43840 -r 200859fe60d9 pkg/devices/util/include/dma.h --- a/pkg/devices/util/include/dma.h Sun Feb 18 22:45:07 2024 +0100 +++ b/pkg/devices/util/include/dma.h Wed Feb 21 00:33:55 2024 +0100 @@ -37,4 +37,9 @@ long get_dma_region(unsigned long size, int align, struct dma_region *region); +long get_dma_region_for_space(unsigned long size, int align, l4_cap_idx_t dma, + struct dma_region *region); + +long get_dma_space(l4_cap_idx_t *dma); + EXTERN_C_END diff -r b60c8cf43840 -r 200859fe60d9 pkg/devices/util/src/dma.cc --- a/pkg/devices/util/src/dma.cc Sun Feb 18 22:45:07 2024 +0100 +++ b/pkg/devices/util/src/dma.cc Wed Feb 21 00:33:55 2024 +0100 @@ -36,32 +36,26 @@ -// Allocate a memory region of the given size for DMA. - -long get_dma_region(unsigned long size, int align, struct dma_region *region) -{ - // Memory allocation capabilities. - - l4_cap_idx_t dma, vbus; +// Obtain a DMA space to which memory regions may be associated. - region->size = 0; - region->align = 0; - - // Obtain capabilities for the DMA region and the vbus. - - dma = ipc_cap_alloc(); - - if (l4_is_invalid_cap(dma)) - return -L4_ENOENT; - - vbus = l4re_env_get_cap("vbus"); +long get_dma_space(l4_cap_idx_t *dma) +{ + l4_cap_idx_t vbus = l4re_env_get_cap("vbus"); if (l4_is_invalid_cap(vbus)) return -L4_ENOENT; + // Obtain capabilities for the DMA region and the vbus. + + *dma = ipc_cap_alloc(); + + if (l4_is_invalid_cap(*dma)) + return -L4_ENOENT; + // Create the DMA space. - if (l4_error(l4_factory_create(l4re_env()->mem_alloc, L4RE_PROTO_DMA_SPACE, dma))) + if (l4_error(l4_factory_create(l4re_env()->mem_alloc, L4RE_PROTO_DMA_SPACE, + *dma))) return -L4_ENOMEM; // Find the DMA domain and assign the DMA space. @@ -74,28 +68,39 @@ if (l4vbus_assign_dma_domain(vbus, dma_resource.start, L4VBUS_DMAD_BIND | L4VBUS_DMAD_L4RE_DMA_SPACE, - dma)) + *dma)) return -L4_ENOMEM; + return L4_EOK; +} + +// Obtain a memory region associated with the given DMA space. + +long get_dma_region_for_space(unsigned long size, int align, l4_cap_idx_t dma, + struct dma_region *region) +{ // Allocate memory at the given alignment. const l4_size_t alloc_flags = L4RE_MA_CONTINUOUS | L4RE_MA_PINNED; const l4re_rm_flags_t attach_flags = L4RE_RM_F_SEARCH_ADDR | L4RE_RM_F_RW; - // Map the allocated memory, obtaining a virtual address. + region->align = 0; + region->paddr = 0; + region->size = 0; + region->vaddr = 0; - region->vaddr = 0; + // Map the allocated memory, obtaining a virtual address. if (ipc_new_dataspace(size, alloc_flags, align, ®ion->mem)) return -L4_ENOMEM; - if (ipc_attach_dataspace_align(region->mem, size, attach_flags, align, (void **) ®ion->vaddr)) + if (ipc_attach_dataspace_align(region->mem, size, attach_flags, align, + (void **) ®ion->vaddr)) return -L4_ENOMEM; // Obtain a physical address. l4_size_t size_out = size; - region->paddr = 0; if (l4re_dma_space_map(dma, region->mem | L4_CAP_FPAGE_RW, 0, &size_out, 0, L4RE_DMA_SPACE_TO_DEVICE, ®ion->paddr)) @@ -103,11 +108,24 @@ // Test the mapped region size. - if (size_out != size) + if (size_out < size) return -L4_ENOMEM; + region->align = align; region->size = size_out; - region->align = align; return L4_EOK; } + +// Obtain a memory region associated with its own DMA space. + +long get_dma_region(unsigned long size, int align, struct dma_region *region) +{ + l4_cap_idx_t dma; + long err = get_dma_space(&dma); + + if (err) + return err; + + return get_dma_region_for_space(size, align, dma, region); +}