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/sys/capability>
13 #include <l4/re/error_helper>
14 #include <l4/re/util/cap_alloc>
16 #include <l4/cxx/avl_tree>
17 #include <l4/cxx/bitmap>
18 #include <l4/sys/ipc.h>
19 #include <l4/sigma0/sigma0.h>
31 Page_shift = L4_PAGESHIFT,
33 Min_rs_mul = 1UL << Min_rs_bits,
34 Min_rs = Page_shift + Min_rs_bits,
43 bool operator < (Phys_region const &o) const throw()
44 { return phys + size - 1 < o.phys; }
45 bool contains(Phys_region const &o) const throw()
46 { return o.phys >= phys && o.phys + o.size -1 <= phys + size -1; }
49 struct Io_region : public Phys_region, public cxx::Avl_tree_node
53 mutable cxx::Bitmap_base pages;
55 Io_region() : pages(0) {}
58 struct Io_region_get_key
60 typedef Phys_region Key_type;
61 static Phys_region const &key_of(Io_region const *o) { return *o; }
65 typedef cxx::Avl_tree<Io_region, Io_region_get_key> Io_set;
69 static L4::Cap<void> sigma0;
74 sigma0 = chkcap(L4Re::Env::env()->get_cap<void>("sigma0"), "getting sigma0 cap", 0);
77 L4::Kip::Mem_desc *md = L4::Kip::Mem_desc::first(l4re_kip());
78 L4::Kip::Mem_desc *mde = md + L4::Kip::Mem_desc::count(l4re_kip());
79 for (; md < mde; ++md)
81 if (md->type() == L4::Kip::Mem_desc::Arch)
83 printf("ARCH REGION %014lx-%014lx (%02x:%02x)\n",
84 md->start(), md->end(), md->type(), md->sub_type());
85 res_map_iomem(md->start(), md->size());
93 map_iomem_range(l4_addr_t phys, l4_addr_t virt, l4_addr_t size)
95 unsigned p2sz = L4_PAGESHIFT;
98 if ((phys & ~(~0UL << p2sz)) || (virt & ~(~0UL << p2sz))
99 || (size & ~(~0UL << p2sz)))
107 unsigned n = p2sz + 1;
108 if ((phys & ~(~0UL << n)) || ((1UL << n) > size))
113 l4_msg_regs_t *m = l4_utcb_mr_u(l4_utcb());
114 l4_buf_regs_t *b = l4_utcb_br_u(l4_utcb());
115 l4_msgtag_t tag = l4_msgtag(L4_PROTO_SIGMA0, 2, 0, 0);
116 m->mr[0] = SIGMA0_REQ_FPAGE_IOMEM;
117 m->mr[1] = l4_fpage(phys, p2sz, L4_FPAGE_RWX).raw;
120 b->br[0] = L4_ITEM_MAP;
121 b->br[1] = l4_fpage(virt, p2sz, L4_FPAGE_RWX).raw;
122 tag = l4_ipc_call(sigma0.cap(), l4_utcb(), tag, L4_IPC_NEVER);
135 while ((1UL << p2sz) > size)
141 l4_addr_t res_map_iomem(l4_addr_t phys, l4_addr_t size)
144 while ((1UL << p2size) < (size + (phys - l4_trunc_size(phys, p2size))))
148 Io_region *iomem = 0;
150 r.phys = l4_trunc_page(phys);
151 r.size = l4_round_page(size + phys - r.phys);
155 Io_region *reg = io_set.find_node(r);
158 iomem = new Io_region();
160 iomem->phys = l4_trunc_size(phys, p2size);
161 iomem->virt = L4_PAGESIZE;
162 iomem->size = 1UL << p2size;
164 int res = L4Re::Env::env()->rm()->reserve_area(&iomem->virt,
165 iomem->size, L4Re::Rm::Search_addr, p2size);
174 = cxx::Bitmap_base::bit_buffer_bytes(iomem->size >> Page_shift);
175 iomem->pages = cxx::Bitmap_base(malloc(bytes));
176 memset(iomem->pages.bit_buffer(), 0, bytes);
178 io_set.insert(iomem);
180 d_printf(DBG_DEBUG, "new iomem region: p=%lx v=%lx s=%lx (bmb=%p)\n",
181 iomem->phys, iomem->virt, iomem->size,
182 iomem->pages.bit_buffer());
185 else if (reg->contains(r))
192 if (reg->pages.bit_buffer())
193 free(reg->pages.bit_buffer());
200 l4_addr_t p_virt = iomem->virt + r.phys - l4_trunc_size(phys, p2size);
201 l4_addr_t min = 0, max;
202 bool not_mapped = false;
205 for (unsigned i = (r.phys - iomem->phys) >> Page_shift;
206 i <= ((r.size + r.phys - iomem->phys) >> Page_shift);
209 if (not_mapped && (i == ((r.size + r.phys - iomem->phys) >> Page_shift)
212 max = i << Page_shift;
215 int res = map_iomem_range(iomem->phys + min, iomem->virt + min,
218 d_printf(DBG_DEBUG2, "map mem: p=%lx v=%lx s=%lx: %s(%d)\n",
220 iomem->virt + min, max - min,
221 res < 0 ? "failed" : "done", res);
225 for (unsigned x = min >> Page_shift; x < i; ++x)
226 iomem->pages.set_bit(x);
231 else if (!not_mapped && !iomem->pages[i])
233 min = i << Page_shift;
241 l4_addr_t ofs = phys - r.phys;
245 #if defined(ARCH_amd64) || defined(ARCH_x86)
247 #include <l4/util/port_io.h>
249 static l4_umword_t iobitmap[0x10000 / L4_MWORD_BITS];
251 static l4_umword_t get_iobit(unsigned port)
253 return iobitmap[port / L4_MWORD_BITS] & (1UL << (port % L4_MWORD_BITS));
256 static void set_iobit(unsigned port)
258 iobitmap[port / L4_MWORD_BITS] |= (1UL << (port % L4_MWORD_BITS));
262 int res_get_ioport(unsigned port, int size)
265 for (unsigned i = 0; i < (1UL << size); ++i)
266 if (!get_iobit(port + i))
275 int res = l4util_ioport_map(sigma0.cap(), port, size);
278 for (unsigned i = 0; i < (1UL << size); ++i)