blob: 585a27bd6c7fd87b7cc9a9ca34cfc50d999f6230 [file] [log] [blame]
Gerd Hoffmannb8842202009-08-20 15:22:21 +02001/*
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ärberbaec1912013-01-23 23:03:54 +000025#include "hw/hw.h"
26#include "hw/ppc/mac.h"
Paolo Bonzini0d09e412013-02-05 17:06:20 +010027#include "hw/ppc/mac_dbdma.h"
Markus Armbruster4be74632014-10-07 13:59:18 +020028#include "sysemu/block-backend.h"
Paolo Bonzini9c17d612012-12-17 18:20:04 +010029#include "sysemu/dma.h"
Gerd Hoffmann59f2a782009-08-20 15:22:26 +020030
31#include <hw/ide/internal.h>
Gerd Hoffmannb8842202009-08-20 15:22:21 +020032
Alexander Graf33ce36b2013-06-30 01:23:45 +020033/* debug MACIO */
34// #define DEBUG_MACIO
35
36#ifdef DEBUG_MACIO
37static const int debug_macio = 1;
38#else
39static 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 Hoffmannb8842202009-08-20 15:22:21 +020049/***********************************************************/
50/* MacIO based PowerPC IDE */
51
Blue Swirl02c7c992010-03-29 19:23:57 +000052#define MACIO_PAGE_SIZE 4096
53
Mark Cave-Ayland4827ac12015-05-22 14:13:44 -040054static 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-Aylandbd4214f2015-05-22 14:13:44 -0400147static 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 Hoffmannb8842202009-08-20 15:22:21 +0200242static 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-Ayland4827ac12015-05-22 14:13:44 -0400247 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 Hoffmannb8842202009-08-20 15:22:21 +0200257
258 if (ret < 0) {
Mark Cave-Ayland4827ac12015-05-22 14:13:44 -0400259 MACIO_DPRINTF("THERE WAS AN ERROR! %d\n", ret);
Gerd Hoffmannb8842202009-08-20 15:22:21 +0200260 ide_atapi_io_error(s, ret);
Christoph Hellwiga597e792011-08-25 08:26:01 +0200261 goto done;
Gerd Hoffmannb8842202009-08-20 15:22:21 +0200262 }
263
Alexander Grafcae32352013-06-30 02:54:35 +0200264 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-Ayland4827ac12015-05-22 14:13:44 -0400272 if (s->io_buffer_size <= 0) {
Gerd Hoffmannb8842202009-08-20 15:22:21 +0200273 ide_atapi_cmd_ok(s);
Alexander Grafcae32352013-06-30 02:54:35 +0200274 m->dma_active = false;
Christoph Hellwiga597e792011-08-25 08:26:01 +0200275 goto done;
Gerd Hoffmannb8842202009-08-20 15:22:21 +0200276 }
277
Mark Cave-Ayland4827ac12015-05-22 14:13:44 -0400278 if (io->len == 0) {
279 MACIO_DPRINTF("End of DMA transfer\n");
280 goto done;
Alexander Graf80fc95d2013-06-28 13:30:01 +0200281 }
282
Mark Cave-Ayland4827ac12015-05-22 14:13:44 -0400283 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 Graf80fc95d2013-06-28 13:30:01 +0200290 }
291
Mark Cave-Ayland4827ac12015-05-22 14:13:44 -0400292 /* 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 Hoffmannb8842202009-08-20 15:22:21 +0200296
Mark Cave-Ayland4827ac12015-05-22 14:13:44 -0400297 MACIO_DPRINTF("nsector: %d remainder: %x\n", nsector, remainder);
298 MACIO_DPRINTF("sector: %"PRIx64" %zx\n", sector_num, io->iov.size / 512);
Alexander Graf33ce36b2013-06-30 01:23:45 +0200299
Mark Cave-Ayland4827ac12015-05-22 14:13:44 -0400300 pmac_dma_read(s->blk, sector_num, nsector, pmac_ide_atapi_transfer_cb, io);
Christoph Hellwiga597e792011-08-25 08:26:01 +0200301 return;
302
303done:
Mark Cave-Ayland4827ac12015-05-22 14:13:44 -0400304 MACIO_DPRINTF("done DMA\n\n");
Markus Armbruster4be74632014-10-07 13:59:18 +0200305 block_acct_done(blk_get_stats(s->blk), &s->acct);
Christoph Hellwiga597e792011-08-25 08:26:01 +0200306 io->dma_end(opaque);
Mark Cave-Ayland4827ac12015-05-22 14:13:44 -0400307
308 return;
Gerd Hoffmannb8842202009-08-20 15:22:21 +0200309}
310
311static 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 Hoffmannb8842202009-08-20 15:22:21 +0200316 int64_t sector_num;
Mark Cave-Aylandbd4214f2015-05-22 14:13:44 -0400317 int nsector, remainder;
318
319 MACIO_DPRINTF("pmac_ide_transfer_cb\n");
Gerd Hoffmannb8842202009-08-20 15:22:21 +0200320
321 if (ret < 0) {
Alexander Graf33ce36b2013-06-30 01:23:45 +0200322 MACIO_DPRINTF("DMA error\n");
Gerd Hoffmannb8842202009-08-20 15:22:21 +0200323 m->aiocb = NULL;
Alexander Graf8aef2912013-06-30 01:43:17 +0200324 ide_dma_error(s);
Alexander Graf80fc95d2013-06-28 13:30:01 +0200325 io->remainder_len = 0;
Christoph Hellwiga597e792011-08-25 08:26:01 +0200326 goto done;
Gerd Hoffmannb8842202009-08-20 15:22:21 +0200327 }
328
Alexander Grafcae32352013-06-30 02:54:35 +0200329 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-Aylandbd4214f2015-05-22 14:13:44 -0400337 if (s->io_buffer_size <= 0) {
Alexander Graf33ce36b2013-06-30 01:23:45 +0200338 MACIO_DPRINTF("end of transfer\n");
Gerd Hoffmannb8842202009-08-20 15:22:21 +0200339 s->status = READY_STAT | SEEK_STAT;
Gerd Hoffmann9cdd03a2009-08-28 16:37:42 +0200340 ide_set_irq(s->bus);
Alexander Grafcae32352013-06-30 02:54:35 +0200341 m->dma_active = false;
Christoph Hellwiga597e792011-08-25 08:26:01 +0200342 goto done;
Gerd Hoffmannb8842202009-08-20 15:22:21 +0200343 }
344
Mark Cave-Aylandbd4214f2015-05-22 14:13:44 -0400345 if (io->len == 0) {
346 MACIO_DPRINTF("End of DMA transfer\n");
347 goto done;
Alexander Graf80fc95d2013-06-28 13:30:01 +0200348 }
349
Mark Cave-Aylandbd4214f2015-05-22 14:13:44 -0400350 /* 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 Graf33ce36b2013-06-30 01:23:45 +0200354
Mark Cave-Aylandbd4214f2015-05-22 14:13:44 -0400355 s->nsector -= nsector;
Alexander Graf80fc95d2013-06-28 13:30:01 +0200356
Mark Cave-Aylandbd4214f2015-05-22 14:13:44 -0400357 MACIO_DPRINTF("nsector: %d remainder: %x\n", nsector, remainder);
358 MACIO_DPRINTF("sector: %"PRIx64" %x\n", sector_num, nsector);
Alexander Graf33ce36b2013-06-30 01:23:45 +0200359
Christoph Hellwig4e1e0052011-05-19 10:58:09 +0200360 switch (s->dma_cmd) {
361 case IDE_DMA_READ:
Mark Cave-Aylandbd4214f2015-05-22 14:13:44 -0400362 pmac_dma_read(s->blk, sector_num, nsector, pmac_ide_transfer_cb, io);
Christoph Hellwig4e1e0052011-05-19 10:58:09 +0200363 break;
364 case IDE_DMA_WRITE:
Mark Cave-Aylandbd4214f2015-05-22 14:13:44 -0400365 pmac_dma_write(s->blk, sector_num, nsector, pmac_ide_transfer_cb, io);
Christoph Hellwig4e1e0052011-05-19 10:58:09 +0200366 break;
Christoph Hellwigd353fb72011-05-19 10:58:19 +0200367 case IDE_DMA_TRIM:
Mark Cave-Aylandbd4214f2015-05-22 14:13:44 -0400368 MACIO_DPRINTF("TRIM command issued!");
Christoph Hellwigd353fb72011-05-19 10:58:19 +0200369 break;
Christoph Hellwig4e1e0052011-05-19 10:58:09 +0200370 }
Alexander Graf3e300fa2014-05-26 10:27:58 +0200371
Christoph Hellwiga597e792011-08-25 08:26:01 +0200372 return;
Paolo Bonzinib9b20082011-11-14 17:50:53 +0100373
Christoph Hellwiga597e792011-08-25 08:26:01 +0200374done:
375 if (s->dma_cmd == IDE_DMA_READ || s->dma_cmd == IDE_DMA_WRITE) {
Markus Armbruster4be74632014-10-07 13:59:18 +0200376 block_acct_done(blk_get_stats(s->blk), &s->acct);
Christoph Hellwiga597e792011-08-25 08:26:01 +0200377 }
Mark Cave-Aylandbd4214f2015-05-22 14:13:44 -0400378 io->dma_end(opaque);
Gerd Hoffmannb8842202009-08-20 15:22:21 +0200379}
380
381static void pmac_ide_transfer(DBDMA_io *io)
382{
383 MACIOIDEState *m = io->opaque;
384 IDEState *s = idebus_active_if(&m->bus);
385
Alexander Graf33ce36b2013-06-30 01:23:45 +0200386 MACIO_DPRINTF("\n");
387
Markus Armbrustercd8722b2010-05-28 13:32:45 +0200388 if (s->drive_kind == IDE_CD) {
Markus Armbruster4be74632014-10-07 13:59:18 +0200389 block_acct_start(blk_get_stats(s->blk), &s->acct, io->len,
Benoît Canet5366d0c2014-09-05 15:46:18 +0200390 BLOCK_ACCT_READ);
Mark Cave-Ayland4827ac12015-05-22 14:13:44 -0400391
Gerd Hoffmannb8842202009-08-20 15:22:21 +0200392 pmac_ide_atapi_transfer_cb(io, 0);
393 return;
394 }
395
Christoph Hellwiga597e792011-08-25 08:26:01 +0200396 switch (s->dma_cmd) {
397 case IDE_DMA_READ:
Markus Armbruster4be74632014-10-07 13:59:18 +0200398 block_acct_start(blk_get_stats(s->blk), &s->acct, io->len,
Benoît Canet5366d0c2014-09-05 15:46:18 +0200399 BLOCK_ACCT_READ);
Christoph Hellwiga597e792011-08-25 08:26:01 +0200400 break;
401 case IDE_DMA_WRITE:
Markus Armbruster4be74632014-10-07 13:59:18 +0200402 block_acct_start(blk_get_stats(s->blk), &s->acct, io->len,
Benoît Canet5366d0c2014-09-05 15:46:18 +0200403 BLOCK_ACCT_WRITE);
Christoph Hellwiga597e792011-08-25 08:26:01 +0200404 break;
405 default:
406 break;
407 }
408
Gerd Hoffmannb8842202009-08-20 15:22:21 +0200409 pmac_ide_transfer_cb(io, 0);
410}
411
412static void pmac_ide_flush(DBDMA_io *io)
413{
414 MACIOIDEState *m = io->opaque;
415
Stefan Hajnoczi922453b2011-11-30 12:23:43 +0000416 if (m->aiocb) {
Markus Armbruster4be74632014-10-07 13:59:18 +0200417 blk_drain_all();
Stefan Hajnoczi922453b2011-11-30 12:23:43 +0000418 }
Gerd Hoffmannb8842202009-08-20 15:22:21 +0200419}
420
421/* PowerMac IDE memory IO */
422static void pmac_ide_writeb (void *opaque,
Avi Kivitya8170e52012-10-23 12:30:10 +0200423 hwaddr addr, uint32_t val)
Gerd Hoffmannb8842202009-08-20 15:22:21 +0200424{
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 Kivitya8170e52012-10-23 12:30:10 +0200441static uint32_t pmac_ide_readb (void *opaque,hwaddr addr)
Gerd Hoffmannb8842202009-08-20 15:22:21 +0200442{
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
462static void pmac_ide_writew (void *opaque,
Avi Kivitya8170e52012-10-23 12:30:10 +0200463 hwaddr addr, uint32_t val)
Gerd Hoffmannb8842202009-08-20 15:22:21 +0200464{
465 MACIOIDEState *d = opaque;
466
467 addr = (addr & 0xFFF) >> 4;
Gerd Hoffmannb8842202009-08-20 15:22:21 +0200468 val = bswap16(val);
Gerd Hoffmannb8842202009-08-20 15:22:21 +0200469 if (addr == 0) {
470 ide_data_writew(&d->bus, 0, val);
471 }
472}
473
Avi Kivitya8170e52012-10-23 12:30:10 +0200474static uint32_t pmac_ide_readw (void *opaque,hwaddr addr)
Gerd Hoffmannb8842202009-08-20 15:22:21 +0200475{
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 Hoffmannb8842202009-08-20 15:22:21 +0200485 retval = bswap16(retval);
Gerd Hoffmannb8842202009-08-20 15:22:21 +0200486 return retval;
487}
488
489static void pmac_ide_writel (void *opaque,
Avi Kivitya8170e52012-10-23 12:30:10 +0200490 hwaddr addr, uint32_t val)
Gerd Hoffmannb8842202009-08-20 15:22:21 +0200491{
492 MACIOIDEState *d = opaque;
493
494 addr = (addr & 0xFFF) >> 4;
Gerd Hoffmannb8842202009-08-20 15:22:21 +0200495 val = bswap32(val);
Gerd Hoffmannb8842202009-08-20 15:22:21 +0200496 if (addr == 0) {
497 ide_data_writel(&d->bus, 0, val);
498 }
499}
500
Avi Kivitya8170e52012-10-23 12:30:10 +0200501static uint32_t pmac_ide_readl (void *opaque,hwaddr addr)
Gerd Hoffmannb8842202009-08-20 15:22:21 +0200502{
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 Hoffmannb8842202009-08-20 15:22:21 +0200512 retval = bswap32(retval);
Gerd Hoffmannb8842202009-08-20 15:22:21 +0200513 return retval;
514}
515
Stefan Weila348f102012-02-05 10:19:07 +0000516static const MemoryRegionOps pmac_ide_ops = {
Avi Kivity23c5e4c2011-08-08 16:09:17 +0300517 .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 Hoffmannb8842202009-08-20 15:22:21 +0200530};
531
Juan Quintela44bfa332009-10-07 19:04:46 +0200532static const VMStateDescription vmstate_pmac = {
533 .name = "ide",
534 .version_id = 3,
535 .minimum_version_id = 0,
Juan Quintela35d08452014-04-16 16:01:33 +0200536 .fields = (VMStateField[]) {
Juan Quintela44bfa332009-10-07 19:04:46 +0200537 VMSTATE_IDE_BUS(bus, MACIOIDEState),
538 VMSTATE_IDE_DRIVES(bus.ifs, MACIOIDEState),
539 VMSTATE_END_OF_LIST()
Gerd Hoffmannb8842202009-08-20 15:22:21 +0200540 }
Juan Quintela44bfa332009-10-07 19:04:46 +0200541};
Gerd Hoffmannb8842202009-08-20 15:22:21 +0200542
Andreas Färber07a74842013-01-23 23:04:01 +0000543static void macio_ide_reset(DeviceState *dev)
Gerd Hoffmannb8842202009-08-20 15:22:21 +0200544{
Andreas Färber07a74842013-01-23 23:04:01 +0000545 MACIOIDEState *d = MACIO_IDE(dev);
Gerd Hoffmannb8842202009-08-20 15:22:21 +0200546
Blue Swirl4a643562009-11-07 14:13:05 +0000547 ide_bus_reset(&d->bus);
Gerd Hoffmannb8842202009-08-20 15:22:21 +0200548}
549
Alexander Graf4aa35102013-06-30 02:36:14 +0200550static int ide_nop_int(IDEDMA *dma, int x)
551{
552 return 0;
553}
554
John Snow3251bdc2014-10-31 16:03:39 -0400555static int32_t ide_nop_int32(IDEDMA *dma, int x)
556{
557 return 0;
558}
559
Alexander Graf4aa35102013-06-30 02:36:14 +0200560static void ide_dbdma_start(IDEDMA *dma, IDEState *s,
Markus Armbruster097310b2014-10-07 13:59:15 +0200561 BlockCompletionFunc *cb)
Alexander Graf4aa35102013-06-30 02:36:14 +0200562{
563 MACIOIDEState *m = container_of(dma, MACIOIDEState, dma);
Mark Cave-Ayland4827ac12015-05-22 14:13:44 -0400564 DBDMAState *dbdma = m->dbdma;
565 DBDMA_io *io;
566 int i;
567
Mark Cave-Aylandbd4214f2015-05-22 14:13:44 -0400568 s->io_buffer_index = 0;
Mark Cave-Ayland4827ac12015-05-22 14:13:44 -0400569 if (s->drive_kind == IDE_CD) {
Mark Cave-Ayland4827ac12015-05-22 14:13:44 -0400570 s->io_buffer_size = s->packet_transfer_size;
Mark Cave-Aylandbd4214f2015-05-22 14:13:44 -0400571 } else {
572 s->io_buffer_size = s->nsector * 0x200;
573 }
Mark Cave-Ayland4827ac12015-05-22 14:13:44 -0400574
Mark Cave-Aylandbd4214f2015-05-22 14:13:44 -0400575 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-Ayland4827ac12015-05-22 14:13:44 -0400580
Mark Cave-Aylandbd4214f2015-05-22 14:13:44 -0400581 for (i = 0; i < DBDMA_CHANNELS; i++) {
582 io = &dbdma->channels[i].io;
Mark Cave-Ayland4827ac12015-05-22 14:13:44 -0400583
Mark Cave-Aylandbd4214f2015-05-22 14:13:44 -0400584 if (io->opaque == m) {
585 io->remainder_len = 0;
Mark Cave-Ayland4827ac12015-05-22 14:13:44 -0400586 }
587 }
Alexander Graf4aa35102013-06-30 02:36:14 +0200588
589 MACIO_DPRINTF("\n");
Alexander Grafcae32352013-06-30 02:54:35 +0200590 m->dma_active = true;
Alexander Graf4aa35102013-06-30 02:36:14 +0200591 DBDMA_kick(m->dbdma);
592}
593
594static const IDEDMAOps dbdma_ops = {
595 .start_dma = ide_dbdma_start,
John Snow3251bdc2014-10-31 16:03:39 -0400596 .prepare_buf = ide_nop_int32,
Alexander Graf4aa35102013-06-30 02:36:14 +0200597 .rw_buf = ide_nop_int,
Alexander Graf4aa35102013-06-30 02:36:14 +0200598};
599
Andreas Färber07a74842013-01-23 23:04:01 +0000600static void macio_ide_realizefn(DeviceState *dev, Error **errp)
Gerd Hoffmannb8842202009-08-20 15:22:21 +0200601{
Andreas Färber07a74842013-01-23 23:04:01 +0000602 MACIOIDEState *s = MACIO_IDE(dev);
Gerd Hoffmannb8842202009-08-20 15:22:21 +0200603
Andreas Färber07a74842013-01-23 23:04:01 +0000604 ide_init2(&s->bus, s->irq);
Alexander Graf4aa35102013-06-30 02:36:14 +0200605
606 /* Register DMA callbacks */
607 s->dma.ops = &dbdma_ops;
608 s->bus.dma = &s->dma;
Gerd Hoffmannb8842202009-08-20 15:22:21 +0200609}
Andreas Färber07a74842013-01-23 23:04:01 +0000610
611static void macio_ide_initfn(Object *obj)
612{
613 SysBusDevice *d = SYS_BUS_DEVICE(obj);
614 MACIOIDEState *s = MACIO_IDE(obj);
615
Andreas Färberc6baf942013-08-23 20:18:50 +0200616 ide_bus_new(&s->bus, sizeof(s->bus), DEVICE(obj), 0, 2);
Paolo Bonzini1437c942013-06-06 21:25:08 -0400617 memory_region_init_io(&s->mem, obj, &pmac_ide_ops, s, "pmac-ide", 0x1000);
Andreas Färber07a74842013-01-23 23:04:01 +0000618 sysbus_init_mmio(d, &s->mem);
619 sysbus_init_irq(d, &s->irq);
620 sysbus_init_irq(d, &s->dma_irq);
621}
622
623static 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
632static 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
640static void macio_ide_register_types(void)
641{
642 type_register_static(&macio_ide_type_info);
643}
644
Alexander Graf14eefd02013-06-24 21:40:50 +0200645/* hd_table must contain 2 block drivers */
Andreas Färber07a74842013-01-23 23:04:01 +0000646void 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
657void macio_ide_register_dma(MACIOIDEState *s, void *dbdma, int channel)
658{
Alexander Graf4aa35102013-06-30 02:36:14 +0200659 s->dbdma = dbdma;
Andreas Färber07a74842013-01-23 23:04:01 +0000660 DBDMA_register_channel(dbdma, channel, s->dma_irq,
661 pmac_ide_transfer, pmac_ide_flush, s);
662}
663
664type_init(macio_ide_register_types)