From: Peter Crosthwaite <peter.crosthwa...@xilinx.com> Add memory io handlers that glue the register API to the memory API. Just translation functions at this stage. Although it does allow for devices to be created without all-in-one mmio r/w handlers.
Signed-off-by: Peter Crosthwaite <peter.crosthwa...@xilinx.com> --- changed from v2: Added fast path to register_write_memory to skip endianness bitbashing hw/core/register.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ include/hw/register.h | 12 ++++++++++++ 2 files changed, 60 insertions(+) diff --git a/hw/core/register.c b/hw/core/register.c index b10212e..e743f16 100644 --- a/hw/core/register.c +++ b/hw/core/register.c @@ -188,3 +188,51 @@ void register_reset(RegisterInfo *reg) register_write_val(reg, reg->access->reset); } + +static inline void register_write_memory(void *opaque, hwaddr addr, + uint64_t value, unsigned size, bool be) +{ + RegisterInfo *reg = opaque; + uint64_t we = ~0; + int shift = 0; + + if (reg->data_size != size) { + we = (size == 8) ? ~0ull : (1ull << size * 8) - 1; + shift = 8 * (be ? reg->data_size - size - addr : addr); + } + + assert(size + addr <= reg->data_size); + register_write(reg, value << shift, we << shift); +} + +void register_write_memory_be(void *opaque, hwaddr addr, uint64_t value, + unsigned size) +{ + register_write_memory(opaque, addr, value, size, true); +} + + +void register_write_memory_le(void *opaque, hwaddr addr, uint64_t value, + unsigned size) +{ + register_write_memory(opaque, addr, value, size, false); +} + +static inline uint64_t register_read_memory(void *opaque, hwaddr addr, + unsigned size, bool be) +{ + RegisterInfo *reg = opaque; + int shift = 8 * (be ? reg->data_size - size - addr : addr); + + return register_read(reg) >> shift; +} + +uint64_t register_read_memory_be(void *opaque, hwaddr addr, unsigned size) +{ + return register_read_memory(opaque, addr, size, true); +} + +uint64_t register_read_memory_le(void *opaque, hwaddr addr, unsigned size) +{ + return register_read_memory(opaque, addr, size, false); +} diff --git a/include/hw/register.h b/include/hw/register.h index a4a8319..4333cd7 100644 --- a/include/hw/register.h +++ b/include/hw/register.h @@ -85,6 +85,8 @@ struct RegisterAccessInfo { * @prefix: String prefix for log and debug messages * * @opaque: Opaque data for the register + * + * @mem: optional Memory region for the register */ struct RegisterInfo { @@ -100,6 +102,8 @@ struct RegisterInfo { /* private */ bool read_lite; bool write_lite; + + MemoryRegion mem; }; /** @@ -126,4 +130,12 @@ uint64_t register_read(RegisterInfo *reg); void register_reset(RegisterInfo *reg); +void register_write_memory_be(void *opaque, hwaddr addr, uint64_t value, + unsigned size); +void register_write_memory_le(void *opaque, hwaddr addr, uint64_t value, + unsigned size); + +uint64_t register_read_memory_be(void *opaque, hwaddr addr, unsigned size); +uint64_t register_read_memory_le(void *opaque, hwaddr addr, unsigned size); + #endif -- 1.8.3.rc1.44.gb387c77.dirty