|
|
1.1 ! root 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 <hw/hw.h> ! 26: #include <hw/ppc_mac.h> ! 27: #include <hw/mac_dbdma.h> ! 28: #include "block.h" ! 29: #include "block_int.h" ! 30: #include "sysemu.h" ! 31: #include "dma.h" ! 32: ! 33: #include <hw/ide/internal.h> ! 34: ! 35: /***********************************************************/ ! 36: /* MacIO based PowerPC IDE */ ! 37: ! 38: typedef struct MACIOIDEState { ! 39: IDEBus bus; ! 40: BlockDriverAIOCB *aiocb; ! 41: } MACIOIDEState; ! 42: ! 43: static void pmac_ide_atapi_transfer_cb(void *opaque, int ret) ! 44: { ! 45: DBDMA_io *io = opaque; ! 46: MACIOIDEState *m = io->opaque; ! 47: IDEState *s = idebus_active_if(&m->bus); ! 48: ! 49: if (ret < 0) { ! 50: m->aiocb = NULL; ! 51: qemu_sglist_destroy(&s->sg); ! 52: ide_atapi_io_error(s, ret); ! 53: io->dma_end(opaque); ! 54: return; ! 55: } ! 56: ! 57: if (s->io_buffer_size > 0) { ! 58: m->aiocb = NULL; ! 59: qemu_sglist_destroy(&s->sg); ! 60: ! 61: s->packet_transfer_size -= s->io_buffer_size; ! 62: ! 63: s->io_buffer_index += s->io_buffer_size; ! 64: s->lba += s->io_buffer_index >> 11; ! 65: s->io_buffer_index &= 0x7ff; ! 66: } ! 67: ! 68: if (s->packet_transfer_size <= 0) ! 69: ide_atapi_cmd_ok(s); ! 70: ! 71: if (io->len == 0) { ! 72: io->dma_end(opaque); ! 73: return; ! 74: } ! 75: ! 76: /* launch next transfer */ ! 77: ! 78: s->io_buffer_size = io->len; ! 79: ! 80: qemu_sglist_init(&s->sg, io->len / TARGET_PAGE_SIZE + 1); ! 81: qemu_sglist_add(&s->sg, io->addr, io->len); ! 82: io->addr += io->len; ! 83: io->len = 0; ! 84: ! 85: m->aiocb = dma_bdrv_read(s->bs, &s->sg, ! 86: (int64_t)(s->lba << 2) + (s->io_buffer_index >> 9), ! 87: pmac_ide_atapi_transfer_cb, io); ! 88: if (!m->aiocb) { ! 89: qemu_sglist_destroy(&s->sg); ! 90: /* Note: media not present is the most likely case */ ! 91: ide_atapi_cmd_error(s, SENSE_NOT_READY, ! 92: ASC_MEDIUM_NOT_PRESENT); ! 93: io->dma_end(opaque); ! 94: return; ! 95: } ! 96: } ! 97: ! 98: static void pmac_ide_transfer_cb(void *opaque, int ret) ! 99: { ! 100: DBDMA_io *io = opaque; ! 101: MACIOIDEState *m = io->opaque; ! 102: IDEState *s = idebus_active_if(&m->bus); ! 103: int n; ! 104: int64_t sector_num; ! 105: ! 106: if (ret < 0) { ! 107: m->aiocb = NULL; ! 108: qemu_sglist_destroy(&s->sg); ! 109: ide_dma_error(s); ! 110: io->dma_end(io); ! 111: return; ! 112: } ! 113: ! 114: sector_num = ide_get_sector(s); ! 115: if (s->io_buffer_size > 0) { ! 116: m->aiocb = NULL; ! 117: qemu_sglist_destroy(&s->sg); ! 118: n = (s->io_buffer_size + 0x1ff) >> 9; ! 119: sector_num += n; ! 120: ide_set_sector(s, sector_num); ! 121: s->nsector -= n; ! 122: } ! 123: ! 124: /* end of transfer ? */ ! 125: if (s->nsector == 0) { ! 126: s->status = READY_STAT | SEEK_STAT; ! 127: ide_set_irq(s->bus); ! 128: } ! 129: ! 130: /* end of DMA ? */ ! 131: ! 132: if (io->len == 0) { ! 133: io->dma_end(io); ! 134: return; ! 135: } ! 136: ! 137: /* launch next transfer */ ! 138: ! 139: s->io_buffer_index = 0; ! 140: s->io_buffer_size = io->len; ! 141: ! 142: qemu_sglist_init(&s->sg, io->len / TARGET_PAGE_SIZE + 1); ! 143: qemu_sglist_add(&s->sg, io->addr, io->len); ! 144: io->addr += io->len; ! 145: io->len = 0; ! 146: ! 147: if (s->is_read) ! 148: m->aiocb = dma_bdrv_read(s->bs, &s->sg, sector_num, ! 149: pmac_ide_transfer_cb, io); ! 150: else ! 151: m->aiocb = dma_bdrv_write(s->bs, &s->sg, sector_num, ! 152: pmac_ide_transfer_cb, io); ! 153: if (!m->aiocb) ! 154: pmac_ide_transfer_cb(io, -1); ! 155: } ! 156: ! 157: static void pmac_ide_transfer(DBDMA_io *io) ! 158: { ! 159: MACIOIDEState *m = io->opaque; ! 160: IDEState *s = idebus_active_if(&m->bus); ! 161: ! 162: s->io_buffer_size = 0; ! 163: if (s->is_cdrom) { ! 164: pmac_ide_atapi_transfer_cb(io, 0); ! 165: return; ! 166: } ! 167: ! 168: pmac_ide_transfer_cb(io, 0); ! 169: } ! 170: ! 171: static void pmac_ide_flush(DBDMA_io *io) ! 172: { ! 173: MACIOIDEState *m = io->opaque; ! 174: ! 175: if (m->aiocb) ! 176: qemu_aio_flush(); ! 177: } ! 178: ! 179: /* PowerMac IDE memory IO */ ! 180: static void pmac_ide_writeb (void *opaque, ! 181: target_phys_addr_t addr, uint32_t val) ! 182: { ! 183: MACIOIDEState *d = opaque; ! 184: ! 185: addr = (addr & 0xFFF) >> 4; ! 186: switch (addr) { ! 187: case 1 ... 7: ! 188: ide_ioport_write(&d->bus, addr, val); ! 189: break; ! 190: case 8: ! 191: case 22: ! 192: ide_cmd_write(&d->bus, 0, val); ! 193: break; ! 194: default: ! 195: break; ! 196: } ! 197: } ! 198: ! 199: static uint32_t pmac_ide_readb (void *opaque,target_phys_addr_t addr) ! 200: { ! 201: uint8_t retval; ! 202: MACIOIDEState *d = opaque; ! 203: ! 204: addr = (addr & 0xFFF) >> 4; ! 205: switch (addr) { ! 206: case 1 ... 7: ! 207: retval = ide_ioport_read(&d->bus, addr); ! 208: break; ! 209: case 8: ! 210: case 22: ! 211: retval = ide_status_read(&d->bus, 0); ! 212: break; ! 213: default: ! 214: retval = 0xFF; ! 215: break; ! 216: } ! 217: return retval; ! 218: } ! 219: ! 220: static void pmac_ide_writew (void *opaque, ! 221: target_phys_addr_t addr, uint32_t val) ! 222: { ! 223: MACIOIDEState *d = opaque; ! 224: ! 225: addr = (addr & 0xFFF) >> 4; ! 226: #ifdef TARGET_WORDS_BIGENDIAN ! 227: val = bswap16(val); ! 228: #endif ! 229: if (addr == 0) { ! 230: ide_data_writew(&d->bus, 0, val); ! 231: } ! 232: } ! 233: ! 234: static uint32_t pmac_ide_readw (void *opaque,target_phys_addr_t addr) ! 235: { ! 236: uint16_t retval; ! 237: MACIOIDEState *d = opaque; ! 238: ! 239: addr = (addr & 0xFFF) >> 4; ! 240: if (addr == 0) { ! 241: retval = ide_data_readw(&d->bus, 0); ! 242: } else { ! 243: retval = 0xFFFF; ! 244: } ! 245: #ifdef TARGET_WORDS_BIGENDIAN ! 246: retval = bswap16(retval); ! 247: #endif ! 248: return retval; ! 249: } ! 250: ! 251: static void pmac_ide_writel (void *opaque, ! 252: target_phys_addr_t addr, uint32_t val) ! 253: { ! 254: MACIOIDEState *d = opaque; ! 255: ! 256: addr = (addr & 0xFFF) >> 4; ! 257: #ifdef TARGET_WORDS_BIGENDIAN ! 258: val = bswap32(val); ! 259: #endif ! 260: if (addr == 0) { ! 261: ide_data_writel(&d->bus, 0, val); ! 262: } ! 263: } ! 264: ! 265: static uint32_t pmac_ide_readl (void *opaque,target_phys_addr_t addr) ! 266: { ! 267: uint32_t retval; ! 268: MACIOIDEState *d = opaque; ! 269: ! 270: addr = (addr & 0xFFF) >> 4; ! 271: if (addr == 0) { ! 272: retval = ide_data_readl(&d->bus, 0); ! 273: } else { ! 274: retval = 0xFFFFFFFF; ! 275: } ! 276: #ifdef TARGET_WORDS_BIGENDIAN ! 277: retval = bswap32(retval); ! 278: #endif ! 279: return retval; ! 280: } ! 281: ! 282: static CPUWriteMemoryFunc * const pmac_ide_write[] = { ! 283: pmac_ide_writeb, ! 284: pmac_ide_writew, ! 285: pmac_ide_writel, ! 286: }; ! 287: ! 288: static CPUReadMemoryFunc * const pmac_ide_read[] = { ! 289: pmac_ide_readb, ! 290: pmac_ide_readw, ! 291: pmac_ide_readl, ! 292: }; ! 293: ! 294: static const VMStateDescription vmstate_pmac = { ! 295: .name = "ide", ! 296: .version_id = 3, ! 297: .minimum_version_id = 0, ! 298: .minimum_version_id_old = 0, ! 299: .fields = (VMStateField []) { ! 300: VMSTATE_IDE_BUS(bus, MACIOIDEState), ! 301: VMSTATE_IDE_DRIVES(bus.ifs, MACIOIDEState), ! 302: VMSTATE_END_OF_LIST() ! 303: } ! 304: }; ! 305: ! 306: static void pmac_ide_reset(void *opaque) ! 307: { ! 308: MACIOIDEState *d = opaque; ! 309: ! 310: ide_bus_reset(&d->bus); ! 311: } ! 312: ! 313: /* hd_table must contain 4 block drivers */ ! 314: /* PowerMac uses memory mapped registers, not I/O. Return the memory ! 315: I/O index to access the ide. */ ! 316: int pmac_ide_init (DriveInfo **hd_table, qemu_irq irq, ! 317: void *dbdma, int channel, qemu_irq dma_irq) ! 318: { ! 319: MACIOIDEState *d; ! 320: int pmac_ide_memory; ! 321: ! 322: d = qemu_mallocz(sizeof(MACIOIDEState)); ! 323: ide_init2(&d->bus, hd_table[0], hd_table[1], irq); ! 324: ! 325: if (dbdma) ! 326: DBDMA_register_channel(dbdma, channel, dma_irq, pmac_ide_transfer, pmac_ide_flush, d); ! 327: ! 328: pmac_ide_memory = cpu_register_io_memory(pmac_ide_read, ! 329: pmac_ide_write, d); ! 330: vmstate_register(0, &vmstate_pmac, d); ! 331: qemu_register_reset(pmac_ide_reset, d); ! 332: ! 333: return pmac_ide_memory; ! 334: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.