xref: /qemu/hw/misc/macio/macio.c (revision 73bcb24d932912f8e75e1d88da0fc0ac6d4bce78)
13cbee15bSj_mayer /*
23cbee15bSj_mayer  * PowerMac MacIO device emulation
33cbee15bSj_mayer  *
43cbee15bSj_mayer  * Copyright (c) 2005-2007 Fabrice Bellard
53cbee15bSj_mayer  * Copyright (c) 2007 Jocelyn Mayer
63cbee15bSj_mayer  *
73cbee15bSj_mayer  * Permission is hereby granted, free of charge, to any person obtaining a copy
83cbee15bSj_mayer  * of this software and associated documentation files (the "Software"), to deal
93cbee15bSj_mayer  * in the Software without restriction, including without limitation the rights
103cbee15bSj_mayer  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
113cbee15bSj_mayer  * copies of the Software, and to permit persons to whom the Software is
123cbee15bSj_mayer  * furnished to do so, subject to the following conditions:
133cbee15bSj_mayer  *
143cbee15bSj_mayer  * The above copyright notice and this permission notice shall be included in
153cbee15bSj_mayer  * all copies or substantial portions of the Software.
163cbee15bSj_mayer  *
173cbee15bSj_mayer  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
183cbee15bSj_mayer  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
193cbee15bSj_mayer  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
203cbee15bSj_mayer  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
213cbee15bSj_mayer  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
223cbee15bSj_mayer  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
233cbee15bSj_mayer  * THE SOFTWARE.
243cbee15bSj_mayer  */
250d75590dSPeter Maydell #include "qemu/osdep.h"
26da34e65cSMarkus Armbruster #include "qapi/error.h"
2783c9f4caSPaolo Bonzini #include "hw/hw.h"
2883c9f4caSPaolo Bonzini #include "hw/ppc/mac.h"
2983c9f4caSPaolo Bonzini #include "hw/pci/pci.h"
300d09e41aSPaolo Bonzini #include "hw/ppc/mac_dbdma.h"
310d09e41aSPaolo Bonzini #include "hw/char/escc.h"
323cbee15bSj_mayer 
33fcf1bbabSAndreas Färber #define TYPE_MACIO "macio"
34fcf1bbabSAndreas Färber #define MACIO(obj) OBJECT_CHECK(MacIOState, (obj), TYPE_MACIO)
35fcf1bbabSAndreas Färber 
36d8c51b05SAnthony Liguori typedef struct MacIOState
37d8c51b05SAnthony Liguori {
38fcf1bbabSAndreas Färber     /*< private >*/
39d8c51b05SAnthony Liguori     PCIDevice parent;
40fcf1bbabSAndreas Färber     /*< public >*/
41fcf1bbabSAndreas Färber 
4223c5e4caSAvi Kivity     MemoryRegion bar;
4345fa67fbSAndreas Färber     CUDAState cuda;
4407a7484eSAndreas Färber     void *dbdma;
4523c5e4caSAvi Kivity     MemoryRegion *pic_mem;
4623c5e4caSAvi Kivity     MemoryRegion *escc_mem;
47b981289cSAlexander Graf     uint64_t frequency;
48d8c51b05SAnthony Liguori } MacIOState;
493cbee15bSj_mayer 
5095ed3b7cSAndreas Färber #define OLDWORLD_MACIO(obj) \
5195ed3b7cSAndreas Färber     OBJECT_CHECK(OldWorldMacIOState, (obj), TYPE_OLDWORLD_MACIO)
5295ed3b7cSAndreas Färber 
5395ed3b7cSAndreas Färber typedef struct OldWorldMacIOState {
5495ed3b7cSAndreas Färber     /*< private >*/
5595ed3b7cSAndreas Färber     MacIOState parent_obj;
5695ed3b7cSAndreas Färber     /*< public >*/
5795ed3b7cSAndreas Färber 
5814eefd0eSAlexander Graf     qemu_irq irqs[5];
5907a7484eSAndreas Färber 
6095ed3b7cSAndreas Färber     MacIONVRAMState nvram;
6114eefd0eSAlexander Graf     MACIOIDEState ide[2];
6295ed3b7cSAndreas Färber } OldWorldMacIOState;
6395ed3b7cSAndreas Färber 
6407a7484eSAndreas Färber #define NEWWORLD_MACIO(obj) \
6507a7484eSAndreas Färber     OBJECT_CHECK(NewWorldMacIOState, (obj), TYPE_NEWWORLD_MACIO)
6607a7484eSAndreas Färber 
6707a7484eSAndreas Färber typedef struct NewWorldMacIOState {
6807a7484eSAndreas Färber     /*< private >*/
6907a7484eSAndreas Färber     MacIOState parent_obj;
7007a7484eSAndreas Färber     /*< public >*/
7145fa67fbSAndreas Färber     qemu_irq irqs[5];
7207a7484eSAndreas Färber     MACIOIDEState ide[2];
7307a7484eSAndreas Färber } NewWorldMacIOState;
7407a7484eSAndreas Färber 
750d54a502SAlexander Graf /*
760d54a502SAlexander Graf  * The mac-io has two interfaces to the ESCC. One is called "escc-legacy",
770d54a502SAlexander Graf  * while the other one is the normal, current ESCC interface.
780d54a502SAlexander Graf  *
790d54a502SAlexander Graf  * The magic below creates memory aliases to spawn the escc-legacy device
800d54a502SAlexander Graf  * purely by rerouting the respective registers to our escc region. This
810d54a502SAlexander Graf  * works because the only difference between the two memory regions is the
820d54a502SAlexander Graf  * register layout, not their semantics.
830d54a502SAlexander Graf  *
840d54a502SAlexander Graf  * Reference: ftp://ftp.software.ibm.com/rs6000/technology/spec/chrp/inwork/CHRP_IORef_1.0.pdf
850d54a502SAlexander Graf  */
860d54a502SAlexander Graf static void macio_escc_legacy_setup(MacIOState *macio_state)
870d54a502SAlexander Graf {
880d54a502SAlexander Graf     MemoryRegion *escc_legacy = g_new(MemoryRegion, 1);
890d54a502SAlexander Graf     MemoryRegion *bar = &macio_state->bar;
900d54a502SAlexander Graf     int i;
910d54a502SAlexander Graf     static const int maps[] = {
920d54a502SAlexander Graf         0x00, 0x00,
930d54a502SAlexander Graf         0x02, 0x20,
940d54a502SAlexander Graf         0x04, 0x10,
950d54a502SAlexander Graf         0x06, 0x30,
960d54a502SAlexander Graf         0x08, 0x40,
970d54a502SAlexander Graf         0x0A, 0x50,
980d54a502SAlexander Graf         0x60, 0x60,
990d54a502SAlexander Graf         0x70, 0x70,
1000d54a502SAlexander Graf         0x80, 0x70,
1010d54a502SAlexander Graf         0x90, 0x80,
1020d54a502SAlexander Graf         0xA0, 0x90,
1030d54a502SAlexander Graf         0xB0, 0xA0,
1040d54a502SAlexander Graf         0xC0, 0xB0,
1050d54a502SAlexander Graf         0xD0, 0xC0,
1060d54a502SAlexander Graf         0xE0, 0xD0,
1070d54a502SAlexander Graf         0xF0, 0xE0,
1080d54a502SAlexander Graf     };
1090d54a502SAlexander Graf 
11081e0ab48SPaolo Bonzini     memory_region_init(escc_legacy, OBJECT(macio_state), "escc-legacy", 256);
1110d54a502SAlexander Graf     for (i = 0; i < ARRAY_SIZE(maps); i += 2) {
1120d54a502SAlexander Graf         MemoryRegion *port = g_new(MemoryRegion, 1);
11381e0ab48SPaolo Bonzini         memory_region_init_alias(port, OBJECT(macio_state), "escc-legacy-port",
1142c9b15caSPaolo Bonzini                                  macio_state->escc_mem, maps[i+1], 0x2);
1150d54a502SAlexander Graf         memory_region_add_subregion(escc_legacy, maps[i], port);
1160d54a502SAlexander Graf     }
1170d54a502SAlexander Graf 
1180d54a502SAlexander Graf     memory_region_add_subregion(bar, 0x12000, escc_legacy);
1190d54a502SAlexander Graf }
1200d54a502SAlexander Graf 
121d8c51b05SAnthony Liguori static void macio_bar_setup(MacIOState *macio_state)
1223cbee15bSj_mayer {
12323c5e4caSAvi Kivity     MemoryRegion *bar = &macio_state->bar;
1243cbee15bSj_mayer 
12523c5e4caSAvi Kivity     if (macio_state->escc_mem) {
12623c5e4caSAvi Kivity         memory_region_add_subregion(bar, 0x13000, macio_state->escc_mem);
1270d54a502SAlexander Graf         macio_escc_legacy_setup(macio_state);
1287fa9ae1aSblueswir1     }
1293cbee15bSj_mayer }
1303cbee15bSj_mayer 
13162e9cd77SMarkus Armbruster static void macio_common_realize(PCIDevice *d, Error **errp)
132d8c51b05SAnthony Liguori {
1337b925079SAndreas Färber     MacIOState *s = MACIO(d);
13445fa67fbSAndreas Färber     SysBusDevice *sysbus_dev;
13562e9cd77SMarkus Armbruster     Error *err = NULL;
136c7104402SPaolo Bonzini     MemoryRegion *dbdma_mem;
137c7104402SPaolo Bonzini 
138c7104402SPaolo Bonzini     s->dbdma = DBDMA_init(&dbdma_mem);
139c7104402SPaolo Bonzini     memory_region_add_subregion(&s->bar, 0x08000, dbdma_mem);
1407b925079SAndreas Färber 
14162e9cd77SMarkus Armbruster     object_property_set_bool(OBJECT(&s->cuda), true, "realized", &err);
14262e9cd77SMarkus Armbruster     if (err) {
14362e9cd77SMarkus Armbruster         error_propagate(errp, err);
14462e9cd77SMarkus Armbruster         return;
14545fa67fbSAndreas Färber     }
14645fa67fbSAndreas Färber     sysbus_dev = SYS_BUS_DEVICE(&s->cuda);
14745fa67fbSAndreas Färber     memory_region_add_subregion(&s->bar, 0x16000,
14845fa67fbSAndreas Färber                                 sysbus_mmio_get_region(sysbus_dev, 0));
14945fa67fbSAndreas Färber 
1507b925079SAndreas Färber     macio_bar_setup(s);
1517b925079SAndreas Färber     pci_register_bar(d, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->bar);
152d8c51b05SAnthony Liguori }
153d8c51b05SAnthony Liguori 
15462e9cd77SMarkus Armbruster static void macio_realize_ide(MacIOState *s, MACIOIDEState *ide,
15562e9cd77SMarkus Armbruster                               qemu_irq irq0, qemu_irq irq1, int dmaid,
15662e9cd77SMarkus Armbruster                               Error **errp)
15714eefd0eSAlexander Graf {
15814eefd0eSAlexander Graf     SysBusDevice *sysbus_dev;
15914eefd0eSAlexander Graf 
16014eefd0eSAlexander Graf     sysbus_dev = SYS_BUS_DEVICE(ide);
16114eefd0eSAlexander Graf     sysbus_connect_irq(sysbus_dev, 0, irq0);
16214eefd0eSAlexander Graf     sysbus_connect_irq(sysbus_dev, 1, irq1);
16314eefd0eSAlexander Graf     macio_ide_register_dma(ide, s->dbdma, dmaid);
16462e9cd77SMarkus Armbruster     object_property_set_bool(OBJECT(ide), true, "realized", errp);
16514eefd0eSAlexander Graf }
16614eefd0eSAlexander Graf 
16762e9cd77SMarkus Armbruster static void macio_oldworld_realize(PCIDevice *d, Error **errp)
168d037834aSAndreas Färber {
169d037834aSAndreas Färber     MacIOState *s = MACIO(d);
17095ed3b7cSAndreas Färber     OldWorldMacIOState *os = OLDWORLD_MACIO(d);
17162e9cd77SMarkus Armbruster     Error *err = NULL;
17295ed3b7cSAndreas Färber     SysBusDevice *sysbus_dev;
17314eefd0eSAlexander Graf     int i;
17414eefd0eSAlexander Graf     int cur_irq = 0;
17562e9cd77SMarkus Armbruster 
17662e9cd77SMarkus Armbruster     macio_common_realize(d, &err);
17762e9cd77SMarkus Armbruster     if (err) {
17862e9cd77SMarkus Armbruster         error_propagate(errp, err);
17962e9cd77SMarkus Armbruster         return;
180d037834aSAndreas Färber     }
181d037834aSAndreas Färber 
18245fa67fbSAndreas Färber     sysbus_dev = SYS_BUS_DEVICE(&s->cuda);
18314eefd0eSAlexander Graf     sysbus_connect_irq(sysbus_dev, 0, os->irqs[cur_irq++]);
18445fa67fbSAndreas Färber 
18562e9cd77SMarkus Armbruster     object_property_set_bool(OBJECT(&os->nvram), true, "realized", &err);
18662e9cd77SMarkus Armbruster     if (err) {
18762e9cd77SMarkus Armbruster         error_propagate(errp, err);
18862e9cd77SMarkus Armbruster         return;
18995ed3b7cSAndreas Färber     }
19095ed3b7cSAndreas Färber     sysbus_dev = SYS_BUS_DEVICE(&os->nvram);
19195ed3b7cSAndreas Färber     memory_region_add_subregion(&s->bar, 0x60000,
19295ed3b7cSAndreas Färber                                 sysbus_mmio_get_region(sysbus_dev, 0));
19395ed3b7cSAndreas Färber     pmac_format_nvram_partition(&os->nvram, os->nvram.size);
19495ed3b7cSAndreas Färber 
195d037834aSAndreas Färber     if (s->pic_mem) {
196d037834aSAndreas Färber         /* Heathrow PIC */
197d037834aSAndreas Färber         memory_region_add_subregion(&s->bar, 0x00000, s->pic_mem);
198d037834aSAndreas Färber     }
199d037834aSAndreas Färber 
20014eefd0eSAlexander Graf     /* IDE buses */
20114eefd0eSAlexander Graf     for (i = 0; i < ARRAY_SIZE(os->ide); i++) {
20214eefd0eSAlexander Graf         qemu_irq irq0 = os->irqs[cur_irq++];
20314eefd0eSAlexander Graf         qemu_irq irq1 = os->irqs[cur_irq++];
20414eefd0eSAlexander Graf 
20562e9cd77SMarkus Armbruster         macio_realize_ide(s, &os->ide[i], irq0, irq1, 0x16 + (i * 4), &err);
20662e9cd77SMarkus Armbruster         if (err) {
20762e9cd77SMarkus Armbruster             error_propagate(errp, err);
20862e9cd77SMarkus Armbruster             return;
20907a7484eSAndreas Färber         }
21014eefd0eSAlexander Graf     }
211d037834aSAndreas Färber }
212d037834aSAndreas Färber 
213213f0c4fSAndreas Färber static void macio_init_ide(MacIOState *s, MACIOIDEState *ide, size_t ide_size,
214213f0c4fSAndreas Färber                            int index)
21514eefd0eSAlexander Graf {
21614eefd0eSAlexander Graf     gchar *name;
21714eefd0eSAlexander Graf 
218213f0c4fSAndreas Färber     object_initialize(ide, ide_size, TYPE_MACIO_IDE);
21914eefd0eSAlexander Graf     qdev_set_parent_bus(DEVICE(ide), sysbus_get_default());
22014eefd0eSAlexander Graf     memory_region_add_subregion(&s->bar, 0x1f000 + ((index + 1) * 0x1000),
22114eefd0eSAlexander Graf                                 &ide->mem);
22214eefd0eSAlexander Graf     name = g_strdup_printf("ide[%i]", index);
22314eefd0eSAlexander Graf     object_property_add_child(OBJECT(s), name, OBJECT(ide), NULL);
22414eefd0eSAlexander Graf     g_free(name);
22514eefd0eSAlexander Graf }
22614eefd0eSAlexander Graf 
22795ed3b7cSAndreas Färber static void macio_oldworld_init(Object *obj)
22895ed3b7cSAndreas Färber {
22907a7484eSAndreas Färber     MacIOState *s = MACIO(obj);
23095ed3b7cSAndreas Färber     OldWorldMacIOState *os = OLDWORLD_MACIO(obj);
23195ed3b7cSAndreas Färber     DeviceState *dev;
23214eefd0eSAlexander Graf     int i;
23395ed3b7cSAndreas Färber 
23407a7484eSAndreas Färber     qdev_init_gpio_out(DEVICE(obj), os->irqs, ARRAY_SIZE(os->irqs));
23507a7484eSAndreas Färber 
236213f0c4fSAndreas Färber     object_initialize(&os->nvram, sizeof(os->nvram), TYPE_MACIO_NVRAM);
23795ed3b7cSAndreas Färber     dev = DEVICE(&os->nvram);
23895ed3b7cSAndreas Färber     qdev_prop_set_uint32(dev, "size", 0x2000);
23995ed3b7cSAndreas Färber     qdev_prop_set_uint32(dev, "it_shift", 4);
24007a7484eSAndreas Färber 
24114eefd0eSAlexander Graf     for (i = 0; i < 2; i++) {
242213f0c4fSAndreas Färber         macio_init_ide(s, &os->ide[i], sizeof(os->ide[i]), i);
24314eefd0eSAlexander Graf     }
24495ed3b7cSAndreas Färber }
24595ed3b7cSAndreas Färber 
246a0f9fdfdSAlexander Graf static void timer_write(void *opaque, hwaddr addr, uint64_t value,
247a0f9fdfdSAlexander Graf                        unsigned size)
248a0f9fdfdSAlexander Graf {
249a0f9fdfdSAlexander Graf }
250a0f9fdfdSAlexander Graf 
251a0f9fdfdSAlexander Graf static uint64_t timer_read(void *opaque, hwaddr addr, unsigned size)
252a0f9fdfdSAlexander Graf {
253a0f9fdfdSAlexander Graf     uint32_t value = 0;
254d696760bSAlexander Graf     uint64_t systime = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
255d696760bSAlexander Graf     uint64_t kltime;
256d696760bSAlexander Graf 
257*73bcb24dSRutuja Shah     kltime = muldiv64(systime, 4194300, NANOSECONDS_PER_SECOND * 4);
258d696760bSAlexander Graf     kltime = muldiv64(kltime, 18432000, 1048575);
259a0f9fdfdSAlexander Graf 
260a0f9fdfdSAlexander Graf     switch (addr) {
261a0f9fdfdSAlexander Graf     case 0x38:
262d696760bSAlexander Graf         value = kltime;
263a0f9fdfdSAlexander Graf         break;
264a0f9fdfdSAlexander Graf     case 0x3c:
265d696760bSAlexander Graf         value = kltime >> 32;
266a0f9fdfdSAlexander Graf         break;
267a0f9fdfdSAlexander Graf     }
268a0f9fdfdSAlexander Graf 
269a0f9fdfdSAlexander Graf     return value;
270a0f9fdfdSAlexander Graf }
271a0f9fdfdSAlexander Graf 
272a0f9fdfdSAlexander Graf static const MemoryRegionOps timer_ops = {
273a0f9fdfdSAlexander Graf     .read = timer_read,
274a0f9fdfdSAlexander Graf     .write = timer_write,
2759397a7c8SAlexander Graf     .endianness = DEVICE_LITTLE_ENDIAN,
276a0f9fdfdSAlexander Graf };
277a0f9fdfdSAlexander Graf 
27862e9cd77SMarkus Armbruster static void macio_newworld_realize(PCIDevice *d, Error **errp)
279d037834aSAndreas Färber {
280d037834aSAndreas Färber     MacIOState *s = MACIO(d);
28107a7484eSAndreas Färber     NewWorldMacIOState *ns = NEWWORLD_MACIO(d);
28262e9cd77SMarkus Armbruster     Error *err = NULL;
28307a7484eSAndreas Färber     SysBusDevice *sysbus_dev;
2846c5819c4SGonglei     MemoryRegion *timer_memory = NULL;
28514eefd0eSAlexander Graf     int i;
28614eefd0eSAlexander Graf     int cur_irq = 0;
28762e9cd77SMarkus Armbruster 
28862e9cd77SMarkus Armbruster     macio_common_realize(d, &err);
28962e9cd77SMarkus Armbruster     if (err) {
29062e9cd77SMarkus Armbruster         error_propagate(errp, err);
29162e9cd77SMarkus Armbruster         return;
292d037834aSAndreas Färber     }
293d037834aSAndreas Färber 
29445fa67fbSAndreas Färber     sysbus_dev = SYS_BUS_DEVICE(&s->cuda);
29514eefd0eSAlexander Graf     sysbus_connect_irq(sysbus_dev, 0, ns->irqs[cur_irq++]);
29645fa67fbSAndreas Färber 
297d037834aSAndreas Färber     if (s->pic_mem) {
298d037834aSAndreas Färber         /* OpenPIC */
299d037834aSAndreas Färber         memory_region_add_subregion(&s->bar, 0x40000, s->pic_mem);
300d037834aSAndreas Färber     }
301d037834aSAndreas Färber 
30214eefd0eSAlexander Graf     /* IDE buses */
30314eefd0eSAlexander Graf     for (i = 0; i < ARRAY_SIZE(ns->ide); i++) {
30414eefd0eSAlexander Graf         qemu_irq irq0 = ns->irqs[cur_irq++];
30514eefd0eSAlexander Graf         qemu_irq irq1 = ns->irqs[cur_irq++];
30614eefd0eSAlexander Graf 
30762e9cd77SMarkus Armbruster         macio_realize_ide(s, &ns->ide[i], irq0, irq1, 0x16 + (i * 4), &err);
30862e9cd77SMarkus Armbruster         if (err) {
30962e9cd77SMarkus Armbruster             error_propagate(errp, err);
31062e9cd77SMarkus Armbruster             return;
31107a7484eSAndreas Färber         }
31207a7484eSAndreas Färber     }
31307a7484eSAndreas Färber 
314a0f9fdfdSAlexander Graf     /* Timer */
3156c5819c4SGonglei     timer_memory = g_new(MemoryRegion, 1);
316a0f9fdfdSAlexander Graf     memory_region_init_io(timer_memory, OBJECT(s), &timer_ops, NULL, "timer",
317a0f9fdfdSAlexander Graf                           0x1000);
318a0f9fdfdSAlexander Graf     memory_region_add_subregion(&s->bar, 0x15000, timer_memory);
319d037834aSAndreas Färber }
320d037834aSAndreas Färber 
32107a7484eSAndreas Färber static void macio_newworld_init(Object *obj)
32207a7484eSAndreas Färber {
32307a7484eSAndreas Färber     MacIOState *s = MACIO(obj);
32407a7484eSAndreas Färber     NewWorldMacIOState *ns = NEWWORLD_MACIO(obj);
32507a7484eSAndreas Färber     int i;
32607a7484eSAndreas Färber 
32707a7484eSAndreas Färber     qdev_init_gpio_out(DEVICE(obj), ns->irqs, ARRAY_SIZE(ns->irqs));
32807a7484eSAndreas Färber 
32907a7484eSAndreas Färber     for (i = 0; i < 2; i++) {
330213f0c4fSAndreas Färber         macio_init_ide(s, &ns->ide[i], sizeof(ns->ide[i]), i);
33107a7484eSAndreas Färber     }
33207a7484eSAndreas Färber }
33307a7484eSAndreas Färber 
334fcf1bbabSAndreas Färber static void macio_instance_init(Object *obj)
335fcf1bbabSAndreas Färber {
336fcf1bbabSAndreas Färber     MacIOState *s = MACIO(obj);
337fcf1bbabSAndreas Färber 
33881e0ab48SPaolo Bonzini     memory_region_init(&s->bar, obj, "macio", 0x80000);
33907a7484eSAndreas Färber 
340213f0c4fSAndreas Färber     object_initialize(&s->cuda, sizeof(s->cuda), TYPE_CUDA);
34145fa67fbSAndreas Färber     qdev_set_parent_bus(DEVICE(&s->cuda), sysbus_get_default());
34245fa67fbSAndreas Färber     object_property_add_child(obj, "cuda", OBJECT(&s->cuda), NULL);
343fcf1bbabSAndreas Färber }
344fcf1bbabSAndreas Färber 
34502635923SMark Cave-Ayland static const VMStateDescription vmstate_macio_oldworld = {
34602635923SMark Cave-Ayland     .name = "macio-oldworld",
34702635923SMark Cave-Ayland     .version_id = 0,
34802635923SMark Cave-Ayland     .minimum_version_id = 0,
34902635923SMark Cave-Ayland     .fields = (VMStateField[]) {
35002635923SMark Cave-Ayland         VMSTATE_PCI_DEVICE(parent_obj.parent, OldWorldMacIOState),
35102635923SMark Cave-Ayland         VMSTATE_END_OF_LIST()
35202635923SMark Cave-Ayland     }
35302635923SMark Cave-Ayland };
35402635923SMark Cave-Ayland 
355d037834aSAndreas Färber static void macio_oldworld_class_init(ObjectClass *oc, void *data)
356d037834aSAndreas Färber {
357d037834aSAndreas Färber     PCIDeviceClass *pdc = PCI_DEVICE_CLASS(oc);
35802635923SMark Cave-Ayland     DeviceClass *dc = DEVICE_CLASS(oc);
359d037834aSAndreas Färber 
36062e9cd77SMarkus Armbruster     pdc->realize = macio_oldworld_realize;
361d037834aSAndreas Färber     pdc->device_id = PCI_DEVICE_ID_APPLE_343S1201;
36202635923SMark Cave-Ayland     dc->vmsd = &vmstate_macio_oldworld;
363d037834aSAndreas Färber }
364d037834aSAndreas Färber 
36502635923SMark Cave-Ayland static const VMStateDescription vmstate_macio_newworld = {
36602635923SMark Cave-Ayland     .name = "macio-newworld",
36702635923SMark Cave-Ayland     .version_id = 0,
36802635923SMark Cave-Ayland     .minimum_version_id = 0,
36902635923SMark Cave-Ayland     .fields = (VMStateField[]) {
37002635923SMark Cave-Ayland         VMSTATE_PCI_DEVICE(parent_obj.parent, NewWorldMacIOState),
37102635923SMark Cave-Ayland         VMSTATE_END_OF_LIST()
37202635923SMark Cave-Ayland     }
37302635923SMark Cave-Ayland };
37402635923SMark Cave-Ayland 
375d037834aSAndreas Färber static void macio_newworld_class_init(ObjectClass *oc, void *data)
376d037834aSAndreas Färber {
377d037834aSAndreas Färber     PCIDeviceClass *pdc = PCI_DEVICE_CLASS(oc);
37802635923SMark Cave-Ayland     DeviceClass *dc = DEVICE_CLASS(oc);
379d037834aSAndreas Färber 
38062e9cd77SMarkus Armbruster     pdc->realize = macio_newworld_realize;
381d037834aSAndreas Färber     pdc->device_id = PCI_DEVICE_ID_APPLE_UNI_N_KEYL;
38202635923SMark Cave-Ayland     dc->vmsd = &vmstate_macio_newworld;
383d037834aSAndreas Färber }
384d037834aSAndreas Färber 
385b981289cSAlexander Graf static Property macio_properties[] = {
386b981289cSAlexander Graf     DEFINE_PROP_UINT64("frequency", MacIOState, frequency, 0),
387b981289cSAlexander Graf     DEFINE_PROP_END_OF_LIST()
388b981289cSAlexander Graf };
389b981289cSAlexander Graf 
39040021f08SAnthony Liguori static void macio_class_init(ObjectClass *klass, void *data)
39140021f08SAnthony Liguori {
39240021f08SAnthony Liguori     PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
393b981289cSAlexander Graf     DeviceClass *dc = DEVICE_CLASS(klass);
39440021f08SAnthony Liguori 
39540021f08SAnthony Liguori     k->vendor_id = PCI_VENDOR_ID_APPLE;
39640021f08SAnthony Liguori     k->class_id = PCI_CLASS_OTHERS << 8;
397b981289cSAlexander Graf     dc->props = macio_properties;
398f9f2a9f2SLaurent Vivier     set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
39940021f08SAnthony Liguori }
40040021f08SAnthony Liguori 
401d037834aSAndreas Färber static const TypeInfo macio_oldworld_type_info = {
402d037834aSAndreas Färber     .name          = TYPE_OLDWORLD_MACIO,
403d037834aSAndreas Färber     .parent        = TYPE_MACIO,
40495ed3b7cSAndreas Färber     .instance_size = sizeof(OldWorldMacIOState),
40595ed3b7cSAndreas Färber     .instance_init = macio_oldworld_init,
406d037834aSAndreas Färber     .class_init    = macio_oldworld_class_init,
407d037834aSAndreas Färber };
408d037834aSAndreas Färber 
409d037834aSAndreas Färber static const TypeInfo macio_newworld_type_info = {
410d037834aSAndreas Färber     .name          = TYPE_NEWWORLD_MACIO,
411d037834aSAndreas Färber     .parent        = TYPE_MACIO,
41207a7484eSAndreas Färber     .instance_size = sizeof(NewWorldMacIOState),
41307a7484eSAndreas Färber     .instance_init = macio_newworld_init,
414d037834aSAndreas Färber     .class_init    = macio_newworld_class_init,
415d037834aSAndreas Färber };
416d037834aSAndreas Färber 
417fcf1bbabSAndreas Färber static const TypeInfo macio_type_info = {
418fcf1bbabSAndreas Färber     .name          = TYPE_MACIO,
41939bffca2SAnthony Liguori     .parent        = TYPE_PCI_DEVICE,
42039bffca2SAnthony Liguori     .instance_size = sizeof(MacIOState),
421fcf1bbabSAndreas Färber     .instance_init = macio_instance_init,
422d037834aSAndreas Färber     .abstract      = true,
42340021f08SAnthony Liguori     .class_init    = macio_class_init,
424d8c51b05SAnthony Liguori };
425d8c51b05SAnthony Liguori 
42683f7d43aSAndreas Färber static void macio_register_types(void)
427d8c51b05SAnthony Liguori {
428fcf1bbabSAndreas Färber     type_register_static(&macio_type_info);
429d037834aSAndreas Färber     type_register_static(&macio_oldworld_type_info);
430d037834aSAndreas Färber     type_register_static(&macio_newworld_type_info);
431d8c51b05SAnthony Liguori }
432d8c51b05SAnthony Liguori 
43383f7d43aSAndreas Färber type_init(macio_register_types)
434d8c51b05SAnthony Liguori 
435d037834aSAndreas Färber void macio_init(PCIDevice *d,
43607a7484eSAndreas Färber                 MemoryRegion *pic_mem,
43723c5e4caSAvi Kivity                 MemoryRegion *escc_mem)
4383cbee15bSj_mayer {
439d037834aSAndreas Färber     MacIOState *macio_state = MACIO(d);
4403cbee15bSj_mayer 
44123c5e4caSAvi Kivity     macio_state->pic_mem = pic_mem;
44223c5e4caSAvi Kivity     macio_state->escc_mem = escc_mem;
4433cbee15bSj_mayer     /* Note: this code is strongly inspirated from the corresponding code
4443cbee15bSj_mayer        in PearPC */
445b981289cSAlexander Graf     qdev_prop_set_uint64(DEVICE(&macio_state->cuda), "frequency",
446b981289cSAlexander Graf                          macio_state->frequency);
447deb54399Saliguori 
4487b925079SAndreas Färber     qdev_init_nofail(DEVICE(d));
4493cbee15bSj_mayer }
450