/* * \brief Type-safe, fine-grained access to a continuous MMIO region * \author Martin stein * \date 2011-10-26 */ /* * Copyright (C) 2011-2017 Genode Labs GmbH * * This file is part of the Genode OS framework, which is distributed * under the terms of the GNU Affero General Public License version 3. */ #ifndef _INCLUDE__UTIL__MMIO_H_ #define _INCLUDE__UTIL__MMIO_H_ /* Genode includes */ #include #include #include namespace Genode { class Mmio_plain_access; template class Mmio; } /** * Plain access implementation for MMIO */ class Genode::Mmio_plain_access { friend Register_set_plain_access; private: Byte_range_ptr const _range; /** * Write 'ACCESS_T' typed 'value' to MMIO base + 'offset' */ template inline void _write(off_t const offset, ACCESS_T const value) { *(ACCESS_T volatile *)(_range.start + offset) = value; } /** * Read 'ACCESS_T' typed from MMIO base + 'offset' */ template inline ACCESS_T _read(off_t const &offset) const { return *(ACCESS_T volatile *)(_range.start + offset); } public: /** * Constructor * * \param base base address of targeted MMIO region */ Mmio_plain_access(Byte_range_ptr const &range) : _range(range.start, range.num_bytes) { } Byte_range_ptr range_at(off_t offset) const { return {_range.start + offset, _range.num_bytes - offset}; } Byte_range_ptr range() const { return range_at(0); } addr_t base() const { return (addr_t)range().start; } }; /** * Type-safe, fine-grained access to a continuous MMIO region * * For further details refer to the documentation of the 'Register_set' class. */ template struct Genode::Mmio : Mmio_plain_access, Register_set { static constexpr size_t SIZE = MMIO_SIZE; class Range_violation : Exception { }; /** * Constructor * * \param range byte range of targeted MMIO region */ Mmio(Byte_range_ptr const &range) : Mmio_plain_access(range), Register_set(*static_cast(this)) { if (range.num_bytes < SIZE) { error("MMIO range is unexpectedly too small"); throw Range_violation { }; } } }; #endif /* _INCLUDE__UTIL__MMIO_H_ */