# HG changeset patch # User Paul Boddie # Date 1698160858 -7200 # Node ID 0221ee7cf79a7aea203a5adb950be52af3e8d6f4 # Parent 7dae17488eda3b23b7e9db01b1503e587534fc2e Added support for DMA region allocation. Expanded memory-related functions to expose physical memory address ranges for use with DMA operations. diff -r 7dae17488eda -r 0221ee7cf79a pkg/devices/util/include/dma.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pkg/devices/util/include/dma.h Tue Oct 24 17:20:58 2023 +0200 @@ -0,0 +1,32 @@ +/* + * DMA-related memory allocation utility functions. + * + * Copyright (C) 2023 Paul Boddie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + */ + +#pragma once + +#include +#include + +EXTERN_C_BEGIN + +long get_dma_region(unsigned long size, int align, l4_addr_t *vaddr, + l4re_dma_space_dma_addr_t *paddr, l4_cap_idx_t *mem); + +EXTERN_C_END diff -r 7dae17488eda -r 0221ee7cf79a pkg/devices/util/include/memory.h --- a/pkg/devices/util/include/memory.h Tue Oct 24 17:18:36 2023 +0200 +++ b/pkg/devices/util/include/memory.h Tue Oct 24 17:20:58 2023 +0200 @@ -40,4 +40,7 @@ int get_memory(char const *hid, l4_addr_t *start, l4_addr_t *end); +int get_memory_complete(char const *hid, l4_addr_t *start, l4_addr_t *end, + l4_addr_t *phys_start, l4_addr_t *phys_end); + EXTERN_C_END diff -r 7dae17488eda -r 0221ee7cf79a pkg/devices/util/src/Makefile --- a/pkg/devices/util/src/Makefile Tue Oct 24 17:18:36 2023 +0200 +++ b/pkg/devices/util/src/Makefile Tue Oct 24 17:20:58 2023 +0200 @@ -4,7 +4,7 @@ TARGET = libdevice_util.o.a libdevice_util.o.so PC_FILENAME := libdevice-util -SRC_CC := dataspace.cc dl.cc event-loop.cc memory.cc +SRC_CC := dataspace.cc dl.cc dma.cc event-loop.cc memory.cc PRIVATE_INCDIR += $(PKGDIR)/util/include diff -r 7dae17488eda -r 0221ee7cf79a pkg/devices/util/src/dma.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pkg/devices/util/src/dma.cc Tue Oct 24 17:20:58 2023 +0200 @@ -0,0 +1,108 @@ +/* + * DMA-related memory allocation utility functions. + * + * Copyright (C) 2023 Paul Boddie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "dma.h" +#include "memory.h" + + + +// Allocate a memory region of the given size for DMA. + +long get_dma_region(unsigned long size, int align, l4_addr_t *vaddr, + l4re_dma_space_dma_addr_t *paddr, l4_cap_idx_t *mem) +{ + // Memory allocation capabilities. + + l4_cap_idx_t dma, vbus; + + // 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"); + + if (l4_is_invalid_cap(vbus)) + return -L4_ENOENT; + + // Create the DMA space. + + 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. + + l4vbus_device_handle_t device = L4VBUS_NULL; + l4vbus_resource_t dma_resource; + + if (!find_resource(&device, &dma_resource, L4VBUS_RESOURCE_DMA_DOMAIN)) + return -L4_ENOENT; + + if (l4vbus_assign_dma_domain(vbus, dma_resource.start, + L4VBUS_DMAD_BIND | L4VBUS_DMAD_L4RE_DMA_SPACE, + dma)) + return -L4_ENOMEM; + + // 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. + + *vaddr = 0; + + if (ipc_new_dataspace(size, alloc_flags, align, mem)) + return -L4_ENOMEM; + + if (ipc_attach_dataspace_align(*mem, size, attach_flags, align, (void **) vaddr)) + return -L4_ENOMEM; + + // Obtain a physical address. + + l4_size_t size_out = size; + *paddr = 0; + + if (l4re_dma_space_map(dma, *mem | L4_CAP_FPAGE_RW, 0, &size_out, 0, + L4RE_DMA_SPACE_TO_DEVICE, paddr)) + return -L4_ENOMEM; + + // Test the mapped region size. + + if (size_out != size) + return -L4_ENOMEM; + + return L4_EOK; +} diff -r 7dae17488eda -r 0221ee7cf79a pkg/devices/util/src/memory.cc --- a/pkg/devices/util/src/memory.cc Tue Oct 24 17:18:36 2023 +0200 +++ b/pkg/devices/util/src/memory.cc Tue Oct 24 17:20:58 2023 +0200 @@ -76,6 +76,14 @@ int get_memory(char const *hid, l4_addr_t *start, l4_addr_t *end) { + l4_addr_t phys_start, phys_end; + + return get_memory_complete(hid, start, end, &phys_start, &phys_end); +} + +int get_memory_complete(char const *hid, l4_addr_t *start, l4_addr_t *end, + l4_addr_t *phys_start, l4_addr_t *phys_end) +{ l4io_device_handle_t dh; l4io_resource_handle_t rh; l4io_resource_t res; @@ -98,6 +106,8 @@ return result; *end = *start + (res.end - res.start + 1); + *phys_start = res.start; + *phys_end = res.end; return 0; }