L4Re Operating System Framework
Interface and Usage Documentation
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
inout_memory.h
1/*
2 * Copyright (C) 2014, 2019-2020, 2024 Kernkonzept GmbH.
3 * Author(s): Sarah Hoffmann <sarah.hoffmann@kernkonzept.com>
4 *
5 * License: see LICENSE.spdx (in this directory or the directories above)
6 */
7#pragma once
8
9#include <l4/re/error_helper>
10#include <l4/re/env>
11#include <l4/re/util/unique_cap>
12#include <l4/re/rm>
13#include <l4/re/dma_space>
14#include <l4/cxx/ref_ptr>
15
16#include <l4/libblock-device/types.h>
17
18namespace Block_device {
19
24template <typename DEV>
25class Inout_memory : public cxx::Ref_obj
26{
27public:
28 using Device_type = DEV;
29
30 Inout_memory() : _paddr(0) {}
31 Inout_memory(l4_uint32_t num_sectors, Device_type *dev,
33 : _device(dev), _paddr(0), _dir(dir), _num_sectors(num_sectors)
34 {
35 auto lcap = L4Re::chkcap(L4Re::Util::make_unique_cap<L4Re::Dataspace>(),
36 "Allocate dataspace capability for IO memory.");
37
38 auto *e = L4Re::Env::env();
39 long sz = num_sectors * _device->sector_size();
40 L4Re::chksys(e->mem_alloc()->alloc(sz, lcap.get(),
43 "Allocate pinned memory.");
44
45 L4Re::chksys(e->rm()->attach(&_region, sz,
47 L4::Ipc::make_cap_rw(lcap.get()), 0,
49 "Attach IO memory.");
50
51 _mem_region =
52 cxx::make_unique<Block_device::Mem_region>(0, sz, 0, cxx::move(lcap));
53 L4Re::chksys(_device->dma_map(_mem_region.get(), 0, _num_sectors, dir,
54 &_paddr),
55 "Lock memory region for DMA.");
56 }
57
58 Inout_memory(Inout_memory const &) = delete;
59 Inout_memory(Inout_memory &&) = delete;
60
61 Inout_memory &operator=(Inout_memory &&rhs)
62 {
63 if (this != &rhs)
64 {
65 _device = rhs._device;
66 _mem_region = cxx::move(rhs._mem_region);
67 _region = cxx::move(rhs._region);
68 _paddr = rhs._paddr;
69 _dir = rhs._dir;
70 _num_sectors = rhs._num_sectors;
71 rhs._paddr = 0;
72 }
73
74 return *this;
75 }
76
78 {
79 if (_paddr)
80 unmap();
81 }
82
83
84 void unmap()
85 {
86 L4Re::chksys(_device->dma_unmap(_paddr, _num_sectors, _dir));
87 _paddr = 0;
88 }
89
90 Inout_block inout_block() const
91 {
92 Inout_block blk;
93
94 blk.dma_addr = _paddr;
95 blk.virt_addr = _region.get();
96 blk.num_sectors = _num_sectors;
97 blk.next.reset();
98
99 return blk;
100 }
101
102 template <class T>
103 T *get(unsigned offset) const
104 { return reinterpret_cast<T *>(_region.get() + offset); }
105
106private:
107 Device_type *_device;
108 cxx::unique_ptr<Block_device::Mem_region> _mem_region;
112 l4_uint32_t _num_sectors;
113};
114
115} // name space
Helper class that temporarily allocates memory that can be used for in/out operations with the device...
l4_uint64_t Dma_addr
Data type for DMA addresses.
Definition dma_space:59
Direction
Direction of the DMA transfers.
Definition dma_space:65
static Env const * env() noexcept
Returns the initial environment for the current task.
Definition env:95
@ Continuous
Allocate physically contiguous memory.
Definition mem_alloc:62
@ Pinned
Deprecated, use L4Re::Dma_space instead.
Definition mem_alloc:63
Unique region.
Definition rm:424
T get() const noexcept
Return the address.
Definition rm:497
Environment interface.
Error helper.
unsigned int l4_uint32_t
Unsigned 32bit value.
Definition l4int.h:29
#define L4_PAGESHIFT
Size of a page, log2-based.
Definition consts.h:26
long chksys(long err, char const *extra="", long ret=0)
Generate C++ exception on error.
Definition error_helper:72
T chkcap(T &&cap, char const *extra="", long err=-L4_ENOMEM)
Check for valid capability or raise C++ exception.
Definition error_helper:149
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:795
Region mapper interface.
Description of an inout block to be sent to the device.
Definition types.h:67
@ RW
Readable and writable region.
Definition rm:139
@ Search_addr
Search for a suitable address range.
Definition rm:114
Unique_cap / Unique_del_cap.