static void pmac_ide_atapi_transfer_cb(void *opaque, int ret)

{

    DBDMA_io *io = opaque;

    MACIOIDEState *m = io->opaque;

    IDEState *s = idebus_active_if(&m->bus);

    int unaligned;



    if (ret < 0) {

        m->aiocb = NULL;

        qemu_sglist_destroy(&s->sg);

        ide_atapi_io_error(s, ret);

        io->remainder_len = 0;

        goto done;

    }



    if (!m->dma_active) {

        MACIO_DPRINTF("waiting for data (%#x - %#x - %x)\n",

                      s->nsector, io->len, s->status);

        /* data not ready yet, wait for the channel to get restarted */

        io->processing = false;

        return;

    }



    MACIO_DPRINTF("io_buffer_size = %#x\n", s->io_buffer_size);



    if (s->io_buffer_size > 0) {

        m->aiocb = NULL;

        qemu_sglist_destroy(&s->sg);



        s->packet_transfer_size -= s->io_buffer_size;



        s->io_buffer_index += s->io_buffer_size;

        s->lba += s->io_buffer_index >> 11;

        s->io_buffer_index &= 0x7ff;

    }



    s->io_buffer_size = MIN(io->len, s->packet_transfer_size);



    MACIO_DPRINTF("remainder: %d io->len: %d size: %d\n", io->remainder_len,

                  io->len, s->packet_transfer_size);

    if (io->remainder_len && io->len) {

        /* guest wants the rest of its previous transfer */

        int remainder_len = MIN(io->remainder_len, io->len);



        MACIO_DPRINTF("copying remainder %d bytes\n", remainder_len);



        cpu_physical_memory_write(io->addr, io->remainder + 0x200 -

                                  remainder_len, remainder_len);



        io->addr += remainder_len;

        io->len -= remainder_len;

        s->io_buffer_size = remainder_len;

        io->remainder_len -= remainder_len;

        /* treat remainder as individual transfer, start again */

        qemu_sglist_init(&s->sg, DEVICE(m), io->len / MACIO_PAGE_SIZE + 1,

                         &address_space_memory);

        pmac_ide_atapi_transfer_cb(opaque, 0);

        return;

    }



    if (!s->packet_transfer_size) {

        MACIO_DPRINTF("end of transfer\n");

        ide_atapi_cmd_ok(s);

        m->dma_active = false;

    }



    if (io->len == 0) {

        MACIO_DPRINTF("end of DMA\n");

        goto done;

    }



    /* launch next transfer */



    /* handle unaligned accesses first, get them over with and only do the

       remaining bulk transfer using our async DMA helpers */

    unaligned = io->len & 0x1ff;

    if (unaligned) {

        int sector_num = (s->lba << 2) + (s->io_buffer_index >> 9);

        int nsector = io->len >> 9;



        MACIO_DPRINTF("precopying unaligned %d bytes to %#" HWADDR_PRIx "\n",

                      unaligned, io->addr + io->len - unaligned);



        bdrv_read(s->bs, sector_num + nsector, io->remainder, 1);

        cpu_physical_memory_write(io->addr + io->len - unaligned,

                                  io->remainder, unaligned);



        io->len -= unaligned;

    }



    MACIO_DPRINTF("io->len = %#x\n", io->len);



    qemu_sglist_init(&s->sg, DEVICE(m), io->len / MACIO_PAGE_SIZE + 1,

                     &address_space_memory);

    qemu_sglist_add(&s->sg, io->addr, io->len);

    io->addr += s->io_buffer_size;

    io->remainder_len = MIN(s->packet_transfer_size - s->io_buffer_size,

                            (0x200 - unaligned) & 0x1ff);

    MACIO_DPRINTF("set remainder to: %d\n", io->remainder_len);



    /* We would read no data from the block layer, thus not get a callback.

       Just fake completion manually. */

    if (!io->len) {

        pmac_ide_atapi_transfer_cb(opaque, 0);

        return;

    }



    io->len = 0;



    MACIO_DPRINTF("sector_num=%d size=%d, cmd_cmd=%d\n",

                  (s->lba << 2) + (s->io_buffer_index >> 9),

                  s->packet_transfer_size, s->dma_cmd);



    m->aiocb = dma_bdrv_read(s->bs, &s->sg,

                             (int64_t)(s->lba << 2) + (s->io_buffer_index >> 9),

                             pmac_ide_atapi_transfer_cb, io);

    return;



done:

    MACIO_DPRINTF("done DMA\n");

    block_acct_done(bdrv_get_stats(s->bs), &s->acct);

    io->dma_end(opaque);

}

