static MemTxResult address_space_write_continue(AddressSpace *as, hwaddr addr,

                                                MemTxAttrs attrs,

                                                const uint8_t *buf,

                                                int len, hwaddr addr1,

                                                hwaddr l, MemoryRegion *mr)

{

    uint8_t *ptr;

    uint64_t val;

    MemTxResult result = MEMTX_OK;

    bool release_lock = false;



    for (;;) {

        if (!memory_access_is_direct(mr, true)) {

            release_lock |= prepare_mmio_access(mr);

            l = memory_access_size(mr, l, addr1);

            /* XXX: could force current_cpu to NULL to avoid

               potential bugs */

            switch (l) {

            case 8:

                /* 64 bit write access */

                val = ldq_p(buf);

                result |= memory_region_dispatch_write(mr, addr1, val, 8,

                                                       attrs);

                break;

            case 4:

                /* 32 bit write access */

                val = (uint32_t)ldl_p(buf);

                result |= memory_region_dispatch_write(mr, addr1, val, 4,

                                                       attrs);

                break;

            case 2:

                /* 16 bit write access */

                val = lduw_p(buf);

                result |= memory_region_dispatch_write(mr, addr1, val, 2,

                                                       attrs);

                break;

            case 1:

                /* 8 bit write access */

                val = ldub_p(buf);

                result |= memory_region_dispatch_write(mr, addr1, val, 1,

                                                       attrs);

                break;

            default:

                abort();

            }

        } else {

            /* RAM case */

            ptr = qemu_map_ram_ptr(mr->ram_block, addr1);

            memcpy(ptr, buf, l);

            invalidate_and_set_dirty(mr, addr1, l);

        }



        if (release_lock) {

            qemu_mutex_unlock_iothread();

            release_lock = false;

        }



        len -= l;

        buf += l;

        addr += l;



        if (!len) {

            break;

        }



        l = len;

        mr = address_space_translate(as, addr, &addr1, &l, true);

    }



    return result;

}
