Extract more generic parts from 'Genode::Mmio'

To accommodate CPU registers, which have a structured layout but don't
depend on a region base address, this patch introduces the generic
'Genode::Register' and 'Genode::Subreg' to 'register.h'.
'Mmio::Register' and 'Mmio::Subreg' inherit from them.
This commit is contained in:
Martin Stein 2012-01-09 21:05:49 +01:00 committed by Norman Feske
parent 1f75ebe9e5
commit 9329b91aca
2 changed files with 77 additions and 24 deletions

View File

@ -7,7 +7,7 @@
#ifndef _BASE__INCLUDE__UTIL__MMIO_H_ #ifndef _BASE__INCLUDE__UTIL__MMIO_H_
#define _BASE__INCLUDE__UTIL__MMIO_H_ #define _BASE__INCLUDE__UTIL__MMIO_H_
#include <base/stdint.h> #include <util/register.h>
namespace Genode namespace Genode
@ -45,40 +45,24 @@ namespace Genode
* A POD-like region at offset 'MMIO_OFFSET' within a MMIO region * A POD-like region at offset 'MMIO_OFFSET' within a MMIO region
*/ */
template <off_t MMIO_OFFSET, typename STORAGE_T> template <off_t MMIO_OFFSET, typename STORAGE_T>
struct Register struct Register : public Genode::Register<STORAGE_T>
{ {
typedef STORAGE_T storage_t;
enum { OFFSET = MMIO_OFFSET }; enum { OFFSET = MMIO_OFFSET };
/** /**
* A bitregion within a register * A bitregion within a register
*/ */
template <unsigned long BIT_SHIFT, unsigned long BIT_SIZE> template <unsigned long BIT_SHIFT, unsigned long BIT_SIZE>
struct Subreg struct Subreg : public Genode::Register<STORAGE_T>::template Subreg<BIT_SHIFT, BIT_SIZE>
{ {
enum {
SHIFT = BIT_SHIFT,
WIDTH = BIT_SIZE,
MASK = (1 << WIDTH) - 1,
};
/** /**
* Back reference to containing register * Back reference to containing register
*/ */
typedef Register<OFFSET, storage_t> Compound_reg; typedef Register<OFFSET, STORAGE_T> 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 * An array of 'SUBREGS' many similar bitregions with distance 'BIT_SHIFT'
* FIXME: Side effects of a combination of 'Reg_array' and 'Subreg_array' * FIXME: Side effects of a combination of 'Reg_array' and 'Subreg_array'
* are not evaluated * are not evaluated
*/ */
@ -90,14 +74,14 @@ namespace Genode
WIDTH = BIT_SIZE, WIDTH = BIT_SIZE,
MASK = (1 << WIDTH) - 1, MASK = (1 << WIDTH) - 1,
ITERATION_WIDTH = (SHIFT + WIDTH), ITERATION_WIDTH = (SHIFT + WIDTH),
STORAGE_WIDTH = BYTE_WIDTH * sizeof(storage_t), STORAGE_WIDTH = BYTE_WIDTH * sizeof(STORAGE_T),
ARRAY_SIZE = (ITERATION_WIDTH * SUBREGS) >> BYTE_EXP, ARRAY_SIZE = (ITERATION_WIDTH * SUBREGS) >> BYTE_EXP,
}; };
/** /**
* Back reference to containing register * Back reference to containing register
*/ */
typedef Register<OFFSET, storage_t> Compound_reg; typedef Register<OFFSET, STORAGE_T> Compound_reg;
/** /**
* Calculate the MMIO-relative offset 'offset' and shift 'shift' * Calculate the MMIO-relative offset 'offset' and shift 'shift'
@ -190,7 +174,7 @@ Genode::Mmio::Register<OFFSET, STORAGE_T>::Subreg_array<BIT_SHIFT, BIT_SIZE, SUB
unsigned long const index) unsigned long const index)
{ {
unsigned long const bit_off = (index+1) * ITERATION_WIDTH - WIDTH; unsigned long const bit_off = (index+1) * ITERATION_WIDTH - WIDTH;
offset = (off_t) ((bit_off / STORAGE_WIDTH) * sizeof(storage_t)); offset = (off_t) ((bit_off / STORAGE_WIDTH) * sizeof(STORAGE_T));
shift = bit_off - ( offset << BYTE_EXP ); shift = bit_off - ( offset << BYTE_EXP );
offset += Compound_reg::OFFSET; offset += Compound_reg::OFFSET;
} }
@ -325,3 +309,4 @@ void Genode::Mmio::write(typename SUBREG_ARRAY::Compound_reg::storage_t const va
#endif /* _BASE__INCLUDE__UTIL__MMIO_H_ */ #endif /* _BASE__INCLUDE__UTIL__MMIO_H_ */

View File

@ -0,0 +1,68 @@
/*
* \brief Generic accessor framework for highly structured memory regions
* \author Martin stein
* \date 2011-11-10
*/
#ifndef _BASE__INCLUDE__UTIL__REGISTER_H_
#define _BASE__INCLUDE__UTIL__REGISTER_H_
#include <base/stdint.h>
namespace Genode
{
/**
* A POD-like highly structured memory region
*/
template <typename STORAGE_T>
struct Register
{
typedef STORAGE_T storage_t;
/**
* A bitregion within a register
*/
template <unsigned long BIT_SHIFT, unsigned long BIT_SIZE>
struct Subreg
{
enum {
SHIFT = BIT_SHIFT,
WIDTH = BIT_SIZE,
MASK = (1 << WIDTH) - 1,
};
/**
* Back reference to containing register
*/
typedef Register<storage_t> 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; }
/**
* Get value of this subreg from 'reg'
*/
static storage_t value(storage_t const reg) { return (reg >> SHIFT) & MASK; }
/**
* Get registervalue 'reg' with this subreg set to zero
*/
static void clear_bits(storage_t & reg) { reg &= ~(MASK << SHIFT); }
/**
* Get registervalue 'reg' with this subreg set to 'value'
*/
static void set_bits(storage_t & reg, storage_t const value = ~0)
{
clear_bits(reg);
reg |= (value & MASK) << SHIFT;
};
};
};
}
#endif /* _BASE__INCLUDE__UTIL__CPU_REGISTER_H_ */