]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/io/server/src/device.h
update
[l4.git] / l4 / pkg / io / server / src / device.h
1 /*
2  * (c) 2010 Alexander Warg <warg@os.inf.tu-dresden.de>
3  *     economic rights: Technische Universität Dresden (Germany)
4  *
5  * This file is part of TUD:OS and distributed under the terms of the
6  * GNU General Public License 2.
7  * Please see the COPYING-GPL-2 file for details.
8  */
9 #pragma once
10
11 #include <l4/sys/l4int.h>
12 #include <l4/vbus/vbus_types.h>
13 #include <l4/cxx/minmax>
14 #include <l4/cxx/string>
15
16 #include "resource.h"
17
18 #include <cstdio> 
19 #include <cstring>
20
21 template< typename D >
22 class Device_tree
23 {
24 private:
25   D *_n;
26   D *_p;
27   D *_c;
28   int _depth;
29
30 public:
31   Device_tree() : _n(0), _p(0), _c(0), _depth(0) {}
32
33   D *parent() const { return _p; }
34   D *children() const { return _c; }
35   D *next() const { return _n; }
36   int depth() const { return _depth; }
37
38   void set_parent(D *p) { _p = p; }
39
40   void add_sibling(D *s)
41   { _n = s; }
42
43   void add_child(D *d, D *self)
44   {
45     for (iterator i = iterator(0, d, L4VBUS_MAX_DEPTH); i != iterator(); ++i)
46       i->set_depth(i->depth() + depth() + 1);
47
48     d->set_parent(self);
49
50     if (!_c)
51       _c = d;
52     else
53       {
54         D *p;
55         for (p = _c; p->next(); p = p->next())
56           ;
57         p->add_sibling(d);
58       }
59   }
60
61   void set_depth(int d) { _depth = d; }
62
63   class iterator
64   {
65   public:
66     iterator(D *p, D *c, int depth = 0)
67     : _p(p), _c(c), _d(depth + (p ? p->depth() : 0))
68     {}
69
70     iterator(D const *p, int depth = 0)
71     : _p(p), _c(p->children()), _d(depth + p->depth())
72     {}
73
74     iterator()
75     : _c(0)
76     {}
77
78     bool operator == (iterator const &i) const
79     {
80       if (!_c && !i._c)
81         return true;
82
83       return _p == i._p && _c == i._c && _d == i._d;
84     }
85
86     bool operator != (iterator const &i) const
87     { return !operator == (i); }
88
89     D *operator -> () const { return _c; }
90     D *operator * () const { return _c; }
91
92     iterator operator ++ ()
93     {
94       if (_d > _c->depth() && _c->children())
95         // go to a child if not at max depth and there are children
96         _c = _c->children();
97       else if (_c->next())
98         // go to the next sibling
99         _c = _c->next();
100       else
101         {
102           for (D *x = _c->parent(); x && x != _p; x = x->parent())
103             if (x->next())
104               {
105                 _c = x->next();
106                 return *this;
107               }
108           _c = 0;
109         }
110
111       return *this;
112     }
113
114     iterator operator ++ (int)
115     {
116       iterator o = *this;
117       ++(*this);
118       return o;
119     }
120
121   private:
122     D const *_p;
123     D *_c;
124     int _d;
125   };
126 };
127
128 template< typename D >
129 class Device_tree_mixin
130 {
131 protected:
132   Device_tree<D> _dt;
133
134 public:
135   typedef typename Device_tree<D>::iterator iterator;
136
137   iterator begin(int depth = 0) const
138   { return iterator(static_cast<D const*>(this), depth); }
139
140   static iterator end() { return iterator(); }
141
142   D *find_by_name(char const *name) const
143   {
144     for (iterator c = begin(0); c != end(); ++c)
145       if (strcmp((*c)->name(), name) == 0)
146         return *c;
147
148     return 0;
149   }
150
151   void set_depth(int d) { return _dt.set_depth(d); }
152   void set_parent(D *p) { _dt.set_parent(p); }
153   void add_sibling(D *s) { _dt.add_sibling(s); }
154   virtual void add_child(D *c) { _dt.add_child(c, static_cast<D*>(this)); }
155   virtual ~Device_tree_mixin() {}
156 };
157
158 class Resource_container
159 {
160 public:
161   virtual Resource_list const *resources() const = 0;
162   virtual bool resource_allocated(Resource const *) const  = 0;
163   virtual ~Resource_container() {}
164 };
165
166
167 class Device : public Resource_container
168 {
169 public:
170   virtual Device *parent() const = 0;
171   virtual Device *children() const = 0;
172   virtual Device *next() const = 0;
173   virtual int depth() const = 0;
174
175   virtual bool request_child_resource(Resource *, Device *) = 0;
176   virtual bool alloc_child_resource(Resource *, Device *)  = 0;
177
178   void request_resource(Resource *r);
179   void request_resources();
180   void request_child_resources();
181   void allocate_pending_child_resources();
182   void allocate_pending_resources();
183   virtual void setup_resources() = 0;
184
185   virtual char const *name() const = 0;
186   virtual char const *hid() const = 0;
187   virtual bool name(cxx::String const &)  = 0;
188
189   virtual void dump(int) const {};
190
191   virtual ~Device() {}
192
193   typedef Device_tree<Device>::iterator iterator;
194
195   iterator begin(int depth = 0) const { return iterator(this, depth); }
196   static iterator end() { return iterator(); }
197
198 };
199
200
201
202 class Generic_device : public Device
203 {
204 private:
205   Resource_list _resources;
206
207 public:
208   //typedef gen_iterator<Generic_device> iterator;
209
210   Resource_list const *resources() const { return &_resources; }
211   void add_resource(Resource *r)
212   { _resources.push_back(r); }
213
214   virtual bool match_cid(cxx::String const &) const { return false; }
215   virtual char const *name() const { return "(noname)"; }
216   virtual char const *hid() const { return 0; }
217   virtual bool name(cxx::String const &) { return false; }
218
219
220   virtual bool request_child_resource(Resource *, Device *);
221   virtual bool alloc_child_resource(Resource *, Device *);
222   virtual void setup_resources();
223
224   virtual ~Generic_device() {}
225
226 };
227
228