static void pmac_ide_atapi_transfer_cb(void *opaque, int ret)

{

    DBDMA_io *io = opaque;

    MACIOIDEState *m = io->opaque;

    IDEState *s = idebus_active_if(&m->bus);

    int unaligned;



    if (ret < 0) {

        m->aiocb = NULL;

        qemu_sglist_destroy(&s->sg);

        ide_atapi_io_error(s, ret);

        io->remainder_len = 0;

        goto done;

    }



    if (!m->dma_active) {

        MACIO_DPRINTF("waiting for data (%#x - %#x - %x)\n",

                      s->nsector, io->len, s->status);

        

        io->processing = false;

        return;

    }



    MACIO_DPRINTF("io_buffer_size = %#x\n", s->io_buffer_size);



    if (s->io_buffer_size > 0) {

        m->aiocb = NULL;

        qemu_sglist_destroy(&s->sg);



        s->packet_transfer_size -= s->io_buffer_size;



        s->io_buffer_index += s->io_buffer_size;

        s->lba += s->io_buffer_index >> 11;

        s->io_buffer_index &= 0x7ff;

    }



    s->io_buffer_size = MIN(io->len, s->packet_transfer_size);



    MACIO_DPRINTF("remainder: %d io->len: %d size: %d\n", io->remainder_len,

                  io->len, s->packet_transfer_size);

    if (io->remainder_len && io->len) {

        

        int remainder_len = MIN(io->remainder_len, io->len);



        MACIO_DPRINTF("copying remainder %d bytes\n", remainder_len);



        cpu_physical_memory_write(io->addr, io->remainder + 0x200 -

                                  remainder_len, remainder_len);



        io->addr += remainder_len;

        io->len -= remainder_len;

        s->io_buffer_size = remainder_len;

        io->remainder_len -= remainder_len;

        

        qemu_sglist_init(&s->sg, DEVICE(m), io->len / MACIO_PAGE_SIZE + 1,

                         &address_space_memory);

        pmac_ide_atapi_transfer_cb(opaque, 0);

        return;

    }



    if (!s->packet_transfer_size) {

        MACIO_DPRINTF("end of transfer\n");

        ide_atapi_cmd_ok(s);

        m->dma_active = false;

    }



    if (io->len == 0) {

        MACIO_DPRINTF("end of DMA\n");

        goto done;

    }



    



    



    unaligned = io->len & 0x1ff;

    if (unaligned) {

        int sector_num = (s->lba << 2) + (s->io_buffer_index >> 9);

        int nsector = io->len >> 9;



        MACIO_DPRINTF("precopying unaligned %d bytes to %#" HWADDR_PRIx "\n",

                      unaligned, io->addr + io->len - unaligned);



        bdrv_read(s->bs, sector_num + nsector, io->remainder, 1);

        cpu_physical_memory_write(io->addr + io->len - unaligned,

                                  io->remainder, unaligned);



        io->len -= unaligned;

    }



    MACIO_DPRINTF("io->len = %#x\n", io->len);



    qemu_sglist_init(&s->sg, DEVICE(m), io->len / MACIO_PAGE_SIZE + 1,

                     &address_space_memory);

    qemu_sglist_add(&s->sg, io->addr, io->len);

    io->addr += s->io_buffer_size;

    io->remainder_len = MIN(s->packet_transfer_size - s->io_buffer_size,

                            (0x200 - unaligned) & 0x1ff);

    MACIO_DPRINTF("set remainder to: %d\n", io->remainder_len);



    



    if (!io->len) {

        pmac_ide_atapi_transfer_cb(opaque, 0);

        return;

    }



    io->len = 0;



    MACIO_DPRINTF("sector_num=%d size=%d, cmd_cmd=%d\n",

                  (s->lba << 2) + (s->io_buffer_index >> 9),

                  s->packet_transfer_size, s->dma_cmd);



    m->aiocb = dma_bdrv_read(s->bs, &s->sg,

                             (int64_t)(s->lba << 2) + (s->io_buffer_index >> 9),

                             pmac_ide_atapi_transfer_cb, io);

    return;



done:

    MACIO_DPRINTF("done DMA\n");

    block_acct_done(bdrv_get_stats(s->bs), &s->acct);

    io->dma_end(opaque);

}

