Hello Genodians
What's the best way to handle multiple sets of identical registers on a hardware device?
In my current use case the device offers multiple DMA engines each of which has a complex set of registers to set up. Each register is located at base device address + base engine address + register offset so uniform handling should be easy.
I handle the device itself and the shared registers using Platform::Device::Mmio.
For the registers associated with each DMA engine I have tried:
a) A template class providing a base offset as the template parameter. This is unsatisfactory however, as there is no common base class providing access to the registers for the software to be agnostic to which engine it handles.
b) A separate class derived from Genode::Mmio. This looks promising, but the Platform::Device::Mmio unfortunatly offers no public accessor to the device base address so I cannot provide the base device address + base engine address to my engine mmio class.
Any suggestions?
Kind regards Stefan
Hi Stefan,
On 9/2/21 3:28 PM, Stefan Thöni wrote:
Hello Genodians
What's the best way to handle multiple sets of identical registers on a hardware device?
In my current use case the device offers multiple DMA engines each of which has a complex set of registers to set up. Each register is located at base device address + base engine address + register offset so uniform handling should be easy.
I handle the device itself and the shared registers using Platform::Device::Mmio.
For the registers associated with each DMA engine I have tried:
a) A template class providing a base offset as the template parameter. This is unsatisfactory however, as there is no common base class providing access to the registers for the software to be agnostic to which engine it handles.
b) A separate class derived from Genode::Mmio. This looks promising, but the Platform::Device::Mmio unfortunatly offers no public accessor to the device base address so I cannot provide the base device address + base engine address to my engine mmio class.
Any suggestions?
When using (b) you can use the. Platform::Device::Mmio::local_addr<> template to pass the address of the locally mapped device resources to a class derived from Genode::Mmio as a base address.
So something like:
! struct Dma_engine : Genode::Mmio ! { ! Dma_engine(addr_t const base) : Mmio(base) { } ! /* from here you only deal with offsets */ ! }; ! ! Platform::Device _dev { <Platform connection>, <Type> }; ! Platform::Device::Mmio _io_mem { _dev }; ! Dma_engine _engine ! { (addr_t)_io_mem.local_addr<addr_t>(); }
should do the trick.
Sebastian