1.1 --- a/pkg/devices/util/include/dma.h Sun Feb 18 22:45:07 2024 +0100
1.2 +++ b/pkg/devices/util/include/dma.h Wed Feb 21 00:33:55 2024 +0100
1.3 @@ -37,4 +37,9 @@
1.4
1.5 long get_dma_region(unsigned long size, int align, struct dma_region *region);
1.6
1.7 +long get_dma_region_for_space(unsigned long size, int align, l4_cap_idx_t dma,
1.8 + struct dma_region *region);
1.9 +
1.10 +long get_dma_space(l4_cap_idx_t *dma);
1.11 +
1.12 EXTERN_C_END
2.1 --- a/pkg/devices/util/src/dma.cc Sun Feb 18 22:45:07 2024 +0100
2.2 +++ b/pkg/devices/util/src/dma.cc Wed Feb 21 00:33:55 2024 +0100
2.3 @@ -36,32 +36,26 @@
2.4
2.5
2.6
2.7 -// Allocate a memory region of the given size for DMA.
2.8 -
2.9 -long get_dma_region(unsigned long size, int align, struct dma_region *region)
2.10 -{
2.11 - // Memory allocation capabilities.
2.12 -
2.13 - l4_cap_idx_t dma, vbus;
2.14 +// Obtain a DMA space to which memory regions may be associated.
2.15
2.16 - region->size = 0;
2.17 - region->align = 0;
2.18 -
2.19 - // Obtain capabilities for the DMA region and the vbus.
2.20 -
2.21 - dma = ipc_cap_alloc();
2.22 -
2.23 - if (l4_is_invalid_cap(dma))
2.24 - return -L4_ENOENT;
2.25 -
2.26 - vbus = l4re_env_get_cap("vbus");
2.27 +long get_dma_space(l4_cap_idx_t *dma)
2.28 +{
2.29 + l4_cap_idx_t vbus = l4re_env_get_cap("vbus");
2.30
2.31 if (l4_is_invalid_cap(vbus))
2.32 return -L4_ENOENT;
2.33
2.34 + // Obtain capabilities for the DMA region and the vbus.
2.35 +
2.36 + *dma = ipc_cap_alloc();
2.37 +
2.38 + if (l4_is_invalid_cap(*dma))
2.39 + return -L4_ENOENT;
2.40 +
2.41 // Create the DMA space.
2.42
2.43 - if (l4_error(l4_factory_create(l4re_env()->mem_alloc, L4RE_PROTO_DMA_SPACE, dma)))
2.44 + if (l4_error(l4_factory_create(l4re_env()->mem_alloc, L4RE_PROTO_DMA_SPACE,
2.45 + *dma)))
2.46 return -L4_ENOMEM;
2.47
2.48 // Find the DMA domain and assign the DMA space.
2.49 @@ -74,28 +68,39 @@
2.50
2.51 if (l4vbus_assign_dma_domain(vbus, dma_resource.start,
2.52 L4VBUS_DMAD_BIND | L4VBUS_DMAD_L4RE_DMA_SPACE,
2.53 - dma))
2.54 + *dma))
2.55 return -L4_ENOMEM;
2.56
2.57 + return L4_EOK;
2.58 +}
2.59 +
2.60 +// Obtain a memory region associated with the given DMA space.
2.61 +
2.62 +long get_dma_region_for_space(unsigned long size, int align, l4_cap_idx_t dma,
2.63 + struct dma_region *region)
2.64 +{
2.65 // Allocate memory at the given alignment.
2.66
2.67 const l4_size_t alloc_flags = L4RE_MA_CONTINUOUS | L4RE_MA_PINNED;
2.68 const l4re_rm_flags_t attach_flags = L4RE_RM_F_SEARCH_ADDR | L4RE_RM_F_RW;
2.69
2.70 - // Map the allocated memory, obtaining a virtual address.
2.71 + region->align = 0;
2.72 + region->paddr = 0;
2.73 + region->size = 0;
2.74 + region->vaddr = 0;
2.75
2.76 - region->vaddr = 0;
2.77 + // Map the allocated memory, obtaining a virtual address.
2.78
2.79 if (ipc_new_dataspace(size, alloc_flags, align, ®ion->mem))
2.80 return -L4_ENOMEM;
2.81
2.82 - if (ipc_attach_dataspace_align(region->mem, size, attach_flags, align, (void **) ®ion->vaddr))
2.83 + if (ipc_attach_dataspace_align(region->mem, size, attach_flags, align,
2.84 + (void **) ®ion->vaddr))
2.85 return -L4_ENOMEM;
2.86
2.87 // Obtain a physical address.
2.88
2.89 l4_size_t size_out = size;
2.90 - region->paddr = 0;
2.91
2.92 if (l4re_dma_space_map(dma, region->mem | L4_CAP_FPAGE_RW, 0, &size_out, 0,
2.93 L4RE_DMA_SPACE_TO_DEVICE, ®ion->paddr))
2.94 @@ -103,11 +108,24 @@
2.95
2.96 // Test the mapped region size.
2.97
2.98 - if (size_out != size)
2.99 + if (size_out < size)
2.100 return -L4_ENOMEM;
2.101
2.102 + region->align = align;
2.103 region->size = size_out;
2.104 - region->align = align;
2.105
2.106 return L4_EOK;
2.107 }
2.108 +
2.109 +// Obtain a memory region associated with its own DMA space.
2.110 +
2.111 +long get_dma_region(unsigned long size, int align, struct dma_region *region)
2.112 +{
2.113 + l4_cap_idx_t dma;
2.114 + long err = get_dma_space(&dma);
2.115 +
2.116 + if (err)
2.117 + return err;
2.118 +
2.119 + return get_dma_region_for_space(size, align, dma, region);
2.120 +}