xref: /openbmc/qemu/hw/ide/macio.c (revision 135a67a692bedb952ea720351026247104da8645)
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 "sysemu/block-backend.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_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 
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 
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);
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);
257 
258     if (ret < 0) {
259         MACIO_DPRINTF("THERE WAS AN ERROR!  %d\n", ret);
260         ide_atapi_io_error(s, ret);
261         goto done;
262     }
263 
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 
272     if (s->io_buffer_size <= 0) {
273         ide_atapi_cmd_ok(s);
274         m->dma_active = false;
275         goto done;
276     }
277 
278     if (io->len == 0) {
279         MACIO_DPRINTF("End of DMA transfer\n");
280         goto done;
281     }
282 
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;
290     }
291 
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;
296 
297     MACIO_DPRINTF("nsector: %d   remainder: %x\n", nsector, remainder);
298     MACIO_DPRINTF("sector: %"PRIx64"   %zx\n", sector_num, io->iov.size / 512);
299 
300     pmac_dma_read(s->blk, sector_num, nsector, pmac_ide_atapi_transfer_cb, io);
301     return;
302 
303 done:
304     MACIO_DPRINTF("done DMA\n\n");
305     block_acct_done(blk_get_stats(s->blk), &s->acct);
306     io->dma_end(opaque);
307 
308     return;
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);
316     int64_t sector_num;
317     int nsector, remainder;
318 
319     MACIO_DPRINTF("pmac_ide_transfer_cb\n");
320 
321     if (ret < 0) {
322         MACIO_DPRINTF("DMA error\n");
323         m->aiocb = NULL;
324         ide_dma_error(s);
325         io->remainder_len = 0;
326         goto done;
327     }
328 
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 
337     if (s->io_buffer_size <= 0) {
338         MACIO_DPRINTF("end of transfer\n");
339         s->status = READY_STAT | SEEK_STAT;
340         ide_set_irq(s->bus);
341         m->dma_active = false;
342         goto done;
343     }
344 
345     if (io->len == 0) {
346         MACIO_DPRINTF("End of DMA transfer\n");
347         goto done;
348     }
349 
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;
354 
355     s->nsector -= nsector;
356 
357     MACIO_DPRINTF("nsector: %d   remainder: %x\n", nsector, remainder);
358     MACIO_DPRINTF("sector: %"PRIx64"   %x\n", sector_num, nsector);
359 
360     switch (s->dma_cmd) {
361     case IDE_DMA_READ:
362         pmac_dma_read(s->blk, sector_num, nsector, pmac_ide_transfer_cb, io);
363         break;
364     case IDE_DMA_WRITE:
365         pmac_dma_write(s->blk, sector_num, nsector, pmac_ide_transfer_cb, io);
366         break;
367     case IDE_DMA_TRIM:
368         MACIO_DPRINTF("TRIM command issued!");
369         break;
370     }
371 
372     return;
373 
374 done:
375     if (s->dma_cmd == IDE_DMA_READ || s->dma_cmd == IDE_DMA_WRITE) {
376         block_acct_done(blk_get_stats(s->blk), &s->acct);
377     }
378     io->dma_end(opaque);
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 
386     MACIO_DPRINTF("\n");
387 
388     if (s->drive_kind == IDE_CD) {
389         block_acct_start(blk_get_stats(s->blk), &s->acct, io->len,
390                          BLOCK_ACCT_READ);
391 
392         pmac_ide_atapi_transfer_cb(io, 0);
393         return;
394     }
395 
396     switch (s->dma_cmd) {
397     case IDE_DMA_READ:
398         block_acct_start(blk_get_stats(s->blk), &s->acct, io->len,
399                          BLOCK_ACCT_READ);
400         break;
401     case IDE_DMA_WRITE:
402         block_acct_start(blk_get_stats(s->blk), &s->acct, io->len,
403                          BLOCK_ACCT_WRITE);
404         break;
405     default:
406         break;
407     }
408 
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 
416     if (m->aiocb) {
417         blk_drain_all();
418     }
419 }
420 
421 /* PowerMac IDE memory IO */
422 static void pmac_ide_writeb (void *opaque,
423                              hwaddr addr, uint32_t val)
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 
441 static uint32_t pmac_ide_readb (void *opaque,hwaddr addr)
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,
463                              hwaddr addr, uint32_t val)
464 {
465     MACIOIDEState *d = opaque;
466 
467     addr = (addr & 0xFFF) >> 4;
468     val = bswap16(val);
469     if (addr == 0) {
470         ide_data_writew(&d->bus, 0, val);
471     }
472 }
473 
474 static uint32_t pmac_ide_readw (void *opaque,hwaddr addr)
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     }
485     retval = bswap16(retval);
486     return retval;
487 }
488 
489 static void pmac_ide_writel (void *opaque,
490                              hwaddr addr, uint32_t val)
491 {
492     MACIOIDEState *d = opaque;
493 
494     addr = (addr & 0xFFF) >> 4;
495     val = bswap32(val);
496     if (addr == 0) {
497         ide_data_writel(&d->bus, 0, val);
498     }
499 }
500 
501 static uint32_t pmac_ide_readl (void *opaque,hwaddr addr)
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     }
512     retval = bswap32(retval);
513     return retval;
514 }
515 
516 static const MemoryRegionOps pmac_ide_ops = {
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,
530 };
531 
532 static const VMStateDescription vmstate_pmac = {
533     .name = "ide",
534     .version_id = 3,
535     .minimum_version_id = 0,
536     .fields = (VMStateField[]) {
537         VMSTATE_IDE_BUS(bus, MACIOIDEState),
538         VMSTATE_IDE_DRIVES(bus.ifs, MACIOIDEState),
539         VMSTATE_END_OF_LIST()
540     }
541 };
542 
543 static void macio_ide_reset(DeviceState *dev)
544 {
545     MACIOIDEState *d = MACIO_IDE(dev);
546 
547     ide_bus_reset(&d->bus);
548 }
549 
550 static int ide_nop_int(IDEDMA *dma, int x)
551 {
552     return 0;
553 }
554 
555 static int32_t ide_nop_int32(IDEDMA *dma, int x)
556 {
557     return 0;
558 }
559 
560 static void ide_dbdma_start(IDEDMA *dma, IDEState *s,
561                             BlockCompletionFunc *cb)
562 {
563     MACIOIDEState *m = container_of(dma, MACIOIDEState, dma);
564     DBDMAState *dbdma = m->dbdma;
565     DBDMA_io *io;
566     int i;
567 
568     s->io_buffer_index = 0;
569     if (s->drive_kind == IDE_CD) {
570         s->io_buffer_size = s->packet_transfer_size;
571     } else {
572         s->io_buffer_size = s->nsector * 0x200;
573     }
574 
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");
580 
581     for (i = 0; i < DBDMA_CHANNELS; i++) {
582         io = &dbdma->channels[i].io;
583 
584         if (io->opaque == m) {
585             io->remainder_len = 0;
586         }
587     }
588 
589     MACIO_DPRINTF("\n");
590     m->dma_active = true;
591     DBDMA_kick(m->dbdma);
592 }
593 
594 static const IDEDMAOps dbdma_ops = {
595     .start_dma      = ide_dbdma_start,
596     .prepare_buf    = ide_nop_int32,
597     .rw_buf         = ide_nop_int,
598 };
599 
600 static void macio_ide_realizefn(DeviceState *dev, Error **errp)
601 {
602     MACIOIDEState *s = MACIO_IDE(dev);
603 
604     ide_init2(&s->bus, s->irq);
605 
606     /* Register DMA callbacks */
607     s->dma.ops = &dbdma_ops;
608     s->bus.dma = &s->dma;
609 }
610 
611 static void macio_ide_initfn(Object *obj)
612 {
613     SysBusDevice *d = SYS_BUS_DEVICE(obj);
614     MACIOIDEState *s = MACIO_IDE(obj);
615 
616     ide_bus_new(&s->bus, sizeof(s->bus), DEVICE(obj), 0, 2);
617     memory_region_init_io(&s->mem, obj, &pmac_ide_ops, s, "pmac-ide", 0x1000);
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 
645 /* hd_table must contain 2 block drivers */
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 {
659     s->dbdma = dbdma;
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)
665