Hi Mark,

On 11/11/2021 10:49 PM, Mark Cave-Ayland wrote:
> On 11/11/2021 01:35, Xiaojuan Yang wrote:
> 
>> This patch realize the EIOINTC interrupt controller.
>>
>> Signed-off-by: Xiaojuan Yang <yangxiaoj...@loongson.cn>
>> Signed-off-by: Song Gao <gaos...@loongson.cn>
>> ---
>>   hw/intc/Kconfig                    |   3 +
>>   hw/intc/loongarch_extioi.c         | 570 +++++++++++++++++++++++++++++
>>   hw/intc/meson.build                |   1 +
>>   hw/loongarch/Kconfig               |   1 +
>>   include/hw/intc/loongarch_extioi.h |  99 +++++
>>   include/hw/loongarch/loongarch.h   |   1 +
>>   6 files changed, 675 insertions(+)
>>   create mode 100644 hw/intc/loongarch_extioi.c
>>   create mode 100644 include/hw/intc/loongarch_extioi.h
>>
>> diff --git a/hw/intc/Kconfig b/hw/intc/Kconfig
>> index c0dc12dfa0..a2d9efd5aa 100644
>> --- a/hw/intc/Kconfig
>> +++ b/hw/intc/Kconfig
>> @@ -82,3 +82,6 @@ config LOONGARCH_PCH_MSI
>>       select MSI_NONBROKEN
>>       bool
>>       select UNIMP
>> +
>> +config LOONGARCH_EXTIOI
>> +    bool
>> diff --git a/hw/intc/loongarch_extioi.c b/hw/intc/loongarch_extioi.c
>> new file mode 100644
>> index 0000000000..592cd8d1e2
>> --- /dev/null
>> +++ b/hw/intc/loongarch_extioi.c
>> @@ -0,0 +1,570 @@
>> +/* SPDX-License-Identifier: GPL-2.0-or-later */
>> +/*
>> + * Loongson 3A5000 ext interrupt controller emulation
>> + *
>> + * Copyright (C) 2021 Loongson Technology Corporation Limited
>> + */
>> +
>> +#include "qemu/osdep.h"
>> +#include "qemu/module.h"
>> +#include "qemu/log.h"
>> +#include "hw/irq.h"
>> +#include "hw/sysbus.h"
>> +#include "hw/loongarch/loongarch.h"
>> +#include "hw/qdev-properties.h"
>> +#include "exec/address-spaces.h"
>> +#include "hw/intc/loongarch_extioi.h"
>> +#include "migration/vmstate.h"
>> +
>> +#define DEBUG_APIC 0
>> +
>> +#define DPRINTF(fmt, ...) \
>> +do { \
>> +    if (DEBUG_APIC) { \
>> +        fprintf(stderr, "APIC: " fmt , ## __VA_ARGS__); \
>> +    } \
>> +} while (0)
> 
> Again please use trace-events insead of DPRINTF().
> 
>> +static void extioi_update_irq(void *opaque, int irq_num, int level)
>> +{
>> +    loongarch_extioi *s = opaque;
>> +    uint8_t  ipnum, cpu;
>> +    unsigned long found1, found2;
>> +
>> +    ipnum = s->sw_ipmap[irq_num];
>> +    cpu   = s->sw_coremap[irq_num];
>> +    if (level == 1) {
>> +        if (test_bit(irq_num, (void *)s->en_reg8) == false) {
>> +            return;
>> +        }
>> +        bitmap_set((void *)s->coreisr_reg8[cpu], irq_num, 1);
>> +        found1 = find_next_bit((void *)&(s->sw_ipisr[cpu][ipnum]),
>> +                               EXTIOI_IRQS, 0);
>> +        bitmap_set((void *)&(s->sw_ipisr[cpu][ipnum]), irq_num, 1);
>> +
>> +        if (found1 >= EXTIOI_IRQS) {
>> +            qemu_set_irq(s->parent_irq[cpu][ipnum], level);
>> +        }
>> +    } else {
>> +        bitmap_clear((void *)s->coreisr_reg8[cpu], irq_num, 1);
>> +        found1 = find_next_bit((void *)&(s->sw_ipisr[cpu][ipnum]),
>> +                               EXTIOI_IRQS, 0);
>> +        bitmap_clear((void *)&(s->sw_ipisr[cpu][ipnum]), irq_num, 1);
>> +        found2 = find_next_bit((void *)&(s->sw_ipisr[cpu][ipnum]),
>> +                               EXTIOI_IRQS, 0);
>> +
>> +        if ((found1 < EXTIOI_IRQS) && (found2 >= EXTIOI_IRQS)) {
>> +            qemu_set_irq(s->parent_irq[cpu][ipnum], level);
>> +        }
>> +    }
>> +}
>> +
>> +static void extioi_setirq(void *opaque, int irq, int level)
>> +{
>> +    loongarch_extioi *s = opaque;
>> +    extioi_update_irq(s, irq, level);
>> +}
>> +
>> +static void extioi_handler(void *opaque, int irq, int level)
>> +{
>> +    loongarch_extioi *extioi = (loongarch_extioi *)opaque;
>> +
>> +    qemu_set_irq(extioi->irq[irq], level);
>> +}
>> +
>> +static uint32_t extioi_readb(void *opaque, hwaddr addr)
>> +{
>> +    loongarch_extioi *state = opaque;
> 
> Add a QOM cast here.
> 
>> +    unsigned long offset, reg_count;
>> +    uint8_t ret;
>> +    int cpu;
>> +
>> +    offset = addr & 0xffff;
>> +
>> +    if ((offset >= EXTIOI_ENABLE_START) && (offset < EXTIOI_ENABLE_END)) {
>> +        reg_count = (offset - EXTIOI_ENABLE_START);
>> +        ret = state->en_reg8[reg_count];
>> +    } else if ((offset >= EXTIOI_BOUNCE_START) &&
>> +               (offset < EXTIOI_BOUNCE_END)) {
>> +        reg_count = (offset - EXTIOI_BOUNCE_START);
>> +        ret = state->bounce_reg8[reg_count];
>> +    } else if ((offset >= EXTIOI_COREISR_START) &&
>> +               (offset < EXTIOI_COREISR_END)) {
>> +        reg_count = ((offset - EXTIOI_COREISR_START) & 0x1f);
>> +        cpu = ((offset - EXTIOI_COREISR_START) >> 8) & 0x3;
>> +        ret = state->coreisr_reg8[cpu][reg_count];
>> +    } else if ((offset >= EXTIOI_IPMAP_START) &&
>> +               (offset < EXTIOI_IPMAP_END)) {
>> +        reg_count = (offset - EXTIOI_IPMAP_START);
>> +        ret = state->ipmap_reg8[reg_count];
>> +    } else if ((offset >= EXTIOI_COREMAP_START) &&
>> +               (offset < EXTIOI_COREMAP_END)) {
>> +        reg_count = (offset - EXTIOI_COREMAP_START);
>> +        ret = state->coremap_reg8[reg_count];
>> +    } else if ((offset >= EXTIOI_NODETYPE_START) &&
>> +               (offset < EXTIOI_NODETYPE_END)) {
>> +        reg_count = (offset - EXTIOI_NODETYPE_START);
>> +        ret = state->nodetype_reg8[reg_count];
>> +    }
>> +
>> +    DPRINTF("readb reg 0x" TARGET_FMT_plx " = %x\n", addr, ret);
>> +    return ret;
>> +}
>> +
>> +static uint32_t extioi_readw(void *opaque, hwaddr addr)
>> +{
>> +    loongarch_extioi *state = opaque;
> 
> And also a QOM cast here.
> 
>> +    unsigned long offset, reg_count;
>> +    uint32_t ret;
>> +    int cpu;
>> +
>> +    offset = addr & 0xffff;
>> +
>> +    if ((offset >= EXTIOI_ENABLE_START) && (offset < EXTIOI_ENABLE_END)) {
>> +        reg_count = (offset - EXTIOI_ENABLE_START) / 4;
>> +        ret = state->en_reg32[reg_count];
>> +    } else if ((offset >= EXTIOI_BOUNCE_START) &&
>> +               (offset < EXTIOI_BOUNCE_END)) {
>> +        reg_count = (offset - EXTIOI_BOUNCE_START) / 4;
>> +        ret = state->bounce_reg32[reg_count];
>> +    } else if ((offset >= EXTIOI_COREISR_START) &&
>> +               (offset < EXTIOI_COREISR_END)) {
>> +        reg_count = ((offset - EXTIOI_COREISR_START) & 0x1f) / 4;
>> +        cpu = ((offset - EXTIOI_COREISR_START) >> 8) & 0x3;
>> +        ret = state->coreisr_reg32[cpu][reg_count];
>> +    } else if ((offset >= EXTIOI_IPMAP_START) &&
>> +               (offset < EXTIOI_IPMAP_END)) {
>> +        reg_count = (offset - EXTIOI_IPMAP_START) / 4;
>> +        ret = state->ipmap_reg32[reg_count];
>> +    } else if ((offset >= EXTIOI_COREMAP_START) &&
>> +               (offset < EXTIOI_COREMAP_END)) {
>> +        reg_count = (offset - EXTIOI_COREMAP_START) / 4;
>> +        ret = state->coremap_reg32[reg_count];
>> +    } else if ((offset >= EXTIOI_NODETYPE_START) &&
>> +               (offset < EXTIOI_NODETYPE_END)) {
>> +        reg_count = (offset - EXTIOI_NODETYPE_START) / 4;
>> +        ret = state->nodetype_reg32[reg_count];
>> +    }
>> +
>> +    DPRINTF("readw reg 0x" TARGET_FMT_plx " = %x\n", addr, ret);
>> +    return ret;
>> +}
>> +
>> +static uint64_t extioi_readl(void *opaque, hwaddr addr)
>> +{
>> +    loongarch_extioi *state = opaque;
> 
> A QOM cast here too.
> 
>> +    unsigned long offset, reg_count;
>> +    uint64_t ret;
>> +    int cpu;
>> +
>> +    offset = addr & 0xffff;
>> +
>> +    if ((offset >= EXTIOI_ENABLE_START) && (offset < EXTIOI_ENABLE_END)) {
>> +        reg_count = (offset - EXTIOI_ENABLE_START) / 8;
>> +        ret = state->en_reg64[reg_count];
>> +    } else if ((offset >= EXTIOI_BOUNCE_START) &&
>> +               (offset < EXTIOI_BOUNCE_END)) {
>> +        reg_count = (offset - EXTIOI_BOUNCE_START) / 8;
>> +        ret = state->bounce_reg64[reg_count];
>> +    } else if ((offset >= EXTIOI_COREISR_START) &&
>> +               (offset < EXTIOI_COREISR_END)) {
>> +        reg_count = ((offset - EXTIOI_COREISR_START) & 0x1f) / 8;
>> +        cpu = ((offset - EXTIOI_COREISR_START) >> 8) & 0x3;
>> +        ret = state->coreisr_reg64[cpu][reg_count];
>> +    } else if ((offset >= EXTIOI_IPMAP_START) &&
>> +               (offset < EXTIOI_IPMAP_END)) {
>> +        ret = state->ipmap_reg64;
>> +    } else if ((offset >= EXTIOI_COREMAP_START) &&
>> +               (offset < EXTIOI_COREMAP_END)) {
>> +        reg_count = (offset - EXTIOI_COREMAP_START) / 8;
>> +        ret = state->coremap_reg64[reg_count];
>> +    } else if ((offset >= EXTIOI_NODETYPE_START) &&
>> +               (offset < EXTIOI_NODETYPE_END)) {
>> +        reg_count = (offset - EXTIOI_NODETYPE_START) / 8;
>> +        ret = state->nodetype_reg64[reg_count];
>> +    }
>> +
>> +    DPRINTF("readl reg 0x" TARGET_FMT_plx " = %lx\n", addr, ret);
>> +    return ret;
>> +}
>> +
>> +static void extioi_writeb(void *opaque, hwaddr addr, uint32_t val)
>> +{
>> +    loongarch_extioi *state = opaque;
> 
> And another cast.
> 
>> +    unsigned long offset, reg_count;
>> +    uint8_t old_data_u8;
>> +    int cpu, i, ipnum, level, mask, irqnum;
>> +
>> +    offset = addr & 0xffff;
>> +    val = val & 0xffUL;
>> +
>> +    if ((offset >= EXTIOI_ENABLE_START) && (offset < EXTIOI_ENABLE_END)) {
>> +        reg_count = (offset - EXTIOI_ENABLE_START);
>> +        old_data_u8 = state->en_reg8[reg_count];
>> +        if (old_data_u8 != val) {
>> +            state->en_reg8[reg_count] = val;
>> +            old_data_u8 = old_data_u8 ^ val;
>> +            mask = 0x1;
>> +
>> +            for (i = 0; i < 8; i++) {
>> +                if (old_data_u8 & mask) {
>> +                    level = !!(val & (0x1 << i));
>> +                    extioi_update_irq(state, i + reg_count * 8, level);
>> +                }
>> +                mask = mask << 1;
>> +            }
>> +        }
>> +    } else if ((offset >= EXTIOI_BOUNCE_START) &&
>> +               (offset < EXTIOI_BOUNCE_END)) {
>> +        reg_count = (offset - EXTIOI_BOUNCE_START);
>> +        state->bounce_reg8[reg_count] = val;
>> +    } else if ((offset >= EXTIOI_ISR_START) && (offset < EXTIOI_ISR_END)) {
>> +        /* Can not be writen */
>> +        reg_count = (offset - EXTIOI_ISR_START) & 0x1f;
>> +        old_data_u8 = state->isr_reg8[reg_count];
>> +        state->isr_reg8[reg_count] = old_data_u8 & (~val);
>> +
>> +        mask = 0x1;
>> +        for (i = 0; i < 8; i++) {
>> +            if ((old_data_u8 & mask) && (val & mask)) {
>> +                extioi_update_irq(state, i + reg_count * 8, 0);
>> +            }
>> +            mask = mask << 1;
>> +        }
>> +    } else if ((offset >= EXTIOI_COREISR_START) &&
>> +               (offset < EXTIOI_COREISR_END)) {
>> +        reg_count = (offset - EXTIOI_COREISR_START) & 0x1f;
>> +        cpu = ((offset - EXTIOI_COREISR_START) >> 8) & 0x3;
>> +
>> +        /* ext_isr */
>> +        old_data_u8 = state->isr_reg8[reg_count];
>> +        state->isr_reg8[reg_count] = old_data_u8 & (~val);
>> +
>> +        old_data_u8 = state->coreisr_reg8[cpu][reg_count];
>> +        state->coreisr_reg8[cpu][reg_count] = old_data_u8 & (~val);
>> +
>> +        if (old_data_u8 != state->coreisr_reg8[cpu][reg_count]) {
>> +            mask = 0x1;
>> +            for (i = 0; i < 8; i++) {
>> +                if ((old_data_u8 & mask) && (val & mask)) {
>> +                    extioi_update_irq(state, i + reg_count * 8, 0);
>> +                }
>> +                mask = mask << 1;
>> +            }
>> +        }
>> +    } else if ((offset >= EXTIOI_IPMAP_START) && (offset < 
>> EXTIOI_IPMAP_END)) {
>> +        /* Drop arch.core_ip_mask use state->ipmap */
>> +        reg_count = (offset - EXTIOI_IPMAP_START);
>> +        state->ipmap_reg8[reg_count] = val;
>> +
>> +        ipnum = 0;
>> +        for (i = 0; i < 4; i++) {
>> +            if (val & (0x1 << i)) {
>> +                ipnum = i;
>> +                break;
>> +            }
>> +        }
>> +
>> +        if (val) {
>> +            for (i = 0; i < 32; i++) {
>> +                irqnum = reg_count * 32 + i;
>> +                state->sw_ipmap[irqnum] = ipnum;
>> +            }
>> +        } else {
>> +            for (i = 0; i < 32; i++) {
>> +                irqnum = reg_count * 32 + i;
>> +                state->sw_ipmap[irqnum] = 0;
>> +            }
>> +        }
>> +    } else if ((offset >= EXTIOI_COREMAP_START) &&
>> +               (offset < EXTIOI_COREMAP_END)) {
>> +        reg_count = (offset - EXTIOI_COREMAP_START);
>> +        cpu = val & 0xf;
>> +
>> +        /* Node map different from kernel */
>> +        if (cpu) {
>> +            cpu = ctz32(cpu);
>> +            state->coremap_reg8[reg_count] = val;
>> +            state->sw_coremap[reg_count] = cpu;
>> +        }
>> +    } else if ((offset >= EXTIOI_NODETYPE_START) &&
>> +               (offset < EXTIOI_NODETYPE_END)) {
>> +        reg_count = (offset - EXTIOI_NODETYPE_START);
>> +        state->nodetype_reg8[reg_count] = val;
>> +    }
>> +
>> +    DPRINTF("writeb reg 0x" TARGET_FMT_plx " = %x\n", addr, val);
>> +}
>> +
>> +static void extioi_writew(void *opaque, hwaddr addr, uint32_t val)
>> +{
>> +    loongarch_extioi *state = opaque;
> 
> And a QOM cast here.
> 
>> +    int cpu, level;
>> +    uint32_t offset, old_data_u32, reg_count, mask, i;
>> +
>> +    offset = addr & 0xffff;
>> +
>> +    if ((offset >= EXTIOI_ENABLE_START) && (offset < EXTIOI_ENABLE_END)) {
>> +        reg_count = (offset - EXTIOI_ENABLE_START) / 4;
>> +        old_data_u32 = state->en_reg32[reg_count];
>> +        if (old_data_u32 != val) {
>> +            state->en_reg32[reg_count] = val;
>> +            old_data_u32 = old_data_u32 ^ val;
>> +
>> +            mask = 0x1;
>> +            for (i = 0; i < 8 * sizeof(old_data_u32); i++) {
>> +                if (old_data_u32 & mask) {
>> +                    level = !!(val & (0x1 << i));
>> +                    extioi_update_irq(state, i + reg_count * 32, level);
>> +                }
>> +                mask = mask << 1;
>> +            }
>> +        }
>> +    } else if ((offset >= EXTIOI_BOUNCE_START) &&
>> +               (offset < EXTIOI_BOUNCE_END)) {
>> +        reg_count = (offset - EXTIOI_BOUNCE_START) / 4;
>> +        state->bounce_reg32[reg_count] = val;
>> +    } else if ((offset >= EXTIOI_COREISR_START) &&
>> +               (offset < EXTIOI_COREISR_END)) {
>> +        reg_count = ((offset - EXTIOI_COREISR_START) & 0x1f) / 4;
>> +        cpu = ((offset - EXTIOI_COREISR_START) >> 8) & 0x3;
>> +
>> +        /* Ext_isr */
>> +        old_data_u32 = state->isr_reg32[reg_count];
>> +        state->isr_reg32[reg_count] = old_data_u32 & (~val);
>> +
>> +        /* Ext_core_ioisr */
>> +        old_data_u32 = state->coreisr_reg32[cpu][reg_count];
>> +        state->coreisr_reg32[cpu][reg_count] = old_data_u32 & (~val);
>> +
>> +        if (old_data_u32 != state->coreisr_reg32[cpu][reg_count]) {
>> +            mask = 0x1;
>> +            for (i = 0; i < 8 * sizeof(old_data_u32); i++) {
>> +                if ((old_data_u32 & mask) && (val & mask)) {
>> +                    extioi_update_irq(state, i + reg_count * 8, 0);
>> +                }
>> +                mask = mask << 1;
>> +            }
>> +        }
>> +    } else if ((offset >= EXTIOI_IPMAP_START) &&
>> +               (offset < EXTIOI_IPMAP_END)) {
>> +        extioi_writeb(opaque, addr, (val) & 0xff);
>> +        extioi_writeb(opaque, addr + 1, (val >> 8) & 0xff);
>> +        extioi_writeb(opaque, addr + 2, (val >> 16) & 0xff);
>> +        extioi_writeb(opaque, addr + 3, (val >> 24) & 0xff);
>> +    } else if ((offset >= EXTIOI_COREMAP_START) &&
>> +               (offset < EXTIOI_COREMAP_END)) {
>> +        extioi_writeb(opaque, addr, (val) & 0xff);
>> +        extioi_writeb(opaque, addr + 1, (val >> 8) & 0xff);
>> +        extioi_writeb(opaque, addr + 2, (val >> 16) & 0xff);
>> +        extioi_writeb(opaque, addr + 3, (val >> 24) & 0xff);
>> +    } else if ((offset >= EXTIOI_NODETYPE_START) &&
>> +               (offset < EXTIOI_NODETYPE_END)) {
>> +        reg_count = (offset - EXTIOI_NODETYPE_START) / 4;
>> +        state->nodetype_reg32[reg_count] = val;
>> +    }
>> +
>> +    DPRINTF("writew reg 0x" TARGET_FMT_plx " = %x\n", addr, val);
>> +}
>> +
>> +static void extioi_writel(void *opaque, hwaddr addr, uint64_t val)
>> +{
>> +    loongarch_extioi *state = (loongarch_extioi *)opaque;
> 
> And a QOM cast here.
> 
>> +    int cpu, level;
>> +    uint64_t offset, old_data_u64, reg_count, mask, i;
>> +
>> +    offset = addr & 0xffff;
>> +
>> +    if ((offset >= EXTIOI_ENABLE_START) && (offset < EXTIOI_ENABLE_END)) {
>> +        reg_count = (offset - EXTIOI_ENABLE_START) / 8;
>> +        old_data_u64 = state->en_reg64[reg_count];
>> +        if (old_data_u64 != val) {
>> +            state->en_reg64[reg_count] = val;
>> +            old_data_u64 = old_data_u64 ^ val;
>> +            mask = 0x1;
>> +            for (i = 0; i < 8 * sizeof(old_data_u64); i++) {
>> +                if (old_data_u64 & mask) {
>> +                    level = !!(val & (0x1 << i));
>> +                    extioi_update_irq(state, i + reg_count * 64, level);
>> +                }
>> +                mask = mask << 1;
>> +            }
>> +        }
>> +    } else if ((offset >= EXTIOI_BOUNCE_START) &&
>> +               (offset < EXTIOI_BOUNCE_END)) {
>> +        reg_count = (offset - EXTIOI_BOUNCE_START) / 8;
>> +        state->bounce_reg64[reg_count] = val;
>> +    } else if ((offset >= EXTIOI_COREISR_START) &&
>> +               (offset < EXTIOI_COREISR_END)) {
>> +        reg_count = ((offset - EXTIOI_COREISR_START) & 0x1f) / 8;
>> +        cpu = ((offset - EXTIOI_COREISR_START) >> 8) & 0x3;
>> +
>> +        /* core_ext_ioisr */
>> +        old_data_u64 = state->coreisr_reg64[cpu][reg_count];
>> +        state->coreisr_reg64[cpu][reg_count] = old_data_u64 & (~val);
>> +
>> +        if (old_data_u64 != state->coreisr_reg64[cpu][reg_count]) {
>> +            mask = 0x1;
>> +            for (i = 0; i < 8 * sizeof(old_data_u64); i++) {
>> +                if ((old_data_u64 & mask) && (val & mask)) {
>> +                    extioi_update_irq(state, i + reg_count * 64, 0);
>> +                }
>> +                mask = mask << 1;
>> +            }
>> +        }
>> +    } else if ((offset >= EXTIOI_IPMAP_START) &&
>> +               (offset < EXTIOI_IPMAP_END)) {
>> +        extioi_writeb(opaque, addr, (val) & 0xff);
>> +        extioi_writeb(opaque, addr + 1, (val >> 8) & 0xff);
>> +        extioi_writeb(opaque, addr + 2, (val >> 16) & 0xff);
>> +        extioi_writeb(opaque, addr + 3, (val >> 24) & 0xff);
>> +        extioi_writeb(opaque, addr + 4, (val >> 32) & 0xff);
>> +        extioi_writeb(opaque, addr + 5, (val >> 40) & 0xff);
>> +        extioi_writeb(opaque, addr + 6, (val >> 48) & 0xff);
>> +        extioi_writeb(opaque, addr + 7, (val >> 56) & 0xff);
>> +    } else if ((offset >= EXTIOI_COREMAP_START) &&
>> +               (offset < EXTIOI_COREMAP_END)) {
>> +        extioi_writeb(opaque, addr, (val) & 0xff);
>> +        extioi_writeb(opaque, addr + 1, (val >> 8) & 0xff);
>> +        extioi_writeb(opaque, addr + 2, (val >> 16) & 0xff);
>> +        extioi_writeb(opaque, addr + 3, (val >> 24) & 0xff);
>> +        extioi_writeb(opaque, addr + 4, (val >> 32) & 0xff);
>> +        extioi_writeb(opaque, addr + 5, (val >> 40) & 0xff);
>> +        extioi_writeb(opaque, addr + 6, (val >> 48) & 0xff);
>> +        extioi_writeb(opaque, addr + 7, (val >> 56) & 0xff);
>> +    } else if ((offset >= EXTIOI_NODETYPE_START) &&
>> +               (offset < EXTIOI_NODETYPE_END)) {
>> +        reg_count = (offset - EXTIOI_NODETYPE_START) / 8;
>> +        state->nodetype_reg64[reg_count] = val;
>> +    }
>> +
>> +    DPRINTF("writel reg 0x" TARGET_FMT_plx " = %lx\n", addr, val);
>> +}
>> +
>> +static uint64_t extioi_readfn(void *opaque, hwaddr addr, unsigned size)
>> +{
>> +    switch (size) {
>> +    case 1:
>> +        return extioi_readb(opaque, addr);
>> +    case 4:
>> +        return extioi_readw(opaque, addr);
>> +    case 8:
>> +        return extioi_readl(opaque, addr);
>> +    default:
>> +        g_assert_not_reached();
>> +    }
>> +}
>> +
>> +static void extioi_writefn(void *opaque, hwaddr addr,
>> +                           uint64_t value, unsigned size)
>> +{
>> +    switch (size) {
>> +    case 1:
>> +        extioi_writeb(opaque, addr, value);
>> +        break;
>> +    case 4:
>> +        extioi_writew(opaque, addr, value);
>> +        break;
>> +    case 8:
>> +        extioi_writel(opaque, addr, value);
>> +        break;
>> +    default:
>> +        g_assert_not_reached();
>> +    }
>> +}
> 
> Ooof. This pattern of using separate functions for different size accesses 
> generally hasn't been needed since the memory API was introduced about 10 
> years ago. I suspect using a single function each for read and write would 
> help simplify things enormously.
> 

 Thank you for your advice, Most of them have been modified. But for different 
size access I haven't thought of a good way yet. 
 Can we just define the readb/writeb and use Multiple readb/writeb or use if 
(size == 1/4/8) to handle separately in a big read/write func?

Thanks,
Xiaojuan


Reply via email to