static void FUNC_0(void *VAR_0, int VAR_1)

{

    DBDMA_io *io = VAR_0;

    MACIOIDEState *m = io->VAR_0;

    IDEState *s = idebus_active_if(&m->bus);

    int VAR_2;



    if (VAR_1 < 0) {

        m->aiocb = NULL;

        qemu_sglist_destroy(&s->sg);

        ide_atapi_io_error(s, VAR_1);

        io->VAR_3 = 0;

        goto done;

    }



    if (!m->dma_active) {

        MACIO_DPRINTF("waiting for data (%#x - %#x - %x)\n",

                      s->VAR_5, io->len, s->status);

        

        io->processing = false;

        return;

    }



    MACIO_DPRINTF("io_buffer_size = %#x\n", s->io_buffer_size);



    if (s->io_buffer_size > 0) {

        m->aiocb = NULL;

        qemu_sglist_destroy(&s->sg);



        s->packet_transfer_size -= s->io_buffer_size;



        s->io_buffer_index += s->io_buffer_size;

        s->lba += s->io_buffer_index >> 11;

        s->io_buffer_index &= 0x7ff;

    }



    s->io_buffer_size = MIN(io->len, s->packet_transfer_size);



    MACIO_DPRINTF("remainder: %d io->len: %d size: %d\n", io->VAR_3,

                  io->len, s->packet_transfer_size);

    if (io->VAR_3 && io->len) {

        

        int VAR_3 = MIN(io->VAR_3, io->len);



        MACIO_DPRINTF("copying remainder %d bytes\n", VAR_3);



        cpu_physical_memory_write(io->addr, io->remainder + 0x200 -

                                  VAR_3, VAR_3);



        io->addr += VAR_3;

        io->len -= VAR_3;

        s->io_buffer_size = VAR_3;

        io->VAR_3 -= VAR_3;

        

        qemu_sglist_init(&s->sg, DEVICE(m), io->len / MACIO_PAGE_SIZE + 1,

                         &address_space_memory);

        FUNC_0(VAR_0, 0);

        return;

    }



    if (!s->packet_transfer_size) {

        MACIO_DPRINTF("end of transfer\n");

        ide_atapi_cmd_ok(s);

        m->dma_active = false;

    }



    if (io->len == 0) {

        MACIO_DPRINTF("end of DMA\n");

        goto done;

    }



    



    



    VAR_2 = io->len & 0x1ff;

    if (VAR_2) {

        int VAR_4 = (s->lba << 2) + (s->io_buffer_index >> 9);

        int VAR_5 = io->len >> 9;



        MACIO_DPRINTF("precopying VAR_2 %d bytes to %#" HWADDR_PRIx "\n",

                      VAR_2, io->addr + io->len - VAR_2);



        bdrv_read(s->bs, VAR_4 + VAR_5, io->remainder, 1);

        cpu_physical_memory_write(io->addr + io->len - VAR_2,

                                  io->remainder, VAR_2);



        io->len -= VAR_2;

    }



    MACIO_DPRINTF("io->len = %#x\n", io->len);



    qemu_sglist_init(&s->sg, DEVICE(m), io->len / MACIO_PAGE_SIZE + 1,

                     &address_space_memory);

    qemu_sglist_add(&s->sg, io->addr, io->len);

    io->addr += s->io_buffer_size;

    io->VAR_3 = MIN(s->packet_transfer_size - s->io_buffer_size,

                            (0x200 - VAR_2) & 0x1ff);

    MACIO_DPRINTF("set remainder to: %d\n", io->VAR_3);



    



    if (!io->len) {

        FUNC_0(VAR_0, 0);

        return;

    }



    io->len = 0;



    MACIO_DPRINTF("VAR_4=%d size=%d, cmd_cmd=%d\n",

                  (s->lba << 2) + (s->io_buffer_index >> 9),

                  s->packet_transfer_size, s->dma_cmd);



    m->aiocb = dma_bdrv_read(s->bs, &s->sg,

                             (int64_t)(s->lba << 2) + (s->io_buffer_index >> 9),

                             FUNC_0, io);

    return;



done:

    MACIO_DPRINTF("done DMA\n");

    block_acct_done(bdrv_get_stats(s->bs), &s->acct);

    io->dma_end(VAR_0);

}

