static void rocker_io_writel(void *opaque, hwaddr addr, uint32_t val)

{

    Rocker *r = opaque;



    if (rocker_addr_is_desc_reg(r, addr)) {

        unsigned index = ROCKER_RING_INDEX(addr);

        unsigned offset = addr & ROCKER_DMA_DESC_MASK;



        switch (offset) {

        case ROCKER_DMA_DESC_ADDR_OFFSET:

            r->lower32 = (uint64_t)val;

            break;

        case ROCKER_DMA_DESC_ADDR_OFFSET + 4:

            desc_ring_set_base_addr(r->rings[index],

                                    ((uint64_t)val) << 32 | r->lower32);

            r->lower32 = 0;

            break;

        case ROCKER_DMA_DESC_SIZE_OFFSET:

            desc_ring_set_size(r->rings[index], val);

            break;

        case ROCKER_DMA_DESC_HEAD_OFFSET:

            if (desc_ring_set_head(r->rings[index], val)) {

                rocker_msix_irq(r, desc_ring_get_msix_vector(r->rings[index]));

            }

            break;

        case ROCKER_DMA_DESC_CTRL_OFFSET:

            desc_ring_set_ctrl(r->rings[index], val);

            break;

        case ROCKER_DMA_DESC_CREDITS_OFFSET:

            if (desc_ring_ret_credits(r->rings[index], val)) {

                rocker_msix_irq(r, desc_ring_get_msix_vector(r->rings[index]));

            }

            break;

        default:

            DPRINTF("not implemented dma reg write(l) addr=0x" TARGET_FMT_plx

                    " val=0x%08x (ring %d, addr=0x%02x)\n",

                    addr, val, index, offset);

            break;

        }

        return;

    }



    switch (addr) {

    case ROCKER_TEST_REG:

        r->test_reg = val;

        break;

    case ROCKER_TEST_REG64:

    case ROCKER_TEST_DMA_ADDR:

    case ROCKER_PORT_PHYS_ENABLE:

        r->lower32 = (uint64_t)val;

        break;

    case ROCKER_TEST_REG64 + 4:

        r->test_reg64 = ((uint64_t)val) << 32 | r->lower32;

        r->lower32 = 0;

        break;

    case ROCKER_TEST_IRQ:

        rocker_msix_irq(r, val);

        break;

    case ROCKER_TEST_DMA_SIZE:

        r->test_dma_size = val;

        break;

    case ROCKER_TEST_DMA_ADDR + 4:

        r->test_dma_addr = ((uint64_t)val) << 32 | r->lower32;

        r->lower32 = 0;

        break;

    case ROCKER_TEST_DMA_CTRL:

        rocker_test_dma_ctrl(r, val);

        break;

    case ROCKER_CONTROL:

        rocker_control(r, val);

        break;

    case ROCKER_PORT_PHYS_ENABLE + 4:

        rocker_port_phys_enable_write(r, ((uint64_t)val) << 32 | r->lower32);

        r->lower32 = 0;

        break;

    default:

        DPRINTF("not implemented write(l) addr=0x" TARGET_FMT_plx

                " val=0x%08x\n", addr, val);

        break;

    }

}
