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)
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.
10 #include <l4/re/protocols>
12 #include <l4/cxx/ipc_server>
15 #include <l4/re/namespace>
16 #include <l4/re/dataspace-sys.h>
18 #include <l4/re/error_helper>
20 #include <l4/vbus/vbus_types.h>
21 #include <l4/vbus/vdevice-ops.h>
33 #include "vbus_factory.h"
35 Vi::System_bus::Root_resource_factory::Factory_list
36 Vi::System_bus::Root_resource_factory::_factories;
40 class Root_irq_rs : public Resource_space
47 Root_irq_rs(Vi::System_bus *bus)
48 : Resource_space(), _bus(bus), _icu(new Vi::Sw_icu())
50 _bus->add_child(_icu);
54 bool request(Resource *parent, Device *, Resource *child, Device *)
56 // printf("VBUS: IRQ resource request: "); child->dump();
62 _icu = new Vi::Sw_icu();
63 _bus->add_child(_icu);
67 d_printf(DBG_DEBUG2, "Add IRQ resources to vbus: ");
68 if (dlevel(DBG_DEBUG2))
71 _icu->add_irqs(child);
72 _bus->resource_set()->insert(child);
77 bool alloc(Resource *parent, Device *, Resource *child, Device *, bool)
79 d_printf(DBG_DEBUG2, "Allocate virtual IRQ resource ...\n");
80 if (dlevel(DBG_DEBUG2))
83 Vi::Msi_resource *msi = dynamic_cast<Vi::Msi_resource*>(child);
87 d_printf(DBG_DEBUG2, " Allocate Virtual MSI...\n");
91 _icu = new Vi::Sw_icu();
92 _bus->add_child(_icu);
95 int nr = _icu->alloc_irq(msi->flags(), msi->hw_msi());
98 d_printf(DBG_ERR, "ERROR: cannot allocate MSI resource\n");
102 msi->start_end(nr, nr);
103 msi->del_flags(Resource::F_disabled);
105 if (dlevel(DBG_DEBUG2))
108 msi->hw_msi()->dump(4);
111 _bus->resource_set()->insert(msi);
118 class Root_x_rs : public Resource_space
121 Vi::System_bus *_bus;
124 Root_x_rs(Vi::System_bus *bus) : Resource_space(), _bus(bus)
127 bool request(Resource *parent, Device *, Resource *child, Device *)
129 //printf("VBUS: X resource request: "); child->dump();
134 _bus->resource_set()->insert(child);
138 bool alloc(Resource *, Device *, Resource *, Device *, bool)
150 System_bus::resource_allocated(Resource const *r) const
152 Resource_set::const_iterator i = _resources.find(const_cast<Resource*>(r));
153 if (i == _resources.end())
156 if ((*i)->start() <= r->start()
157 && (*i)->end() >= r->end())
164 System_bus::System_bus() : _sw_icu(0)
167 add_resource(new Root_resource(Resource::Irq_res, new Root_irq_rs(this)));
168 Resource_space *x = new Root_x_rs(this);
169 add_resource(new Root_resource(Resource::Mmio_res, x));
170 add_resource(new Root_resource(Resource::Mmio_res | Resource::F_prefetchable, x));
171 add_resource(new Root_resource(Resource::Io_res, x));
172 typedef Root_resource_factory RF;
173 for (RF::Factory_list::Const_iterator i = RF::_factories.begin();
174 i != RF::_factories.end();
176 add_resource((*i)->create(this));
179 System_bus::~System_bus()
181 registry->unregister_obj(this);
182 // FIXME: must delete all devices
187 System_bus::dump_resources() const
189 for (Resource_set::const_iterator i = _resources.begin(); i != _resources.end(); ++i)
194 System_bus::request_resource(L4::Ipc::Iostream &ios)
196 l4vbus_resource_t res;
199 Resource ires(res.type, res.start, res.end);
200 if (dlevel(DBG_DEBUG2))
202 printf("request resource: ");
207 Resource_set::const_iterator i = _resources.find(&ires);
209 for (Resource_set::Const_iterator m = _resources.begin(); m != _resources.end(); ++m)
216 if (i == _resources.end() || !(*i)->contains(ires))
220 if (Io_config::cfg->verbose() > 1)
222 printf(" found resource: ");
228 if (res.type == L4VBUS_RESOURCE_PORT)
230 l4_uint64_t sz = res.end + 1 - res.start;
233 while ((1UL << szl2) < sz)
236 if ((1UL << szl2) > sz)
239 ios << L4::Ipc::Snd_fpage::io(res.start, szl2, L4_FPAGE_RWX);
248 System_bus::request_iomem(L4::Ipc::Iostream &ios)
254 case L4Re::Dataspace_::Map:
256 l4_addr_t offset, spot;
258 ios >> offset >> spot >> flags;
260 // printf("map iomem: %lx...\n", offset);
261 Resource pivot(L4VBUS_RESOURCE_MEM, offset, offset);
262 Resource_set::iterator r = _resources.find(&pivot);
264 if (r == _resources.end())
267 offset = l4_trunc_page(offset);
269 l4_addr_t st = l4_trunc_page((*r)->start());
270 l4_addr_t adr = (*r)->map_iomem();
275 adr = l4_trunc_page(adr);
277 l4_addr_t addr = offset - st + adr;
279 = l4_fpage_max_order(L4_PAGESHIFT,
280 addr, addr, addr + (*r)->size(), spot);
282 // we also might want to do WB instead of UNCACHED...
283 ios << L4::Ipc::Snd_fpage::mem(l4_trunc_size(addr, order), order,
284 L4_FPAGE_RWX, l4_trunc_page(spot),
285 L4::Ipc::Snd_fpage::Map,
286 L4::Ipc::Snd_fpage::Uncached);
294 System_bus::dispatch(l4_umword_t obj, L4::Ipc::Iostream &ios)
299 if (tag.label() == 0)
301 l4vbus_device_handle_t devid;
303 ios >> devid >> func;
304 Device *dev = get_dev_by_id(devid);
307 return dev->vdevice_dispatch(obj, func, ios);
310 if (tag.label() == L4Re::Protocol::Dataspace)
311 return request_iomem(ios);
313 return -L4_EBADPROTO;
318 System_bus::dispatch(l4_umword_t, l4_uint32_t func, L4::Ipc::Iostream &ios)
322 case L4vbus_vbus_request_resource:
323 return request_resource(ios);
330 static Dev_factory_t<System_bus> __sb_root_factory("System_bus");