diff --git a/base/include/util/mmio.h b/base/include/util/mmio.h
new file mode 100644
index 0000000000..d4506fb5e5
--- /dev/null
+++ b/base/include/util/mmio.h
@@ -0,0 +1,327 @@
+/*
+ * \brief Generic MMIO accessor framework
+ * \author Martin stein
+ * \date 2011-10-26
+ */
+
+#ifndef _BASE__INCLUDE__UTIL__MMIO_H_
+#define _BASE__INCLUDE__UTIL__MMIO_H_
+
+#include
+
+
+namespace Genode
+{
+ /**
+ * A continuous MMIO region
+ */
+ class Mmio
+ {
+ protected:
+
+ /**
+ * Write 'value' typed to MMIO base + 'o'
+ */
+ template
+ void _write(off_t const o, STORAGE_T const value);
+
+ /**
+ * Read typed from MMIO base + 'o'
+ */
+ template
+ STORAGE_T _read(off_t const o) const;
+
+ public:
+
+ enum { BYTE_EXP = 3, BYTE_WIDTH = 8 };
+
+ /**
+ * Holds additional info for an array of the inheriting type
+ */
+ template
+ struct Array { enum { MAX_INDEX = SIZE-1 }; };
+
+ /**
+ * A POD-like region at offset 'MMIO_OFFSET' within a MMIO region
+ */
+ template
+ struct Register
+ {
+ typedef STORAGE_T storage_t;
+ enum { OFFSET = MMIO_OFFSET };
+
+ /**
+ * A bitregion within a register
+ */
+ template
+ struct Subreg
+ {
+ enum {
+ SHIFT = BIT_SHIFT,
+ WIDTH = BIT_SIZE,
+ MASK = (1 << WIDTH) - 1,
+ };
+
+ /**
+ * Back reference to containing register
+ */
+ typedef Register Compound_reg;
+
+ /**
+ * Get a register value with this subreg set to 'value'
+ * and the rest left zero
+ */
+ static storage_t bits(storage_t const value)
+ {
+ return (value & MASK) << SHIFT;
+ };
+ };
+
+ /**
+ * An array of 'SUBREGS' many similar bitregions
+ * FIXME: Side effects of a combination of 'Reg_array' and 'Subreg_array'
+ * are not evaluated
+ */
+ template
+ struct Subreg_array : public Array
+ {
+ enum {
+ SHIFT = BIT_SHIFT,
+ WIDTH = BIT_SIZE,
+ MASK = (1 << WIDTH) - 1,
+ ITERATION_WIDTH = (SHIFT + WIDTH),
+ STORAGE_WIDTH = BYTE_WIDTH * sizeof(storage_t),
+ ARRAY_SIZE = (ITERATION_WIDTH * SUBREGS) >> BYTE_EXP,
+ };
+
+ /**
+ * Back reference to containing register
+ */
+ typedef Register Compound_reg;
+
+ /**
+ * Calculate the MMIO-relative offset 'offset' and shift 'shift'
+ * within the according 'storage_t' value to acces subreg no. 'index'
+ */
+ inline static void access_dest(off_t & offset, unsigned long & shift,
+ unsigned long const index);
+ };
+ };
+
+ /**
+ * An array of 'REGS' many similar 'Register's
+ */
+ template
+ struct Reg_array : public Register,
+ public Array
+ { };
+
+ addr_t const base;
+
+ /**
+ * Constructor
+ */
+ inline Mmio(addr_t mmio_base);
+
+ /**
+ * Typed address of register 'REGISTER'
+ */
+ template
+ inline typename REGISTER::storage_t volatile * typed_addr() const;
+
+ /**
+ * Read the whole register 'REGISTER'
+ */
+ template
+ inline typename REGISTER::storage_t read() const;
+
+ /**
+ * Read the subreg 'SUBREG'
+ */
+ template
+ inline typename SUBREG::Compound_reg::storage_t read() const;
+
+ /**
+ * Read the whole register no. 'index' of the array 'REG_ARRAY'
+ */
+ template
+ inline typename REG_ARRAY::storage_t read(unsigned long const index) const;
+
+ /**
+ * Read the subreg no. 'index' of the array 'SUBREG_ARRAY'
+ */
+ template
+ inline typename SUBREG_ARRAY::Compound_reg::storage_t read(unsigned long const index);
+
+ /**
+ * Write 'value' into the register 'REGISTER'
+ */
+ template
+ inline void write(typename REGISTER::storage_t const value);
+
+ /**
+ * Write 'value' into the register no. 'index' of the array 'REG_ARRAY'
+ */
+ template
+ inline void write(typename REG_ARRAY::storage_t const value,
+ unsigned long const index);
+
+ /**
+ * Write 'value' into the subregister 'SUBREG'
+ */
+ template
+ inline void write(typename SUBREG::Compound_reg::storage_t const value);
+
+ /**
+ * Write 'value' into the bitfield no. 'index' of the array 'SUBREG_ARRAY'
+ */
+ template
+ inline void write(typename SUBREG_ARRAY::Compound_reg::storage_t const value,
+ unsigned long const index);
+ };
+}
+
+
+template
+template
+void
+Genode::Mmio::Register::Subreg_array::access_dest(Genode::off_t & offset,
+ unsigned long & shift,
+ unsigned long const index)
+{
+ unsigned long const bit_off = (index+1) * ITERATION_WIDTH - WIDTH;
+ offset = (off_t) ((bit_off / STORAGE_WIDTH) * sizeof(storage_t));
+ shift = bit_off - ( offset << BYTE_EXP );
+ offset += Compound_reg::OFFSET;
+}
+
+
+template
+void Genode::Mmio::_write(off_t const o, STORAGE_T const value)
+{
+ *(STORAGE_T volatile *)((addr_t)base + o) = value;
+}
+
+
+template
+STORAGE_T Genode::Mmio::_read(off_t const o) const
+{
+ return *(STORAGE_T volatile *)((addr_t)base + o);
+}
+
+
+Genode::Mmio::Mmio(addr_t mmio_base) : base(mmio_base) { }
+
+
+template
+typename REGISTER::storage_t volatile * Genode::Mmio::typed_addr() const
+{
+ return (typename REGISTER::storage_t volatile *)base + REGISTER::OFFSET;
+}
+
+
+template
+typename REGISTER::storage_t Genode::Mmio::read() const
+{
+ return _read(REGISTER::OFFSET);
+}
+
+
+template
+typename SUBREG::Compound_reg::storage_t Genode::Mmio::read() const
+{
+ typedef typename SUBREG::Compound_reg Register;
+ typedef typename Register::storage_t storage_t;
+
+ return (_read(Register::OFFSET) >> SUBREG::SHIFT) & SUBREG::MASK;
+}
+
+
+template
+typename REG_ARRAY::storage_t Genode::Mmio::read(unsigned long const index) const
+{
+ typedef typename REG_ARRAY::storage_t storage_t;
+
+ if (index > REG_ARRAY::MAX_INDEX) return 0;
+
+ addr_t const offset = REG_ARRAY::OFFSET + index*sizeof(storage_t);
+ return _read(offset);
+}
+
+
+template
+typename SUBREG_ARRAY::Compound_reg::storage_t Genode::Mmio::read(unsigned long const index)
+{
+ enum { MASK = SUBREG_ARRAY::MASK };
+
+ typedef typename SUBREG_ARRAY::Compound_reg Register;
+ typedef typename Register::storage_t storage_t;
+
+ if (index > SUBREG_ARRAY::MAX_INDEX) return;
+
+ off_t const offset = Register::OFFSET + SUBREG_ARRAY::access_off(index);
+ unsigned long const shift = SUBREG_ARRAY::access_shift(index);
+
+ return (_read(offset) >> shift) & MASK;
+}
+
+
+template
+void Genode::Mmio::write(typename REGISTER::storage_t const value)
+{
+ _write(REGISTER::OFFSET, value);
+}
+
+
+template
+void Genode::Mmio::write(typename REG_ARRAY::storage_t const value,
+ unsigned long const index)
+{
+ typedef typename REG_ARRAY::storage_t storage_t;
+
+ if (index > REG_ARRAY::MAX_INDEX) return;
+
+ addr_t const offset = REG_ARRAY::OFFSET + index*sizeof(storage_t);
+ _write(offset, value);
+}
+
+
+template
+void Genode::Mmio::write(typename SUBREG::Compound_reg::storage_t const value)
+{
+ typedef typename SUBREG::Compound_reg Register;
+ typedef typename Register::storage_t storage_t;
+
+ storage_t new_reg = read();
+
+ new_reg &= ~(SUBREG::MASK << SUBREG::SHIFT);
+ new_reg |= (value & SUBREG::MASK) << SUBREG::SHIFT;
+
+ write(new_reg);
+}
+
+
+template
+void Genode::Mmio::write(typename SUBREG_ARRAY::Compound_reg::storage_t const value,
+ unsigned long const index)
+{
+ enum { MASK = SUBREG_ARRAY::MASK };
+
+ typedef typename SUBREG_ARRAY::Compound_reg Register;
+ typedef typename Register::storage_t storage_t;
+
+ if (index > SUBREG_ARRAY::MAX_INDEX) return;
+
+ off_t offset;
+ unsigned long shift;
+ SUBREG_ARRAY::access_dest(offset, shift, index);
+
+ storage_t new_field = _read(offset);
+ new_field &= ~(MASK << shift);
+ new_field |= (value & MASK) << shift;
+
+ _write(offset, new_field);
+}
+
+
+#endif /* _BASE__INCLUDE__UTIL__MMIO_H_ */
diff --git a/base/src/test/util_mmio/main.cc b/base/src/test/util_mmio/main.cc
new file mode 100644
index 0000000000..5534805133
--- /dev/null
+++ b/base/src/test/util_mmio/main.cc
@@ -0,0 +1,19 @@
+/*
+ * \brief Basic test for MMIO access framework
+ * \author Christian Helmuth
+ * \date 2012-01-09
+ */
+
+/*
+ * Copyright (C) 2011-2012 Genode Labs GmbH
+ *
+ * This file is part of the Genode OS framework, which is distributed
+ * under the terms of the GNU General Public License version 2.
+ */
+
+#include
+
+
+int main()
+{
+}
diff --git a/base/src/test/util_mmio/target.mk b/base/src/test/util_mmio/target.mk
new file mode 100644
index 0000000000..42246e1dae
--- /dev/null
+++ b/base/src/test/util_mmio/target.mk
@@ -0,0 +1,4 @@
+TARGET = test-util_mmio
+SRC_CC = main.cc
+
+LIBS = cxx env