qemu/hw/ide/macio.c
<<
>>
Prefs
   1/*
   2 * QEMU IDE Emulation: MacIO support.
   3 *
   4 * Copyright (c) 2003 Fabrice Bellard
   5 * Copyright (c) 2006 Openedhand Ltd.
   6 *
   7 * Permission is hereby granted, free of charge, to any person obtaining a copy
   8 * of this software and associated documentation files (the "Software"), to deal
   9 * in the Software without restriction, including without limitation the rights
  10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  11 * copies of the Software, and to permit persons to whom the Software is
  12 * furnished to do so, subject to the following conditions:
  13 *
  14 * The above copyright notice and this permission notice shall be included in
  15 * all copies or substantial portions of the Software.
  16 *
  17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  23 * THE SOFTWARE.
  24 */
  25#include "qemu/osdep.h"
  26#include "hw/hw.h"
  27#include "hw/ppc/mac.h"
  28#include "hw/ppc/mac_dbdma.h"
  29#include "hw/misc/macio/macio.h"
  30#include "sysemu/block-backend.h"
  31#include "sysemu/dma.h"
  32
  33#include "hw/ide/internal.h"
  34
  35/* debug MACIO */
  36// #define DEBUG_MACIO
  37
  38#ifdef DEBUG_MACIO
  39static const int debug_macio = 1;
  40#else
  41static const int debug_macio = 0;
  42#endif
  43
  44#define MACIO_DPRINTF(fmt, ...) do { \
  45        if (debug_macio) { \
  46            printf(fmt , ## __VA_ARGS__); \
  47        } \
  48    } while (0)
  49
  50
  51/***********************************************************/
  52/* MacIO based PowerPC IDE */
  53
  54#define MACIO_PAGE_SIZE 4096
  55
  56static void pmac_ide_atapi_transfer_cb(void *opaque, int ret)
  57{
  58    DBDMA_io *io = opaque;
  59    MACIOIDEState *m = io->opaque;
  60    IDEState *s = idebus_active_if(&m->bus);
  61    int64_t offset;
  62
  63    MACIO_DPRINTF("pmac_ide_atapi_transfer_cb\n");
  64
  65    if (ret < 0) {
  66        MACIO_DPRINTF("DMA error: %d\n", ret);
  67        qemu_sglist_destroy(&s->sg);
  68        ide_atapi_io_error(s, ret);
  69        goto done;
  70    }
  71
  72    if (!m->dma_active) {
  73        MACIO_DPRINTF("waiting for data (%#x - %#x - %x)\n",
  74                      s->nsector, io->len, s->status);
  75        /* data not ready yet, wait for the channel to get restarted */
  76        io->processing = false;
  77        return;
  78    }
  79
  80    if (s->io_buffer_size <= 0) {
  81        MACIO_DPRINTF("End of IDE transfer\n");
  82        qemu_sglist_destroy(&s->sg);
  83        ide_atapi_cmd_ok(s);
  84        m->dma_active = false;
  85        goto done;
  86    }
  87
  88    if (io->len == 0) {
  89        MACIO_DPRINTF("End of DMA transfer\n");
  90        goto done;
  91    }
  92
  93    if (s->lba == -1) {
  94        /* Non-block ATAPI transfer - just copy to RAM */
  95        s->io_buffer_size = MIN(s->io_buffer_size, io->len);
  96        dma_memory_write(&address_space_memory, io->addr, s->io_buffer,
  97                         s->io_buffer_size);
  98        io->len = 0;
  99        ide_atapi_cmd_ok(s);
 100        m->dma_active = false;
 101        goto done;
 102    }
 103
 104    /* Calculate current offset */
 105    offset = ((int64_t)s->lba << 11) + s->io_buffer_index;
 106
 107    qemu_sglist_init(&s->sg, DEVICE(m), io->len / MACIO_PAGE_SIZE + 1,
 108                     &address_space_memory);
 109    qemu_sglist_add(&s->sg, io->addr, io->len);
 110    s->io_buffer_size -= io->len;
 111    s->io_buffer_index += io->len;
 112    io->len = 0;
 113
 114    s->bus->dma->aiocb = dma_blk_read(s->blk, &s->sg, offset, 0x1,
 115                                      pmac_ide_atapi_transfer_cb, io);
 116    return;
 117
 118done:
 119    dma_memory_unmap(&address_space_memory, io->dma_mem, io->dma_len,
 120                     io->dir, io->dma_len);
 121
 122    if (ret < 0) {
 123        block_acct_failed(blk_get_stats(s->blk), &s->acct);
 124    } else {
 125        block_acct_done(blk_get_stats(s->blk), &s->acct);
 126    }
 127
 128    ide_set_inactive(s, false);
 129    io->dma_end(opaque);
 130}
 131
 132static void pmac_ide_transfer_cb(void *opaque, int ret)
 133{
 134    DBDMA_io *io = opaque;
 135    MACIOIDEState *m = io->opaque;
 136    IDEState *s = idebus_active_if(&m->bus);
 137    int64_t offset;
 138
 139    MACIO_DPRINTF("pmac_ide_transfer_cb\n");
 140
 141    if (ret < 0) {
 142        MACIO_DPRINTF("DMA error: %d\n", ret);
 143        qemu_sglist_destroy(&s->sg);
 144        ide_dma_error(s);
 145        goto done;
 146    }
 147
 148    if (!m->dma_active) {
 149        MACIO_DPRINTF("waiting for data (%#x - %#x - %x)\n",
 150                      s->nsector, io->len, s->status);
 151        /* data not ready yet, wait for the channel to get restarted */
 152        io->processing = false;
 153        return;
 154    }
 155
 156    if (s->io_buffer_size <= 0) {
 157        MACIO_DPRINTF("End of IDE transfer\n");
 158        qemu_sglist_destroy(&s->sg);
 159        s->status = READY_STAT | SEEK_STAT;
 160        ide_set_irq(s->bus);
 161        m->dma_active = false;
 162        goto done;
 163    }
 164
 165    if (io->len == 0) {
 166        MACIO_DPRINTF("End of DMA transfer\n");
 167        goto done;
 168    }
 169
 170    /* Calculate number of sectors */
 171    offset = (ide_get_sector(s) << 9) + s->io_buffer_index;
 172
 173    qemu_sglist_init(&s->sg, DEVICE(m), io->len / MACIO_PAGE_SIZE + 1,
 174                     &address_space_memory);
 175    qemu_sglist_add(&s->sg, io->addr, io->len);
 176    s->io_buffer_size -= io->len;
 177    s->io_buffer_index += io->len;
 178    io->len = 0;
 179
 180    switch (s->dma_cmd) {
 181    case IDE_DMA_READ:
 182        s->bus->dma->aiocb = dma_blk_read(s->blk, &s->sg, offset, 0x1,
 183                                          pmac_ide_atapi_transfer_cb, io);
 184        break;
 185    case IDE_DMA_WRITE:
 186        s->bus->dma->aiocb = dma_blk_write(s->blk, &s->sg, offset, 0x1,
 187                                           pmac_ide_transfer_cb, io);
 188        break;
 189    case IDE_DMA_TRIM:
 190        s->bus->dma->aiocb = dma_blk_io(blk_get_aio_context(s->blk), &s->sg,
 191                                        offset, 0x1, ide_issue_trim, s,
 192                                        pmac_ide_transfer_cb, io,
 193                                        DMA_DIRECTION_TO_DEVICE);
 194        break;
 195    default:
 196        abort();
 197    }
 198
 199    return;
 200
 201done:
 202    dma_memory_unmap(&address_space_memory, io->dma_mem, io->dma_len,
 203                     io->dir, io->dma_len);
 204
 205    if (s->dma_cmd == IDE_DMA_READ || s->dma_cmd == IDE_DMA_WRITE) {
 206        if (ret < 0) {
 207            block_acct_failed(blk_get_stats(s->blk), &s->acct);
 208        } else {
 209            block_acct_done(blk_get_stats(s->blk), &s->acct);
 210        }
 211    }
 212
 213    ide_set_inactive(s, false);
 214    io->dma_end(opaque);
 215}
 216
 217static void pmac_ide_transfer(DBDMA_io *io)
 218{
 219    MACIOIDEState *m = io->opaque;
 220    IDEState *s = idebus_active_if(&m->bus);
 221
 222    MACIO_DPRINTF("\n");
 223
 224    if (s->drive_kind == IDE_CD) {
 225        block_acct_start(blk_get_stats(s->blk), &s->acct, io->len,
 226                         BLOCK_ACCT_READ);
 227
 228        pmac_ide_atapi_transfer_cb(io, 0);
 229        return;
 230    }
 231
 232    switch (s->dma_cmd) {
 233    case IDE_DMA_READ:
 234        block_acct_start(blk_get_stats(s->blk), &s->acct, io->len,
 235                         BLOCK_ACCT_READ);
 236        break;
 237    case IDE_DMA_WRITE:
 238        block_acct_start(blk_get_stats(s->blk), &s->acct, io->len,
 239                         BLOCK_ACCT_WRITE);
 240        break;
 241    default:
 242        break;
 243    }
 244
 245    pmac_ide_transfer_cb(io, 0);
 246}
 247
 248static void pmac_ide_flush(DBDMA_io *io)
 249{
 250    MACIOIDEState *m = io->opaque;
 251    IDEState *s = idebus_active_if(&m->bus);
 252
 253    if (s->bus->dma->aiocb) {
 254        blk_drain(s->blk);
 255    }
 256}
 257
 258/* PowerMac IDE memory IO */
 259static uint64_t pmac_ide_read(void *opaque, hwaddr addr, unsigned size)
 260{
 261    MACIOIDEState *d = opaque;
 262    uint64_t retval = 0xffffffff;
 263    int reg = addr >> 4;
 264
 265    switch (reg) {
 266    case 0x0:
 267        if (size == 2) {
 268            retval = ide_data_readw(&d->bus, 0);
 269        } else if (size == 4) {
 270            retval = ide_data_readl(&d->bus, 0);
 271        }
 272        break;
 273    case 0x1 ... 0x7:
 274        if (size == 1) {
 275            retval = ide_ioport_read(&d->bus, reg);
 276        }
 277        break;
 278    case 0x8:
 279    case 0x16:
 280        if (size == 1) {
 281            retval = ide_status_read(&d->bus, 0);
 282        }
 283        break;
 284    case 0x20:
 285        if (size == 4) {
 286            retval = d->timing_reg;
 287        }
 288        break;
 289    case 0x30:
 290        /* This is an interrupt state register that only exists
 291         * in the KeyLargo and later variants. Bit 0x8000_0000
 292         * latches the DMA interrupt and has to be written to
 293         * clear. Bit 0x4000_0000 is an image of the disk
 294         * interrupt. MacOS X relies on this and will hang if
 295         * we don't provide at least the disk interrupt
 296         */
 297        if (size == 4) {
 298            retval = d->irq_reg;
 299        }
 300        break;
 301    }
 302
 303    return retval;
 304}
 305
 306
 307static void pmac_ide_write(void *opaque, hwaddr addr, uint64_t val,
 308                           unsigned size)
 309{
 310    MACIOIDEState *d = opaque;
 311    int reg = addr >> 4;
 312
 313    switch (reg) {
 314    case 0x0:
 315        if (size == 2) {
 316            ide_data_writew(&d->bus, 0, val);
 317        } else if (size == 4) {
 318            ide_data_writel(&d->bus, 0, val);
 319        }
 320        break;
 321    case 0x1 ... 0x7:
 322        if (size == 1) {
 323            ide_ioport_write(&d->bus, reg, val);
 324        }
 325        break;
 326    case 0x8:
 327    case 0x16:
 328        if (size == 1) {
 329            ide_cmd_write(&d->bus, 0, val);
 330        }
 331        break;
 332    case 0x20:
 333        if (size == 4) {
 334            d->timing_reg = val;
 335        }
 336        break;
 337    case 0x30:
 338        if (size == 4) {
 339            if (val & 0x80000000u) {
 340                d->irq_reg &= 0x7fffffff;
 341            }
 342        }
 343        break;
 344    }
 345}
 346
 347static const MemoryRegionOps pmac_ide_ops = {
 348    .read = pmac_ide_read,
 349    .write = pmac_ide_write,
 350    .valid.min_access_size = 1,
 351    .valid.max_access_size = 4,
 352    .endianness = DEVICE_LITTLE_ENDIAN,
 353};
 354
 355static const VMStateDescription vmstate_pmac = {
 356    .name = "ide",
 357    .version_id = 5,
 358    .minimum_version_id = 0,
 359    .fields = (VMStateField[]) {
 360        VMSTATE_IDE_BUS(bus, MACIOIDEState),
 361        VMSTATE_IDE_DRIVES(bus.ifs, MACIOIDEState),
 362        VMSTATE_BOOL(dma_active, MACIOIDEState),
 363        VMSTATE_UINT32(timing_reg, MACIOIDEState),
 364        VMSTATE_UINT32(irq_reg, MACIOIDEState),
 365        VMSTATE_END_OF_LIST()
 366    }
 367};
 368
 369static void macio_ide_reset(DeviceState *dev)
 370{
 371    MACIOIDEState *d = MACIO_IDE(dev);
 372
 373    ide_bus_reset(&d->bus);
 374}
 375
 376static int ide_nop_int(IDEDMA *dma, int x)
 377{
 378    return 0;
 379}
 380
 381static int32_t ide_nop_int32(IDEDMA *dma, int32_t l)
 382{
 383    return 0;
 384}
 385
 386static void ide_dbdma_start(IDEDMA *dma, IDEState *s,
 387                            BlockCompletionFunc *cb)
 388{
 389    MACIOIDEState *m = container_of(dma, MACIOIDEState, dma);
 390
 391    s->io_buffer_index = 0;
 392    if (s->drive_kind == IDE_CD) {
 393        s->io_buffer_size = s->packet_transfer_size;
 394    } else {
 395        s->io_buffer_size = s->nsector * BDRV_SECTOR_SIZE;
 396    }
 397
 398    MACIO_DPRINTF("\n\n------------ IDE transfer\n");
 399    MACIO_DPRINTF("buffer_size: %x   buffer_index: %x\n",
 400                  s->io_buffer_size, s->io_buffer_index);
 401    MACIO_DPRINTF("lba: %x    size: %x\n", s->lba, s->io_buffer_size);
 402    MACIO_DPRINTF("-------------------------\n");
 403
 404    m->dma_active = true;
 405    DBDMA_kick(m->dbdma);
 406}
 407
 408static const IDEDMAOps dbdma_ops = {
 409    .start_dma      = ide_dbdma_start,
 410    .prepare_buf    = ide_nop_int32,
 411    .rw_buf         = ide_nop_int,
 412};
 413
 414static void macio_ide_realizefn(DeviceState *dev, Error **errp)
 415{
 416    MACIOIDEState *s = MACIO_IDE(dev);
 417
 418    ide_init2(&s->bus, s->ide_irq);
 419
 420    /* Register DMA callbacks */
 421    s->dma.ops = &dbdma_ops;
 422    s->bus.dma = &s->dma;
 423}
 424
 425static void pmac_ide_irq(void *opaque, int n, int level)
 426{
 427    MACIOIDEState *s = opaque;
 428    uint32_t mask = 0x80000000u >> n;
 429
 430    /* We need to reflect the IRQ state in the irq register */
 431    if (level) {
 432        s->irq_reg |= mask;
 433    } else {
 434        s->irq_reg &= ~mask;
 435    }
 436
 437    if (n) {
 438        qemu_set_irq(s->real_ide_irq, level);
 439    } else {
 440        qemu_set_irq(s->real_dma_irq, level);
 441    }
 442}
 443
 444static void macio_ide_initfn(Object *obj)
 445{
 446    SysBusDevice *d = SYS_BUS_DEVICE(obj);
 447    MACIOIDEState *s = MACIO_IDE(obj);
 448
 449    ide_bus_new(&s->bus, sizeof(s->bus), DEVICE(obj), 0, 2);
 450    memory_region_init_io(&s->mem, obj, &pmac_ide_ops, s, "pmac-ide", 0x1000);
 451    sysbus_init_mmio(d, &s->mem);
 452    sysbus_init_irq(d, &s->real_ide_irq);
 453    sysbus_init_irq(d, &s->real_dma_irq);
 454    s->dma_irq = qemu_allocate_irq(pmac_ide_irq, s, 0);
 455    s->ide_irq = qemu_allocate_irq(pmac_ide_irq, s, 1);
 456
 457    object_property_add_link(obj, "dbdma", TYPE_MAC_DBDMA,
 458                             (Object **) &s->dbdma,
 459                             qdev_prop_allow_set_link_before_realize, 0, NULL);
 460}
 461
 462static Property macio_ide_properties[] = {
 463    DEFINE_PROP_UINT32("channel", MACIOIDEState, channel, 0),
 464    DEFINE_PROP_UINT32("addr", MACIOIDEState, addr, -1),
 465    DEFINE_PROP_END_OF_LIST(),
 466};
 467
 468static void macio_ide_class_init(ObjectClass *oc, void *data)
 469{
 470    DeviceClass *dc = DEVICE_CLASS(oc);
 471
 472    dc->realize = macio_ide_realizefn;
 473    dc->reset = macio_ide_reset;
 474    dc->props = macio_ide_properties;
 475    dc->vmsd = &vmstate_pmac;
 476    set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
 477}
 478
 479static const TypeInfo macio_ide_type_info = {
 480    .name = TYPE_MACIO_IDE,
 481    .parent = TYPE_SYS_BUS_DEVICE,
 482    .instance_size = sizeof(MACIOIDEState),
 483    .instance_init = macio_ide_initfn,
 484    .class_init = macio_ide_class_init,
 485};
 486
 487static void macio_ide_register_types(void)
 488{
 489    type_register_static(&macio_ide_type_info);
 490}
 491
 492/* hd_table must contain 2 block drivers */
 493void macio_ide_init_drives(MACIOIDEState *s, DriveInfo **hd_table)
 494{
 495    int i;
 496
 497    for (i = 0; i < 2; i++) {
 498        if (hd_table[i]) {
 499            ide_create_drive(&s->bus, i, hd_table[i]);
 500        }
 501    }
 502}
 503
 504void macio_ide_register_dma(MACIOIDEState *s)
 505{
 506    DBDMA_register_channel(s->dbdma, s->channel, s->dma_irq,
 507                           pmac_ide_transfer, pmac_ide_flush, s);
 508}
 509
 510type_init(macio_ide_register_types)
 511