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>
30 Page_shift = L4_PAGESHIFT,
32 Min_rs_mul = 1UL << Min_rs_bits,
33 Min_rs = Page_shift + Min_rs_bits,
42 bool operator < (Phys_region const &o) const throw()
43 { return phys + size - 1 < o.phys; }
44 bool contains(Phys_region const &o) const throw()
45 { return o.phys >= phys && o.phys + o.size -1 <= phys + size -1; }
48 struct Io_region : public Phys_region, public cxx::Avl_tree_node
52 mutable cxx::Bitmap_base pages;
54 Io_region() : pages(0) {}
57 struct Io_region_get_key
59 typedef Phys_region Key_type;
60 static Phys_region const &key_of(Io_region const *o) { return *o; }
64 typedef cxx::Avl_tree<Io_region, Io_region_get_key> Io_set;
68 static L4::Cap<void> sigma0;
73 sigma0 = chkcap(L4Re::Env::env()->get_cap<void>("sigma0"), "getting sigma0 cap", 0);
76 L4::Kip::Mem_desc *md = L4::Kip::Mem_desc::first(l4re_kip());
77 L4::Kip::Mem_desc *mde = md + L4::Kip::Mem_desc::count(l4re_kip());
78 for (; md < mde; ++md)
80 if (md->type() == L4::Kip::Mem_desc::Arch)
82 printf("ARCH REGION %014lx-%014lx (%02x:%02x)\n",
83 md->start(), md->end(), md->type(), md->sub_type());
84 res_map_iomem(md->start(), md->size());
92 map_iomem_range(l4_addr_t phys, l4_addr_t virt, l4_addr_t size)
94 unsigned p2sz = L4_PAGESHIFT;
97 if ((phys & ~(~0UL << p2sz)) || (virt & ~(~0UL << p2sz))
98 || (size & ~(~0UL << p2sz)))
106 unsigned n = p2sz + 1;
107 if ((phys & ~(~0UL << n)) || ((1UL << n) > size))
112 l4_msg_regs_t *m = l4_utcb_mr_u(l4_utcb());
113 l4_buf_regs_t *b = l4_utcb_br_u(l4_utcb());
114 l4_msgtag_t tag = l4_msgtag(L4_PROTO_SIGMA0, 2, 0, 0);
115 m->mr[0] = SIGMA0_REQ_FPAGE_IOMEM;
116 m->mr[1] = l4_fpage(phys, p2sz, L4_FPAGE_RWX).raw;
119 b->br[0] = L4_ITEM_MAP;
120 b->br[1] = l4_fpage(virt, p2sz, L4_FPAGE_RWX).raw;
121 tag = l4_ipc_call(sigma0.cap(), l4_utcb(), tag, L4_IPC_NEVER);
134 while ((1UL << p2sz) > size)
140 l4_addr_t res_map_iomem(l4_addr_t phys, l4_addr_t size)
143 while ((1UL << p2size) < (size + (phys - l4_trunc_size(phys, p2size))))
147 Io_region *iomem = 0;
149 r.phys = l4_trunc_page(phys);
150 r.size = l4_round_page(size + phys - r.phys);
154 Io_region *reg = io_set.find_node(r);
157 iomem = new Io_region();
159 iomem->phys = l4_trunc_size(phys, p2size);
160 iomem->virt = L4_PAGESIZE;
161 iomem->size = 1UL << p2size;
163 int res = L4Re::Env::env()->rm()->reserve_area(&iomem->virt,
164 iomem->size, L4Re::Rm::Search_addr, p2size);
173 = cxx::Bitmap_base::bit_buffer_bytes(iomem->size >> Page_shift);
174 iomem->pages = cxx::Bitmap_base(malloc(bytes));
175 memset(iomem->pages.bit_buffer(), 0, bytes);
177 io_set.insert(iomem);
179 if (Io_config::cfg->verbose())
180 printf("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 if (Io_config::cfg->verbose() > 1)
219 printf("map mem: p=%lx v=%lx s=%lx: %s\n", iomem->phys + min,
220 iomem->virt + min, max - min,
221 res < 0 ? "failed" : "done");
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)