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