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