L4Re Operating System Framework
Interface and Usage Documentation
Loading...
Searching...
No Matches
inout_memory.h
1/*
2 * Copyright (C) 2014, 2019-2020 Kernkonzept GmbH.
3 * Author(s): Sarah Hoffmann <sarah.hoffmann@kernkonzept.com>
4 *
5 * This file is distributed under the terms of the GNU General Public
6 * License, version 2. Please see the COPYING-GPL-2 file for details.
7 */
8#pragma once
9
10#include <l4/re/error_helper>
11#include <l4/re/env>
12#include <l4/re/util/unique_cap>
13#include <l4/re/rm>
14#include <l4/re/dma_space>
15#include <l4/cxx/ref_ptr>
16
17#include <l4/libblock-device/types.h>
18
19namespace Block_device {
20
25template <typename DEV>
26class Inout_memory : public cxx::Ref_obj
27{
28public:
29 using Device_type = DEV;
30
31 Inout_memory() : _paddr(0) {}
32 Inout_memory(l4_uint32_t num_sectors, Device_type *dev,
34 : _device(dev), _paddr(0), _dir(dir), _num_sectors(num_sectors)
35 {
36 auto lcap = L4Re::chkcap(L4Re::Util::make_unique_cap<L4Re::Dataspace>(),
37 "Allocate dataspace capability for IO memory.");
38
39 auto *e = L4Re::Env::env();
40 long sz = num_sectors * _device->sector_size();
41 L4Re::chksys(e->mem_alloc()->alloc(sz, lcap.get(),
44 "Allocate pinned memory.");
45
46 L4Re::chksys(e->rm()->attach(&_region, sz,
48 L4::Ipc::make_cap_rw(lcap.get()), 0,
50 "Attach IO memory.");
51
52 _mem_region =
53 cxx::make_unique<Block_device::Mem_region>(0, sz, 0, cxx::move(lcap));
54 L4Re::chksys(_device->dma_map(_mem_region.get(), 0, _num_sectors, dir,
55 &_paddr),
56 "Lock memory region for DMA.");
57 }
58
59 Inout_memory(Inout_memory const &) = delete;
60 Inout_memory(Inout_memory &&) = delete;
61
62 Inout_memory &operator=(Inout_memory &&rhs)
63 {
64 if (this != &rhs)
65 {
66 _device = rhs._device;
67 _mem_region = cxx::move(rhs._mem_region);
68 _region = cxx::move(rhs._region);
69 _paddr = rhs._paddr;
70 _dir = rhs._dir;
71 _num_sectors = rhs._num_sectors;
72 rhs._paddr = 0;
73 }
74
75 return *this;
76 }
77
79 {
80 if (_paddr)
81 unmap();
82 }
83
84
85 void unmap()
86 {
87 L4Re::chksys(_device->dma_unmap(_paddr, _num_sectors, _dir));
88 _paddr = 0;
89 }
90
91 Inout_block inout_block() const
92 {
93 Inout_block blk;
94
95 blk.dma_addr = _paddr;
96 blk.virt_addr = _region.get();
97 blk.num_sectors = _num_sectors;
98 blk.next.reset();
99
100 return blk;
101 }
102
103 template <class T>
104 T *get(unsigned offset) const
105 { return reinterpret_cast<T *>(_region.get() + offset); }
106
107private:
108 Device_type *_device;
109 cxx::unique_ptr<Block_device::Mem_region> _mem_region;
113 l4_uint32_t _num_sectors;
114};
115
116} // 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:70
Direction
Direction of the DMA transfers.
Definition dma_space:76
static Env const * env() noexcept
Returns the initial environment for the current task.
Definition env:103
@ Continuous
Allocate physically contiguous memory.
Definition mem_alloc:73
@ Pinned
Deprecated, use L4Re::Dma_space instead.
Definition mem_alloc:74
Unique region.
Definition rm:435
T get() const noexcept
Return the address.
Definition rm:508
Environment interface.
Error helper.
unsigned int l4_uint32_t
Unsigned 32bit value.
Definition l4int.h:40
#define L4_PAGESHIFT
Size of a page, log2-based.
Definition consts.h:37
long chksys(long err, char const *extra="", long ret=0)
Generate C++ exception on error.
Definition error_helper:68
T chkcap(T &&cap, char const *extra="", long err=-L4_ENOMEM)
Check for valid capability or raise C++ exception.
Definition error_helper:145
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:659
Region mapper interface.
Description of an inout block to be sent to the device.
Definition types.h:68
@ RW
Readable and writable region.
Definition rm:150
@ Search_addr
Search for a suitable address range.
Definition rm:125
Unique_cap / Unique_del_cap.