]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/io/server/src/device.cc
update
[l4.git] / l4 / pkg / io / server / src / device.cc
1 /*
2  * (c) 2011 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 #include "device.h"
10 #include "debug.h"
11
12 #include <cassert>
13 #include <set>
14
15
16 bool
17 Generic_device::alloc_child_resource(Resource *r, Device *cld)
18 {
19   bool found_as = false;
20   for (Resource_list::iterator br = resources()->begin();
21        br != resources()->end(); ++br)
22     {
23       if (!*br)
24         continue;
25
26       if (br->disabled())
27         continue;
28
29       if (!br->provided())
30         continue;
31
32       if (!br->compatible(r, true))
33         continue;
34
35       found_as = true;
36
37       if (br->provided()->alloc(*br, this, r, cld, parent() && !parent()->resource_allocated(*br)))
38         {
39           d_printf(DBG_ALL, "allocated resource: ");
40           if (dlevel(DBG_ALL))
41             r->dump();
42
43           return true;
44         }
45     }
46
47   if (!found_as && parent())
48     return parent()->alloc_child_resource(r, cld);
49
50
51   d_printf(DBG_ERR, "ERROR: could not reserve resource\n");
52   if (dlevel(DBG_ERR))
53     r->dump();
54
55   r->disable();
56   return false;
57 }
58
59
60 void
61 Device::request_resource(Resource *r)
62 {
63   Device *p = parent();
64
65   // Are we the root device?
66   if (!p)
67     return;
68
69   if (r->empty())
70     return;
71
72   if (p->resource_allocated(r))
73     return; // already allocated
74
75   if (r->disabled())
76     return;
77
78   if (!p->request_child_resource(r, this))
79     {
80 #if 0
81       printf("WARNING: could not request resource in parent resource\n");
82       r->dump();
83 #endif
84     }
85 }
86
87 void
88 Device::request_resources()
89 {
90   Resource_list const *rl = resources();
91
92   // Are we the root device?
93   if (!parent())
94     return;
95
96   for (Resource_list::iterator r = rl->begin();
97       r != rl->end(); ++r)
98     if (*r)
99       request_resource(*r);
100 }
101
102
103 void
104 Device::request_child_resources()
105 {
106   for (iterator dev = begin(0); dev != end(); ++dev)
107     {
108       // First, try to map all our resources of out child (dev) into
109       // provided resources of ourselves
110       (*dev)->request_resources();
111
112       // Second, recurse down to our child (dev)
113       (*dev)->request_child_resources();
114     }
115 }
116
117
118 // sortet set of resource, device pairs
119 namespace {
120
121 struct Res_dev
122 {
123   Resource *r;
124   Device *d;
125
126   Res_dev() {}
127   Res_dev(Resource *r, Device *d) : r(r), d(d) {}
128 };
129
130 static bool res_cmp(Res_dev const &l, Res_dev const &r)
131 { return l.r->alignment() > r.r->alignment(); }
132
133 typedef std::multiset<Res_dev, bool (*)(Res_dev const &l, Res_dev const &r)> UAD;
134
135 }
136
137 void
138 Device::allocate_pending_resources()
139 {
140   allocate_pending_child_resources();
141   Device *p = parent();
142
143   if (!p)
144     return;
145
146   UAD to_allocate(res_cmp);
147
148   for (Resource_list::iterator r = resources()->begin();
149       r != resources()->end(); ++r)
150     {
151       if (!*r)
152         continue;
153
154       if (r->fixed_addr())
155         continue;
156
157       if (r->empty())
158         continue;
159
160       if (p->resource_allocated(*r))
161         continue;
162 #if 0
163       printf("unallocated resource: ");
164       r->dump();
165 #endif
166       to_allocate.insert(Res_dev(*r, this));
167     }
168
169   for (UAD::const_iterator i = to_allocate.begin(); i != to_allocate.end(); ++i)
170     p->alloc_child_resource((*i).r, this);
171 }
172
173 void
174 Device::allocate_pending_child_resources()
175 {
176   UAD to_allocate(res_cmp);
177
178   for (iterator dev = begin(0); dev != end(); ++dev)
179     {
180       dev->allocate_pending_child_resources();
181
182       for (Resource_list::iterator r = dev->resources()->begin();
183            r != dev->resources()->end(); ++r)
184         {
185           if (!*r)
186             continue;
187
188           if (r->fixed_addr())
189             continue;
190
191           if (r->empty())
192             continue;
193
194           if (resource_allocated(*r))
195             continue;
196 #if 0
197           printf("unallocated resource: ");
198           r->dump();
199 #endif
200           to_allocate.insert(Res_dev(*r, *dev));
201         }
202     }
203
204   for (UAD::const_iterator i = to_allocate.begin(); i != to_allocate.end(); ++i)
205     alloc_child_resource((*i).r, (*i).d);
206 }
207
208
209 void
210 Generic_device::setup_resources()
211 {
212   for (iterator i = begin(0); i != end(); ++i)
213     i->setup_resources();
214 }
215
216 bool
217 Generic_device::request_child_resource(Resource *r, Device *cld)
218 {
219   bool found_as = false;
220   bool exact = true;
221   while (true)
222     {
223       // scan through all our resources and try to find a
224       // provided resource that is consumed by resource 'r'
225       for (Resource_list::iterator br = resources()->begin();
226            br != resources()->end(); ++br)
227         {
228           if (!*br)
229             continue;
230
231           if (br->disabled())
232             continue;
233
234           if (!br->provided())
235             continue;
236
237           if (!br->compatible(r, exact))
238             continue;
239
240           found_as = true;
241
242           if (br->provided()->request(*br, this, r, cld))
243             return true;
244         }
245
246       if (exact)
247         exact = false;
248       else if (!found_as && parent())
249         {
250           // If there is no proper resource provided by
251           // ourselves that fits resource r, than try to
252           // go up the hierarchy to our parent node
253 #if 0
254           printf("try parent resource request...\n");
255           r->dump();
256 #endif
257           return parent()->request_child_resource(r, cld);
258         }
259       else
260         return false;
261     }
262 }
263