]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/io/server/src/vbus.cc
Inital import
[l4.git] / l4 / pkg / io / server / src / vbus.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 <l4/re/protocols>
8
9 #include <l4/cxx/ipc_server>
10 #include <l4/cxx/iostream>
11 #include <l4/cxx/l4iostream>
12
13 #include <l4/re/env>
14 #include <l4/re/namespace>
15 #include <l4/re/dataspace-sys.h>
16
17 #include <l4/re/error_helper>
18
19 #include <l4/vbus/vbus_types.h>
20 #include <l4/vbus/vdevice-ops.h>
21
22 #include <cstdio>
23
24 #include "vbus.h"
25 #include "vicu.h"
26 #include "server.h"
27 #include "res.h"
28 #include "cfg.h"
29 #include "vbus_factory.h"
30
31 namespace {
32
33 class Root_irq_rs : public Resource_space
34 {
35 private:
36   Vi::System_bus *_bus;
37   Vi::Sw_icu *_icu;
38
39 public:
40   Root_irq_rs(Vi::System_bus *bus) : Resource_space(), _bus(bus), _icu(0)
41   {}
42
43   bool request(Resource *parent, Device *, Resource *child, Device *)
44   {
45     // printf("VBUS: IRQ resource request: "); child->dump();
46     Adr_resource *r = dynamic_cast<Adr_resource*>(child);
47     if (!r || !parent)
48       return false;
49
50     if (!_icu)
51       {
52         _icu = new Vi::Sw_icu();
53         _bus->add_child(_icu);
54       }
55
56     _icu->add_irqs(r);
57     _bus->resource_set()->insert(r);
58
59     return true;
60   };
61
62   bool alloc(Resource *, Device *, Resource *, Device *, bool)
63   { return false; }
64
65   ~Root_irq_rs() {}
66 };
67
68 class Root_x_rs : public Resource_space
69 {
70 private:
71   Vi::System_bus *_bus;
72
73 public:
74   Root_x_rs(Vi::System_bus *bus) : Resource_space(), _bus(bus)
75   {}
76
77   bool request(Resource *parent, Device *, Resource *child, Device *)
78   {
79     //printf("VBUS: X resource request: "); child->dump();
80     Adr_resource *r = dynamic_cast<Adr_resource*>(child);
81     if (!r || !parent)
82       return false;
83
84
85     _bus->resource_set()->insert(r);
86     return true;
87   }
88
89   bool alloc(Resource *, Device *, Resource *, Device *, bool)
90   { return false; }
91
92   ~Root_x_rs() {}
93 };
94 }
95
96
97
98 namespace Vi {
99
100 bool
101 System_bus::resource_allocated(Resource const *_r) const
102 {
103   Adr_resource const *r = dynamic_cast<Adr_resource const *>(_r);
104   if (!r)
105     return false;
106
107   Resource_set::const_iterator i = _resources.find(const_cast<Adr_resource*>(r));
108   if (i == _resources.end())
109     return false;
110
111   if ((*i)->data().start() <= r->data().start()
112       && (*i)->data().end() >= r->data().end())
113     return true;
114
115   return false;
116 }
117
118
119 System_bus::System_bus()
120 {
121   add_feature(this);
122   add_resource(new Root_resource(Resource::Irq_res, new Root_irq_rs(this)));
123   Resource_space *x = new Root_x_rs(this);
124   add_resource(new Root_resource(Resource::Mmio_res, x));
125   add_resource(new Root_resource(Resource::Mmio_res | Resource::F_prefetchable, x));
126   add_resource(new Root_resource(Resource::Io_res, x));
127 }
128
129 System_bus::~System_bus()
130 {
131   registry->unregister_obj(this);
132   // FIXME: must delete all devices
133 }
134
135
136 void
137 System_bus::dump_resources() const
138 {
139   for (Resource_set::const_iterator i = _resources.begin(); i != _resources.end(); ++i)
140     (*i)->dump();
141 }
142
143 int
144 System_bus::request_resource(L4::Ipc_iostream &ios)
145 {
146   l4vbus_resource_t res;
147   ios.get(res);
148
149   ::Adr_resource ires(res.type, res.start, res.end);
150   if (Io_config::cfg->verbose() > 1)
151     {
152       printf("request resource: ");
153       Adr_resource(ires).dump();
154       puts("");
155     }
156
157   Resource_set::const_iterator i = _resources.find(&ires);
158 #if 0
159   for (Resource_set::Const_iterator m = _resources.begin(); m != _resources.end(); ++m)
160     {
161       m->dump();
162       puts("");
163     }
164 #endif
165
166   if (i == _resources.end())
167     return -L4_ENOENT;
168
169 #if 0
170   if (Io_config::cfg->verbose() > 1)
171     {
172       printf("  found resource: ");
173       i->dump();
174       puts("");
175     }
176 #endif
177
178   if (res.type == L4VBUS_RESOURCE_PORT)
179     {
180       l4_uint64_t sz = res.end + 1 - res.start;
181
182       int szl2 = 0;
183       while ((1UL << szl2) < sz)
184         ++szl2;
185
186       if ((1UL << szl2) > sz)
187         --szl2;
188
189       ios << L4::Snd_fpage::io(res.start, szl2, L4_FPAGE_RWX);
190       return L4_EOK;
191     }
192
193
194   return -L4_ENOENT;
195 }
196
197
198 int
199 System_bus::request_iomem(L4::Ipc_iostream &ios)
200 {
201   L4::Opcode op;
202   ios >> op;
203   switch (op)
204     {
205     case L4Re::Dataspace_::Map:
206         {
207           l4_addr_t offset, spot;
208           unsigned long flags;
209           ios >> offset >> spot >> flags;
210
211 //        printf("map iomem: %lx...\n", offset);
212           Adr_resource pivot(L4VBUS_RESOURCE_MEM, offset, offset);
213           Resource_set::iterator r = _resources.find(&pivot);
214
215           if (r == _resources.end())
216             return -L4_ERANGE;
217
218           offset = l4_trunc_page(offset);
219
220           l4_addr_t st = l4_trunc_page((*r)->_data().start());
221           l4_addr_t adr = (*r)->map_iomem();
222
223           if (!adr)
224             return -L4_ENOMEM;
225
226           adr = l4_trunc_page(adr);
227
228           ios << L4::Snd_fpage::mem(offset - st + adr, L4_PAGESHIFT, L4_FPAGE_RWX, l4_trunc_page(spot));
229           return L4_EOK;
230         }
231     }
232   return -L4_ENOSYS;
233 };
234
235 int
236 System_bus::dispatch(l4_umword_t obj, L4::Ipc_iostream &ios)
237 {
238   l4_msgtag_t tag;
239   ios >> tag;
240
241   if (tag.label() == 0)
242     {
243       l4vbus_device_handle_t devid;
244       l4_uint32_t func;
245       ios >> devid >> func;
246       Device *dev = get_dev_by_id(devid);
247       if (!dev)
248         return -L4_ENODEV;
249       return dev->vdevice_dispatch(obj, func, ios);
250     }
251
252   if (tag.label() == L4Re::Protocol::Dataspace)
253     return request_iomem(ios);
254
255   return -L4_EBADPROTO;
256
257 }
258
259 int
260 System_bus::dispatch(l4_umword_t, l4_uint32_t func, L4::Ipc_iostream &ios)
261 {
262   switch (func)
263     {
264     case L4vbus_vbus_request_resource:
265       return request_resource(ios);
266     default:
267       return -L4_ENOSYS;
268     }
269 }
270
271
272 static Dev_factory_t<System_bus> __sb_root_factory("System_bus");
273
274 }