blob: bab8c45a4338802e91c7cc4b74d2841d6a390d29 [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 */
Peter Maydell53239262016-01-26 18:17:09 +000025#include "qemu/osdep.h"
Andreas Färberbaec1912013-01-23 23:03:54 +000026#include "hw/hw.h"
27#include "hw/ppc/mac.h"
Paolo Bonzini0d09e412013-02-05 17:06:20 +010028#include "hw/ppc/mac_dbdma.h"
Mark Cave-Ayland9b164a42018-08-29 17:59:05 +010029#include "hw/misc/macio/macio.h"
Markus Armbruster4be74632014-10-07 13:59:18 +020030#include "sysemu/block-backend.h"
Paolo Bonzini9c17d612012-12-17 18:20:04 +010031#include "sysemu/dma.h"
Gerd Hoffmann59f2a782009-08-20 15:22:26 +020032
Markus Armbrustera9c94272016-06-22 19:11:19 +020033#include "hw/ide/internal.h"
Gerd Hoffmannb8842202009-08-20 15:22:21 +020034
Alexander Graf33ce36b2013-06-30 01:23:45 +020035/* 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
Gerd Hoffmannb8842202009-08-20 15:22:21 +020051/***********************************************************/
52/* MacIO based PowerPC IDE */
53
Blue Swirl02c7c992010-03-29 19:23:57 +000054#define MACIO_PAGE_SIZE 4096
55
Gerd Hoffmannb8842202009-08-20 15:22:21 +020056static 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);
Mark Cave-Ayland0389b8f2015-06-04 22:59:34 +010061 int64_t offset;
Mark Cave-Ayland4827ac12015-05-22 14:13:44 -040062
Mark Cave-Aylandb01d44c2015-06-04 22:59:36 +010063 MACIO_DPRINTF("pmac_ide_atapi_transfer_cb\n");
Gerd Hoffmannb8842202009-08-20 15:22:21 +020064
65 if (ret < 0) {
Mark Cave-Aylandb01d44c2015-06-04 22:59:36 +010066 MACIO_DPRINTF("DMA error: %d\n", ret);
Mark Cave-Aylandbe1e3432016-10-27 16:29:13 -040067 qemu_sglist_destroy(&s->sg);
Gerd Hoffmannb8842202009-08-20 15:22:21 +020068 ide_atapi_io_error(s, ret);
Christoph Hellwiga597e792011-08-25 08:26:01 +020069 goto done;
Gerd Hoffmannb8842202009-08-20 15:22:21 +020070 }
71
Alexander Grafcae32352013-06-30 02:54:35 +020072 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
Mark Cave-Ayland4827ac12015-05-22 14:13:44 -040080 if (s->io_buffer_size <= 0) {
Mark Cave-Aylandb01d44c2015-06-04 22:59:36 +010081 MACIO_DPRINTF("End of IDE transfer\n");
Mark Cave-Aylandbe1e3432016-10-27 16:29:13 -040082 qemu_sglist_destroy(&s->sg);
Gerd Hoffmannb8842202009-08-20 15:22:21 +020083 ide_atapi_cmd_ok(s);
Alexander Grafcae32352013-06-30 02:54:35 +020084 m->dma_active = false;
Christoph Hellwiga597e792011-08-25 08:26:01 +020085 goto done;
Gerd Hoffmannb8842202009-08-20 15:22:21 +020086 }
87
Mark Cave-Ayland4827ac12015-05-22 14:13:44 -040088 if (io->len == 0) {
89 MACIO_DPRINTF("End of DMA transfer\n");
90 goto done;
Alexander Graf80fc95d2013-06-28 13:30:01 +020091 }
92
Mark Cave-Ayland4827ac12015-05-22 14:13:44 -040093 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);
Mark Cave-Aylandddd495e2016-06-05 23:36:42 +010096 dma_memory_write(&address_space_memory, io->addr, s->io_buffer,
97 s->io_buffer_size);
Mark Cave-Ayland16275ed2016-08-05 08:30:02 +010098 io->len = 0;
Mark Cave-Ayland4827ac12015-05-22 14:13:44 -040099 ide_atapi_cmd_ok(s);
100 m->dma_active = false;
101 goto done;
Alexander Graf80fc95d2013-06-28 13:30:01 +0200102 }
103
Mark Cave-Ayland0389b8f2015-06-04 22:59:34 +0100104 /* Calculate current offset */
Mark Cave-Ayland97225172016-01-11 14:10:42 -0500105 offset = ((int64_t)s->lba << 11) + s->io_buffer_index;
Mark Cave-Ayland0389b8f2015-06-04 22:59:34 +0100106
Mark Cave-Aylandbe1e3432016-10-27 16:29:13 -0400107 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);
Christoph Hellwiga597e792011-08-25 08:26:01 +0200116 return;
117
118done:
Mark Cave-Aylandbc9ca592016-06-10 19:26:37 +0100119 dma_memory_unmap(&address_space_memory, io->dma_mem, io->dma_len,
120 io->dir, io->dma_len);
121
Alberto Garciab88b3c82015-10-28 17:33:16 +0200122 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 }
Mark Cave-Ayland03c12802016-01-30 23:36:52 +1100127
128 ide_set_inactive(s, false);
Christoph Hellwiga597e792011-08-25 08:26:01 +0200129 io->dma_end(opaque);
Gerd Hoffmannb8842202009-08-20 15:22:21 +0200130}
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);
Mark Cave-Ayland0389b8f2015-06-04 22:59:34 +0100137 int64_t offset;
Mark Cave-Aylandbd4214f2015-05-22 14:13:44 -0400138
139 MACIO_DPRINTF("pmac_ide_transfer_cb\n");
Gerd Hoffmannb8842202009-08-20 15:22:21 +0200140
141 if (ret < 0) {
Mark Cave-Aylandb01d44c2015-06-04 22:59:36 +0100142 MACIO_DPRINTF("DMA error: %d\n", ret);
Mark Cave-Aylandbe1e3432016-10-27 16:29:13 -0400143 qemu_sglist_destroy(&s->sg);
Alexander Graf8aef2912013-06-30 01:43:17 +0200144 ide_dma_error(s);
Christoph Hellwiga597e792011-08-25 08:26:01 +0200145 goto done;
Gerd Hoffmannb8842202009-08-20 15:22:21 +0200146 }
147
Alexander Grafcae32352013-06-30 02:54:35 +0200148 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
Mark Cave-Aylandbd4214f2015-05-22 14:13:44 -0400156 if (s->io_buffer_size <= 0) {
Mark Cave-Aylandb01d44c2015-06-04 22:59:36 +0100157 MACIO_DPRINTF("End of IDE transfer\n");
Mark Cave-Aylandbe1e3432016-10-27 16:29:13 -0400158 qemu_sglist_destroy(&s->sg);
Gerd Hoffmannb8842202009-08-20 15:22:21 +0200159 s->status = READY_STAT | SEEK_STAT;
Gerd Hoffmann9cdd03a2009-08-28 16:37:42 +0200160 ide_set_irq(s->bus);
Alexander Grafcae32352013-06-30 02:54:35 +0200161 m->dma_active = false;
Christoph Hellwiga597e792011-08-25 08:26:01 +0200162 goto done;
Gerd Hoffmannb8842202009-08-20 15:22:21 +0200163 }
164
Mark Cave-Aylandbd4214f2015-05-22 14:13:44 -0400165 if (io->len == 0) {
166 MACIO_DPRINTF("End of DMA transfer\n");
167 goto done;
Alexander Graf80fc95d2013-06-28 13:30:01 +0200168 }
169
Mark Cave-Aylandbd4214f2015-05-22 14:13:44 -0400170 /* Calculate number of sectors */
Mark Cave-Ayland0389b8f2015-06-04 22:59:34 +0100171 offset = (ide_get_sector(s) << 9) + s->io_buffer_index;
Alexander Graf33ce36b2013-06-30 01:23:45 +0200172
Mark Cave-Aylandbe1e3432016-10-27 16:29:13 -0400173 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
Christoph Hellwig4e1e0052011-05-19 10:58:09 +0200180 switch (s->dma_cmd) {
181 case IDE_DMA_READ:
Mark Cave-Aylandbe1e3432016-10-27 16:29:13 -0400182 s->bus->dma->aiocb = dma_blk_read(s->blk, &s->sg, offset, 0x1,
183 pmac_ide_atapi_transfer_cb, io);
Christoph Hellwig4e1e0052011-05-19 10:58:09 +0200184 break;
185 case IDE_DMA_WRITE:
Mark Cave-Aylandbe1e3432016-10-27 16:29:13 -0400186 s->bus->dma->aiocb = dma_blk_write(s->blk, &s->sg, offset, 0x1,
187 pmac_ide_transfer_cb, io);
Christoph Hellwig4e1e0052011-05-19 10:58:09 +0200188 break;
Christoph Hellwigd353fb72011-05-19 10:58:19 +0200189 case IDE_DMA_TRIM:
Mark Cave-Aylandbe1e3432016-10-27 16:29:13 -0400190 s->bus->dma->aiocb = dma_blk_io(blk_get_aio_context(s->blk), &s->sg,
Mark Cave-Aylandeb699532018-03-27 00:38:00 -0400191 offset, 0x1, ide_issue_trim, s,
Mark Cave-Aylandbe1e3432016-10-27 16:29:13 -0400192 pmac_ide_transfer_cb, io,
193 DMA_DIRECTION_TO_DEVICE);
Christoph Hellwigd353fb72011-05-19 10:58:19 +0200194 break;
Pavel Butsykin502356e2016-04-12 18:48:15 -0400195 default:
196 abort();
Christoph Hellwig4e1e0052011-05-19 10:58:09 +0200197 }
Alexander Graf3e300fa2014-05-26 10:27:58 +0200198
Christoph Hellwiga597e792011-08-25 08:26:01 +0200199 return;
Paolo Bonzinib9b20082011-11-14 17:50:53 +0100200
Christoph Hellwiga597e792011-08-25 08:26:01 +0200201done:
Mark Cave-Aylandbc9ca592016-06-10 19:26:37 +0100202 dma_memory_unmap(&address_space_memory, io->dma_mem, io->dma_len,
203 io->dir, io->dma_len);
204
Christoph Hellwiga597e792011-08-25 08:26:01 +0200205 if (s->dma_cmd == IDE_DMA_READ || s->dma_cmd == IDE_DMA_WRITE) {
Alberto Garciab88b3c82015-10-28 17:33:16 +0200206 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 }
Christoph Hellwiga597e792011-08-25 08:26:01 +0200211 }
Mark Cave-Ayland03c12802016-01-30 23:36:52 +1100212
213 ide_set_inactive(s, false);
Mark Cave-Aylandbd4214f2015-05-22 14:13:44 -0400214 io->dma_end(opaque);
Gerd Hoffmannb8842202009-08-20 15:22:21 +0200215}
216
217static void pmac_ide_transfer(DBDMA_io *io)
218{
219 MACIOIDEState *m = io->opaque;
220 IDEState *s = idebus_active_if(&m->bus);
221
Alexander Graf33ce36b2013-06-30 01:23:45 +0200222 MACIO_DPRINTF("\n");
223
Markus Armbrustercd8722b2010-05-28 13:32:45 +0200224 if (s->drive_kind == IDE_CD) {
Markus Armbruster4be74632014-10-07 13:59:18 +0200225 block_acct_start(blk_get_stats(s->blk), &s->acct, io->len,
Benoît Canet5366d0c2014-09-05 15:46:18 +0200226 BLOCK_ACCT_READ);
Mark Cave-Ayland4827ac12015-05-22 14:13:44 -0400227
Gerd Hoffmannb8842202009-08-20 15:22:21 +0200228 pmac_ide_atapi_transfer_cb(io, 0);
229 return;
230 }
231
Christoph Hellwiga597e792011-08-25 08:26:01 +0200232 switch (s->dma_cmd) {
233 case IDE_DMA_READ:
Markus Armbruster4be74632014-10-07 13:59:18 +0200234 block_acct_start(blk_get_stats(s->blk), &s->acct, io->len,
Benoît Canet5366d0c2014-09-05 15:46:18 +0200235 BLOCK_ACCT_READ);
Christoph Hellwiga597e792011-08-25 08:26:01 +0200236 break;
237 case IDE_DMA_WRITE:
Markus Armbruster4be74632014-10-07 13:59:18 +0200238 block_acct_start(blk_get_stats(s->blk), &s->acct, io->len,
Benoît Canet5366d0c2014-09-05 15:46:18 +0200239 BLOCK_ACCT_WRITE);
Christoph Hellwiga597e792011-08-25 08:26:01 +0200240 break;
241 default:
242 break;
243 }
244
Gerd Hoffmannb8842202009-08-20 15:22:21 +0200245 pmac_ide_transfer_cb(io, 0);
246}
247
248static void pmac_ide_flush(DBDMA_io *io)
249{
250 MACIOIDEState *m = io->opaque;
Mark Cave-Ayland03c12802016-01-30 23:36:52 +1100251 IDEState *s = idebus_active_if(&m->bus);
Gerd Hoffmannb8842202009-08-20 15:22:21 +0200252
Mark Cave-Ayland03c12802016-01-30 23:36:52 +1100253 if (s->bus->dma->aiocb) {
Fam Zheng0d0437a2016-06-27 14:28:31 -0400254 blk_drain(s->blk);
Stefan Hajnoczi922453b2011-11-30 12:23:43 +0000255 }
Gerd Hoffmannb8842202009-08-20 15:22:21 +0200256}
257
258/* PowerMac IDE memory IO */
Mark Cave-Ayland5abdf672017-09-20 07:20:01 +0100259static uint64_t pmac_ide_read(void *opaque, hwaddr addr, unsigned size)
Gerd Hoffmannb8842202009-08-20 15:22:21 +0200260{
261 MACIOIDEState *d = opaque;
Mark Cave-Ayland5abdf672017-09-20 07:20:01 +0100262 uint64_t retval = 0xffffffff;
263 int reg = addr >> 4;
Gerd Hoffmannb8842202009-08-20 15:22:21 +0200264
Mark Cave-Ayland5abdf672017-09-20 07:20:01 +0100265 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);
Benjamin Herrenschmidt4f7265f2017-09-20 07:20:00 +0100271 }
Mark Cave-Ayland5abdf672017-09-20 07:20:01 +0100272 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:
Benjamin Herrenschmidt4f7265f2017-09-20 07:20:00 +0100290 /* 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 */
Mark Cave-Ayland5abdf672017-09-20 07:20:01 +0100297 if (size == 4) {
298 retval = d->irq_reg;
299 }
300 break;
Gerd Hoffmannb8842202009-08-20 15:22:21 +0200301 }
Mark Cave-Ayland5abdf672017-09-20 07:20:01 +0100302
Gerd Hoffmannb8842202009-08-20 15:22:21 +0200303 return retval;
304}
305
Mark Cave-Ayland5abdf672017-09-20 07:20:01 +0100306
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
Stefan Weila348f102012-02-05 10:19:07 +0000347static const MemoryRegionOps pmac_ide_ops = {
Mark Cave-Ayland5abdf672017-09-20 07:20:01 +0100348 .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,
Gerd Hoffmannb8842202009-08-20 15:22:21 +0200353};
354
Juan Quintela44bfa332009-10-07 19:04:46 +0200355static const VMStateDescription vmstate_pmac = {
356 .name = "ide",
Mark Cave-Aylandc2a01252017-09-30 17:49:35 +0100357 .version_id = 5,
Juan Quintela44bfa332009-10-07 19:04:46 +0200358 .minimum_version_id = 0,
Juan Quintela35d08452014-04-16 16:01:33 +0200359 .fields = (VMStateField[]) {
Juan Quintela44bfa332009-10-07 19:04:46 +0200360 VMSTATE_IDE_BUS(bus, MACIOIDEState),
361 VMSTATE_IDE_DRIVES(bus.ifs, MACIOIDEState),
Mark Cave-Aylandbb37a8e2016-01-06 20:37:24 +0000362 VMSTATE_BOOL(dma_active, MACIOIDEState),
Mark Cave-Aylandc2a01252017-09-30 17:49:35 +0100363 VMSTATE_UINT32(timing_reg, MACIOIDEState),
364 VMSTATE_UINT32(irq_reg, MACIOIDEState),
Juan Quintela44bfa332009-10-07 19:04:46 +0200365 VMSTATE_END_OF_LIST()
Gerd Hoffmannb8842202009-08-20 15:22:21 +0200366 }
Juan Quintela44bfa332009-10-07 19:04:46 +0200367};
Gerd Hoffmannb8842202009-08-20 15:22:21 +0200368
Andreas Färber07a74842013-01-23 23:04:01 +0000369static void macio_ide_reset(DeviceState *dev)
Gerd Hoffmannb8842202009-08-20 15:22:21 +0200370{
Andreas Färber07a74842013-01-23 23:04:01 +0000371 MACIOIDEState *d = MACIO_IDE(dev);
Gerd Hoffmannb8842202009-08-20 15:22:21 +0200372
Blue Swirl4a643562009-11-07 14:13:05 +0000373 ide_bus_reset(&d->bus);
Gerd Hoffmannb8842202009-08-20 15:22:21 +0200374}
375
Alexander Graf4aa35102013-06-30 02:36:14 +0200376static int ide_nop_int(IDEDMA *dma, int x)
377{
378 return 0;
379}
380
John Snowa7189782015-07-04 02:06:04 -0400381static int32_t ide_nop_int32(IDEDMA *dma, int32_t l)
John Snow3251bdc2014-10-31 16:03:39 -0400382{
383 return 0;
384}
385
Alexander Graf4aa35102013-06-30 02:36:14 +0200386static void ide_dbdma_start(IDEDMA *dma, IDEState *s,
Markus Armbruster097310b2014-10-07 13:59:15 +0200387 BlockCompletionFunc *cb)
Alexander Graf4aa35102013-06-30 02:36:14 +0200388{
389 MACIOIDEState *m = container_of(dma, MACIOIDEState, dma);
Mark Cave-Ayland4827ac12015-05-22 14:13:44 -0400390
Mark Cave-Aylandbd4214f2015-05-22 14:13:44 -0400391 s->io_buffer_index = 0;
Mark Cave-Ayland4827ac12015-05-22 14:13:44 -0400392 if (s->drive_kind == IDE_CD) {
Mark Cave-Ayland4827ac12015-05-22 14:13:44 -0400393 s->io_buffer_size = s->packet_transfer_size;
Mark Cave-Aylandbd4214f2015-05-22 14:13:44 -0400394 } else {
Mark Cave-Aylandb01d44c2015-06-04 22:59:36 +0100395 s->io_buffer_size = s->nsector * BDRV_SECTOR_SIZE;
Mark Cave-Aylandbd4214f2015-05-22 14:13:44 -0400396 }
Mark Cave-Ayland4827ac12015-05-22 14:13:44 -0400397
Mark Cave-Aylandbd4214f2015-05-22 14:13:44 -0400398 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");
Mark Cave-Ayland4827ac12015-05-22 14:13:44 -0400403
Alexander Grafcae32352013-06-30 02:54:35 +0200404 m->dma_active = true;
Alexander Graf4aa35102013-06-30 02:36:14 +0200405 DBDMA_kick(m->dbdma);
406}
407
408static const IDEDMAOps dbdma_ops = {
409 .start_dma = ide_dbdma_start,
John Snow3251bdc2014-10-31 16:03:39 -0400410 .prepare_buf = ide_nop_int32,
Alexander Graf4aa35102013-06-30 02:36:14 +0200411 .rw_buf = ide_nop_int,
Alexander Graf4aa35102013-06-30 02:36:14 +0200412};
413
Andreas Färber07a74842013-01-23 23:04:01 +0000414static void macio_ide_realizefn(DeviceState *dev, Error **errp)
Gerd Hoffmannb8842202009-08-20 15:22:21 +0200415{
Andreas Färber07a74842013-01-23 23:04:01 +0000416 MACIOIDEState *s = MACIO_IDE(dev);
Gerd Hoffmannb8842202009-08-20 15:22:21 +0200417
Benjamin Herrenschmidt4f7265f2017-09-20 07:20:00 +0100418 ide_init2(&s->bus, s->ide_irq);
Alexander Graf4aa35102013-06-30 02:36:14 +0200419
420 /* Register DMA callbacks */
421 s->dma.ops = &dbdma_ops;
422 s->bus.dma = &s->dma;
Gerd Hoffmannb8842202009-08-20 15:22:21 +0200423}
Andreas Färber07a74842013-01-23 23:04:01 +0000424
Benjamin Herrenschmidt4f7265f2017-09-20 07:20:00 +0100425static 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
Andreas Färber07a74842013-01-23 23:04:01 +0000444static void macio_ide_initfn(Object *obj)
445{
446 SysBusDevice *d = SYS_BUS_DEVICE(obj);
447 MACIOIDEState *s = MACIO_IDE(obj);
448
Andreas Färberc6baf942013-08-23 20:18:50 +0200449 ide_bus_new(&s->bus, sizeof(s->bus), DEVICE(obj), 0, 2);
Paolo Bonzini1437c942013-06-06 21:25:08 -0400450 memory_region_init_io(&s->mem, obj, &pmac_ide_ops, s, "pmac-ide", 0x1000);
Andreas Färber07a74842013-01-23 23:04:01 +0000451 sysbus_init_mmio(d, &s->mem);
Benjamin Herrenschmidt4f7265f2017-09-20 07:20:00 +0100452 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);
Mark Cave-Aylande451b852017-09-24 15:47:44 +0100456
457 object_property_add_link(obj, "dbdma", TYPE_MAC_DBDMA,
458 (Object **) &s->dbdma,
459 qdev_prop_allow_set_link_before_realize, 0, NULL);
Andreas Färber07a74842013-01-23 23:04:01 +0000460}
461
Mark Cave-Ayland0fc84332017-09-24 15:47:43 +0100462static Property macio_ide_properties[] = {
463 DEFINE_PROP_UINT32("channel", MACIOIDEState, channel, 0),
Mark Cave-Ayland5c8e3d12018-08-29 17:59:07 +0100464 DEFINE_PROP_UINT32("addr", MACIOIDEState, addr, -1),
Mark Cave-Ayland0fc84332017-09-24 15:47:43 +0100465 DEFINE_PROP_END_OF_LIST(),
466};
467
Andreas Färber07a74842013-01-23 23:04:01 +0000468static 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;
Mark Cave-Ayland0fc84332017-09-24 15:47:43 +0100474 dc->props = macio_ide_properties;
Andreas Färber07a74842013-01-23 23:04:01 +0000475 dc->vmsd = &vmstate_pmac;
Laurent Vivier3469d9b2015-09-26 18:22:08 +0200476 set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
Andreas Färber07a74842013-01-23 23:04:01 +0000477}
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
Alexander Graf14eefd02013-06-24 21:40:50 +0200492/* hd_table must contain 2 block drivers */
Andreas Färber07a74842013-01-23 23:04:01 +0000493void 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
Mark Cave-Aylande451b852017-09-24 15:47:44 +0100504void macio_ide_register_dma(MACIOIDEState *s)
Andreas Färber07a74842013-01-23 23:04:01 +0000505{
Mark Cave-Aylande451b852017-09-24 15:47:44 +0100506 DBDMA_register_channel(s->dbdma, s->channel, s->dma_irq,
Andreas Färber07a74842013-01-23 23:04:01 +0000507 pmac_ide_transfer, pmac_ide_flush, s);
508}
509
510type_init(macio_ide_register_types)