]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/io/server/src/resource.cc
update
[l4.git] / l4 / pkg / io / server / src / resource.cc
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 #include <l4/re/mem_alloc>
11 #include <l4/re/util/cap_alloc>
12 #include <l4/re/env>
13 #include <l4/cxx/exceptions>
14 #include <l4/re/error_helper>
15
16 #include "device.h"
17
18 #include <cstdio>
19 #include <cassert>
20
21 void
22 Resource::dump(char const *ty, int indent) const
23 { printf("<%p>", this);
24   //bool abs = true;
25
26   //if (!valid())
27   //  return;
28
29   l4_uint64_t s, e;
30 #if 0
31   if (abs)
32     {
33       s = abs_start();
34       e = abs_end();
35     }
36   else
37 #endif
38     {
39       s = _s;
40       e = _e;
41     }
42
43   static char const * const irq_trigger[]
44     = { "none", // 0
45         "raising edge", // 1
46         "<unkn>", // 2
47         "level high", // 3
48         "<unkn>", // 4
49         "falling edge", // 5
50         "<unkn>", // 6
51         "level low", // 7
52         "<unkn>", // 8
53         "both edges", // 9
54         "<unkn>", // 10
55         "<unkn>", // 11
56         "<unkn>", // 12
57         "<unkn>", // 13
58         "<unkn>", // 14
59         "<unkn>", // 15
60     };
61
62   char const *tp = prefetchable() ? "pref" : "non-pref";
63   if (type() == Irq_res)
64     tp = irq_trigger[(flags() / Irq_type_base) & 0xf];
65
66   printf("%*.s%s%c [%014llx-%014llx %llx] %s (%dbit) (align=%llx flags=%lx)\n",
67          indent, " ",
68          ty, provided() ? '*' : ' ',
69          s, e, (l4_uint64_t)size(),
70          tp,
71          is_64bit() ? 64 : 32, (unsigned long long)alignment(), flags());
72 }
73
74
75 void
76 Resource::dump(int indent) const
77 {
78   static char const *ty[] = { "INVALID", "IRQ   ", "IOMEM ", "IOPORT",
79                               "BUS   ", "unk" };
80
81   dump(ty[type()], indent);
82 }
83
84
85
86 bool
87 Resource_provider::_RS::request(Resource *parent, Device *,
88                                 Resource *child, Device *)
89 {
90   Addr start = child->start();
91   Addr end   = child->end();
92
93   if (end < start)
94     return false;
95
96   if (start < parent->start())
97     return false;
98
99   if (end > parent->end())
100     return false;
101
102   Resource_list::iterator r = _rl.begin();
103   while (true)
104     {
105       if (r == _rl.end() || (*r)->start() > end)
106         {
107           // insert before r
108           _rl.insert(r, child);
109           child->parent(parent);
110           return true;
111         }
112
113       if ((*r)->end() >= start)
114         return false;
115
116       ++r;
117     }
118 }
119
120
121 bool
122 Resource_provider::_RS::alloc(Resource *parent, Device *pdev,
123                               Resource *child, Device *cdev,
124                               bool resize)
125 {
126   Resource_list::iterator p = _rl.begin();
127   Addr start = parent->start();
128   Addr end;
129   Size min_align = L4_PAGESIZE - 1;
130
131   if (p != _rl.end() && (*p)->start() == 0)
132     {
133       start = (*p)->end() + 1;
134       ++p;
135     }
136
137   while (true)
138     {
139       if (p != _rl.end())
140         end = (*p)->start() - 1;
141       else
142         end = parent->end();
143
144       Size align = cxx::max<Size>(child->alignment(), min_align);
145       start = (start + align) & ~align; // pad to get alignment
146
147       if (start < end && end - start >= (Addr)child->size() - 1)
148         {
149           child->start(start);
150           break;
151         }
152
153       if (p == _rl.end() && !resize)
154         return false;
155
156       if (p == _rl.end() && resize)
157         {
158           end = start + child->size() - 1;
159           if (end < start)
160             return false; // wrapped around
161
162           parent->end(end);
163           child->start(start);
164           break;
165         }
166
167       start = (*p)->end() + 1;
168       ++p;
169     }
170   return request(parent, pdev, child, cdev);
171 }
172
173 void Mmio_data_space::alloc_ram(Size size, unsigned long alloc_flags)
174 {
175   long ma_flags = L4Re::Mem_alloc::Continuous;
176
177   ma_flags |= alloc_flags ? L4Re::Mem_alloc::Super_pages : 0;
178
179   _ds_ram = L4Re::Util::cap_alloc.alloc<L4Re::Dataspace>();
180   if (!_ds_ram.is_valid())
181     throw(L4::Out_of_memory(""));
182
183   L4Re::chksys(L4Re::Env::env()->mem_alloc()->alloc(size, _ds_ram.get(),
184                                                     ma_flags));
185
186   l4_size_t ds_size = size;
187   l4_addr_t phys_start;
188   L4Re::chksys(_ds_ram->phys(0, phys_start, ds_size));
189   if (size > ds_size)
190     throw(L4::Out_of_memory("not really"));
191
192   start(phys_start);
193
194   add_flags(Resource::F_fixed_size | Resource::F_fixed_addr);
195
196   L4Re::chksys(L4Re::Env::env()->rm()->attach(&_r, ds_size,
197                                               L4Re::Rm::Search_addr |
198                                                 L4Re::Rm::Eager_map,
199                                               _ds_ram.get()));
200 }