#include <hw/hw.h>
#include <hw/ppc_mac.h>
#include <hw/mac_dbdma.h>
-#include "block.h"
-#include "block_int.h"
-#include "sysemu.h"
-#include "dma.h"
+#include "block/block.h"
+#include "sysemu/dma.h"
#include <hw/ide/internal.h>
/* MacIO based PowerPC IDE */
typedef struct MACIOIDEState {
+ MemoryRegion mem;
IDEBus bus;
BlockDriverAIOCB *aiocb;
} MACIOIDEState;
+#define MACIO_PAGE_SIZE 4096
+
static void pmac_ide_atapi_transfer_cb(void *opaque, int ret)
{
DBDMA_io *io = opaque;
m->aiocb = NULL;
qemu_sglist_destroy(&s->sg);
ide_atapi_io_error(s, ret);
- io->dma_end(opaque);
- return;
+ goto done;
}
if (s->io_buffer_size > 0) {
ide_atapi_cmd_ok(s);
if (io->len == 0) {
- io->dma_end(opaque);
- return;
+ goto done;
}
/* launch next transfer */
s->io_buffer_size = io->len;
- qemu_sglist_init(&s->sg, io->len / TARGET_PAGE_SIZE + 1);
+ qemu_sglist_init(&s->sg, io->len / MACIO_PAGE_SIZE + 1,
+ &dma_context_memory);
qemu_sglist_add(&s->sg, io->addr, io->len);
io->addr += io->len;
io->len = 0;
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);
- if (!m->aiocb) {
- qemu_sglist_destroy(&s->sg);
- /* Note: media not present is the most likely case */
- ide_atapi_cmd_error(s, SENSE_NOT_READY,
- ASC_MEDIUM_NOT_PRESENT);
- io->dma_end(opaque);
- return;
- }
+ return;
+
+done:
+ bdrv_acct_done(s->bs, &s->acct);
+ io->dma_end(opaque);
}
static void pmac_ide_transfer_cb(void *opaque, int ret)
m->aiocb = NULL;
qemu_sglist_destroy(&s->sg);
ide_dma_error(s);
- io->dma_end(io);
- return;
+ goto done;
}
sector_num = ide_get_sector(s);
/* end of transfer ? */
if (s->nsector == 0) {
s->status = READY_STAT | SEEK_STAT;
- ide_set_irq(s);
+ ide_set_irq(s->bus);
}
/* end of DMA ? */
-
if (io->len == 0) {
- io->dma_end(io);
- return;
+ goto done;
}
/* launch next transfer */
s->io_buffer_index = 0;
s->io_buffer_size = io->len;
- qemu_sglist_init(&s->sg, io->len / TARGET_PAGE_SIZE + 1);
+ qemu_sglist_init(&s->sg, io->len / MACIO_PAGE_SIZE + 1,
+ &dma_context_memory);
qemu_sglist_add(&s->sg, io->addr, io->len);
io->addr += io->len;
io->len = 0;
- if (s->is_read)
+ switch (s->dma_cmd) {
+ case IDE_DMA_READ:
m->aiocb = dma_bdrv_read(s->bs, &s->sg, sector_num,
pmac_ide_transfer_cb, io);
- else
+ break;
+ case IDE_DMA_WRITE:
m->aiocb = dma_bdrv_write(s->bs, &s->sg, sector_num,
pmac_ide_transfer_cb, io);
- if (!m->aiocb)
- pmac_ide_transfer_cb(io, -1);
+ break;
+ case IDE_DMA_TRIM:
+ m->aiocb = dma_bdrv_io(s->bs, &s->sg, sector_num,
+ ide_issue_trim, pmac_ide_transfer_cb, s,
+ DMA_DIRECTION_TO_DEVICE);
+ break;
+ }
+ return;
+
+done:
+ if (s->dma_cmd == IDE_DMA_READ || s->dma_cmd == IDE_DMA_WRITE) {
+ bdrv_acct_done(s->bs, &s->acct);
+ }
+ io->dma_end(io);
}
static void pmac_ide_transfer(DBDMA_io *io)
IDEState *s = idebus_active_if(&m->bus);
s->io_buffer_size = 0;
- if (s->is_cdrom) {
+ if (s->drive_kind == IDE_CD) {
+ bdrv_acct_start(s->bs, &s->acct, io->len, BDRV_ACCT_READ);
pmac_ide_atapi_transfer_cb(io, 0);
return;
}
+ switch (s->dma_cmd) {
+ case IDE_DMA_READ:
+ bdrv_acct_start(s->bs, &s->acct, io->len, BDRV_ACCT_READ);
+ break;
+ case IDE_DMA_WRITE:
+ bdrv_acct_start(s->bs, &s->acct, io->len, BDRV_ACCT_WRITE);
+ break;
+ default:
+ break;
+ }
+
pmac_ide_transfer_cb(io, 0);
}
{
MACIOIDEState *m = io->opaque;
- if (m->aiocb)
- qemu_aio_flush();
+ if (m->aiocb) {
+ bdrv_drain_all();
+ }
}
/* PowerMac IDE memory IO */
static void pmac_ide_writeb (void *opaque,
- target_phys_addr_t addr, uint32_t val)
+ hwaddr addr, uint32_t val)
{
MACIOIDEState *d = opaque;
}
}
-static uint32_t pmac_ide_readb (void *opaque,target_phys_addr_t addr)
+static uint32_t pmac_ide_readb (void *opaque,hwaddr addr)
{
uint8_t retval;
MACIOIDEState *d = opaque;
}
static void pmac_ide_writew (void *opaque,
- target_phys_addr_t addr, uint32_t val)
+ hwaddr addr, uint32_t val)
{
MACIOIDEState *d = opaque;
addr = (addr & 0xFFF) >> 4;
-#ifdef TARGET_WORDS_BIGENDIAN
val = bswap16(val);
-#endif
if (addr == 0) {
ide_data_writew(&d->bus, 0, val);
}
}
-static uint32_t pmac_ide_readw (void *opaque,target_phys_addr_t addr)
+static uint32_t pmac_ide_readw (void *opaque,hwaddr addr)
{
uint16_t retval;
MACIOIDEState *d = opaque;
} else {
retval = 0xFFFF;
}
-#ifdef TARGET_WORDS_BIGENDIAN
retval = bswap16(retval);
-#endif
return retval;
}
static void pmac_ide_writel (void *opaque,
- target_phys_addr_t addr, uint32_t val)
+ hwaddr addr, uint32_t val)
{
MACIOIDEState *d = opaque;
addr = (addr & 0xFFF) >> 4;
-#ifdef TARGET_WORDS_BIGENDIAN
val = bswap32(val);
-#endif
if (addr == 0) {
ide_data_writel(&d->bus, 0, val);
}
}
-static uint32_t pmac_ide_readl (void *opaque,target_phys_addr_t addr)
+static uint32_t pmac_ide_readl (void *opaque,hwaddr addr)
{
uint32_t retval;
MACIOIDEState *d = opaque;
} else {
retval = 0xFFFFFFFF;
}
-#ifdef TARGET_WORDS_BIGENDIAN
retval = bswap32(retval);
-#endif
return retval;
}
-static CPUWriteMemoryFunc * const pmac_ide_write[] = {
- pmac_ide_writeb,
- pmac_ide_writew,
- pmac_ide_writel,
-};
-
-static CPUReadMemoryFunc * const pmac_ide_read[] = {
- pmac_ide_readb,
- pmac_ide_readw,
- pmac_ide_readl,
+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 void pmac_ide_save(QEMUFile *f, void *opaque)
-{
- MACIOIDEState *d = opaque;
- unsigned int i;
-
- /* per IDE interface data */
- idebus_save(f, &d->bus);
-
- /* per IDE drive data */
- for(i = 0; i < 2; i++) {
- ide_save(f, &d->bus.ifs[i]);
+static const VMStateDescription vmstate_pmac = {
+ .name = "ide",
+ .version_id = 3,
+ .minimum_version_id = 0,
+ .minimum_version_id_old = 0,
+ .fields = (VMStateField []) {
+ VMSTATE_IDE_BUS(bus, MACIOIDEState),
+ VMSTATE_IDE_DRIVES(bus.ifs, MACIOIDEState),
+ VMSTATE_END_OF_LIST()
}
-}
-
-static int pmac_ide_load(QEMUFile *f, void *opaque, int version_id)
-{
- MACIOIDEState *d = opaque;
- unsigned int i;
-
- if (version_id != 1 && version_id != 3)
- return -EINVAL;
-
- /* per IDE interface data */
- idebus_load(f, &d->bus, version_id);
-
- /* per IDE drive data */
- for(i = 0; i < 2; i++) {
- ide_load(f, &d->bus.ifs[i], version_id);
- }
- return 0;
-}
+};
static void pmac_ide_reset(void *opaque)
{
MACIOIDEState *d = opaque;
- ide_reset(d->bus.ifs +0);
- ide_reset(d->bus.ifs +1);
+ ide_bus_reset(&d->bus);
}
/* hd_table must contain 4 block drivers */
/* PowerMac uses memory mapped registers, not I/O. Return the memory
I/O index to access the ide. */
-int pmac_ide_init (DriveInfo **hd_table, qemu_irq irq,
- void *dbdma, int channel, qemu_irq dma_irq)
+MemoryRegion *pmac_ide_init (DriveInfo **hd_table, qemu_irq irq,
+ void *dbdma, int channel, qemu_irq dma_irq)
{
MACIOIDEState *d;
- int pmac_ide_memory;
- d = qemu_mallocz(sizeof(MACIOIDEState));
- ide_init2(&d->bus, hd_table[0], hd_table[1], irq);
+ d = g_malloc0(sizeof(MACIOIDEState));
+ ide_init2_with_non_qdev_drives(&d->bus, hd_table[0], hd_table[1], irq);
if (dbdma)
DBDMA_register_channel(dbdma, channel, dma_irq, pmac_ide_transfer, pmac_ide_flush, d);
- pmac_ide_memory = cpu_register_io_memory(pmac_ide_read,
- pmac_ide_write, d);
- register_savevm("ide", 0, 3, pmac_ide_save, pmac_ide_load, d);
+ memory_region_init_io(&d->mem, &pmac_ide_ops, d, "pmac-ide", 0x1000);
+ vmstate_register(NULL, 0, &vmstate_pmac, d);
qemu_register_reset(pmac_ide_reset, d);
- pmac_ide_reset(d);
- return pmac_ide_memory;
+ return &d->mem;
}