1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/pkg/devices/util/include/dma.h Tue Oct 24 17:20:58 2023 +0200
1.3 @@ -0,0 +1,32 @@
1.4 +/*
1.5 + * DMA-related memory allocation utility functions.
1.6 + *
1.7 + * Copyright (C) 2023 Paul Boddie <paul@boddie.org.uk>
1.8 + *
1.9 + * This program is free software; you can redistribute it and/or
1.10 + * modify it under the terms of the GNU General Public License as
1.11 + * published by the Free Software Foundation; either version 2 of
1.12 + * the License, or (at your option) any later version.
1.13 + *
1.14 + * This program is distributed in the hope that it will be useful,
1.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1.17 + * GNU General Public License for more details.
1.18 + *
1.19 + * You should have received a copy of the GNU General Public License
1.20 + * along with this program; if not, write to the Free Software
1.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
1.22 + * Boston, MA 02110-1301, USA
1.23 + */
1.24 +
1.25 +#pragma once
1.26 +
1.27 +#include <l4/re/c/dma_space.h>
1.28 +#include <l4/sys/types.h>
1.29 +
1.30 +EXTERN_C_BEGIN
1.31 +
1.32 +long get_dma_region(unsigned long size, int align, l4_addr_t *vaddr,
1.33 + l4re_dma_space_dma_addr_t *paddr, l4_cap_idx_t *mem);
1.34 +
1.35 +EXTERN_C_END
2.1 --- a/pkg/devices/util/include/memory.h Tue Oct 24 17:18:36 2023 +0200
2.2 +++ b/pkg/devices/util/include/memory.h Tue Oct 24 17:20:58 2023 +0200
2.3 @@ -40,4 +40,7 @@
2.4
2.5 int get_memory(char const *hid, l4_addr_t *start, l4_addr_t *end);
2.6
2.7 +int get_memory_complete(char const *hid, l4_addr_t *start, l4_addr_t *end,
2.8 + l4_addr_t *phys_start, l4_addr_t *phys_end);
2.9 +
2.10 EXTERN_C_END
3.1 --- a/pkg/devices/util/src/Makefile Tue Oct 24 17:18:36 2023 +0200
3.2 +++ b/pkg/devices/util/src/Makefile Tue Oct 24 17:20:58 2023 +0200
3.3 @@ -4,7 +4,7 @@
3.4 TARGET = libdevice_util.o.a libdevice_util.o.so
3.5 PC_FILENAME := libdevice-util
3.6
3.7 -SRC_CC := dataspace.cc dl.cc event-loop.cc memory.cc
3.8 +SRC_CC := dataspace.cc dl.cc dma.cc event-loop.cc memory.cc
3.9
3.10 PRIVATE_INCDIR += $(PKGDIR)/util/include
3.11
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
4.2 +++ b/pkg/devices/util/src/dma.cc Tue Oct 24 17:20:58 2023 +0200
4.3 @@ -0,0 +1,108 @@
4.4 +/*
4.5 + * DMA-related memory allocation utility functions.
4.6 + *
4.7 + * Copyright (C) 2023 Paul Boddie <paul@boddie.org.uk>
4.8 + *
4.9 + * This program is free software; you can redistribute it and/or
4.10 + * modify it under the terms of the GNU General Public License as
4.11 + * published by the Free Software Foundation; either version 2 of
4.12 + * the License, or (at your option) any later version.
4.13 + *
4.14 + * This program is distributed in the hope that it will be useful,
4.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
4.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4.17 + * GNU General Public License for more details.
4.18 + *
4.19 + * You should have received a copy of the GNU General Public License
4.20 + * along with this program; if not, write to the Free Software
4.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
4.22 + * Boston, MA 02110-1301, USA
4.23 + */
4.24 +
4.25 +#include <l4/re/c/dataspace.h>
4.26 +#include <l4/re/c/dma_space.h>
4.27 +#include <l4/re/c/mem_alloc.h>
4.28 +#include <l4/re/env.h>
4.29 +#include <l4/re/protocols.h>
4.30 +#include <l4/sys/factory.h>
4.31 +#include <l4/sys/types.h>
4.32 +#include <l4/vbus/vbus.h>
4.33 +
4.34 +#include <ipc/cap_alloc.h>
4.35 +#include <ipc/mem_ipc.h>
4.36 +
4.37 +#include "dma.h"
4.38 +#include "memory.h"
4.39 +
4.40 +
4.41 +
4.42 +// Allocate a memory region of the given size for DMA.
4.43 +
4.44 +long get_dma_region(unsigned long size, int align, l4_addr_t *vaddr,
4.45 + l4re_dma_space_dma_addr_t *paddr, l4_cap_idx_t *mem)
4.46 +{
4.47 + // Memory allocation capabilities.
4.48 +
4.49 + l4_cap_idx_t dma, vbus;
4.50 +
4.51 + // Obtain capabilities for the DMA region and the vbus.
4.52 +
4.53 + dma = ipc_cap_alloc();
4.54 +
4.55 + if (l4_is_invalid_cap(dma))
4.56 + return -L4_ENOENT;
4.57 +
4.58 + vbus = l4re_env_get_cap("vbus");
4.59 +
4.60 + if (l4_is_invalid_cap(vbus))
4.61 + return -L4_ENOENT;
4.62 +
4.63 + // Create the DMA space.
4.64 +
4.65 + if (l4_error(l4_factory_create(l4re_env()->mem_alloc, L4RE_PROTO_DMA_SPACE, dma)))
4.66 + return -L4_ENOMEM;
4.67 +
4.68 + // Find the DMA domain and assign the DMA space.
4.69 +
4.70 + l4vbus_device_handle_t device = L4VBUS_NULL;
4.71 + l4vbus_resource_t dma_resource;
4.72 +
4.73 + if (!find_resource(&device, &dma_resource, L4VBUS_RESOURCE_DMA_DOMAIN))
4.74 + return -L4_ENOENT;
4.75 +
4.76 + if (l4vbus_assign_dma_domain(vbus, dma_resource.start,
4.77 + L4VBUS_DMAD_BIND | L4VBUS_DMAD_L4RE_DMA_SPACE,
4.78 + dma))
4.79 + return -L4_ENOMEM;
4.80 +
4.81 + // Allocate memory at the given alignment.
4.82 +
4.83 + const l4_size_t alloc_flags = L4RE_MA_CONTINUOUS | L4RE_MA_PINNED;
4.84 + const l4re_rm_flags_t attach_flags = L4RE_RM_F_SEARCH_ADDR | L4RE_RM_F_RW;
4.85 +
4.86 + // Map the allocated memory, obtaining a virtual address.
4.87 +
4.88 + *vaddr = 0;
4.89 +
4.90 + if (ipc_new_dataspace(size, alloc_flags, align, mem))
4.91 + return -L4_ENOMEM;
4.92 +
4.93 + if (ipc_attach_dataspace_align(*mem, size, attach_flags, align, (void **) vaddr))
4.94 + return -L4_ENOMEM;
4.95 +
4.96 + // Obtain a physical address.
4.97 +
4.98 + l4_size_t size_out = size;
4.99 + *paddr = 0;
4.100 +
4.101 + if (l4re_dma_space_map(dma, *mem | L4_CAP_FPAGE_RW, 0, &size_out, 0,
4.102 + L4RE_DMA_SPACE_TO_DEVICE, paddr))
4.103 + return -L4_ENOMEM;
4.104 +
4.105 + // Test the mapped region size.
4.106 +
4.107 + if (size_out != size)
4.108 + return -L4_ENOMEM;
4.109 +
4.110 + return L4_EOK;
4.111 +}
5.1 --- a/pkg/devices/util/src/memory.cc Tue Oct 24 17:18:36 2023 +0200
5.2 +++ b/pkg/devices/util/src/memory.cc Tue Oct 24 17:20:58 2023 +0200
5.3 @@ -76,6 +76,14 @@
5.4
5.5 int get_memory(char const *hid, l4_addr_t *start, l4_addr_t *end)
5.6 {
5.7 + l4_addr_t phys_start, phys_end;
5.8 +
5.9 + return get_memory_complete(hid, start, end, &phys_start, &phys_end);
5.10 +}
5.11 +
5.12 +int get_memory_complete(char const *hid, l4_addr_t *start, l4_addr_t *end,
5.13 + l4_addr_t *phys_start, l4_addr_t *phys_end)
5.14 +{
5.15 l4io_device_handle_t dh;
5.16 l4io_resource_handle_t rh;
5.17 l4io_resource_t res;
5.18 @@ -98,6 +106,8 @@
5.19 return result;
5.20
5.21 *end = *start + (res.end - res.start + 1);
5.22 + *phys_start = res.start;
5.23 + *phys_end = res.end;
5.24
5.25 return 0;
5.26 }