2 * (c) 2008-2010 Technische Universität Dresden
3 * This file is part of TUD:OS and distributed under the terms of the
4 * GNU Lesser General Public License 2.1.
5 * Please see the COPYING-LGPL-2.1 file for details.
7 #include <l4/cxx/exceptions>
8 #include <l4/cxx/iostream>
10 #include <l4/vbus/vbus.h>
11 #include <l4/io/types.h>
12 #include <l4/re/namespace>
15 #include <l4/re/error_helper>
16 #include <l4/re/util/cap_alloc>
17 #include <l4/sys/factory>
20 #include <l4/sys/semaphore>
21 #include <l4/sys/task>
22 #include <l4/sys/kdebug.h>
23 #include <l4/util/splitlog2.h>
24 #include <l4/crtn/initpriorities.h>
31 using L4Re::Util::Auto_cap;
35 /***********************************************************************
37 ***********************************************************************/
38 static Cap<void> &vbus()
40 static Cap<void> _vbus;
44 static Cap<L4::Icu> &icu()
46 static Cap<L4::Icu> _icu;
52 extern "C" void __attribute__((__used__))
53 __internal_l4io_init()
57 L4::Cap<L4Re::Rm> rm = L4Re::Env::env()->rm();
59 vbus() = L4Re::Env::env()->get_cap<void>("vbus");
60 if (!vbus().is_valid())
62 printf("libio: Warning: Query of 'vbus' failed with!\n");
66 l4vbus_device_handle_t handle = 0;
67 int ret = l4vbus_get_device_by_hid(vbus().cap(), 0, &handle, "L40009",
71 //printf("libio: Warning: Finding 'icu' in system bus failed with '%s'\n",
72 // l4sys_errtostr(ret));
76 icu() = L4Re::chkcap(L4Re::Util::cap_alloc.alloc<L4::Icu>(),
77 "allocating ICU cap");
79 ret = l4vbus_vicu_get_cap(vbus().cap(), handle, icu().cap());
82 printf("libio: Warning: Getting 'icu' device failed.\n");
83 L4Re::Util::cap_alloc.free(icu());
87 catch (L4::Runtime_error const &e)
90 printf("Libio caught exception\n");
95 L4_DECLARE_CONSTRUCTOR(__internal_l4io_init, INIT_PRIO_LIBIO_INIT);
98 /***********************************************************************
100 ***********************************************************************/
103 l4io_request_irq(int irqnum, l4_cap_idx_t irq_cap)
105 L4::Cap<L4::Irq> irq(irq_cap);
106 long ret = l4_ipc_error(L4Re::Env::env()->factory()->create_irq(irq), l4_utcb());
108 printf("Create irq failed with %ld\n", ret);
112 ret = l4_ipc_error(icu()->bind(irqnum, irq), l4_utcb());
114 printf("Bind irq to icu failed with %ld\n", ret);
123 { return icu().cap(); }
126 l4io_release_irq(int irqnum, l4_cap_idx_t irq_cap)
128 long ret = l4_error(icu()->unbind(irqnum, L4::Cap<L4::Irq>(irq_cap)));
130 printf("Unbind irq %d from icu failed with %ld\n", irqnum, ret);
134 l4_task_unmap(L4_BASE_TASK_CAP,
135 l4_obj_fpage(irq_cap, 0, L4_FPAGE_RWX),
141 /***********************************************************************
143 ***********************************************************************/
146 __map_iomem(l4_addr_t phys, l4_addr_t* virt, unsigned long size, int flags)
148 Cap<L4Re::Dataspace> iomem = L4::cap_cast<L4Re::Dataspace>(vbus());
150 int res = L4Re::Env::env()->rm()->attach(virt, size,
152 ? (flags & L4IO_MEM_USE_RESERVED_AREA ? L4Re::Rm::In_area : 0)
153 : L4Re::Rm::Search_addr, iomem, phys);
156 printf("Cannot attach iomem to virtual address %lx with size %lx: %s(%d).\n",
157 *virt, size, l4sys_errtostr(res), res);
165 l4io_request_iomem(l4_addr_t phys, unsigned long size,
166 int flags, l4_addr_t *virt)
169 return __map_iomem(phys, virt, size, flags);
173 l4io_request_iomem_region(l4_addr_t phys, l4_addr_t virt, unsigned long size,
177 return -L4_EADDRNOTAVAIL;
178 return __map_iomem(phys, &virt, size, flags);
182 l4io_release_iomem(l4_addr_t virt, unsigned long size)
185 return L4Re::Env::env()->rm()->detach(virt, 0);
189 l4io_search_iomem_region(l4_addr_t phys, l4_addr_t size,
190 l4_addr_t *rstart, l4_addr_t *rsize)
192 *rstart = l4_trunc_page(phys);
193 *rsize = l4_round_page(size + phys - *rstart);
197 /***********************************************************************
199 ***********************************************************************/
202 l4io_request_ioport(unsigned portnum, unsigned len)
204 l4vbus_resource_t res;
205 res.type = L4IO_RESOURCE_PORT;
207 res.end = portnum + len - 1;
208 return l4vbus_request_resource(vbus().cap(), &res, 0);
212 l4io_release_ioport(unsigned portnum, unsigned len)
214 l4vbus_resource_t res;
215 res.type = L4IO_RESOURCE_PORT;
217 res.end = portnum + len - 1;
218 return l4vbus_release_resource(vbus().cap(), &res);
221 /***********************************************************************
223 ***********************************************************************/
226 l4io_iterate_devices(l4io_device_handle_t *devhandle,
227 l4io_device_t *dev, l4io_resource_handle_t *reshandle)
232 return l4vbus_get_next_device(vbus().cap(), L4VBUS_NULL,
233 devhandle, L4VBUS_MAX_DEPTH, dev);
237 l4io_lookup_device(const char *devname,
238 l4io_device_handle_t *dev_handle, l4io_device_t *dev,
239 l4io_resource_handle_t *res_handle)
242 l4io_device_handle_t dh = 0;
244 if ((r = l4vbus_get_device_by_hid(vbus().cap(), 0,
245 &dh, devname, L4VBUS_MAX_DEPTH, dev)))
258 l4io_lookup_resource(l4io_device_handle_t devhandle,
259 enum l4io_resource_types_t type,
260 l4io_resource_handle_t *res_handle,
261 l4io_resource_t *desc)
263 l4vbus_resource_t resource;
264 while (!l4vbus_get_resource(vbus().cap(), devhandle, *res_handle, &resource))
267 // copy device description
268 if (resource.type == type || type == L4IO_RESOURCE_ANY)
279 l4io_request_resource_iomem(l4io_device_handle_t devhandle,
280 l4io_resource_handle_t *reshandle)
285 if (l4io_lookup_resource(devhandle, L4IO_RESOURCE_MEM,
290 if (l4io_request_iomem(res.start, res.end - res.start + 1,
291 L4IO_MEM_NONCACHED, &v))
298 void __l4io_get_all_ports(l4vbus_device_handle_t parent)
300 l4vbus_device_handle_t next_dev = 0;
301 l4vbus_device_t info;
303 while (!l4vbus_get_next_device(vbus().cap(), parent, &next_dev,
304 L4VBUS_MAX_DEPTH, &info))
306 l4vbus_resource_t resource;
307 for (unsigned r = 0; r < info.num_resources; ++r)
309 l4vbus_get_resource(vbus().cap(), next_dev, r, &resource);
310 if (resource.type == L4IO_RESOURCE_PORT)
311 l4vbus_request_resource(vbus().cap(), &resource, 0);
317 l4io_request_all_ioports(void)
319 __l4io_get_all_ports(l4io_get_root_device());