2 * (c) 2008-2010 Adam Lackorzynski <adam@os.inf.tu-dresden.de>,
3 * Alexander Warg <warg@os.inf.tu-dresden.de>,
4 * Torsten Frenzel <frenzel@os.inf.tu-dresden.de>,
5 * Henning Schild <hschild@os.inf.tu-dresden.de>
6 * economic rights: Technische Universität Dresden (Germany)
7 * This file is part of TUD:OS and distributed under the terms of the
8 * GNU Lesser General Public License 2.1.
9 * Please see the COPYING-LGPL-2.1 file for details.
12 #include <l4/vbus/vbus.h>
13 #include <l4/io/types.h>
14 #include <l4/re/namespace>
17 #include <l4/re/error_helper>
18 #include <l4/re/util/cap_alloc>
19 #include <l4/sys/factory>
22 #include <l4/sys/task>
23 #include <l4/sys/kdebug.h>
24 #include <l4/util/splitlog2.h>
25 #include <l4/crtn/initpriorities.h>
32 using L4Re::Util::Auto_cap;
42 : _vbus(Cap<void>::No_init), _icu(Cap<void>::No_init)
44 _vbus = L4Re::Env::env()->get_cap<void>("vbus");
47 printf("libio: Warning: Query of 'vbus' failed!\n");
51 l4vbus_device_handle_t handle = 0;
52 int ret = l4vbus_get_device_by_hid(_vbus.cap(), 0, &handle, "L40009",
56 printf("libio: Warning: Finding 'icu' in system bus failed with '%s'\n",
61 _icu = L4Re::Util::cap_alloc.alloc<L4::Icu>();
64 printf("libio: cannot allocate ICU cap\n");
68 ret = l4vbus_vicu_get_cap(_vbus.cap(), handle, _icu.cap());
71 printf("libio: Warning: Getting 'icu' device failed.\n");
72 L4Re::Util::cap_alloc.free(_icu);
78 static Internals _internal __attribute__((init_priority(INIT_PRIO_LIBIO_INIT)));
80 static Cap<void> &vbus()
82 return _internal._vbus;
85 static Cap<L4::Icu> &icu()
87 return _internal._icu;
92 /***********************************************************************
94 ***********************************************************************/
97 l4io_request_irq(int irqnum, l4_cap_idx_t irq_cap)
99 L4::Cap<L4::Irq> irq(irq_cap);
100 long ret = l4_error(L4Re::Env::env()->factory()->create_irq(irq));
102 printf("Create irq failed with %ld\n", ret);
106 ret = l4_error(icu()->bind(irqnum, irq));
108 printf("Bind irq to icu failed with %ld\n", ret);
117 { return icu().cap(); }
120 l4io_release_irq(int irqnum, l4_cap_idx_t irq_cap)
122 long ret = l4_error(icu()->unbind(irqnum, L4::Cap<L4::Irq>(irq_cap)));
124 printf("Unbind irq %d from icu failed with %ld\n", irqnum, ret);
128 l4_task_unmap(L4_BASE_TASK_CAP,
129 l4_obj_fpage(irq_cap, 0, L4_FPAGE_RWX),
135 /***********************************************************************
137 ***********************************************************************/
140 __map_iomem(l4_addr_t phys, l4_addr_t* virt, unsigned long size, int flags)
142 Cap<L4Re::Dataspace> iomem = L4::cap_cast<L4Re::Dataspace>(vbus());
143 unsigned char align = L4_PAGESHIFT;
145 if (size >= L4_SUPERPAGESIZE)
146 align = L4_SUPERPAGESHIFT;
148 unsigned long rmflags = 0;
150 if (flags & L4IO_MEM_EAGER_MAP)
151 rmflags |= L4Re::Rm::Eager_map;
153 if (*virt && (flags & L4IO_MEM_USE_RESERVED_AREA))
154 rmflags |= L4Re::Rm::In_area;
157 rmflags |= L4Re::Rm::Search_addr;
159 int res = L4Re::Env::env()->rm()->attach(virt, size, rmflags, iomem, phys, align);
162 printf("Cannot attach iomem to virtual address %lx with size %lx: %s(%d).\n",
163 *virt, size, l4sys_errtostr(res), res);
171 l4io_request_iomem(l4_addr_t phys, unsigned long size,
172 int flags, l4_addr_t *virt)
175 return __map_iomem(phys, virt, size, flags);
179 l4io_request_iomem_region(l4_addr_t phys, l4_addr_t virt, unsigned long size,
183 return -L4_EADDRNOTAVAIL;
184 return __map_iomem(phys, &virt, size, flags);
188 l4io_release_iomem(l4_addr_t virt, unsigned long size)
191 return L4Re::Env::env()->rm()->detach(virt, 0);
195 l4io_search_iomem_region(l4_addr_t phys, l4_addr_t size,
196 l4_addr_t *rstart, l4_addr_t *rsize)
198 *rstart = l4_trunc_page(phys);
199 *rsize = l4_round_page(size + phys - *rstart);
203 /***********************************************************************
205 ***********************************************************************/
208 l4io_request_ioport(unsigned portnum, unsigned len)
210 l4vbus_resource_t res;
211 res.type = L4IO_RESOURCE_PORT;
213 res.end = portnum + len - 1;
214 return l4vbus_request_resource(vbus().cap(), &res, 0);
218 l4io_release_ioport(unsigned portnum, unsigned len)
220 l4vbus_resource_t res;
221 res.type = L4IO_RESOURCE_PORT;
223 res.end = portnum + len - 1;
224 return l4vbus_release_resource(vbus().cap(), &res);
227 /***********************************************************************
229 ***********************************************************************/
232 l4io_iterate_devices(l4io_device_handle_t *devhandle,
233 l4io_device_t *dev, l4io_resource_handle_t *reshandle)
235 if (!vbus().is_valid())
241 return l4vbus_get_next_device(vbus().cap(), L4VBUS_NULL,
242 devhandle, L4VBUS_MAX_DEPTH, dev);
246 l4io_lookup_device(const char *devname,
247 l4io_device_handle_t *dev_handle, l4io_device_t *dev,
248 l4io_resource_handle_t *res_handle)
251 l4io_device_handle_t dh = 0;
253 if (!vbus().is_valid())
256 if ((r = l4vbus_get_device_by_hid(vbus().cap(), 0,
257 &dh, devname, L4VBUS_MAX_DEPTH, dev)))
270 l4io_lookup_resource(l4io_device_handle_t devhandle,
271 enum l4io_resource_types_t type,
272 l4io_resource_handle_t *res_handle,
273 l4io_resource_t *desc)
275 l4vbus_resource_t resource;
276 while (!l4vbus_get_resource(vbus().cap(), devhandle, *res_handle, &resource))
279 // copy device description
280 if (resource.type == type || type == L4IO_RESOURCE_ANY)
291 l4io_request_resource_iomem(l4io_device_handle_t devhandle,
292 l4io_resource_handle_t *reshandle)
297 if (l4io_lookup_resource(devhandle, L4IO_RESOURCE_MEM,
302 if (l4io_request_iomem(res.start, res.end - res.start + 1,
303 L4IO_MEM_NONCACHED, &v))
310 void __l4io_get_all_ports(l4vbus_device_handle_t parent)
312 l4vbus_device_handle_t next_dev = 0;
313 l4vbus_device_t info;
315 while (!l4vbus_get_next_device(vbus().cap(), parent, &next_dev,
316 L4VBUS_MAX_DEPTH, &info))
318 l4vbus_resource_t resource;
319 for (unsigned r = 0; r < info.num_resources; ++r)
321 l4vbus_get_resource(vbus().cap(), next_dev, r, &resource);
322 if (resource.type == L4IO_RESOURCE_PORT)
323 l4vbus_request_resource(vbus().cap(), &resource, 0);
329 l4io_request_all_ioports(void)
331 __l4io_get_all_ports(l4io_get_root_device());
335 l4io_has_resource(enum l4io_resource_types_t type,
336 l4vbus_paddr_t start, l4vbus_paddr_t end)
338 l4io_device_handle_t dh = l4io_get_root_device();
340 l4io_resource_handle_t reshandle;
346 if (l4io_iterate_devices(&dh, &dev, &reshandle))
349 if (dev.num_resources)
350 while (!l4io_lookup_resource(dh, type, &reshandle, &res))
351 if (start >= res.start && end <= res.end)