Il 29/05/2013 15:54, Peter Crosthwaite ha scritto:
> Hi Paolo,
> 
> On Wed, May 29, 2013 at 6:51 PM, Paolo Bonzini <pbonz...@redhat.com> wrote:
>> Il 24/05/2013 07:49, peter.crosthwa...@xilinx.com ha scritto:
>>> +static const MemoryRegionOps devcfg_reg_ops = {
>>> +    .read = register_read_memory_le,
>>> +    .write = register_write_memory_le,
>>> +    .endianness = DEVICE_LITTLE_ENDIAN,
>>> +    .valid = {
>>> +        .min_access_size = 4,
>>> +        .max_access_size = 4,
>>
>> What happens if you have registers of mixed size within the same "bank"?
>>
> 
> You Probably should change these access restrictions per-register
> accordingly.

Can you add a generic .valid.accepts callback for the register API that
will check against the size of the register at that offset?

> The degenerate case is allowing greater-than-register size or
> misaligned accesses, which is dependent on the behaviour of the memory
> API. I can do some research, but do you know if the memory API
> supports misaligned transactions that span a memory region boundary?

I don't really care about that for now.

But the way to do that would be to add a .impl.accepts method (right now
there's only .valid.accepts).  Then you would point the register API's
implementation to .impl.accepts, and use

    .impl.accepts = register_accepts,
    .valid = {
         .min_access_size = 1,
         .max_access_size = 4,
     }

The memory API will do a RMW operation if needed.  Won't make much sense
with write-1-clear bits and the like, but for simple registers it would
work.

Paolo

> If so then there are no concerns, as the memory API will handle it for
> us. If not then I don't see it as an issue as its very rare (at least
> in my experience) for registers to support such strange misaligned or
> mulit-register accesses. That or we can look into memory API for
> answers.
> 
>>> +    }
>>> +};
>>> +
>>> +static void xilinx_devcfg_realize(DeviceState *dev, Error **errp)
>>> +{
>>> +    XilinxDevcfg *s = XILINX_DEVCFG(dev);
>>> +    const char *prefix = object_get_canonical_path(OBJECT(dev));
>>> +    int i;
>>> +
>>> +    for (i = 0; i < R_MAX; ++i) {
>>> +        RegisterInfo *r = &s->regs_info[i];
>>> +
>>> +        *r = (RegisterInfo) {
>>> +            .data = &s->regs[i],
>>> +            .data_size = sizeof(uint32_t),
>>> +            .access = &xilinx_devcfg_regs_info[i],
>>> +            .debug = XILINX_DEVCFG_ERR_DEBUG,
>>> +            .prefix = prefix,
>>> +            .opaque = s,
>>> +        };
>>> +        memory_region_init_io(&r->mem, &devcfg_reg_ops, r, "devcfg-regs", 
>>> 4);
>>
>> Could you add a register_init function that does register_reset +
>> memory_region_init_io?
>>
> 
> I wanted to factor this loop out into a helper as a next step so I
> think its already in my todo list, but i'm confused as to why reset
> and memory_region_init would bundled together - arent they normally in
> Device::reset and Device::realize (or Object::Init) respectively?
> 
> Regards,
> Peter
> 
>>> +        memory_region_add_subregion(&s->iomem, i * 4, &r->mem);
>>
>> Paolo
>>


Reply via email to