From patchwork Fri Jan 29 05:06:35 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Gibson X-Patchwork-Id: 8159201 Return-Path: X-Original-To: patchwork-qemu-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 45ED6BEEE5 for ; Fri, 29 Jan 2016 05:25:14 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id C9E3D20351 for ; Fri, 29 Jan 2016 05:25:12 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 1B076200F4 for ; Fri, 29 Jan 2016 05:25:11 +0000 (UTC) Received: from localhost ([::1]:59987 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1aP1YU-0005QA-Dz for patchwork-qemu-devel@patchwork.kernel.org; Fri, 29 Jan 2016 00:25:10 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:38544) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1aP1GN-0003c2-Vw for qemu-devel@nongnu.org; Fri, 29 Jan 2016 00:06:35 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1aP1GI-0001Mv-0V for qemu-devel@nongnu.org; Fri, 29 Jan 2016 00:06:27 -0500 Received: from ozlabs.org ([2401:3900:2:1::2]:48392) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1aP1GH-0001KC-5i; Fri, 29 Jan 2016 00:06:21 -0500 Received: by ozlabs.org (Postfix, from userid 1007) id D352A140C4B; Fri, 29 Jan 2016 16:06:16 +1100 (AEDT) From: David Gibson To: peter.maydell@linaro.org, agraf@suse.de Date: Fri, 29 Jan 2016 16:06:35 +1100 Message-Id: <1454044031-5930-5-git-send-email-david@gibson.dropbear.id.au> X-Mailer: git-send-email 2.5.0 In-Reply-To: <1454044031-5930-1-git-send-email-david@gibson.dropbear.id.au> References: <1454044031-5930-1-git-send-email-david@gibson.dropbear.id.au> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 2401:3900:2:1::2 Cc: aik@ozlabs.ru, Mark Cave-Ayland , mdroth@linux.vnet.ibm.com, qemu-devel@nongnu.org, qemu-ppc@nongnu.org, David Gibson Subject: [Qemu-devel] [PULL 03/39] macio: use the existing IDEDMA aiocb to hold the active DMA aiocb X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Mark Cave-Ayland Currently the aiocb is held within MACIOIDEState, however the IDE core code assumes that the current actvie DMA aiocb is held in aiocb in a few places, e.g. ide_bus_reset() and ide_reset(). Switch over to using IDEDMA aiocb to store the aiocb for the current active DMA request so that bus resets and restarts are handled correctly. As a consequence we can now use ide_set_inactive() rather than handling its functionality ourselves. Signed-off-by: Mark Cave-Ayland Reviewed-by: John Snow Signed-off-by: David Gibson --- hw/ide/macio.c | 20 +- hw/ide/macio.c.orig | 634 ++++++++++++++++++++++++++++++++++++++++++++++++++++ hw/ppc/mac.h | 1 - 3 files changed, 646 insertions(+), 9 deletions(-) create mode 100644 hw/ide/macio.c.orig diff --git a/hw/ide/macio.c b/hw/ide/macio.c index d4031b6..110af46 100644 --- a/hw/ide/macio.c +++ b/hw/ide/macio.c @@ -119,8 +119,8 @@ static void pmac_dma_read(BlockBackend *blk, MACIO_DPRINTF("--- Block read transfer - sector_num: %" PRIx64 " " "nsector: %x\n", (offset >> 9), (bytes >> 9)); - m->aiocb = blk_aio_readv(blk, (offset >> 9), &io->iov, (bytes >> 9), - cb, io); + s->bus->dma->aiocb = blk_aio_readv(blk, (offset >> 9), &io->iov, + (bytes >> 9), cb, io); } static void pmac_dma_write(BlockBackend *blk, @@ -204,8 +204,8 @@ static void pmac_dma_write(BlockBackend *blk, MACIO_DPRINTF("--- Block write transfer - sector_num: %" PRIx64 " " "nsector: %x\n", (offset >> 9), (bytes >> 9)); - m->aiocb = blk_aio_writev(blk, (offset >> 9), &io->iov, (bytes >> 9), - cb, io); + s->bus->dma->aiocb = blk_aio_writev(blk, (offset >> 9), &io->iov, + (bytes >> 9), cb, io); } static void pmac_dma_trim(BlockBackend *blk, @@ -231,8 +231,8 @@ static void pmac_dma_trim(BlockBackend *blk, s->io_buffer_index += io->len; io->len = 0; - m->aiocb = ide_issue_trim(blk, (offset >> 9), &io->iov, (bytes >> 9), - cb, io); + s->bus->dma->aiocb = ide_issue_trim(blk, (offset >> 9), &io->iov, + (bytes >> 9), cb, io); } static void pmac_ide_atapi_transfer_cb(void *opaque, int ret) @@ -291,6 +291,8 @@ done: } else { block_acct_done(blk_get_stats(s->blk), &s->acct); } + + ide_set_inactive(s, false); io->dma_end(opaque); } @@ -305,7 +307,6 @@ static void pmac_ide_transfer_cb(void *opaque, int ret) if (ret < 0) { MACIO_DPRINTF("DMA error: %d\n", ret); - m->aiocb = NULL; ide_dma_error(s); goto done; } @@ -356,6 +357,8 @@ done: block_acct_done(blk_get_stats(s->blk), &s->acct); } } + + ide_set_inactive(s, false); io->dma_end(opaque); } @@ -393,8 +396,9 @@ static void pmac_ide_transfer(DBDMA_io *io) static void pmac_ide_flush(DBDMA_io *io) { MACIOIDEState *m = io->opaque; + IDEState *s = idebus_active_if(&m->bus); - if (m->aiocb) { + if (s->bus->dma->aiocb) { blk_drain_all(); } } diff --git a/hw/ide/macio.c.orig b/hw/ide/macio.c.orig new file mode 100644 index 0000000..d4031b6 --- /dev/null +++ b/hw/ide/macio.c.orig @@ -0,0 +1,634 @@ +/* + * QEMU IDE Emulation: MacIO support. + * + * Copyright (c) 2003 Fabrice Bellard + * Copyright (c) 2006 Openedhand Ltd. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include "hw/hw.h" +#include "hw/ppc/mac.h" +#include "hw/ppc/mac_dbdma.h" +#include "sysemu/block-backend.h" +#include "sysemu/dma.h" + +#include + +/* debug MACIO */ +// #define DEBUG_MACIO + +#ifdef DEBUG_MACIO +static const int debug_macio = 1; +#else +static const int debug_macio = 0; +#endif + +#define MACIO_DPRINTF(fmt, ...) do { \ + if (debug_macio) { \ + printf(fmt , ## __VA_ARGS__); \ + } \ + } while (0) + + +/***********************************************************/ +/* MacIO based PowerPC IDE */ + +#define MACIO_PAGE_SIZE 4096 + +/* + * Unaligned DMA read/write access functions required for OS X/Darwin which + * don't perform DMA transactions on sector boundaries. These functions are + * modelled on bdrv_co_do_preadv()/bdrv_co_do_pwritev() and so should be + * easy to remove if the unaligned block APIs are ever exposed. + */ + +static void pmac_dma_read(BlockBackend *blk, + int64_t offset, unsigned int bytes, + void (*cb)(void *opaque, int ret), void *opaque) +{ + DBDMA_io *io = opaque; + MACIOIDEState *m = io->opaque; + IDEState *s = idebus_active_if(&m->bus); + dma_addr_t dma_addr, dma_len; + void *mem; + int64_t sector_num; + int nsector; + uint64_t align = BDRV_SECTOR_SIZE; + size_t head_bytes, tail_bytes; + + qemu_iovec_destroy(&io->iov); + qemu_iovec_init(&io->iov, io->len / MACIO_PAGE_SIZE + 1); + + sector_num = (offset >> 9); + nsector = (io->len >> 9); + + MACIO_DPRINTF("--- DMA read transfer (0x%" HWADDR_PRIx ",0x%x): " + "sector_num: %" PRId64 ", nsector: %d\n", io->addr, io->len, + sector_num, nsector); + + dma_addr = io->addr; + dma_len = io->len; + mem = dma_memory_map(&address_space_memory, dma_addr, &dma_len, + DMA_DIRECTION_FROM_DEVICE); + + if (offset & (align - 1)) { + head_bytes = offset & (align - 1); + + MACIO_DPRINTF("--- DMA unaligned head: sector %" PRId64 ", " + "discarding %zu bytes\n", sector_num, head_bytes); + + qemu_iovec_add(&io->iov, &io->head_remainder, head_bytes); + + bytes += offset & (align - 1); + offset = offset & ~(align - 1); + } + + qemu_iovec_add(&io->iov, mem, io->len); + + if ((offset + bytes) & (align - 1)) { + tail_bytes = (offset + bytes) & (align - 1); + + MACIO_DPRINTF("--- DMA unaligned tail: sector %" PRId64 ", " + "discarding bytes %zu\n", sector_num, tail_bytes); + + qemu_iovec_add(&io->iov, &io->tail_remainder, align - tail_bytes); + bytes = ROUND_UP(bytes, align); + } + + s->io_buffer_size -= io->len; + s->io_buffer_index += io->len; + + io->len = 0; + + MACIO_DPRINTF("--- Block read transfer - sector_num: %" PRIx64 " " + "nsector: %x\n", (offset >> 9), (bytes >> 9)); + + m->aiocb = blk_aio_readv(blk, (offset >> 9), &io->iov, (bytes >> 9), + cb, io); +} + +static void pmac_dma_write(BlockBackend *blk, + int64_t offset, int bytes, + void (*cb)(void *opaque, int ret), void *opaque) +{ + DBDMA_io *io = opaque; + MACIOIDEState *m = io->opaque; + IDEState *s = idebus_active_if(&m->bus); + dma_addr_t dma_addr, dma_len; + void *mem; + int64_t sector_num; + int nsector; + uint64_t align = BDRV_SECTOR_SIZE; + size_t head_bytes, tail_bytes; + bool unaligned_head = false, unaligned_tail = false; + + qemu_iovec_destroy(&io->iov); + qemu_iovec_init(&io->iov, io->len / MACIO_PAGE_SIZE + 1); + + sector_num = (offset >> 9); + nsector = (io->len >> 9); + + MACIO_DPRINTF("--- DMA write transfer (0x%" HWADDR_PRIx ",0x%x): " + "sector_num: %" PRId64 ", nsector: %d\n", io->addr, io->len, + sector_num, nsector); + + dma_addr = io->addr; + dma_len = io->len; + mem = dma_memory_map(&address_space_memory, dma_addr, &dma_len, + DMA_DIRECTION_TO_DEVICE); + + if (offset & (align - 1)) { + head_bytes = offset & (align - 1); + sector_num = ((offset & ~(align - 1)) >> 9); + + MACIO_DPRINTF("--- DMA unaligned head: pre-reading head sector %" + PRId64 "\n", sector_num); + + blk_pread(s->blk, (sector_num << 9), &io->head_remainder, align); + + qemu_iovec_add(&io->iov, &io->head_remainder, head_bytes); + qemu_iovec_add(&io->iov, mem, io->len); + + bytes += offset & (align - 1); + offset = offset & ~(align - 1); + + unaligned_head = true; + } + + if ((offset + bytes) & (align - 1)) { + tail_bytes = (offset + bytes) & (align - 1); + sector_num = (((offset + bytes) & ~(align - 1)) >> 9); + + MACIO_DPRINTF("--- DMA unaligned tail: pre-reading tail sector %" + PRId64 "\n", sector_num); + + blk_pread(s->blk, (sector_num << 9), &io->tail_remainder, align); + + if (!unaligned_head) { + qemu_iovec_add(&io->iov, mem, io->len); + } + + qemu_iovec_add(&io->iov, &io->tail_remainder + tail_bytes, + align - tail_bytes); + + bytes = ROUND_UP(bytes, align); + + unaligned_tail = true; + } + + if (!unaligned_head && !unaligned_tail) { + qemu_iovec_add(&io->iov, mem, io->len); + } + + s->io_buffer_size -= io->len; + s->io_buffer_index += io->len; + + io->len = 0; + + MACIO_DPRINTF("--- Block write transfer - sector_num: %" PRIx64 " " + "nsector: %x\n", (offset >> 9), (bytes >> 9)); + + m->aiocb = blk_aio_writev(blk, (offset >> 9), &io->iov, (bytes >> 9), + cb, io); +} + +static void pmac_dma_trim(BlockBackend *blk, + int64_t offset, int bytes, + void (*cb)(void *opaque, int ret), void *opaque) +{ + DBDMA_io *io = opaque; + MACIOIDEState *m = io->opaque; + IDEState *s = idebus_active_if(&m->bus); + dma_addr_t dma_addr, dma_len; + void *mem; + + qemu_iovec_destroy(&io->iov); + qemu_iovec_init(&io->iov, io->len / MACIO_PAGE_SIZE + 1); + + dma_addr = io->addr; + dma_len = io->len; + mem = dma_memory_map(&address_space_memory, dma_addr, &dma_len, + DMA_DIRECTION_TO_DEVICE); + + qemu_iovec_add(&io->iov, mem, io->len); + s->io_buffer_size -= io->len; + s->io_buffer_index += io->len; + io->len = 0; + + m->aiocb = ide_issue_trim(blk, (offset >> 9), &io->iov, (bytes >> 9), + cb, io); +} + +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); + int64_t offset; + + MACIO_DPRINTF("pmac_ide_atapi_transfer_cb\n"); + + if (ret < 0) { + MACIO_DPRINTF("DMA error: %d\n", ret); + ide_atapi_io_error(s, ret); + 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; + } + + if (s->io_buffer_size <= 0) { + MACIO_DPRINTF("End of IDE transfer\n"); + ide_atapi_cmd_ok(s); + m->dma_active = false; + goto done; + } + + if (io->len == 0) { + MACIO_DPRINTF("End of DMA transfer\n"); + goto done; + } + + if (s->lba == -1) { + /* Non-block ATAPI transfer - just copy to RAM */ + s->io_buffer_size = MIN(s->io_buffer_size, io->len); + cpu_physical_memory_write(io->addr, s->io_buffer, s->io_buffer_size); + ide_atapi_cmd_ok(s); + m->dma_active = false; + goto done; + } + + /* Calculate current offset */ + offset = ((int64_t)s->lba << 11) + s->io_buffer_index; + + pmac_dma_read(s->blk, offset, io->len, pmac_ide_atapi_transfer_cb, io); + return; + +done: + if (ret < 0) { + block_acct_failed(blk_get_stats(s->blk), &s->acct); + } else { + block_acct_done(blk_get_stats(s->blk), &s->acct); + } + io->dma_end(opaque); +} + +static void pmac_ide_transfer_cb(void *opaque, int ret) +{ + DBDMA_io *io = opaque; + MACIOIDEState *m = io->opaque; + IDEState *s = idebus_active_if(&m->bus); + int64_t offset; + + MACIO_DPRINTF("pmac_ide_transfer_cb\n"); + + if (ret < 0) { + MACIO_DPRINTF("DMA error: %d\n", ret); + m->aiocb = NULL; + ide_dma_error(s); + 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; + } + + if (s->io_buffer_size <= 0) { + MACIO_DPRINTF("End of IDE transfer\n"); + s->status = READY_STAT | SEEK_STAT; + ide_set_irq(s->bus); + m->dma_active = false; + goto done; + } + + if (io->len == 0) { + MACIO_DPRINTF("End of DMA transfer\n"); + goto done; + } + + /* Calculate number of sectors */ + offset = (ide_get_sector(s) << 9) + s->io_buffer_index; + + switch (s->dma_cmd) { + case IDE_DMA_READ: + pmac_dma_read(s->blk, offset, io->len, pmac_ide_transfer_cb, io); + break; + case IDE_DMA_WRITE: + pmac_dma_write(s->blk, offset, io->len, pmac_ide_transfer_cb, io); + break; + case IDE_DMA_TRIM: + pmac_dma_trim(s->blk, offset, io->len, pmac_ide_transfer_cb, io); + break; + } + + return; + +done: + if (s->dma_cmd == IDE_DMA_READ || s->dma_cmd == IDE_DMA_WRITE) { + if (ret < 0) { + block_acct_failed(blk_get_stats(s->blk), &s->acct); + } else { + block_acct_done(blk_get_stats(s->blk), &s->acct); + } + } + io->dma_end(opaque); +} + +static void pmac_ide_transfer(DBDMA_io *io) +{ + MACIOIDEState *m = io->opaque; + IDEState *s = idebus_active_if(&m->bus); + + MACIO_DPRINTF("\n"); + + if (s->drive_kind == IDE_CD) { + block_acct_start(blk_get_stats(s->blk), &s->acct, io->len, + BLOCK_ACCT_READ); + + pmac_ide_atapi_transfer_cb(io, 0); + return; + } + + switch (s->dma_cmd) { + case IDE_DMA_READ: + block_acct_start(blk_get_stats(s->blk), &s->acct, io->len, + BLOCK_ACCT_READ); + break; + case IDE_DMA_WRITE: + block_acct_start(blk_get_stats(s->blk), &s->acct, io->len, + BLOCK_ACCT_WRITE); + break; + default: + break; + } + + pmac_ide_transfer_cb(io, 0); +} + +static void pmac_ide_flush(DBDMA_io *io) +{ + MACIOIDEState *m = io->opaque; + + if (m->aiocb) { + blk_drain_all(); + } +} + +/* PowerMac IDE memory IO */ +static void pmac_ide_writeb (void *opaque, + hwaddr addr, uint32_t val) +{ + MACIOIDEState *d = opaque; + + addr = (addr & 0xFFF) >> 4; + switch (addr) { + case 1 ... 7: + ide_ioport_write(&d->bus, addr, val); + break; + case 8: + case 22: + ide_cmd_write(&d->bus, 0, val); + break; + default: + break; + } +} + +static uint32_t pmac_ide_readb (void *opaque,hwaddr addr) +{ + uint8_t retval; + MACIOIDEState *d = opaque; + + addr = (addr & 0xFFF) >> 4; + switch (addr) { + case 1 ... 7: + retval = ide_ioport_read(&d->bus, addr); + break; + case 8: + case 22: + retval = ide_status_read(&d->bus, 0); + break; + default: + retval = 0xFF; + break; + } + return retval; +} + +static void pmac_ide_writew (void *opaque, + hwaddr addr, uint32_t val) +{ + MACIOIDEState *d = opaque; + + addr = (addr & 0xFFF) >> 4; + val = bswap16(val); + if (addr == 0) { + ide_data_writew(&d->bus, 0, val); + } +} + +static uint32_t pmac_ide_readw (void *opaque,hwaddr addr) +{ + uint16_t retval; + MACIOIDEState *d = opaque; + + addr = (addr & 0xFFF) >> 4; + if (addr == 0) { + retval = ide_data_readw(&d->bus, 0); + } else { + retval = 0xFFFF; + } + retval = bswap16(retval); + return retval; +} + +static void pmac_ide_writel (void *opaque, + hwaddr addr, uint32_t val) +{ + MACIOIDEState *d = opaque; + + addr = (addr & 0xFFF) >> 4; + val = bswap32(val); + if (addr == 0) { + ide_data_writel(&d->bus, 0, val); + } +} + +static uint32_t pmac_ide_readl (void *opaque,hwaddr addr) +{ + uint32_t retval; + MACIOIDEState *d = opaque; + + addr = (addr & 0xFFF) >> 4; + if (addr == 0) { + retval = ide_data_readl(&d->bus, 0); + } else { + retval = 0xFFFFFFFF; + } + retval = bswap32(retval); + return retval; +} + +static const MemoryRegionOps pmac_ide_ops = { + .old_mmio = { + .write = { + pmac_ide_writeb, + pmac_ide_writew, + pmac_ide_writel, + }, + .read = { + pmac_ide_readb, + pmac_ide_readw, + pmac_ide_readl, + }, + }, + .endianness = DEVICE_NATIVE_ENDIAN, +}; + +static const VMStateDescription vmstate_pmac = { + .name = "ide", + .version_id = 3, + .minimum_version_id = 0, + .fields = (VMStateField[]) { + VMSTATE_IDE_BUS(bus, MACIOIDEState), + VMSTATE_IDE_DRIVES(bus.ifs, MACIOIDEState), + VMSTATE_END_OF_LIST() + } +}; + +static void macio_ide_reset(DeviceState *dev) +{ + MACIOIDEState *d = MACIO_IDE(dev); + + ide_bus_reset(&d->bus); +} + +static int ide_nop_int(IDEDMA *dma, int x) +{ + return 0; +} + +static int32_t ide_nop_int32(IDEDMA *dma, int32_t l) +{ + return 0; +} + +static void ide_dbdma_start(IDEDMA *dma, IDEState *s, + BlockCompletionFunc *cb) +{ + MACIOIDEState *m = container_of(dma, MACIOIDEState, dma); + + s->io_buffer_index = 0; + if (s->drive_kind == IDE_CD) { + s->io_buffer_size = s->packet_transfer_size; + } else { + s->io_buffer_size = s->nsector * BDRV_SECTOR_SIZE; + } + + MACIO_DPRINTF("\n\n------------ IDE transfer\n"); + MACIO_DPRINTF("buffer_size: %x buffer_index: %x\n", + s->io_buffer_size, s->io_buffer_index); + MACIO_DPRINTF("lba: %x size: %x\n", s->lba, s->io_buffer_size); + MACIO_DPRINTF("-------------------------\n"); + + m->dma_active = true; + DBDMA_kick(m->dbdma); +} + +static const IDEDMAOps dbdma_ops = { + .start_dma = ide_dbdma_start, + .prepare_buf = ide_nop_int32, + .rw_buf = ide_nop_int, +}; + +static void macio_ide_realizefn(DeviceState *dev, Error **errp) +{ + MACIOIDEState *s = MACIO_IDE(dev); + + ide_init2(&s->bus, s->irq); + + /* Register DMA callbacks */ + s->dma.ops = &dbdma_ops; + s->bus.dma = &s->dma; +} + +static void macio_ide_initfn(Object *obj) +{ + SysBusDevice *d = SYS_BUS_DEVICE(obj); + MACIOIDEState *s = MACIO_IDE(obj); + + ide_bus_new(&s->bus, sizeof(s->bus), DEVICE(obj), 0, 2); + memory_region_init_io(&s->mem, obj, &pmac_ide_ops, s, "pmac-ide", 0x1000); + sysbus_init_mmio(d, &s->mem); + sysbus_init_irq(d, &s->irq); + sysbus_init_irq(d, &s->dma_irq); +} + +static void macio_ide_class_init(ObjectClass *oc, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(oc); + + dc->realize = macio_ide_realizefn; + dc->reset = macio_ide_reset; + dc->vmsd = &vmstate_pmac; + set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); +} + +static const TypeInfo macio_ide_type_info = { + .name = TYPE_MACIO_IDE, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(MACIOIDEState), + .instance_init = macio_ide_initfn, + .class_init = macio_ide_class_init, +}; + +static void macio_ide_register_types(void) +{ + type_register_static(&macio_ide_type_info); +} + +/* hd_table must contain 2 block drivers */ +void macio_ide_init_drives(MACIOIDEState *s, DriveInfo **hd_table) +{ + int i; + + for (i = 0; i < 2; i++) { + if (hd_table[i]) { + ide_create_drive(&s->bus, i, hd_table[i]); + } + } +} + +void macio_ide_register_dma(MACIOIDEState *s, void *dbdma, int channel) +{ + s->dbdma = dbdma; + DBDMA_register_channel(dbdma, channel, s->dma_irq, + pmac_ide_transfer, pmac_ide_flush, s); +} + +type_init(macio_ide_register_types) diff --git a/hw/ppc/mac.h b/hw/ppc/mac.h index e375ed2..ecf7792 100644 --- a/hw/ppc/mac.h +++ b/hw/ppc/mac.h @@ -134,7 +134,6 @@ typedef struct MACIOIDEState { MemoryRegion mem; IDEBus bus; - BlockAIOCB *aiocb; IDEDMA dma; void *dbdma; bool dma_active;