Gerd Hoffmann | b884220 | 2009-08-20 15:22:21 +0200 | [diff] [blame] | 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 | */ |
Andreas Färber | baec191 | 2013-01-23 23:03:54 +0000 | [diff] [blame] | 25 | #include "hw/hw.h" |
| 26 | #include "hw/ppc/mac.h" |
Paolo Bonzini | 0d09e41 | 2013-02-05 17:06:20 +0100 | [diff] [blame] | 27 | #include "hw/ppc/mac_dbdma.h" |
Markus Armbruster | 4be7463 | 2014-10-07 13:59:18 +0200 | [diff] [blame] | 28 | #include "sysemu/block-backend.h" |
Paolo Bonzini | 9c17d61 | 2012-12-17 18:20:04 +0100 | [diff] [blame] | 29 | #include "sysemu/dma.h" |
Gerd Hoffmann | 59f2a78 | 2009-08-20 15:22:26 +0200 | [diff] [blame] | 30 | |
| 31 | #include <hw/ide/internal.h> |
Gerd Hoffmann | b884220 | 2009-08-20 15:22:21 +0200 | [diff] [blame] | 32 | |
Alexander Graf | 33ce36b | 2013-06-30 01:23:45 +0200 | [diff] [blame] | 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 | |
Gerd Hoffmann | b884220 | 2009-08-20 15:22:21 +0200 | [diff] [blame] | 49 | /***********************************************************/ |
| 50 | /* MacIO based PowerPC IDE */ |
| 51 | |
Blue Swirl | 02c7c99 | 2010-03-29 19:23:57 +0000 | [diff] [blame] | 52 | #define MACIO_PAGE_SIZE 4096 |
| 53 | |
Mark Cave-Ayland | 4827ac1 | 2015-05-22 14:13:44 -0400 | [diff] [blame] | 54 | static void pmac_dma_read(BlockBackend *blk, |
| 55 | int64_t sector_num, int nb_sectors, |
| 56 | void (*cb)(void *opaque, int ret), void *opaque) |
| 57 | { |
| 58 | DBDMA_io *io = opaque; |
| 59 | MACIOIDEState *m = io->opaque; |
| 60 | IDEState *s = idebus_active_if(&m->bus); |
| 61 | dma_addr_t dma_addr, dma_len; |
| 62 | void *mem; |
| 63 | int nsector, remainder; |
| 64 | |
| 65 | qemu_iovec_destroy(&io->iov); |
| 66 | qemu_iovec_init(&io->iov, io->len / MACIO_PAGE_SIZE + 1); |
| 67 | |
| 68 | if (io->remainder_len > 0) { |
| 69 | /* Return remainder of request */ |
| 70 | int transfer = MIN(io->remainder_len, io->len); |
| 71 | |
| 72 | MACIO_DPRINTF("--- DMA read pop - bounce addr: %p addr: %" |
| 73 | HWADDR_PRIx " remainder_len: %x\n", |
| 74 | &io->remainder + (0x200 - transfer), io->addr, |
| 75 | io->remainder_len); |
| 76 | |
| 77 | cpu_physical_memory_write(io->addr, |
| 78 | &io->remainder + (0x200 - transfer), |
| 79 | transfer); |
| 80 | |
| 81 | io->remainder_len -= transfer; |
| 82 | io->len -= transfer; |
| 83 | io->addr += transfer; |
| 84 | |
| 85 | s->io_buffer_index += transfer; |
| 86 | s->io_buffer_size -= transfer; |
| 87 | |
| 88 | if (io->remainder_len != 0) { |
| 89 | /* Still waiting for remainder */ |
| 90 | return; |
| 91 | } |
| 92 | |
| 93 | if (io->len == 0) { |
| 94 | MACIO_DPRINTF("--- finished all read processing; go and finish\n"); |
| 95 | cb(opaque, 0); |
| 96 | return; |
| 97 | } |
| 98 | } |
| 99 | |
| 100 | if (s->drive_kind == IDE_CD) { |
| 101 | sector_num = (int64_t)(s->lba << 2) + (s->io_buffer_index >> 9); |
| 102 | } else { |
| 103 | sector_num = ide_get_sector(s) + (s->io_buffer_index >> 9); |
| 104 | } |
| 105 | |
| 106 | nsector = ((io->len + 0x1ff) >> 9); |
| 107 | remainder = (nsector << 9) - io->len; |
| 108 | |
| 109 | MACIO_DPRINTF("--- DMA read transfer - addr: %" HWADDR_PRIx " len: %x\n", |
| 110 | io->addr, io->len); |
| 111 | |
| 112 | dma_addr = io->addr; |
| 113 | dma_len = io->len; |
| 114 | mem = dma_memory_map(&address_space_memory, dma_addr, &dma_len, |
| 115 | DMA_DIRECTION_FROM_DEVICE); |
| 116 | |
| 117 | if (!remainder) { |
| 118 | MACIO_DPRINTF("--- DMA read aligned - addr: %" HWADDR_PRIx |
| 119 | " len: %x\n", io->addr, io->len); |
| 120 | qemu_iovec_add(&io->iov, mem, io->len); |
| 121 | } else { |
| 122 | MACIO_DPRINTF("--- DMA read unaligned - addr: %" HWADDR_PRIx |
| 123 | " len: %x\n", io->addr, io->len); |
| 124 | qemu_iovec_add(&io->iov, mem, io->len); |
| 125 | |
| 126 | MACIO_DPRINTF("--- DMA read push - bounce addr: %p " |
| 127 | "remainder_len: %x\n", |
| 128 | &io->remainder + 0x200 - remainder, remainder); |
| 129 | qemu_iovec_add(&io->iov, &io->remainder + 0x200 - remainder, |
| 130 | remainder); |
| 131 | |
| 132 | io->remainder_len = remainder; |
| 133 | } |
| 134 | |
| 135 | s->io_buffer_size -= io->len; |
| 136 | s->io_buffer_index += io->len; |
| 137 | |
| 138 | io->len = 0; |
| 139 | |
| 140 | MACIO_DPRINTF("--- Block read transfer - sector_num: %"PRIx64" " |
| 141 | "nsector: %x\n", |
| 142 | sector_num, nsector); |
| 143 | |
| 144 | m->aiocb = blk_aio_readv(blk, sector_num, &io->iov, nsector, cb, io); |
| 145 | } |
| 146 | |
Mark Cave-Ayland | bd4214f | 2015-05-22 14:13:44 -0400 | [diff] [blame^] | 147 | static void pmac_dma_write(BlockBackend *blk, |
| 148 | int64_t sector_num, int nb_sectors, |
| 149 | void (*cb)(void *opaque, int ret), void *opaque) |
| 150 | { |
| 151 | DBDMA_io *io = opaque; |
| 152 | MACIOIDEState *m = io->opaque; |
| 153 | IDEState *s = idebus_active_if(&m->bus); |
| 154 | dma_addr_t dma_addr, dma_len; |
| 155 | void *mem; |
| 156 | int nsector, remainder; |
| 157 | int extra = 0; |
| 158 | |
| 159 | qemu_iovec_destroy(&io->iov); |
| 160 | qemu_iovec_init(&io->iov, io->len / MACIO_PAGE_SIZE + 1); |
| 161 | |
| 162 | if (io->remainder_len > 0) { |
| 163 | /* Return remainder of request */ |
| 164 | int transfer = MIN(io->remainder_len, io->len); |
| 165 | |
| 166 | MACIO_DPRINTF("--- processing write remainder %x\n", transfer); |
| 167 | cpu_physical_memory_read(io->addr, |
| 168 | &io->remainder + (0x200 - transfer), |
| 169 | transfer); |
| 170 | |
| 171 | io->remainder_len -= transfer; |
| 172 | io->len -= transfer; |
| 173 | io->addr += transfer; |
| 174 | |
| 175 | s->io_buffer_index += transfer; |
| 176 | s->io_buffer_size -= transfer; |
| 177 | |
| 178 | if (io->remainder_len != 0) { |
| 179 | /* Still waiting for remainder */ |
| 180 | return; |
| 181 | } |
| 182 | |
| 183 | MACIO_DPRINTF("--> prepending bounce buffer with size 0x200\n"); |
| 184 | |
| 185 | /* Sector transfer complete - prepend to request */ |
| 186 | qemu_iovec_add(&io->iov, &io->remainder, 0x200); |
| 187 | extra = 1; |
| 188 | } |
| 189 | |
| 190 | if (s->drive_kind == IDE_CD) { |
| 191 | sector_num = (int64_t)(s->lba << 2) + (s->io_buffer_index >> 9); |
| 192 | } else { |
| 193 | sector_num = ide_get_sector(s) + (s->io_buffer_index >> 9); |
| 194 | } |
| 195 | |
| 196 | nsector = (io->len >> 9); |
| 197 | remainder = io->len - (nsector << 9); |
| 198 | |
| 199 | MACIO_DPRINTF("--- DMA write transfer - addr: %" HWADDR_PRIx " len: %x\n", |
| 200 | io->addr, io->len); |
| 201 | MACIO_DPRINTF("xxx remainder: %x\n", remainder); |
| 202 | MACIO_DPRINTF("xxx sector_num: %"PRIx64" nsector: %x\n", |
| 203 | sector_num, nsector); |
| 204 | |
| 205 | dma_addr = io->addr; |
| 206 | dma_len = io->len; |
| 207 | mem = dma_memory_map(&address_space_memory, dma_addr, &dma_len, |
| 208 | DMA_DIRECTION_TO_DEVICE); |
| 209 | |
| 210 | if (!remainder) { |
| 211 | MACIO_DPRINTF("--- DMA write aligned - addr: %" HWADDR_PRIx |
| 212 | " len: %x\n", io->addr, io->len); |
| 213 | qemu_iovec_add(&io->iov, mem, io->len); |
| 214 | } else { |
| 215 | /* Write up to last complete sector */ |
| 216 | MACIO_DPRINTF("--- DMA write unaligned - addr: %" HWADDR_PRIx |
| 217 | " len: %x\n", io->addr, (nsector << 9)); |
| 218 | qemu_iovec_add(&io->iov, mem, (nsector << 9)); |
| 219 | |
| 220 | MACIO_DPRINTF("--- DMA write read - bounce addr: %p " |
| 221 | "remainder_len: %x\n", &io->remainder, remainder); |
| 222 | cpu_physical_memory_read(io->addr + (nsector << 9), &io->remainder, |
| 223 | remainder); |
| 224 | |
| 225 | io->remainder_len = 0x200 - remainder; |
| 226 | |
| 227 | MACIO_DPRINTF("xxx remainder_len: %x\n", io->remainder_len); |
| 228 | } |
| 229 | |
| 230 | s->io_buffer_size -= ((nsector + extra) << 9); |
| 231 | s->io_buffer_index += ((nsector + extra) << 9); |
| 232 | |
| 233 | io->len = 0; |
| 234 | |
| 235 | MACIO_DPRINTF("--- Block write transfer - sector_num: %"PRIx64" " |
| 236 | "nsector: %x\n", sector_num, nsector + extra); |
| 237 | |
| 238 | m->aiocb = blk_aio_writev(blk, sector_num, &io->iov, nsector + extra, cb, |
| 239 | io); |
| 240 | } |
| 241 | |
Gerd Hoffmann | b884220 | 2009-08-20 15:22:21 +0200 | [diff] [blame] | 242 | static void pmac_ide_atapi_transfer_cb(void *opaque, int ret) |
| 243 | { |
| 244 | DBDMA_io *io = opaque; |
| 245 | MACIOIDEState *m = io->opaque; |
| 246 | IDEState *s = idebus_active_if(&m->bus); |
Mark Cave-Ayland | 4827ac1 | 2015-05-22 14:13:44 -0400 | [diff] [blame] | 247 | int64_t sector_num; |
| 248 | int nsector, remainder; |
| 249 | |
| 250 | MACIO_DPRINTF("\ns is %p\n", s); |
| 251 | MACIO_DPRINTF("io_buffer_index: %x\n", s->io_buffer_index); |
| 252 | MACIO_DPRINTF("io_buffer_size: %x packet_transfer_size: %x\n", |
| 253 | s->io_buffer_size, s->packet_transfer_size); |
| 254 | MACIO_DPRINTF("lba: %x\n", s->lba); |
| 255 | MACIO_DPRINTF("io_addr: %" HWADDR_PRIx " io_len: %x\n", io->addr, |
| 256 | io->len); |
Gerd Hoffmann | b884220 | 2009-08-20 15:22:21 +0200 | [diff] [blame] | 257 | |
| 258 | if (ret < 0) { |
Mark Cave-Ayland | 4827ac1 | 2015-05-22 14:13:44 -0400 | [diff] [blame] | 259 | MACIO_DPRINTF("THERE WAS AN ERROR! %d\n", ret); |
Gerd Hoffmann | b884220 | 2009-08-20 15:22:21 +0200 | [diff] [blame] | 260 | ide_atapi_io_error(s, ret); |
Christoph Hellwig | a597e79 | 2011-08-25 08:26:01 +0200 | [diff] [blame] | 261 | goto done; |
Gerd Hoffmann | b884220 | 2009-08-20 15:22:21 +0200 | [diff] [blame] | 262 | } |
| 263 | |
Alexander Graf | cae3235 | 2013-06-30 02:54:35 +0200 | [diff] [blame] | 264 | if (!m->dma_active) { |
| 265 | MACIO_DPRINTF("waiting for data (%#x - %#x - %x)\n", |
| 266 | s->nsector, io->len, s->status); |
| 267 | /* data not ready yet, wait for the channel to get restarted */ |
| 268 | io->processing = false; |
| 269 | return; |
| 270 | } |
| 271 | |
Mark Cave-Ayland | 4827ac1 | 2015-05-22 14:13:44 -0400 | [diff] [blame] | 272 | if (s->io_buffer_size <= 0) { |
Gerd Hoffmann | b884220 | 2009-08-20 15:22:21 +0200 | [diff] [blame] | 273 | ide_atapi_cmd_ok(s); |
Alexander Graf | cae3235 | 2013-06-30 02:54:35 +0200 | [diff] [blame] | 274 | m->dma_active = false; |
Christoph Hellwig | a597e79 | 2011-08-25 08:26:01 +0200 | [diff] [blame] | 275 | goto done; |
Gerd Hoffmann | b884220 | 2009-08-20 15:22:21 +0200 | [diff] [blame] | 276 | } |
| 277 | |
Mark Cave-Ayland | 4827ac1 | 2015-05-22 14:13:44 -0400 | [diff] [blame] | 278 | if (io->len == 0) { |
| 279 | MACIO_DPRINTF("End of DMA transfer\n"); |
| 280 | goto done; |
Alexander Graf | 80fc95d | 2013-06-28 13:30:01 +0200 | [diff] [blame] | 281 | } |
| 282 | |
Mark Cave-Ayland | 4827ac1 | 2015-05-22 14:13:44 -0400 | [diff] [blame] | 283 | if (s->lba == -1) { |
| 284 | /* Non-block ATAPI transfer - just copy to RAM */ |
| 285 | s->io_buffer_size = MIN(s->io_buffer_size, io->len); |
| 286 | cpu_physical_memory_write(io->addr, s->io_buffer, s->io_buffer_size); |
| 287 | ide_atapi_cmd_ok(s); |
| 288 | m->dma_active = false; |
| 289 | goto done; |
Alexander Graf | 80fc95d | 2013-06-28 13:30:01 +0200 | [diff] [blame] | 290 | } |
| 291 | |
Mark Cave-Ayland | 4827ac1 | 2015-05-22 14:13:44 -0400 | [diff] [blame] | 292 | /* Calculate number of sectors */ |
| 293 | sector_num = (int64_t)(s->lba << 2) + (s->io_buffer_index >> 9); |
| 294 | nsector = (io->len + 0x1ff) >> 9; |
| 295 | remainder = io->len & 0x1ff; |
Gerd Hoffmann | b884220 | 2009-08-20 15:22:21 +0200 | [diff] [blame] | 296 | |
Mark Cave-Ayland | 4827ac1 | 2015-05-22 14:13:44 -0400 | [diff] [blame] | 297 | MACIO_DPRINTF("nsector: %d remainder: %x\n", nsector, remainder); |
| 298 | MACIO_DPRINTF("sector: %"PRIx64" %zx\n", sector_num, io->iov.size / 512); |
Alexander Graf | 33ce36b | 2013-06-30 01:23:45 +0200 | [diff] [blame] | 299 | |
Mark Cave-Ayland | 4827ac1 | 2015-05-22 14:13:44 -0400 | [diff] [blame] | 300 | pmac_dma_read(s->blk, sector_num, nsector, pmac_ide_atapi_transfer_cb, io); |
Christoph Hellwig | a597e79 | 2011-08-25 08:26:01 +0200 | [diff] [blame] | 301 | return; |
| 302 | |
| 303 | done: |
Mark Cave-Ayland | 4827ac1 | 2015-05-22 14:13:44 -0400 | [diff] [blame] | 304 | MACIO_DPRINTF("done DMA\n\n"); |
Markus Armbruster | 4be7463 | 2014-10-07 13:59:18 +0200 | [diff] [blame] | 305 | block_acct_done(blk_get_stats(s->blk), &s->acct); |
Christoph Hellwig | a597e79 | 2011-08-25 08:26:01 +0200 | [diff] [blame] | 306 | io->dma_end(opaque); |
Mark Cave-Ayland | 4827ac1 | 2015-05-22 14:13:44 -0400 | [diff] [blame] | 307 | |
| 308 | return; |
Gerd Hoffmann | b884220 | 2009-08-20 15:22:21 +0200 | [diff] [blame] | 309 | } |
| 310 | |
| 311 | static void pmac_ide_transfer_cb(void *opaque, int ret) |
| 312 | { |
| 313 | DBDMA_io *io = opaque; |
| 314 | MACIOIDEState *m = io->opaque; |
| 315 | IDEState *s = idebus_active_if(&m->bus); |
Gerd Hoffmann | b884220 | 2009-08-20 15:22:21 +0200 | [diff] [blame] | 316 | int64_t sector_num; |
Mark Cave-Ayland | bd4214f | 2015-05-22 14:13:44 -0400 | [diff] [blame^] | 317 | int nsector, remainder; |
| 318 | |
| 319 | MACIO_DPRINTF("pmac_ide_transfer_cb\n"); |
Gerd Hoffmann | b884220 | 2009-08-20 15:22:21 +0200 | [diff] [blame] | 320 | |
| 321 | if (ret < 0) { |
Alexander Graf | 33ce36b | 2013-06-30 01:23:45 +0200 | [diff] [blame] | 322 | MACIO_DPRINTF("DMA error\n"); |
Gerd Hoffmann | b884220 | 2009-08-20 15:22:21 +0200 | [diff] [blame] | 323 | m->aiocb = NULL; |
Alexander Graf | 8aef291 | 2013-06-30 01:43:17 +0200 | [diff] [blame] | 324 | ide_dma_error(s); |
Alexander Graf | 80fc95d | 2013-06-28 13:30:01 +0200 | [diff] [blame] | 325 | io->remainder_len = 0; |
Christoph Hellwig | a597e79 | 2011-08-25 08:26:01 +0200 | [diff] [blame] | 326 | goto done; |
Gerd Hoffmann | b884220 | 2009-08-20 15:22:21 +0200 | [diff] [blame] | 327 | } |
| 328 | |
Alexander Graf | cae3235 | 2013-06-30 02:54:35 +0200 | [diff] [blame] | 329 | if (!m->dma_active) { |
| 330 | MACIO_DPRINTF("waiting for data (%#x - %#x - %x)\n", |
| 331 | s->nsector, io->len, s->status); |
| 332 | /* data not ready yet, wait for the channel to get restarted */ |
| 333 | io->processing = false; |
| 334 | return; |
| 335 | } |
| 336 | |
Mark Cave-Ayland | bd4214f | 2015-05-22 14:13:44 -0400 | [diff] [blame^] | 337 | if (s->io_buffer_size <= 0) { |
Alexander Graf | 33ce36b | 2013-06-30 01:23:45 +0200 | [diff] [blame] | 338 | MACIO_DPRINTF("end of transfer\n"); |
Gerd Hoffmann | b884220 | 2009-08-20 15:22:21 +0200 | [diff] [blame] | 339 | s->status = READY_STAT | SEEK_STAT; |
Gerd Hoffmann | 9cdd03a | 2009-08-28 16:37:42 +0200 | [diff] [blame] | 340 | ide_set_irq(s->bus); |
Alexander Graf | cae3235 | 2013-06-30 02:54:35 +0200 | [diff] [blame] | 341 | m->dma_active = false; |
Christoph Hellwig | a597e79 | 2011-08-25 08:26:01 +0200 | [diff] [blame] | 342 | goto done; |
Gerd Hoffmann | b884220 | 2009-08-20 15:22:21 +0200 | [diff] [blame] | 343 | } |
| 344 | |
Mark Cave-Ayland | bd4214f | 2015-05-22 14:13:44 -0400 | [diff] [blame^] | 345 | if (io->len == 0) { |
| 346 | MACIO_DPRINTF("End of DMA transfer\n"); |
| 347 | goto done; |
Alexander Graf | 80fc95d | 2013-06-28 13:30:01 +0200 | [diff] [blame] | 348 | } |
| 349 | |
Mark Cave-Ayland | bd4214f | 2015-05-22 14:13:44 -0400 | [diff] [blame^] | 350 | /* Calculate number of sectors */ |
| 351 | sector_num = ide_get_sector(s) + (s->io_buffer_index >> 9); |
| 352 | nsector = (io->len + 0x1ff) >> 9; |
| 353 | remainder = io->len & 0x1ff; |
Alexander Graf | 33ce36b | 2013-06-30 01:23:45 +0200 | [diff] [blame] | 354 | |
Mark Cave-Ayland | bd4214f | 2015-05-22 14:13:44 -0400 | [diff] [blame^] | 355 | s->nsector -= nsector; |
Alexander Graf | 80fc95d | 2013-06-28 13:30:01 +0200 | [diff] [blame] | 356 | |
Mark Cave-Ayland | bd4214f | 2015-05-22 14:13:44 -0400 | [diff] [blame^] | 357 | MACIO_DPRINTF("nsector: %d remainder: %x\n", nsector, remainder); |
| 358 | MACIO_DPRINTF("sector: %"PRIx64" %x\n", sector_num, nsector); |
Alexander Graf | 33ce36b | 2013-06-30 01:23:45 +0200 | [diff] [blame] | 359 | |
Christoph Hellwig | 4e1e005 | 2011-05-19 10:58:09 +0200 | [diff] [blame] | 360 | switch (s->dma_cmd) { |
| 361 | case IDE_DMA_READ: |
Mark Cave-Ayland | bd4214f | 2015-05-22 14:13:44 -0400 | [diff] [blame^] | 362 | pmac_dma_read(s->blk, sector_num, nsector, pmac_ide_transfer_cb, io); |
Christoph Hellwig | 4e1e005 | 2011-05-19 10:58:09 +0200 | [diff] [blame] | 363 | break; |
| 364 | case IDE_DMA_WRITE: |
Mark Cave-Ayland | bd4214f | 2015-05-22 14:13:44 -0400 | [diff] [blame^] | 365 | pmac_dma_write(s->blk, sector_num, nsector, pmac_ide_transfer_cb, io); |
Christoph Hellwig | 4e1e005 | 2011-05-19 10:58:09 +0200 | [diff] [blame] | 366 | break; |
Christoph Hellwig | d353fb7 | 2011-05-19 10:58:19 +0200 | [diff] [blame] | 367 | case IDE_DMA_TRIM: |
Mark Cave-Ayland | bd4214f | 2015-05-22 14:13:44 -0400 | [diff] [blame^] | 368 | MACIO_DPRINTF("TRIM command issued!"); |
Christoph Hellwig | d353fb7 | 2011-05-19 10:58:19 +0200 | [diff] [blame] | 369 | break; |
Christoph Hellwig | 4e1e005 | 2011-05-19 10:58:09 +0200 | [diff] [blame] | 370 | } |
Alexander Graf | 3e300fa | 2014-05-26 10:27:58 +0200 | [diff] [blame] | 371 | |
Christoph Hellwig | a597e79 | 2011-08-25 08:26:01 +0200 | [diff] [blame] | 372 | return; |
Paolo Bonzini | b9b2008 | 2011-11-14 17:50:53 +0100 | [diff] [blame] | 373 | |
Christoph Hellwig | a597e79 | 2011-08-25 08:26:01 +0200 | [diff] [blame] | 374 | done: |
| 375 | if (s->dma_cmd == IDE_DMA_READ || s->dma_cmd == IDE_DMA_WRITE) { |
Markus Armbruster | 4be7463 | 2014-10-07 13:59:18 +0200 | [diff] [blame] | 376 | block_acct_done(blk_get_stats(s->blk), &s->acct); |
Christoph Hellwig | a597e79 | 2011-08-25 08:26:01 +0200 | [diff] [blame] | 377 | } |
Mark Cave-Ayland | bd4214f | 2015-05-22 14:13:44 -0400 | [diff] [blame^] | 378 | io->dma_end(opaque); |
Gerd Hoffmann | b884220 | 2009-08-20 15:22:21 +0200 | [diff] [blame] | 379 | } |
| 380 | |
| 381 | static void pmac_ide_transfer(DBDMA_io *io) |
| 382 | { |
| 383 | MACIOIDEState *m = io->opaque; |
| 384 | IDEState *s = idebus_active_if(&m->bus); |
| 385 | |
Alexander Graf | 33ce36b | 2013-06-30 01:23:45 +0200 | [diff] [blame] | 386 | MACIO_DPRINTF("\n"); |
| 387 | |
Markus Armbruster | cd8722b | 2010-05-28 13:32:45 +0200 | [diff] [blame] | 388 | if (s->drive_kind == IDE_CD) { |
Markus Armbruster | 4be7463 | 2014-10-07 13:59:18 +0200 | [diff] [blame] | 389 | block_acct_start(blk_get_stats(s->blk), &s->acct, io->len, |
Benoît Canet | 5366d0c | 2014-09-05 15:46:18 +0200 | [diff] [blame] | 390 | BLOCK_ACCT_READ); |
Mark Cave-Ayland | 4827ac1 | 2015-05-22 14:13:44 -0400 | [diff] [blame] | 391 | |
Gerd Hoffmann | b884220 | 2009-08-20 15:22:21 +0200 | [diff] [blame] | 392 | pmac_ide_atapi_transfer_cb(io, 0); |
| 393 | return; |
| 394 | } |
| 395 | |
Christoph Hellwig | a597e79 | 2011-08-25 08:26:01 +0200 | [diff] [blame] | 396 | switch (s->dma_cmd) { |
| 397 | case IDE_DMA_READ: |
Markus Armbruster | 4be7463 | 2014-10-07 13:59:18 +0200 | [diff] [blame] | 398 | block_acct_start(blk_get_stats(s->blk), &s->acct, io->len, |
Benoît Canet | 5366d0c | 2014-09-05 15:46:18 +0200 | [diff] [blame] | 399 | BLOCK_ACCT_READ); |
Christoph Hellwig | a597e79 | 2011-08-25 08:26:01 +0200 | [diff] [blame] | 400 | break; |
| 401 | case IDE_DMA_WRITE: |
Markus Armbruster | 4be7463 | 2014-10-07 13:59:18 +0200 | [diff] [blame] | 402 | block_acct_start(blk_get_stats(s->blk), &s->acct, io->len, |
Benoît Canet | 5366d0c | 2014-09-05 15:46:18 +0200 | [diff] [blame] | 403 | BLOCK_ACCT_WRITE); |
Christoph Hellwig | a597e79 | 2011-08-25 08:26:01 +0200 | [diff] [blame] | 404 | break; |
| 405 | default: |
| 406 | break; |
| 407 | } |
| 408 | |
Gerd Hoffmann | b884220 | 2009-08-20 15:22:21 +0200 | [diff] [blame] | 409 | pmac_ide_transfer_cb(io, 0); |
| 410 | } |
| 411 | |
| 412 | static void pmac_ide_flush(DBDMA_io *io) |
| 413 | { |
| 414 | MACIOIDEState *m = io->opaque; |
| 415 | |
Stefan Hajnoczi | 922453b | 2011-11-30 12:23:43 +0000 | [diff] [blame] | 416 | if (m->aiocb) { |
Markus Armbruster | 4be7463 | 2014-10-07 13:59:18 +0200 | [diff] [blame] | 417 | blk_drain_all(); |
Stefan Hajnoczi | 922453b | 2011-11-30 12:23:43 +0000 | [diff] [blame] | 418 | } |
Gerd Hoffmann | b884220 | 2009-08-20 15:22:21 +0200 | [diff] [blame] | 419 | } |
| 420 | |
| 421 | /* PowerMac IDE memory IO */ |
| 422 | static void pmac_ide_writeb (void *opaque, |
Avi Kivity | a8170e5 | 2012-10-23 12:30:10 +0200 | [diff] [blame] | 423 | hwaddr addr, uint32_t val) |
Gerd Hoffmann | b884220 | 2009-08-20 15:22:21 +0200 | [diff] [blame] | 424 | { |
| 425 | MACIOIDEState *d = opaque; |
| 426 | |
| 427 | addr = (addr & 0xFFF) >> 4; |
| 428 | switch (addr) { |
| 429 | case 1 ... 7: |
| 430 | ide_ioport_write(&d->bus, addr, val); |
| 431 | break; |
| 432 | case 8: |
| 433 | case 22: |
| 434 | ide_cmd_write(&d->bus, 0, val); |
| 435 | break; |
| 436 | default: |
| 437 | break; |
| 438 | } |
| 439 | } |
| 440 | |
Avi Kivity | a8170e5 | 2012-10-23 12:30:10 +0200 | [diff] [blame] | 441 | static uint32_t pmac_ide_readb (void *opaque,hwaddr addr) |
Gerd Hoffmann | b884220 | 2009-08-20 15:22:21 +0200 | [diff] [blame] | 442 | { |
| 443 | uint8_t retval; |
| 444 | MACIOIDEState *d = opaque; |
| 445 | |
| 446 | addr = (addr & 0xFFF) >> 4; |
| 447 | switch (addr) { |
| 448 | case 1 ... 7: |
| 449 | retval = ide_ioport_read(&d->bus, addr); |
| 450 | break; |
| 451 | case 8: |
| 452 | case 22: |
| 453 | retval = ide_status_read(&d->bus, 0); |
| 454 | break; |
| 455 | default: |
| 456 | retval = 0xFF; |
| 457 | break; |
| 458 | } |
| 459 | return retval; |
| 460 | } |
| 461 | |
| 462 | static void pmac_ide_writew (void *opaque, |
Avi Kivity | a8170e5 | 2012-10-23 12:30:10 +0200 | [diff] [blame] | 463 | hwaddr addr, uint32_t val) |
Gerd Hoffmann | b884220 | 2009-08-20 15:22:21 +0200 | [diff] [blame] | 464 | { |
| 465 | MACIOIDEState *d = opaque; |
| 466 | |
| 467 | addr = (addr & 0xFFF) >> 4; |
Gerd Hoffmann | b884220 | 2009-08-20 15:22:21 +0200 | [diff] [blame] | 468 | val = bswap16(val); |
Gerd Hoffmann | b884220 | 2009-08-20 15:22:21 +0200 | [diff] [blame] | 469 | if (addr == 0) { |
| 470 | ide_data_writew(&d->bus, 0, val); |
| 471 | } |
| 472 | } |
| 473 | |
Avi Kivity | a8170e5 | 2012-10-23 12:30:10 +0200 | [diff] [blame] | 474 | static uint32_t pmac_ide_readw (void *opaque,hwaddr addr) |
Gerd Hoffmann | b884220 | 2009-08-20 15:22:21 +0200 | [diff] [blame] | 475 | { |
| 476 | uint16_t retval; |
| 477 | MACIOIDEState *d = opaque; |
| 478 | |
| 479 | addr = (addr & 0xFFF) >> 4; |
| 480 | if (addr == 0) { |
| 481 | retval = ide_data_readw(&d->bus, 0); |
| 482 | } else { |
| 483 | retval = 0xFFFF; |
| 484 | } |
Gerd Hoffmann | b884220 | 2009-08-20 15:22:21 +0200 | [diff] [blame] | 485 | retval = bswap16(retval); |
Gerd Hoffmann | b884220 | 2009-08-20 15:22:21 +0200 | [diff] [blame] | 486 | return retval; |
| 487 | } |
| 488 | |
| 489 | static void pmac_ide_writel (void *opaque, |
Avi Kivity | a8170e5 | 2012-10-23 12:30:10 +0200 | [diff] [blame] | 490 | hwaddr addr, uint32_t val) |
Gerd Hoffmann | b884220 | 2009-08-20 15:22:21 +0200 | [diff] [blame] | 491 | { |
| 492 | MACIOIDEState *d = opaque; |
| 493 | |
| 494 | addr = (addr & 0xFFF) >> 4; |
Gerd Hoffmann | b884220 | 2009-08-20 15:22:21 +0200 | [diff] [blame] | 495 | val = bswap32(val); |
Gerd Hoffmann | b884220 | 2009-08-20 15:22:21 +0200 | [diff] [blame] | 496 | if (addr == 0) { |
| 497 | ide_data_writel(&d->bus, 0, val); |
| 498 | } |
| 499 | } |
| 500 | |
Avi Kivity | a8170e5 | 2012-10-23 12:30:10 +0200 | [diff] [blame] | 501 | static uint32_t pmac_ide_readl (void *opaque,hwaddr addr) |
Gerd Hoffmann | b884220 | 2009-08-20 15:22:21 +0200 | [diff] [blame] | 502 | { |
| 503 | uint32_t retval; |
| 504 | MACIOIDEState *d = opaque; |
| 505 | |
| 506 | addr = (addr & 0xFFF) >> 4; |
| 507 | if (addr == 0) { |
| 508 | retval = ide_data_readl(&d->bus, 0); |
| 509 | } else { |
| 510 | retval = 0xFFFFFFFF; |
| 511 | } |
Gerd Hoffmann | b884220 | 2009-08-20 15:22:21 +0200 | [diff] [blame] | 512 | retval = bswap32(retval); |
Gerd Hoffmann | b884220 | 2009-08-20 15:22:21 +0200 | [diff] [blame] | 513 | return retval; |
| 514 | } |
| 515 | |
Stefan Weil | a348f10 | 2012-02-05 10:19:07 +0000 | [diff] [blame] | 516 | static const MemoryRegionOps pmac_ide_ops = { |
Avi Kivity | 23c5e4c | 2011-08-08 16:09:17 +0300 | [diff] [blame] | 517 | .old_mmio = { |
| 518 | .write = { |
| 519 | pmac_ide_writeb, |
| 520 | pmac_ide_writew, |
| 521 | pmac_ide_writel, |
| 522 | }, |
| 523 | .read = { |
| 524 | pmac_ide_readb, |
| 525 | pmac_ide_readw, |
| 526 | pmac_ide_readl, |
| 527 | }, |
| 528 | }, |
| 529 | .endianness = DEVICE_NATIVE_ENDIAN, |
Gerd Hoffmann | b884220 | 2009-08-20 15:22:21 +0200 | [diff] [blame] | 530 | }; |
| 531 | |
Juan Quintela | 44bfa33 | 2009-10-07 19:04:46 +0200 | [diff] [blame] | 532 | static const VMStateDescription vmstate_pmac = { |
| 533 | .name = "ide", |
| 534 | .version_id = 3, |
| 535 | .minimum_version_id = 0, |
Juan Quintela | 35d0845 | 2014-04-16 16:01:33 +0200 | [diff] [blame] | 536 | .fields = (VMStateField[]) { |
Juan Quintela | 44bfa33 | 2009-10-07 19:04:46 +0200 | [diff] [blame] | 537 | VMSTATE_IDE_BUS(bus, MACIOIDEState), |
| 538 | VMSTATE_IDE_DRIVES(bus.ifs, MACIOIDEState), |
| 539 | VMSTATE_END_OF_LIST() |
Gerd Hoffmann | b884220 | 2009-08-20 15:22:21 +0200 | [diff] [blame] | 540 | } |
Juan Quintela | 44bfa33 | 2009-10-07 19:04:46 +0200 | [diff] [blame] | 541 | }; |
Gerd Hoffmann | b884220 | 2009-08-20 15:22:21 +0200 | [diff] [blame] | 542 | |
Andreas Färber | 07a7484 | 2013-01-23 23:04:01 +0000 | [diff] [blame] | 543 | static void macio_ide_reset(DeviceState *dev) |
Gerd Hoffmann | b884220 | 2009-08-20 15:22:21 +0200 | [diff] [blame] | 544 | { |
Andreas Färber | 07a7484 | 2013-01-23 23:04:01 +0000 | [diff] [blame] | 545 | MACIOIDEState *d = MACIO_IDE(dev); |
Gerd Hoffmann | b884220 | 2009-08-20 15:22:21 +0200 | [diff] [blame] | 546 | |
Blue Swirl | 4a64356 | 2009-11-07 14:13:05 +0000 | [diff] [blame] | 547 | ide_bus_reset(&d->bus); |
Gerd Hoffmann | b884220 | 2009-08-20 15:22:21 +0200 | [diff] [blame] | 548 | } |
| 549 | |
Alexander Graf | 4aa3510 | 2013-06-30 02:36:14 +0200 | [diff] [blame] | 550 | static int ide_nop_int(IDEDMA *dma, int x) |
| 551 | { |
| 552 | return 0; |
| 553 | } |
| 554 | |
John Snow | 3251bdc | 2014-10-31 16:03:39 -0400 | [diff] [blame] | 555 | static int32_t ide_nop_int32(IDEDMA *dma, int x) |
| 556 | { |
| 557 | return 0; |
| 558 | } |
| 559 | |
Alexander Graf | 4aa3510 | 2013-06-30 02:36:14 +0200 | [diff] [blame] | 560 | static void ide_dbdma_start(IDEDMA *dma, IDEState *s, |
Markus Armbruster | 097310b | 2014-10-07 13:59:15 +0200 | [diff] [blame] | 561 | BlockCompletionFunc *cb) |
Alexander Graf | 4aa3510 | 2013-06-30 02:36:14 +0200 | [diff] [blame] | 562 | { |
| 563 | MACIOIDEState *m = container_of(dma, MACIOIDEState, dma); |
Mark Cave-Ayland | 4827ac1 | 2015-05-22 14:13:44 -0400 | [diff] [blame] | 564 | DBDMAState *dbdma = m->dbdma; |
| 565 | DBDMA_io *io; |
| 566 | int i; |
| 567 | |
Mark Cave-Ayland | bd4214f | 2015-05-22 14:13:44 -0400 | [diff] [blame^] | 568 | s->io_buffer_index = 0; |
Mark Cave-Ayland | 4827ac1 | 2015-05-22 14:13:44 -0400 | [diff] [blame] | 569 | if (s->drive_kind == IDE_CD) { |
Mark Cave-Ayland | 4827ac1 | 2015-05-22 14:13:44 -0400 | [diff] [blame] | 570 | s->io_buffer_size = s->packet_transfer_size; |
Mark Cave-Ayland | bd4214f | 2015-05-22 14:13:44 -0400 | [diff] [blame^] | 571 | } else { |
| 572 | s->io_buffer_size = s->nsector * 0x200; |
| 573 | } |
Mark Cave-Ayland | 4827ac1 | 2015-05-22 14:13:44 -0400 | [diff] [blame] | 574 | |
Mark Cave-Ayland | bd4214f | 2015-05-22 14:13:44 -0400 | [diff] [blame^] | 575 | MACIO_DPRINTF("\n\n------------ IDE transfer\n"); |
| 576 | MACIO_DPRINTF("buffer_size: %x buffer_index: %x\n", |
| 577 | s->io_buffer_size, s->io_buffer_index); |
| 578 | MACIO_DPRINTF("lba: %x size: %x\n", s->lba, s->io_buffer_size); |
| 579 | MACIO_DPRINTF("-------------------------\n"); |
Mark Cave-Ayland | 4827ac1 | 2015-05-22 14:13:44 -0400 | [diff] [blame] | 580 | |
Mark Cave-Ayland | bd4214f | 2015-05-22 14:13:44 -0400 | [diff] [blame^] | 581 | for (i = 0; i < DBDMA_CHANNELS; i++) { |
| 582 | io = &dbdma->channels[i].io; |
Mark Cave-Ayland | 4827ac1 | 2015-05-22 14:13:44 -0400 | [diff] [blame] | 583 | |
Mark Cave-Ayland | bd4214f | 2015-05-22 14:13:44 -0400 | [diff] [blame^] | 584 | if (io->opaque == m) { |
| 585 | io->remainder_len = 0; |
Mark Cave-Ayland | 4827ac1 | 2015-05-22 14:13:44 -0400 | [diff] [blame] | 586 | } |
| 587 | } |
Alexander Graf | 4aa3510 | 2013-06-30 02:36:14 +0200 | [diff] [blame] | 588 | |
| 589 | MACIO_DPRINTF("\n"); |
Alexander Graf | cae3235 | 2013-06-30 02:54:35 +0200 | [diff] [blame] | 590 | m->dma_active = true; |
Alexander Graf | 4aa3510 | 2013-06-30 02:36:14 +0200 | [diff] [blame] | 591 | DBDMA_kick(m->dbdma); |
| 592 | } |
| 593 | |
| 594 | static const IDEDMAOps dbdma_ops = { |
| 595 | .start_dma = ide_dbdma_start, |
John Snow | 3251bdc | 2014-10-31 16:03:39 -0400 | [diff] [blame] | 596 | .prepare_buf = ide_nop_int32, |
Alexander Graf | 4aa3510 | 2013-06-30 02:36:14 +0200 | [diff] [blame] | 597 | .rw_buf = ide_nop_int, |
Alexander Graf | 4aa3510 | 2013-06-30 02:36:14 +0200 | [diff] [blame] | 598 | }; |
| 599 | |
Andreas Färber | 07a7484 | 2013-01-23 23:04:01 +0000 | [diff] [blame] | 600 | static void macio_ide_realizefn(DeviceState *dev, Error **errp) |
Gerd Hoffmann | b884220 | 2009-08-20 15:22:21 +0200 | [diff] [blame] | 601 | { |
Andreas Färber | 07a7484 | 2013-01-23 23:04:01 +0000 | [diff] [blame] | 602 | MACIOIDEState *s = MACIO_IDE(dev); |
Gerd Hoffmann | b884220 | 2009-08-20 15:22:21 +0200 | [diff] [blame] | 603 | |
Andreas Färber | 07a7484 | 2013-01-23 23:04:01 +0000 | [diff] [blame] | 604 | ide_init2(&s->bus, s->irq); |
Alexander Graf | 4aa3510 | 2013-06-30 02:36:14 +0200 | [diff] [blame] | 605 | |
| 606 | /* Register DMA callbacks */ |
| 607 | s->dma.ops = &dbdma_ops; |
| 608 | s->bus.dma = &s->dma; |
Gerd Hoffmann | b884220 | 2009-08-20 15:22:21 +0200 | [diff] [blame] | 609 | } |
Andreas Färber | 07a7484 | 2013-01-23 23:04:01 +0000 | [diff] [blame] | 610 | |
| 611 | static void macio_ide_initfn(Object *obj) |
| 612 | { |
| 613 | SysBusDevice *d = SYS_BUS_DEVICE(obj); |
| 614 | MACIOIDEState *s = MACIO_IDE(obj); |
| 615 | |
Andreas Färber | c6baf94 | 2013-08-23 20:18:50 +0200 | [diff] [blame] | 616 | ide_bus_new(&s->bus, sizeof(s->bus), DEVICE(obj), 0, 2); |
Paolo Bonzini | 1437c94 | 2013-06-06 21:25:08 -0400 | [diff] [blame] | 617 | memory_region_init_io(&s->mem, obj, &pmac_ide_ops, s, "pmac-ide", 0x1000); |
Andreas Färber | 07a7484 | 2013-01-23 23:04:01 +0000 | [diff] [blame] | 618 | sysbus_init_mmio(d, &s->mem); |
| 619 | sysbus_init_irq(d, &s->irq); |
| 620 | sysbus_init_irq(d, &s->dma_irq); |
| 621 | } |
| 622 | |
| 623 | static void macio_ide_class_init(ObjectClass *oc, void *data) |
| 624 | { |
| 625 | DeviceClass *dc = DEVICE_CLASS(oc); |
| 626 | |
| 627 | dc->realize = macio_ide_realizefn; |
| 628 | dc->reset = macio_ide_reset; |
| 629 | dc->vmsd = &vmstate_pmac; |
| 630 | } |
| 631 | |
| 632 | static const TypeInfo macio_ide_type_info = { |
| 633 | .name = TYPE_MACIO_IDE, |
| 634 | .parent = TYPE_SYS_BUS_DEVICE, |
| 635 | .instance_size = sizeof(MACIOIDEState), |
| 636 | .instance_init = macio_ide_initfn, |
| 637 | .class_init = macio_ide_class_init, |
| 638 | }; |
| 639 | |
| 640 | static void macio_ide_register_types(void) |
| 641 | { |
| 642 | type_register_static(&macio_ide_type_info); |
| 643 | } |
| 644 | |
Alexander Graf | 14eefd0 | 2013-06-24 21:40:50 +0200 | [diff] [blame] | 645 | /* hd_table must contain 2 block drivers */ |
Andreas Färber | 07a7484 | 2013-01-23 23:04:01 +0000 | [diff] [blame] | 646 | void macio_ide_init_drives(MACIOIDEState *s, DriveInfo **hd_table) |
| 647 | { |
| 648 | int i; |
| 649 | |
| 650 | for (i = 0; i < 2; i++) { |
| 651 | if (hd_table[i]) { |
| 652 | ide_create_drive(&s->bus, i, hd_table[i]); |
| 653 | } |
| 654 | } |
| 655 | } |
| 656 | |
| 657 | void macio_ide_register_dma(MACIOIDEState *s, void *dbdma, int channel) |
| 658 | { |
Alexander Graf | 4aa3510 | 2013-06-30 02:36:14 +0200 | [diff] [blame] | 659 | s->dbdma = dbdma; |
Andreas Färber | 07a7484 | 2013-01-23 23:04:01 +0000 | [diff] [blame] | 660 | DBDMA_register_channel(dbdma, channel, s->dma_irq, |
| 661 | pmac_ide_transfer, pmac_ide_flush, s); |
| 662 | } |
| 663 | |
| 664 | type_init(macio_ide_register_types) |