L4Re Operating System Framework
Interface and Usage Documentation
Loading...
Searching...
No Matches
device_impl_dma.h
1/*
2 * Copyright (C) 2026 Kernkonzept GmbH.
3 * Author(s): Jakub Jermar <jakub.jermar@kernkonzept.com>
4 *
5 * License: see LICENSE.spdx (in this directory or the directories above)
6 */
7
8#pragma once
9
10#include <l4/cxx/ref_ptr>
11#include <l4/re/dataspace>
12#include <l4/re/dma_space>
13
14#include <l4/libblock-device/types.h>
15#include <l4/libblock-device/debug.h>
16
17namespace Block_device {
18
19// DEV must be the same class used by the client factory
20template <typename DEV>
21struct Device_dma_map_all_impl
22{
23 using Device_type = DEV;
24
25private:
26 struct Dma_info : public Block_device::Dma_region_info
27 {
29 l4_size_t size;
30 cxx::Ref_ptr<Device_type> device;
31
32 Dma_info() = delete;
33 explicit Dma_info(L4Re::Dma_space::Dma_addr addr, l4_size_t size,
34 cxx::Ref_ptr<Device_type> device)
35 : addr(addr), size(size), device(device)
36 {
37 }
38
39 virtual ~Dma_info() override
40 {
41 device->dma_unmap_region(this);
42 }
43 };
44
45protected:
46 Device_dma_map_all_impl(L4Re::Util::Shared_cap<L4Re::Dma_space> const &dma)
47 : _dma(dma)
48 {}
49
50 int dma_map_all(Block_device::Mem_region *region, l4_addr_t offset,
53 {
54 if (!region->dma_info)
55 {
56 l4_size_t size = region->size();
58 auto ret =
59 _dma->map(L4::Ipc::make_cap_rw(region->ds()), region->ds_offset(),
62 if (ret < 0 || size < num_sectors * device()->sector_size())
63 {
64 *dma_addr = 0;
65 Dbg::info().printf(
66 "Cannot resolve DMA address (ret = %d, %zu < %zu).\n", ret,
67 size, num_sectors * device()->sector_size());
68 return -L4_ENOMEM;
69 }
70
71 auto dev = cxx::Ref_ptr<Device_type>(device());
72 auto dma_info = cxx::make_unique<Dma_info>(addr, size, dev);
73 region->dma_info =
74 cxx::unique_ptr<Block_device::Dma_region_info>(dma_info.release());
75 }
76
77 auto *dma_info = static_cast<Dma_info *>(region->dma_info.get());
78 *dma_addr = dma_info->addr + offset - region->ds_offset();
79
80 return L4_EOK;
81 }
82
83 void dma_unmap_region(Dma_info *dma_info)
84 {
85 auto ret = _dma->unmap(dma_info->addr, dma_info->size,
88 if (ret < 0)
89 Dbg::info().printf(
90 "Failed to unmap (ret = %d, addr = %llx, size = %zu)\n", ret,
91 dma_info->addr, dma_info->size);
92 }
93
94private:
95 Device_type *device()
96 { return static_cast<Device_type *>(this); }
97
99};
100
101} // name space
l4_uint64_t Dma_addr
Data type for DMA addresses.
Definition dma_space:57
Direction
Direction of the DMA transfers.
Definition dma_space:67
@ Bidirectional
device reads and writes to the memory
Definition dma_space:68
l4_addr_t ds_offset() const
Definition l4virtio:593
l4_umword_t size() const
Definition l4virtio:590
L4::Cap< L4Re::Dataspace > ds() const
Definition l4virtio:596
Dataspace interface.
unsigned int l4_size_t
Unsigned size type.
Definition l4int.h:22
unsigned long l4_addr_t
Address type.
Definition l4int.h:34
@ L4_EOK
Ok.
Definition err.h:33
@ L4_ENOMEM
No memory.
Definition err.h:40
L4::Detail::Shared_cap_impl< T, L4Re::Util::Smart_count_cap< L4_FP_ALL_SPACES > > Shared_cap
Shared capability that implements automatic free and unmap of the capability selector.
Definition shared_cap:49
Cap< T > make_cap_rw(L4::Cap< T > cap) noexcept
Make an L4::Ipc::Cap<T> for the given capability with L4_CAP_FPAGE_RW rights.
Definition ipc_types:855