diff --git a/base/include/util/mmio.h b/base/include/util/mmio.h index e1fd8a15ba..7ab8933ca4 100644 --- a/base/include/util/mmio.h +++ b/base/include/util/mmio.h @@ -29,21 +29,67 @@ namespace Genode */ class Mmio { + /* + * If set 0 verbosity isn't needed at all and the enum enables the + * compiler to remove all verbosity code. If set 1 verbosity code + * gets compiled and is then switched via '*_verbose' member variables. + */ + enum { VERBOSITY_AVAILABLE = 0 }; + + /** + * Proclaim a MMIO access + * + * \param _ACCESS_T integer type of access + * \param dst access destination + * \param v access value + * \param w 1: write access 0: read access + */ + template + inline void _access_verbosity(addr_t const dst, _ACCESS_T const v, + bool const w) const + { + if (!VERBOSITY_AVAILABLE) return; + if (!_write_verbose) return; + printf("mmio %s 0x%p: 0x", w ? "write" : "read ", (void *)dst); + Trait::Uint_type<_ACCESS_T>::print_hex(v); + printf("\n"); + } + + /** + * Write '_ACCESS_T' typed 'value' to MMIO base + 'o' + */ + template + inline void _write(off_t const o, _ACCESS_T const value) + { + addr_t const dst = (addr_t)base + o; + _access_verbosity<_ACCESS_T>(dst, value, 1); + *(_ACCESS_T volatile *)dst = value; + } + + /** + * Read '_ACCESS_T' typed from MMIO base + 'o' + */ + template + inline _ACCESS_T _read(off_t const o) const + { + addr_t const dst = (addr_t)base + o; + _ACCESS_T const value = *(_ACCESS_T volatile *)dst; + _access_verbosity<_ACCESS_T>(dst, value, 0); + return value; + } + protected: - /** - * Write typed 'value' to MMIO base + 'o' + /* + * If VERBOSITY_AVAILABLE is set MMIO isn't verbose by default. + * Instead it causes this switches to be asked everytime MMIO + * could be verbose. This way the user can either enable verbosity + * locally by overwriting them in a deriving class or change their + * initialization temporarily to enable verbosity globally and + * then supress it locally by overwriting it. */ - template - inline void _write(off_t const o, _ACCESS_T const value) - { *(_ACCESS_T volatile *)((addr_t)base + o) = value; } - - /** - * Read typed from MMIO base + 'o' - */ - template - inline _ACCESS_T _read(off_t const o) const - { return *(_ACCESS_T volatile *)((addr_t)base + o); } + bool _write_verbose; + bool _read_verbose; public: @@ -151,7 +197,7 @@ namespace Genode struct Register_array : public Register<_OFFSET, _ACCESS_WIDTH, _STRICT_WRITE> { - typedef typename Trait::Uint_type<_ACCESS_WIDTH>:: + typedef typename Trait::Uint_width<_ACCESS_WIDTH>:: template Divisor<_ITEM_WIDTH> Item; enum { @@ -240,7 +286,8 @@ namespace Genode * * \param mmio_base base address of targeted MMIO region */ - inline Mmio(addr_t mmio_base) : base(mmio_base) { } + inline Mmio(addr_t mmio_base) + : _write_verbose(0), _read_verbose(0), base(mmio_base) { } /************************* diff --git a/base/include/util/register.h b/base/include/util/register.h index 728a6e20b0..7546024e4a 100644 --- a/base/include/util/register.h +++ b/base/include/util/register.h @@ -16,6 +16,7 @@ /* Genode includes */ #include +#include namespace Genode { @@ -24,61 +25,76 @@ namespace Genode /** * Properties of integer types with a given bitwidth */ - template struct Uint_type; + template struct Uint_width; - /*************************************************************** - ** Provide the integer type and the width as exponent to the ** - ** base of 2 for all supported widths in 'Uint_type' ** - ***************************************************************/ - - template <> struct Uint_type<1> + template <> struct Uint_width<1> { typedef bool Type; enum { WIDTH_LOG2 = 0 }; /** - * Access widths, wich are dividers to the compound type width + * Access widths wich are dividers to the compound type width */ template struct Divisor; + + static inline void print_hex(bool const v) { + printf("%01x", v); } }; - template <> struct Uint_type<8> : Uint_type<1> + template <> struct Uint_width<8> : Uint_width<1> { typedef uint8_t Type; enum { WIDTH_LOG2 = 3 }; + + static inline void print_hex(uint8_t const v) { + printf("%02x", v); } }; - template <> struct Uint_type<16> : Uint_type<8> + template <> struct Uint_width<16> : Uint_width<8> { typedef uint16_t Type; enum { WIDTH_LOG2 = 4 }; + + static inline void print_hex(uint16_t const v) { + printf("%04x", v); } }; - template <> struct Uint_type<32> : Uint_type<16> + template <> struct Uint_width<32> : Uint_width<16> { typedef uint32_t Type; enum { WIDTH_LOG2 = 5 }; + + static inline void print_hex (uint32_t const v) { + printf("%08x", v); } }; - template <> struct Uint_type<64> : Uint_type<32> + template <> struct Uint_width<64> : Uint_width<32> { typedef uint64_t Type; enum { WIDTH_LOG2 = 6 }; + + static inline void print_hex(uint64_t const v) { + printf("%016llx", v); } }; + template <> struct Uint_width<1>::Divisor<1> { enum { WIDTH_LOG2 = 0 }; }; + template <> struct Uint_width<8>::Divisor<2> { enum { WIDTH_LOG2 = 1 }; }; + template <> struct Uint_width<8>::Divisor<4> { enum { WIDTH_LOG2 = 2 }; }; + template <> struct Uint_width<8>::Divisor<8> { enum { WIDTH_LOG2 = 3 }; }; + template <> struct Uint_width<16>::Divisor<16> { enum { WIDTH_LOG2 = 4 }; }; + template <> struct Uint_width<32>::Divisor<32> { enum { WIDTH_LOG2 = 5 }; }; + template <> struct Uint_width<64>::Divisor<64> { enum { WIDTH_LOG2 = 6 }; }; - /******************************************************************** - ** Provide widths as exponents to the base of 2 for all supported ** - ** access widths in 'Uint_type::Divisor' ** - ********************************************************************/ + /** + * Reference 'Uint_width' through typenames + */ + template struct Uint_type; - template <> struct Uint_type<1>::Divisor<1> { enum { WIDTH_LOG2 = 0 }; }; - template <> struct Uint_type<8>::Divisor<2> { enum { WIDTH_LOG2 = 1 }; }; - template <> struct Uint_type<8>::Divisor<4> { enum { WIDTH_LOG2 = 2 }; }; - template <> struct Uint_type<8>::Divisor<8> { enum { WIDTH_LOG2 = 3 }; }; - template <> struct Uint_type<16>::Divisor<16> { enum { WIDTH_LOG2 = 4 }; }; - template <> struct Uint_type<32>::Divisor<32> { enum { WIDTH_LOG2 = 5 }; }; - template <> struct Uint_type<64>::Divisor<64> { enum { WIDTH_LOG2 = 6 }; }; + template <> struct Uint_type : Uint_width<1> { }; + template <> struct Uint_type : Uint_width<8> { }; + template <> struct Uint_type : Uint_width<16> { }; + template <> struct Uint_type : Uint_width<32> { }; + template <> struct Uint_type : Uint_width<64> { }; } /** @@ -96,11 +112,10 @@ namespace Genode { enum { ACCESS_WIDTH = _ACCESS_WIDTH, - - ACCESS_WIDTH_LOG2 = Trait::Uint_type::WIDTH_LOG2, + ACCESS_WIDTH_LOG2 = Trait::Uint_width::WIDTH_LOG2, }; - typedef typename Trait::Uint_type::Type access_t; + typedef typename Trait::Uint_width::Type access_t; /** * A bitregion within a register