]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/io/server/src/resource.h
update
[l4.git] / l4 / pkg / io / server / src / resource.h
1 /*
2  * (c) 2010 Adam Lackorzynski <adam@os.inf.tu-dresden.de>,
3  *          Alexander Warg <warg@os.inf.tu-dresden.de>
4  *     economic rights: Technische Universität Dresden (Germany)
5  *
6  * This file is part of TUD:OS and distributed under the terms of the
7  * GNU General Public License 2.
8  * Please see the COPYING-GPL-2 file for details.
9  */
10 #pragma once
11
12 #include <l4/sys/icu>
13
14 #include <l4/vbus/vbus_types.h>
15 #include <vector>
16
17 #include <l4/re/dataspace>
18 #include <l4/re/util/cap_alloc>
19 #include <l4/re/rm>
20
21 #include "res.h"
22
23 class Resource;
24 class Device;
25
26
27 class Resource_list : public std::vector<Resource *>
28 {
29 public:
30   /**
31    * \brief Find a resource by their ID.
32    * \param id  The resource id (usually 4 letters ASCII, little endian
33    *            encoded).
34    * \return The first resource with the given ID, or null_ptr if non found.
35    */
36   Resource *find(l4_uint32_t id) const;
37
38   /**
39    * \brief Find a resource by their ID (using a 4-letter string).
40    * \param id  The resource id (usually up to 4 letters ASCII).
41    * \return The first resource with the given ID, or null_ptr if non found.
42    */
43   Resource *find(char const *id) const;
44 };
45
46 class Resource_space
47 {
48 public:
49   virtual bool request(Resource *parent, Device *pdev,
50                        Resource *child, Device *cdev) = 0;
51   virtual bool alloc(Resource *parent, Device *pdev,
52                      Resource *child, Device *cdev, bool resize) = 0;
53   virtual ~Resource_space() = 0;
54 };
55
56 inline Resource_space::~Resource_space() {}
57
58 class Resource
59 {
60 private:
61   unsigned long _f;
62   l4_uint32_t _id;
63   Resource *_p;
64
65 public:
66   typedef l4_uint64_t Addr;
67   typedef l4_int64_t Size;
68
69   enum Type
70   {
71     Invalid_res = L4VBUS_RESOURCE_INVALID,
72     Irq_res     = L4VBUS_RESOURCE_IRQ,
73     Mmio_res    = L4VBUS_RESOURCE_MEM,
74     Io_res      = L4VBUS_RESOURCE_PORT,
75     Bus_res     = L4VBUS_RESOURCE_BUS,
76     Gpio_res    = L4VBUS_RESOURCE_GPIO
77   };
78
79   enum Flags
80   {
81     F_type_mask    = 0x00ff,
82     F_disabled     = 0x0100,
83     F_hierarchical = 0x0200,
84     F_prefetchable = 0x0400,
85     F_size_aligned = 0x0800,
86     F_empty        = 0x1000,
87     F_rom          = 0x2000,
88     F_can_resize   = 0x4000,
89     F_can_move     = 0x8000,
90
91     F_width_64bit   = 0x010000,
92     F_relative      = 0x040000,
93
94     Irq_type_base         = 0x100000,
95     Irq_type_mask         = L4_IRQ_F_MASK       * Irq_type_base,
96     Irq_type_none         = L4_IRQ_F_NONE       * Irq_type_base,
97     Irq_type_level_high   = L4_IRQ_F_LEVEL_HIGH * Irq_type_base,
98     Irq_type_level_low    = L4_IRQ_F_LEVEL_LOW  * Irq_type_base,
99     Irq_type_raising_edge = L4_IRQ_F_POS_EDGE   * Irq_type_base,
100     Irq_type_falling_edge = L4_IRQ_F_NEG_EDGE   * Irq_type_base,
101     Irq_type_both_edges   = L4_IRQ_F_BOTH_EDGE  * Irq_type_base,
102   };
103
104   bool irq_is_level_triggered() const
105   { return (_f & Irq_type_mask) & (L4_IRQ_F_LEVEL * Irq_type_base); }
106
107   bool irq_is_low_polarity() const
108   { return (_f & Irq_type_mask) & (L4_IRQ_F_NEG   * Irq_type_base); }
109
110   explicit Resource(unsigned long flags = 0)
111   : _f(flags), _id(0), _p(0), _s(0), _e(0), _a(0) {}
112
113   Resource(unsigned long flags, Addr start, Addr end)
114   : _f(flags), _id(0), _p(0), _s(start), _e(end), _a(end - start)
115   {}
116
117   Resource(unsigned type, unsigned long flags, Addr start, Addr end)
118   : _f((type & F_type_mask) | (flags & ~(unsigned long)F_type_mask)),
119     _id(0), _p(0), _s(start), _e(end), _a(end - start)
120   {}
121
122   unsigned long flags() const { return _f; }
123   void add_flags(unsigned long flags) { _f |= flags; }
124   void del_flags(unsigned long flags) { _f &= ~flags; }
125   bool hierarchical() const { return _f & F_hierarchical; }
126   bool disabled() const { return _f & F_disabled; }
127   bool prefetchable() const { return _f & F_prefetchable; }
128   bool empty() const { return _f & F_empty; }
129   bool fixed_addr() const { return !(_f & F_can_move); }
130   bool fixed_size() const { return !(_f & F_can_resize); }
131   bool relative() const { return _f & F_relative; }
132   unsigned type() const { return _f & F_type_mask; }
133
134   virtual bool lt_compare(Resource const *o) const
135   { return end() < o->start(); }
136
137   static l4_uint32_t str_to_id(char const *id)
138   {
139     l4_uint32_t res = 0;
140     for (unsigned i = 0; i < 4 && id && id[i]; ++i)
141       res |= (l4_uint32_t)id[i] << (8 * i);
142     return res;
143   }
144
145   void set_id(l4_uint32_t id)
146   { _id = id; }
147
148   void set_id(char const *id)
149   { _id = str_to_id(id); }
150
151   l4_uint32_t id() const { return _id; }
152
153
154 public:
155 //private:
156   void set_empty(bool empty)
157   {
158     if (empty)
159       _f |= F_empty;
160     else
161       _f &= ~F_empty;
162   }
163
164 public:
165   void disable() { _f |= F_disabled; }
166   void enable()  { _f &= ~F_disabled; }
167
168   virtual Resource_space *provided() const { return 0; }
169
170   void dump(char const *type, int indent) const;
171   virtual void dump(int indent = 0) const;
172
173   virtual bool compatible(Resource *consumer, bool pref = true) const
174   {
175     if (type() != consumer->type())
176       return false;
177
178     return prefetchable() == (consumer->prefetchable() && pref);
179   }
180
181   Resource *parent() const { return _p; }
182   void parent(Resource *p) { _p = p; }
183
184   virtual ~Resource() {}
185
186 private:
187   Addr _s, _e;
188   l4_umword_t _a;
189
190   void _start_end(Addr s, Addr e) { _s = s; _e = e; }
191
192 public:
193   void set_empty() { _s = _e = 0; set_empty(true); }
194   void alignment(Size a)
195   {
196     _a = a;
197     del_flags(F_size_aligned);
198   }
199
200   bool valid() const { return flags() && _s <= _e; }
201
202   void validate()
203   {
204     if (!valid())
205       disable();
206   }
207
208   Addr start() const { return _s; }
209   Addr end() const { return _e; }
210   Size size() const { return (Size)_e + 1 - _s; }
211
212   bool contains(Resource const &o) const
213   { return start() <= o.start() && end() >= o.end(); }
214
215   void start(Addr start) { _e = start + (_e - _s); _s = start; }
216   void end(Addr end)
217   {
218     _e = end;
219     set_empty(false);
220   }
221
222   void size(Size size)
223   {
224     _e = _s - 1 + size;
225     set_empty(false);
226   }
227
228   void start_end(Addr start, Addr end)
229   {
230     _start_end(start, end);
231     set_empty(false);
232   }
233
234   void start_size(Addr start, Size s)
235   {
236     _start_end(start, start - 1 + s);
237     set_empty(false);
238   }
239
240   bool is_64bit() const { return flags() & F_width_64bit; }
241
242   l4_umword_t alignment() const
243   {
244     return  flags() & F_size_aligned ? (_e - _s) : _a;
245   }
246
247   virtual l4_addr_t map_iomem() const
248   {
249     if (type() != Mmio_res)
250       return 0;
251     return res_map_iomem(start(), size());
252   }
253
254   virtual l4vbus_device_handle_t provider_device_handle() const
255   { return ~0; }
256 };
257
258 class Resource_provider : public Resource
259 {
260 private:
261   class _RS : public Resource_space
262   {
263   private:
264     typedef Resource::Addr Addr;
265     typedef Resource::Size Size;
266     Resource_list _rl;
267
268   public:
269     bool request(Resource *parent, Device *pdev, Resource *child, Device *cdev);
270     bool alloc(Resource *parent, Device *pdev, Resource *child, Device *cdev,
271                bool resize);
272
273     ~_RS() {}
274   };
275
276   mutable _RS _rs;
277
278 public:
279   explicit Resource_provider(unsigned long flags)
280   : Resource(flags), _rs() {}
281
282   Resource_provider(unsigned long flags, Addr s, Addr e)
283   : Resource(flags, s, e), _rs() {}
284
285   Resource_space *provided() const
286   { return &_rs; }
287 };
288
289 class Root_resource : public Resource
290 {
291 private:
292   Resource_space *_rs;
293
294 public:
295   Root_resource(unsigned long flags, Resource_space *rs)
296   : Resource(flags), _rs(rs) {}
297
298   Resource_space *provided() const { return _rs; }
299   void dump(int) const {}
300 };
301
302
303 class Mmio_data_space : public Resource
304 {
305 private:
306   L4Re::Util::Auto_cap<L4Re::Dataspace>::Cap _ds_ram;
307
308 public:
309   L4Re::Rm::Auto_region<l4_addr_t> _r;
310
311   Mmio_data_space(Size size, unsigned long alloc_flags = 0)
312   : Resource(Mmio_res, 0, size - 1)
313   {
314     alloc_ram(size, alloc_flags);
315   }
316
317   void alloc_ram(Size size, unsigned long alloc_flags);
318
319   l4_addr_t map_iomem() const
320   {
321     return _r.get();
322   }
323 };