1.1 --- a/pkg/devices/util/src/dma.cc Sun Feb 18 22:45:07 2024 +0100
1.2 +++ b/pkg/devices/util/src/dma.cc Wed Feb 21 00:33:55 2024 +0100
1.3 @@ -36,32 +36,26 @@
1.4
1.5
1.6
1.7 -// Allocate a memory region of the given size for DMA.
1.8 -
1.9 -long get_dma_region(unsigned long size, int align, struct dma_region *region)
1.10 -{
1.11 - // Memory allocation capabilities.
1.12 -
1.13 - l4_cap_idx_t dma, vbus;
1.14 +// Obtain a DMA space to which memory regions may be associated.
1.15
1.16 - region->size = 0;
1.17 - region->align = 0;
1.18 -
1.19 - // Obtain capabilities for the DMA region and the vbus.
1.20 -
1.21 - dma = ipc_cap_alloc();
1.22 -
1.23 - if (l4_is_invalid_cap(dma))
1.24 - return -L4_ENOENT;
1.25 -
1.26 - vbus = l4re_env_get_cap("vbus");
1.27 +long get_dma_space(l4_cap_idx_t *dma)
1.28 +{
1.29 + l4_cap_idx_t vbus = l4re_env_get_cap("vbus");
1.30
1.31 if (l4_is_invalid_cap(vbus))
1.32 return -L4_ENOENT;
1.33
1.34 + // Obtain capabilities for the DMA region and the vbus.
1.35 +
1.36 + *dma = ipc_cap_alloc();
1.37 +
1.38 + if (l4_is_invalid_cap(*dma))
1.39 + return -L4_ENOENT;
1.40 +
1.41 // Create the DMA space.
1.42
1.43 - if (l4_error(l4_factory_create(l4re_env()->mem_alloc, L4RE_PROTO_DMA_SPACE, dma)))
1.44 + if (l4_error(l4_factory_create(l4re_env()->mem_alloc, L4RE_PROTO_DMA_SPACE,
1.45 + *dma)))
1.46 return -L4_ENOMEM;
1.47
1.48 // Find the DMA domain and assign the DMA space.
1.49 @@ -74,28 +68,39 @@
1.50
1.51 if (l4vbus_assign_dma_domain(vbus, dma_resource.start,
1.52 L4VBUS_DMAD_BIND | L4VBUS_DMAD_L4RE_DMA_SPACE,
1.53 - dma))
1.54 + *dma))
1.55 return -L4_ENOMEM;
1.56
1.57 + return L4_EOK;
1.58 +}
1.59 +
1.60 +// Obtain a memory region associated with the given DMA space.
1.61 +
1.62 +long get_dma_region_for_space(unsigned long size, int align, l4_cap_idx_t dma,
1.63 + struct dma_region *region)
1.64 +{
1.65 // Allocate memory at the given alignment.
1.66
1.67 const l4_size_t alloc_flags = L4RE_MA_CONTINUOUS | L4RE_MA_PINNED;
1.68 const l4re_rm_flags_t attach_flags = L4RE_RM_F_SEARCH_ADDR | L4RE_RM_F_RW;
1.69
1.70 - // Map the allocated memory, obtaining a virtual address.
1.71 + region->align = 0;
1.72 + region->paddr = 0;
1.73 + region->size = 0;
1.74 + region->vaddr = 0;
1.75
1.76 - region->vaddr = 0;
1.77 + // Map the allocated memory, obtaining a virtual address.
1.78
1.79 if (ipc_new_dataspace(size, alloc_flags, align, ®ion->mem))
1.80 return -L4_ENOMEM;
1.81
1.82 - if (ipc_attach_dataspace_align(region->mem, size, attach_flags, align, (void **) ®ion->vaddr))
1.83 + if (ipc_attach_dataspace_align(region->mem, size, attach_flags, align,
1.84 + (void **) ®ion->vaddr))
1.85 return -L4_ENOMEM;
1.86
1.87 // Obtain a physical address.
1.88
1.89 l4_size_t size_out = size;
1.90 - region->paddr = 0;
1.91
1.92 if (l4re_dma_space_map(dma, region->mem | L4_CAP_FPAGE_RW, 0, &size_out, 0,
1.93 L4RE_DMA_SPACE_TO_DEVICE, ®ion->paddr))
1.94 @@ -103,11 +108,24 @@
1.95
1.96 // Test the mapped region size.
1.97
1.98 - if (size_out != size)
1.99 + if (size_out < size)
1.100 return -L4_ENOMEM;
1.101
1.102 + region->align = align;
1.103 region->size = size_out;
1.104 - region->align = align;
1.105
1.106 return L4_EOK;
1.107 }
1.108 +
1.109 +// Obtain a memory region associated with its own DMA space.
1.110 +
1.111 +long get_dma_region(unsigned long size, int align, struct dma_region *region)
1.112 +{
1.113 + l4_cap_idx_t dma;
1.114 + long err = get_dma_space(&dma);
1.115 +
1.116 + if (err)
1.117 + return err;
1.118 +
1.119 + return get_dma_region_for_space(size, align, dma, region);
1.120 +}