static void FUNC_0(void *VAR_0, int VAR_1)
{ DBDMA_io *io = VAR_0; MACIOIDEState *m = io->VAR_0; IDEState *s = idebus_active_if(&m->bus); int VAR_2; if (VAR_1 < 0) { m->aiocb = NULL; qemu_sglist_destroy(&s->sg); ide_atapi_io_error(s, VAR_1); io->VAR_3 = 0; goto done; } if (!m->dma_active) { MACIO_DPRINTF("waiting for data (%#x - %#x - %x)\n",
s->VAR_5, io->len, s->status); io->processing = false; return; } MACIO_DPRINTF("io_buffer_size = %#x\n", s->io_buffer_size); if (s->io_buffer_size > 0) { m->aiocb = NULL; qemu_sglist_destroy(&s->sg); s->packet_transfer_size -= s->io_buffer_size; s->io_buffer_index += s->io_buffer_size; s->lba += s->io_buffer_index >> 11; s->io_buffer_index &= 0x7ff; } s->io_buffer_size = MIN(io->len, s->packet_transfer_size); MACIO_DPRINTF("remainder: %d io->len: %d size: %d\n", io->VAR_3,
io->len, s->packet_transfer_size); if (io->VAR_3 && io->len) { int VAR_3 = MIN(io->VAR_3, io->len); MACIO_DPRINTF("copying remainder %d bytes\n", VAR_3); cpu_physical_memory_write(io->addr, io->remainder + 0x200 -
VAR_3, VAR_3); io->addr += VAR_3; io->len -= VAR_3; s->io_buffer_size = VAR_3; io->VAR_3 -= VAR_3; qemu_sglist_init(&s->sg, DEVICE(m), io->len / MACIO_PAGE_SIZE + 1,
&address_space_memory); FUNC_0(VAR_0, 0); return; } if (!s->packet_transfer_size) { MACIO_DPRINTF("end of transfer\n"); ide_atapi_cmd_ok(s); m->dma_active = false; } if (io->len == 0) { MACIO_DPRINTF("end of DMA\n"); goto done; } VAR_2 = io->len & 0x1ff; if (VAR_2) { int VAR_4 = (s->lba << 2) + (s->io_buffer_index >> 9); int VAR_5 = io->len >> 9; MACIO_DPRINTF("precopying VAR_2 %d bytes to %#" HWADDR_PRIx "\n",
VAR_2, io->addr + io->len - VAR_2); bdrv_read(s->bs, VAR_4 + VAR_5, io->remainder, 1); cpu_physical_memory_write(io->addr + io->len - VAR_2,
io->remainder, VAR_2); io->len -= VAR_2; } MACIO_DPRINTF("io->len = %#x\n", io->len); qemu_sglist_init(&s->sg, DEVICE(m), io->len / MACIO_PAGE_SIZE + 1,
&address_space_memory); qemu_sglist_add(&s->sg, io->addr, io->len); io->addr += s->io_buffer_size; io->VAR_3 = MIN(s->packet_transfer_size - s->io_buffer_size,
(0x200 - VAR_2) & 0x1ff); MACIO_DPRINTF("set remainder to: %d\n", io->VAR_3); if (!io->len) { FUNC_0(VAR_0, 0); return; } io->len = 0; MACIO_DPRINTF("VAR_4=%d size=%d, cmd_cmd=%d\n",
(s->lba << 2) + (s->io_buffer_index >> 9),
s->packet_transfer_size, s->dma_cmd); m->aiocb = dma_bdrv_read(s->bs, &s->sg,
(int64_t)(s->lba << 2) + (s->io_buffer_index >> 9),
FUNC_0, io); return; done:
MACIO_DPRINTF("done DMA\n"); block_acct_done(bdrv_get_stats(s->bs), &s->acct); io->dma_end(VAR_0); }