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/ppc/mac_dbdma.h" 28 #include "block/block.h" 29 #include "sysemu/dma.h" 30 31 #include <hw/ide/internal.h> 32 33 /* debug MACIO */ 34 // #define DEBUG_MACIO 35 36 #ifdef DEBUG_MACIO 37 static const int debug_macio = 1; 38 #else 39 static const int debug_macio = 0; 40 #endif 41 42 #define MACIO_DPRINTF(fmt, ...) do { \ 43 if (debug_macio) { \ 44 printf(fmt , ## __VA_ARGS__); \ 45 } \ 46 } while (0) 47 48 49 /***********************************************************/ 50 /* MacIO based PowerPC IDE */ 51 52 #define MACIO_PAGE_SIZE 4096 53 54 static void pmac_ide_atapi_transfer_cb(void *opaque, int ret) 55 { 56 DBDMA_io *io = opaque; 57 MACIOIDEState *m = io->opaque; 58 IDEState *s = idebus_active_if(&m->bus); 59 60 if (ret < 0) { 61 m->aiocb = NULL; 62 qemu_sglist_destroy(&s->sg); 63 ide_atapi_io_error(s, ret); 64 goto done; 65 } 66 67 MACIO_DPRINTF("io_buffer_size = %#x\n", s->io_buffer_size); 68 69 if (s->io_buffer_size > 0) { 70 m->aiocb = NULL; 71 qemu_sglist_destroy(&s->sg); 72 73 s->packet_transfer_size -= s->io_buffer_size; 74 75 s->io_buffer_index += s->io_buffer_size; 76 s->lba += s->io_buffer_index >> 11; 77 s->io_buffer_index &= 0x7ff; 78 } 79 80 if (s->packet_transfer_size <= 0) { 81 MACIO_DPRINTF("end of transfer\n"); 82 ide_atapi_cmd_ok(s); 83 } 84 85 if (io->len == 0) { 86 MACIO_DPRINTF("end of DMA\n"); 87 goto done; 88 } 89 90 /* launch next transfer */ 91 92 MACIO_DPRINTF("io->len = %#x\n", io->len); 93 94 s->io_buffer_size = io->len; 95 96 qemu_sglist_init(&s->sg, DEVICE(m), io->len / MACIO_PAGE_SIZE + 1, 97 &address_space_memory); 98 qemu_sglist_add(&s->sg, io->addr, io->len); 99 io->addr += io->len; 100 io->len = 0; 101 102 MACIO_DPRINTF("sector_num=%d size=%d, cmd_cmd=%d\n", 103 (s->lba << 2) + (s->io_buffer_index >> 9), 104 s->packet_transfer_size, s->dma_cmd); 105 106 m->aiocb = dma_bdrv_read(s->bs, &s->sg, 107 (int64_t)(s->lba << 2) + (s->io_buffer_index >> 9), 108 pmac_ide_atapi_transfer_cb, io); 109 return; 110 111 done: 112 MACIO_DPRINTF("done DMA\n"); 113 bdrv_acct_done(s->bs, &s->acct); 114 io->dma_end(opaque); 115 } 116 117 static void pmac_ide_transfer_cb(void *opaque, int ret) 118 { 119 DBDMA_io *io = opaque; 120 MACIOIDEState *m = io->opaque; 121 IDEState *s = idebus_active_if(&m->bus); 122 int n; 123 int64_t sector_num; 124 125 if (ret < 0) { 126 MACIO_DPRINTF("DMA error\n"); 127 m->aiocb = NULL; 128 qemu_sglist_destroy(&s->sg); 129 ide_dma_error(s); 130 goto done; 131 } 132 133 sector_num = ide_get_sector(s); 134 MACIO_DPRINTF("io_buffer_size = %#x\n", s->io_buffer_size); 135 if (s->io_buffer_size > 0) { 136 m->aiocb = NULL; 137 qemu_sglist_destroy(&s->sg); 138 n = (s->io_buffer_size + 0x1ff) >> 9; 139 sector_num += n; 140 ide_set_sector(s, sector_num); 141 s->nsector -= n; 142 } 143 144 if (s->nsector == 0) { 145 MACIO_DPRINTF("end of transfer\n"); 146 s->status = READY_STAT | SEEK_STAT; 147 ide_set_irq(s->bus); 148 } 149 150 if (io->len == 0) { 151 MACIO_DPRINTF("end of DMA\n"); 152 goto done; 153 } 154 155 /* launch next transfer */ 156 157 s->io_buffer_index = 0; 158 s->io_buffer_size = io->len; 159 160 MACIO_DPRINTF("io->len = %#x\n", io->len); 161 162 qemu_sglist_init(&s->sg, DEVICE(m), io->len / MACIO_PAGE_SIZE + 1, 163 &address_space_memory); 164 qemu_sglist_add(&s->sg, io->addr, io->len); 165 io->addr += io->len; 166 io->len = 0; 167 168 MACIO_DPRINTF("sector_num=%" PRId64 " n=%d, nsector=%d, cmd_cmd=%d\n", 169 sector_num, n, s->nsector, s->dma_cmd); 170 171 switch (s->dma_cmd) { 172 case IDE_DMA_READ: 173 m->aiocb = dma_bdrv_read(s->bs, &s->sg, sector_num, 174 pmac_ide_transfer_cb, io); 175 break; 176 case IDE_DMA_WRITE: 177 m->aiocb = dma_bdrv_write(s->bs, &s->sg, sector_num, 178 pmac_ide_transfer_cb, io); 179 break; 180 case IDE_DMA_TRIM: 181 m->aiocb = dma_bdrv_io(s->bs, &s->sg, sector_num, 182 ide_issue_trim, pmac_ide_transfer_cb, io, 183 DMA_DIRECTION_TO_DEVICE); 184 break; 185 } 186 return; 187 188 done: 189 if (s->dma_cmd == IDE_DMA_READ || s->dma_cmd == IDE_DMA_WRITE) { 190 bdrv_acct_done(s->bs, &s->acct); 191 } 192 io->dma_end(io); 193 } 194 195 static void pmac_ide_transfer(DBDMA_io *io) 196 { 197 MACIOIDEState *m = io->opaque; 198 IDEState *s = idebus_active_if(&m->bus); 199 200 MACIO_DPRINTF("\n"); 201 202 s->io_buffer_size = 0; 203 if (s->drive_kind == IDE_CD) { 204 bdrv_acct_start(s->bs, &s->acct, io->len, BDRV_ACCT_READ); 205 pmac_ide_atapi_transfer_cb(io, 0); 206 return; 207 } 208 209 switch (s->dma_cmd) { 210 case IDE_DMA_READ: 211 bdrv_acct_start(s->bs, &s->acct, io->len, BDRV_ACCT_READ); 212 break; 213 case IDE_DMA_WRITE: 214 bdrv_acct_start(s->bs, &s->acct, io->len, BDRV_ACCT_WRITE); 215 break; 216 default: 217 break; 218 } 219 220 pmac_ide_transfer_cb(io, 0); 221 } 222 223 static void pmac_ide_flush(DBDMA_io *io) 224 { 225 MACIOIDEState *m = io->opaque; 226 227 if (m->aiocb) { 228 bdrv_drain_all(); 229 } 230 } 231 232 /* PowerMac IDE memory IO */ 233 static void pmac_ide_writeb (void *opaque, 234 hwaddr addr, uint32_t val) 235 { 236 MACIOIDEState *d = opaque; 237 238 addr = (addr & 0xFFF) >> 4; 239 switch (addr) { 240 case 1 ... 7: 241 ide_ioport_write(&d->bus, addr, val); 242 break; 243 case 8: 244 case 22: 245 ide_cmd_write(&d->bus, 0, val); 246 break; 247 default: 248 break; 249 } 250 } 251 252 static uint32_t pmac_ide_readb (void *opaque,hwaddr addr) 253 { 254 uint8_t retval; 255 MACIOIDEState *d = opaque; 256 257 addr = (addr & 0xFFF) >> 4; 258 switch (addr) { 259 case 1 ... 7: 260 retval = ide_ioport_read(&d->bus, addr); 261 break; 262 case 8: 263 case 22: 264 retval = ide_status_read(&d->bus, 0); 265 break; 266 default: 267 retval = 0xFF; 268 break; 269 } 270 return retval; 271 } 272 273 static void pmac_ide_writew (void *opaque, 274 hwaddr addr, uint32_t val) 275 { 276 MACIOIDEState *d = opaque; 277 278 addr = (addr & 0xFFF) >> 4; 279 val = bswap16(val); 280 if (addr == 0) { 281 ide_data_writew(&d->bus, 0, val); 282 } 283 } 284 285 static uint32_t pmac_ide_readw (void *opaque,hwaddr addr) 286 { 287 uint16_t retval; 288 MACIOIDEState *d = opaque; 289 290 addr = (addr & 0xFFF) >> 4; 291 if (addr == 0) { 292 retval = ide_data_readw(&d->bus, 0); 293 } else { 294 retval = 0xFFFF; 295 } 296 retval = bswap16(retval); 297 return retval; 298 } 299 300 static void pmac_ide_writel (void *opaque, 301 hwaddr addr, uint32_t val) 302 { 303 MACIOIDEState *d = opaque; 304 305 addr = (addr & 0xFFF) >> 4; 306 val = bswap32(val); 307 if (addr == 0) { 308 ide_data_writel(&d->bus, 0, val); 309 } 310 } 311 312 static uint32_t pmac_ide_readl (void *opaque,hwaddr addr) 313 { 314 uint32_t retval; 315 MACIOIDEState *d = opaque; 316 317 addr = (addr & 0xFFF) >> 4; 318 if (addr == 0) { 319 retval = ide_data_readl(&d->bus, 0); 320 } else { 321 retval = 0xFFFFFFFF; 322 } 323 retval = bswap32(retval); 324 return retval; 325 } 326 327 static const MemoryRegionOps pmac_ide_ops = { 328 .old_mmio = { 329 .write = { 330 pmac_ide_writeb, 331 pmac_ide_writew, 332 pmac_ide_writel, 333 }, 334 .read = { 335 pmac_ide_readb, 336 pmac_ide_readw, 337 pmac_ide_readl, 338 }, 339 }, 340 .endianness = DEVICE_NATIVE_ENDIAN, 341 }; 342 343 static const VMStateDescription vmstate_pmac = { 344 .name = "ide", 345 .version_id = 3, 346 .minimum_version_id = 0, 347 .minimum_version_id_old = 0, 348 .fields = (VMStateField []) { 349 VMSTATE_IDE_BUS(bus, MACIOIDEState), 350 VMSTATE_IDE_DRIVES(bus.ifs, MACIOIDEState), 351 VMSTATE_END_OF_LIST() 352 } 353 }; 354 355 static void macio_ide_reset(DeviceState *dev) 356 { 357 MACIOIDEState *d = MACIO_IDE(dev); 358 359 ide_bus_reset(&d->bus); 360 } 361 362 static int ide_nop(IDEDMA *dma) 363 { 364 return 0; 365 } 366 367 static int ide_nop_int(IDEDMA *dma, int x) 368 { 369 return 0; 370 } 371 372 static void ide_nop_restart(void *opaque, int x, RunState y) 373 { 374 } 375 376 static void ide_dbdma_start(IDEDMA *dma, IDEState *s, 377 BlockDriverCompletionFunc *cb) 378 { 379 MACIOIDEState *m = container_of(dma, MACIOIDEState, dma); 380 381 MACIO_DPRINTF("\n"); 382 DBDMA_kick(m->dbdma); 383 } 384 385 static const IDEDMAOps dbdma_ops = { 386 .start_dma = ide_dbdma_start, 387 .start_transfer = ide_nop, 388 .prepare_buf = ide_nop_int, 389 .rw_buf = ide_nop_int, 390 .set_unit = ide_nop_int, 391 .add_status = ide_nop_int, 392 .set_inactive = ide_nop, 393 .restart_cb = ide_nop_restart, 394 .reset = ide_nop, 395 }; 396 397 static void macio_ide_realizefn(DeviceState *dev, Error **errp) 398 { 399 MACIOIDEState *s = MACIO_IDE(dev); 400 401 ide_init2(&s->bus, s->irq); 402 403 /* Register DMA callbacks */ 404 s->dma.ops = &dbdma_ops; 405 s->bus.dma = &s->dma; 406 } 407 408 static void macio_ide_initfn(Object *obj) 409 { 410 SysBusDevice *d = SYS_BUS_DEVICE(obj); 411 MACIOIDEState *s = MACIO_IDE(obj); 412 413 ide_bus_new(&s->bus, DEVICE(obj), 0, 2); 414 memory_region_init_io(&s->mem, obj, &pmac_ide_ops, s, "pmac-ide", 0x1000); 415 sysbus_init_mmio(d, &s->mem); 416 sysbus_init_irq(d, &s->irq); 417 sysbus_init_irq(d, &s->dma_irq); 418 } 419 420 static void macio_ide_class_init(ObjectClass *oc, void *data) 421 { 422 DeviceClass *dc = DEVICE_CLASS(oc); 423 424 dc->realize = macio_ide_realizefn; 425 dc->reset = macio_ide_reset; 426 dc->vmsd = &vmstate_pmac; 427 } 428 429 static const TypeInfo macio_ide_type_info = { 430 .name = TYPE_MACIO_IDE, 431 .parent = TYPE_SYS_BUS_DEVICE, 432 .instance_size = sizeof(MACIOIDEState), 433 .instance_init = macio_ide_initfn, 434 .class_init = macio_ide_class_init, 435 }; 436 437 static void macio_ide_register_types(void) 438 { 439 type_register_static(&macio_ide_type_info); 440 } 441 442 /* hd_table must contain 2 block drivers */ 443 void macio_ide_init_drives(MACIOIDEState *s, DriveInfo **hd_table) 444 { 445 int i; 446 447 for (i = 0; i < 2; i++) { 448 if (hd_table[i]) { 449 ide_create_drive(&s->bus, i, hd_table[i]); 450 } 451 } 452 } 453 454 void macio_ide_register_dma(MACIOIDEState *s, void *dbdma, int channel) 455 { 456 s->dbdma = dbdma; 457 DBDMA_register_channel(dbdma, channel, s->dma_irq, 458 pmac_ide_transfer, pmac_ide_flush, s); 459 } 460 461 type_init(macio_ide_register_types) 462