1 /*
2  * (c) 2014 Alexander Warg <alexander.warg@kernkonzept.com>
3  *
4  * This file is part of TUD:OS and distributed under the terms of the
5  * GNU General Public License 2.
6  * Please see the COPYING-GPL-2 file for details.
7  */
8 #pragma once
9 
10 #include <cstddef>
11 #include <l4/sys/types.h>
12 #include <l4/re/dma_space>
13 #include <l4/sys/cxx/ipc_epiface>
14 #include <l4/cxx/hlist>
15 #include <l4/cxx/avl_tree>
16 #include <l4/cxx/ref_ptr>
17 
18 #include "quota.h"
19 #include "server_obj.h"
20 #include "globals.h"
21 
22 namespace Moe {
23 
24 class Dma_space;
25 
26 namespace Dma {
27 
28 struct Mapping;
29 
30 class Mapper : public cxx::Ref_obj
31 {
32 public:
33   Mapper(Mapper const &) = delete;
34   Mapper() = default;
35   Mapper &operator = (Mapper const &) = delete;
36 
37   typedef L4Re::Dma_space::Attributes Attributes;
38   typedef L4Re::Dma_space::Direction Direction;
39   typedef L4Re::Dma_space::Dma_addr Dma_addr;
40 
41   virtual Mapping *map(Dataspace *ds, Q_alloc *,
42                        l4_addr_t offset, l4_size_t *size,
43                        Attributes attrs, Direction dir,
44                        Dma_addr *dma_addr) = 0;
45 
46   virtual int unmap(Dma_addr dma_addr, l4_size_t size,
47                     Attributes attrs, Direction dir) = 0;
48 
49   virtual void remove(Mapping *m) = 0;
50 
51   virtual ~Mapper() = default;
52 };
53 
54 struct Region
55 {
56   l4_addr_t start;
57   l4_addr_t end;
58   bool operator < (Region const &r) const
59   { return end < r.start; }
60 
61   Region() = default;
RegionRegion62   Region(l4_addr_t s) : start(s), end(s) {}
RegionRegion63   Region(l4_addr_t s, l4_addr_t e) : start(s), end(e) {}
64 };
65 
66 struct Mapping : cxx::H_list_item_t<Mapping>, cxx::Avl_tree_node
67 {
68   typedef Region Key_type;
69   typedef cxx::Avl_tree<Mapping, Mapping, cxx::Lt_functor<Region>> Map;
70   typedef cxx::H_list_t<Dma::Mapping> List;
71   typedef L4Re::Dma_space::Direction Direction;
72   typedef L4Re::Dma_space::Attributes Attributes;
73 
74   Region key;
75   Mapper *mapper = 0;
76   Attributes attrs = Attributes::None;
77   Direction dir = Direction::None;
78 
key_ofMapping79   static Key_type key_of(Mapping const *m) { return m->key; }
80 
81   Mapping(Mapping const &) = delete;
82   Mapping &operator = (Mapping const &) = delete;
83   Mapping() = default;
84 
~MappingMapping85   ~Mapping()
86   {
87     if (mapper)
88       mapper->remove(this);
89 
90     if (0)
91       printf("DMA: del mapping: map=%p %lx %lx\n", mapper, key.start, key.end);
92   }
93 };
94 
95 }
96 
97 class Dma_space :
98   public L4::Epiface_t<Dma_space, L4Re::Dma_space, Server_object>,
99   public Q_object
100 {
101 public:
102   typedef L4Re::Dma_space::Dma_addr Dma_addr;
103   typedef L4Re::Dma_space::Direction Direction;
104   typedef L4Re::Dma_space::Attributes Attributes;
105   typedef L4Re::Dma_space::Space_attribs Space_attribs;
106 
107   long op_map(L4Re::Dma_space::Rights rights,
108               L4::Ipc::Snd_fpage src_ds, l4_addr_t offset,
109               l4_size_t &size, Attributes attrs, Direction dir,
110               Dma_addr &dma_addr);
111 
112   long op_unmap(L4Re::Dma_space::Rights rights,
113                 Dma_addr dma_addr,
114                 l4_size_t size, Attributes attrs, Direction dir);
115 
116   long op_associate(L4Re::Dma_space::Rights rights,
117                     L4::Ipc::Snd_fpage dma_task,
118                     Space_attribs attr);
119 
120   long op_disassociate(L4Re::Dma_space::Rights rights);
121 
122   void delete_all_mappings();
123 
~Dma_space()124   ~Dma_space() { delete_all_mappings(); }
125 
126 private:
127   Space_attribs _attr = Space_attribs::None;
128   cxx::Ref_ptr<Dma::Mapper> _mapper;
129   Dma::Mapping::List _mappings;
130 };
131 
132 }
133