xref: /qemu/hw/misc/macio/macio.c (revision 0d75590d919454be322f21d55494b8937651fc86)
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  */
25*0d75590dSPeter Maydell #include "qemu/osdep.h"
2683c9f4caSPaolo Bonzini #include "hw/hw.h"
2783c9f4caSPaolo Bonzini #include "hw/ppc/mac.h"
2883c9f4caSPaolo Bonzini #include "hw/pci/pci.h"
290d09e41aSPaolo Bonzini #include "hw/ppc/mac_dbdma.h"
300d09e41aSPaolo Bonzini #include "hw/char/escc.h"
313cbee15bSj_mayer 
32fcf1bbabSAndreas Färber #define TYPE_MACIO "macio"
33fcf1bbabSAndreas Färber #define MACIO(obj) OBJECT_CHECK(MacIOState, (obj), TYPE_MACIO)
34fcf1bbabSAndreas Färber 
35d8c51b05SAnthony Liguori typedef struct MacIOState
36d8c51b05SAnthony Liguori {
37fcf1bbabSAndreas Färber     /*< private >*/
38d8c51b05SAnthony Liguori     PCIDevice parent;
39fcf1bbabSAndreas Färber     /*< public >*/
40fcf1bbabSAndreas Färber 
4123c5e4caSAvi Kivity     MemoryRegion bar;
4245fa67fbSAndreas Färber     CUDAState cuda;
4307a7484eSAndreas Färber     void *dbdma;
4423c5e4caSAvi Kivity     MemoryRegion *pic_mem;
4523c5e4caSAvi Kivity     MemoryRegion *escc_mem;
46b981289cSAlexander Graf     uint64_t frequency;
47d8c51b05SAnthony Liguori } MacIOState;
483cbee15bSj_mayer 
4995ed3b7cSAndreas Färber #define OLDWORLD_MACIO(obj) \
5095ed3b7cSAndreas Färber     OBJECT_CHECK(OldWorldMacIOState, (obj), TYPE_OLDWORLD_MACIO)
5195ed3b7cSAndreas Färber 
5295ed3b7cSAndreas Färber typedef struct OldWorldMacIOState {
5395ed3b7cSAndreas Färber     /*< private >*/
5495ed3b7cSAndreas Färber     MacIOState parent_obj;
5595ed3b7cSAndreas Färber     /*< public >*/
5695ed3b7cSAndreas Färber 
5714eefd0eSAlexander Graf     qemu_irq irqs[5];
5807a7484eSAndreas Färber 
5995ed3b7cSAndreas Färber     MacIONVRAMState nvram;
6014eefd0eSAlexander Graf     MACIOIDEState ide[2];
6195ed3b7cSAndreas Färber } OldWorldMacIOState;
6295ed3b7cSAndreas Färber 
6307a7484eSAndreas Färber #define NEWWORLD_MACIO(obj) \
6407a7484eSAndreas Färber     OBJECT_CHECK(NewWorldMacIOState, (obj), TYPE_NEWWORLD_MACIO)
6507a7484eSAndreas Färber 
6607a7484eSAndreas Färber typedef struct NewWorldMacIOState {
6707a7484eSAndreas Färber     /*< private >*/
6807a7484eSAndreas Färber     MacIOState parent_obj;
6907a7484eSAndreas Färber     /*< public >*/
7045fa67fbSAndreas Färber     qemu_irq irqs[5];
7107a7484eSAndreas Färber     MACIOIDEState ide[2];
7207a7484eSAndreas Färber } NewWorldMacIOState;
7307a7484eSAndreas Färber 
740d54a502SAlexander Graf /*
750d54a502SAlexander Graf  * The mac-io has two interfaces to the ESCC. One is called "escc-legacy",
760d54a502SAlexander Graf  * while the other one is the normal, current ESCC interface.
770d54a502SAlexander Graf  *
780d54a502SAlexander Graf  * The magic below creates memory aliases to spawn the escc-legacy device
790d54a502SAlexander Graf  * purely by rerouting the respective registers to our escc region. This
800d54a502SAlexander Graf  * works because the only difference between the two memory regions is the
810d54a502SAlexander Graf  * register layout, not their semantics.
820d54a502SAlexander Graf  *
830d54a502SAlexander Graf  * Reference: ftp://ftp.software.ibm.com/rs6000/technology/spec/chrp/inwork/CHRP_IORef_1.0.pdf
840d54a502SAlexander Graf  */
850d54a502SAlexander Graf static void macio_escc_legacy_setup(MacIOState *macio_state)
860d54a502SAlexander Graf {
870d54a502SAlexander Graf     MemoryRegion *escc_legacy = g_new(MemoryRegion, 1);
880d54a502SAlexander Graf     MemoryRegion *bar = &macio_state->bar;
890d54a502SAlexander Graf     int i;
900d54a502SAlexander Graf     static const int maps[] = {
910d54a502SAlexander Graf         0x00, 0x00,
920d54a502SAlexander Graf         0x02, 0x20,
930d54a502SAlexander Graf         0x04, 0x10,
940d54a502SAlexander Graf         0x06, 0x30,
950d54a502SAlexander Graf         0x08, 0x40,
960d54a502SAlexander Graf         0x0A, 0x50,
970d54a502SAlexander Graf         0x60, 0x60,
980d54a502SAlexander Graf         0x70, 0x70,
990d54a502SAlexander Graf         0x80, 0x70,
1000d54a502SAlexander Graf         0x90, 0x80,
1010d54a502SAlexander Graf         0xA0, 0x90,
1020d54a502SAlexander Graf         0xB0, 0xA0,
1030d54a502SAlexander Graf         0xC0, 0xB0,
1040d54a502SAlexander Graf         0xD0, 0xC0,
1050d54a502SAlexander Graf         0xE0, 0xD0,
1060d54a502SAlexander Graf         0xF0, 0xE0,
1070d54a502SAlexander Graf     };
1080d54a502SAlexander Graf 
10981e0ab48SPaolo Bonzini     memory_region_init(escc_legacy, OBJECT(macio_state), "escc-legacy", 256);
1100d54a502SAlexander Graf     for (i = 0; i < ARRAY_SIZE(maps); i += 2) {
1110d54a502SAlexander Graf         MemoryRegion *port = g_new(MemoryRegion, 1);
11281e0ab48SPaolo Bonzini         memory_region_init_alias(port, OBJECT(macio_state), "escc-legacy-port",
1132c9b15caSPaolo Bonzini                                  macio_state->escc_mem, maps[i+1], 0x2);
1140d54a502SAlexander Graf         memory_region_add_subregion(escc_legacy, maps[i], port);
1150d54a502SAlexander Graf     }
1160d54a502SAlexander Graf 
1170d54a502SAlexander Graf     memory_region_add_subregion(bar, 0x12000, escc_legacy);
1180d54a502SAlexander Graf }
1190d54a502SAlexander Graf 
120d8c51b05SAnthony Liguori static void macio_bar_setup(MacIOState *macio_state)
1213cbee15bSj_mayer {
12223c5e4caSAvi Kivity     MemoryRegion *bar = &macio_state->bar;
1233cbee15bSj_mayer 
12423c5e4caSAvi Kivity     if (macio_state->escc_mem) {
12523c5e4caSAvi Kivity         memory_region_add_subregion(bar, 0x13000, macio_state->escc_mem);
1260d54a502SAlexander Graf         macio_escc_legacy_setup(macio_state);
1277fa9ae1aSblueswir1     }
1283cbee15bSj_mayer }
1293cbee15bSj_mayer 
13062e9cd77SMarkus Armbruster static void macio_common_realize(PCIDevice *d, Error **errp)
131d8c51b05SAnthony Liguori {
1327b925079SAndreas Färber     MacIOState *s = MACIO(d);
13345fa67fbSAndreas Färber     SysBusDevice *sysbus_dev;
13462e9cd77SMarkus Armbruster     Error *err = NULL;
135c7104402SPaolo Bonzini     MemoryRegion *dbdma_mem;
136c7104402SPaolo Bonzini 
137c7104402SPaolo Bonzini     s->dbdma = DBDMA_init(&dbdma_mem);
138c7104402SPaolo Bonzini     memory_region_add_subregion(&s->bar, 0x08000, dbdma_mem);
1397b925079SAndreas Färber 
14062e9cd77SMarkus Armbruster     object_property_set_bool(OBJECT(&s->cuda), true, "realized", &err);
14162e9cd77SMarkus Armbruster     if (err) {
14262e9cd77SMarkus Armbruster         error_propagate(errp, err);
14362e9cd77SMarkus Armbruster         return;
14445fa67fbSAndreas Färber     }
14545fa67fbSAndreas Färber     sysbus_dev = SYS_BUS_DEVICE(&s->cuda);
14645fa67fbSAndreas Färber     memory_region_add_subregion(&s->bar, 0x16000,
14745fa67fbSAndreas Färber                                 sysbus_mmio_get_region(sysbus_dev, 0));
14845fa67fbSAndreas Färber 
1497b925079SAndreas Färber     macio_bar_setup(s);
1507b925079SAndreas Färber     pci_register_bar(d, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->bar);
151d8c51b05SAnthony Liguori }
152d8c51b05SAnthony Liguori 
15362e9cd77SMarkus Armbruster static void macio_realize_ide(MacIOState *s, MACIOIDEState *ide,
15462e9cd77SMarkus Armbruster                               qemu_irq irq0, qemu_irq irq1, int dmaid,
15562e9cd77SMarkus Armbruster                               Error **errp)
15614eefd0eSAlexander Graf {
15714eefd0eSAlexander Graf     SysBusDevice *sysbus_dev;
15814eefd0eSAlexander Graf 
15914eefd0eSAlexander Graf     sysbus_dev = SYS_BUS_DEVICE(ide);
16014eefd0eSAlexander Graf     sysbus_connect_irq(sysbus_dev, 0, irq0);
16114eefd0eSAlexander Graf     sysbus_connect_irq(sysbus_dev, 1, irq1);
16214eefd0eSAlexander Graf     macio_ide_register_dma(ide, s->dbdma, dmaid);
16362e9cd77SMarkus Armbruster     object_property_set_bool(OBJECT(ide), true, "realized", errp);
16414eefd0eSAlexander Graf }
16514eefd0eSAlexander Graf 
16662e9cd77SMarkus Armbruster static void macio_oldworld_realize(PCIDevice *d, Error **errp)
167d037834aSAndreas Färber {
168d037834aSAndreas Färber     MacIOState *s = MACIO(d);
16995ed3b7cSAndreas Färber     OldWorldMacIOState *os = OLDWORLD_MACIO(d);
17062e9cd77SMarkus Armbruster     Error *err = NULL;
17195ed3b7cSAndreas Färber     SysBusDevice *sysbus_dev;
17214eefd0eSAlexander Graf     int i;
17314eefd0eSAlexander Graf     int cur_irq = 0;
17462e9cd77SMarkus Armbruster 
17562e9cd77SMarkus Armbruster     macio_common_realize(d, &err);
17662e9cd77SMarkus Armbruster     if (err) {
17762e9cd77SMarkus Armbruster         error_propagate(errp, err);
17862e9cd77SMarkus Armbruster         return;
179d037834aSAndreas Färber     }
180d037834aSAndreas Färber 
18145fa67fbSAndreas Färber     sysbus_dev = SYS_BUS_DEVICE(&s->cuda);
18214eefd0eSAlexander Graf     sysbus_connect_irq(sysbus_dev, 0, os->irqs[cur_irq++]);
18345fa67fbSAndreas Färber 
18462e9cd77SMarkus Armbruster     object_property_set_bool(OBJECT(&os->nvram), true, "realized", &err);
18562e9cd77SMarkus Armbruster     if (err) {
18662e9cd77SMarkus Armbruster         error_propagate(errp, err);
18762e9cd77SMarkus Armbruster         return;
18895ed3b7cSAndreas Färber     }
18995ed3b7cSAndreas Färber     sysbus_dev = SYS_BUS_DEVICE(&os->nvram);
19095ed3b7cSAndreas Färber     memory_region_add_subregion(&s->bar, 0x60000,
19195ed3b7cSAndreas Färber                                 sysbus_mmio_get_region(sysbus_dev, 0));
19295ed3b7cSAndreas Färber     pmac_format_nvram_partition(&os->nvram, os->nvram.size);
19395ed3b7cSAndreas Färber 
194d037834aSAndreas Färber     if (s->pic_mem) {
195d037834aSAndreas Färber         /* Heathrow PIC */
196d037834aSAndreas Färber         memory_region_add_subregion(&s->bar, 0x00000, s->pic_mem);
197d037834aSAndreas Färber     }
198d037834aSAndreas Färber 
19914eefd0eSAlexander Graf     /* IDE buses */
20014eefd0eSAlexander Graf     for (i = 0; i < ARRAY_SIZE(os->ide); i++) {
20114eefd0eSAlexander Graf         qemu_irq irq0 = os->irqs[cur_irq++];
20214eefd0eSAlexander Graf         qemu_irq irq1 = os->irqs[cur_irq++];
20314eefd0eSAlexander Graf 
20462e9cd77SMarkus Armbruster         macio_realize_ide(s, &os->ide[i], irq0, irq1, 0x16 + (i * 4), &err);
20562e9cd77SMarkus Armbruster         if (err) {
20662e9cd77SMarkus Armbruster             error_propagate(errp, err);
20762e9cd77SMarkus Armbruster             return;
20807a7484eSAndreas Färber         }
20914eefd0eSAlexander Graf     }
210d037834aSAndreas Färber }
211d037834aSAndreas Färber 
212213f0c4fSAndreas Färber static void macio_init_ide(MacIOState *s, MACIOIDEState *ide, size_t ide_size,
213213f0c4fSAndreas Färber                            int index)
21414eefd0eSAlexander Graf {
21514eefd0eSAlexander Graf     gchar *name;
21614eefd0eSAlexander Graf 
217213f0c4fSAndreas Färber     object_initialize(ide, ide_size, TYPE_MACIO_IDE);
21814eefd0eSAlexander Graf     qdev_set_parent_bus(DEVICE(ide), sysbus_get_default());
21914eefd0eSAlexander Graf     memory_region_add_subregion(&s->bar, 0x1f000 + ((index + 1) * 0x1000),
22014eefd0eSAlexander Graf                                 &ide->mem);
22114eefd0eSAlexander Graf     name = g_strdup_printf("ide[%i]", index);
22214eefd0eSAlexander Graf     object_property_add_child(OBJECT(s), name, OBJECT(ide), NULL);
22314eefd0eSAlexander Graf     g_free(name);
22414eefd0eSAlexander Graf }
22514eefd0eSAlexander Graf 
22695ed3b7cSAndreas Färber static void macio_oldworld_init(Object *obj)
22795ed3b7cSAndreas Färber {
22807a7484eSAndreas Färber     MacIOState *s = MACIO(obj);
22995ed3b7cSAndreas Färber     OldWorldMacIOState *os = OLDWORLD_MACIO(obj);
23095ed3b7cSAndreas Färber     DeviceState *dev;
23114eefd0eSAlexander Graf     int i;
23295ed3b7cSAndreas Färber 
23307a7484eSAndreas Färber     qdev_init_gpio_out(DEVICE(obj), os->irqs, ARRAY_SIZE(os->irqs));
23407a7484eSAndreas Färber 
235213f0c4fSAndreas Färber     object_initialize(&os->nvram, sizeof(os->nvram), TYPE_MACIO_NVRAM);
23695ed3b7cSAndreas Färber     dev = DEVICE(&os->nvram);
23795ed3b7cSAndreas Färber     qdev_prop_set_uint32(dev, "size", 0x2000);
23895ed3b7cSAndreas Färber     qdev_prop_set_uint32(dev, "it_shift", 4);
23907a7484eSAndreas Färber 
24014eefd0eSAlexander Graf     for (i = 0; i < 2; i++) {
241213f0c4fSAndreas Färber         macio_init_ide(s, &os->ide[i], sizeof(os->ide[i]), i);
24214eefd0eSAlexander Graf     }
24395ed3b7cSAndreas Färber }
24495ed3b7cSAndreas Färber 
245a0f9fdfdSAlexander Graf static void timer_write(void *opaque, hwaddr addr, uint64_t value,
246a0f9fdfdSAlexander Graf                        unsigned size)
247a0f9fdfdSAlexander Graf {
248a0f9fdfdSAlexander Graf }
249a0f9fdfdSAlexander Graf 
250a0f9fdfdSAlexander Graf static uint64_t timer_read(void *opaque, hwaddr addr, unsigned size)
251a0f9fdfdSAlexander Graf {
252a0f9fdfdSAlexander Graf     uint32_t value = 0;
253d696760bSAlexander Graf     uint64_t systime = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
254d696760bSAlexander Graf     uint64_t kltime;
255d696760bSAlexander Graf 
256d696760bSAlexander Graf     kltime = muldiv64(systime, 4194300, get_ticks_per_sec() * 4);
257d696760bSAlexander Graf     kltime = muldiv64(kltime, 18432000, 1048575);
258a0f9fdfdSAlexander Graf 
259a0f9fdfdSAlexander Graf     switch (addr) {
260a0f9fdfdSAlexander Graf     case 0x38:
261d696760bSAlexander Graf         value = kltime;
262a0f9fdfdSAlexander Graf         break;
263a0f9fdfdSAlexander Graf     case 0x3c:
264d696760bSAlexander Graf         value = kltime >> 32;
265a0f9fdfdSAlexander Graf         break;
266a0f9fdfdSAlexander Graf     }
267a0f9fdfdSAlexander Graf 
268a0f9fdfdSAlexander Graf     return value;
269a0f9fdfdSAlexander Graf }
270a0f9fdfdSAlexander Graf 
271a0f9fdfdSAlexander Graf static const MemoryRegionOps timer_ops = {
272a0f9fdfdSAlexander Graf     .read = timer_read,
273a0f9fdfdSAlexander Graf     .write = timer_write,
2749397a7c8SAlexander Graf     .endianness = DEVICE_LITTLE_ENDIAN,
275a0f9fdfdSAlexander Graf };
276a0f9fdfdSAlexander Graf 
27762e9cd77SMarkus Armbruster static void macio_newworld_realize(PCIDevice *d, Error **errp)
278d037834aSAndreas Färber {
279d037834aSAndreas Färber     MacIOState *s = MACIO(d);
28007a7484eSAndreas Färber     NewWorldMacIOState *ns = NEWWORLD_MACIO(d);
28162e9cd77SMarkus Armbruster     Error *err = NULL;
28207a7484eSAndreas Färber     SysBusDevice *sysbus_dev;
2836c5819c4SGonglei     MemoryRegion *timer_memory = NULL;
28414eefd0eSAlexander Graf     int i;
28514eefd0eSAlexander Graf     int cur_irq = 0;
28662e9cd77SMarkus Armbruster 
28762e9cd77SMarkus Armbruster     macio_common_realize(d, &err);
28862e9cd77SMarkus Armbruster     if (err) {
28962e9cd77SMarkus Armbruster         error_propagate(errp, err);
29062e9cd77SMarkus Armbruster         return;
291d037834aSAndreas Färber     }
292d037834aSAndreas Färber 
29345fa67fbSAndreas Färber     sysbus_dev = SYS_BUS_DEVICE(&s->cuda);
29414eefd0eSAlexander Graf     sysbus_connect_irq(sysbus_dev, 0, ns->irqs[cur_irq++]);
29545fa67fbSAndreas Färber 
296d037834aSAndreas Färber     if (s->pic_mem) {
297d037834aSAndreas Färber         /* OpenPIC */
298d037834aSAndreas Färber         memory_region_add_subregion(&s->bar, 0x40000, s->pic_mem);
299d037834aSAndreas Färber     }
300d037834aSAndreas Färber 
30114eefd0eSAlexander Graf     /* IDE buses */
30214eefd0eSAlexander Graf     for (i = 0; i < ARRAY_SIZE(ns->ide); i++) {
30314eefd0eSAlexander Graf         qemu_irq irq0 = ns->irqs[cur_irq++];
30414eefd0eSAlexander Graf         qemu_irq irq1 = ns->irqs[cur_irq++];
30514eefd0eSAlexander Graf 
30662e9cd77SMarkus Armbruster         macio_realize_ide(s, &ns->ide[i], irq0, irq1, 0x16 + (i * 4), &err);
30762e9cd77SMarkus Armbruster         if (err) {
30862e9cd77SMarkus Armbruster             error_propagate(errp, err);
30962e9cd77SMarkus Armbruster             return;
31007a7484eSAndreas Färber         }
31107a7484eSAndreas Färber     }
31207a7484eSAndreas Färber 
313a0f9fdfdSAlexander Graf     /* Timer */
3146c5819c4SGonglei     timer_memory = g_new(MemoryRegion, 1);
315a0f9fdfdSAlexander Graf     memory_region_init_io(timer_memory, OBJECT(s), &timer_ops, NULL, "timer",
316a0f9fdfdSAlexander Graf                           0x1000);
317a0f9fdfdSAlexander Graf     memory_region_add_subregion(&s->bar, 0x15000, timer_memory);
318d037834aSAndreas Färber }
319d037834aSAndreas Färber 
32007a7484eSAndreas Färber static void macio_newworld_init(Object *obj)
32107a7484eSAndreas Färber {
32207a7484eSAndreas Färber     MacIOState *s = MACIO(obj);
32307a7484eSAndreas Färber     NewWorldMacIOState *ns = NEWWORLD_MACIO(obj);
32407a7484eSAndreas Färber     int i;
32507a7484eSAndreas Färber 
32607a7484eSAndreas Färber     qdev_init_gpio_out(DEVICE(obj), ns->irqs, ARRAY_SIZE(ns->irqs));
32707a7484eSAndreas Färber 
32807a7484eSAndreas Färber     for (i = 0; i < 2; i++) {
329213f0c4fSAndreas Färber         macio_init_ide(s, &ns->ide[i], sizeof(ns->ide[i]), i);
33007a7484eSAndreas Färber     }
33107a7484eSAndreas Färber }
33207a7484eSAndreas Färber 
333fcf1bbabSAndreas Färber static void macio_instance_init(Object *obj)
334fcf1bbabSAndreas Färber {
335fcf1bbabSAndreas Färber     MacIOState *s = MACIO(obj);
336fcf1bbabSAndreas Färber 
33781e0ab48SPaolo Bonzini     memory_region_init(&s->bar, obj, "macio", 0x80000);
33807a7484eSAndreas Färber 
339213f0c4fSAndreas Färber     object_initialize(&s->cuda, sizeof(s->cuda), TYPE_CUDA);
34045fa67fbSAndreas Färber     qdev_set_parent_bus(DEVICE(&s->cuda), sysbus_get_default());
34145fa67fbSAndreas Färber     object_property_add_child(obj, "cuda", OBJECT(&s->cuda), NULL);
342fcf1bbabSAndreas Färber }
343fcf1bbabSAndreas Färber 
34402635923SMark Cave-Ayland static const VMStateDescription vmstate_macio_oldworld = {
34502635923SMark Cave-Ayland     .name = "macio-oldworld",
34602635923SMark Cave-Ayland     .version_id = 0,
34702635923SMark Cave-Ayland     .minimum_version_id = 0,
34802635923SMark Cave-Ayland     .fields = (VMStateField[]) {
34902635923SMark Cave-Ayland         VMSTATE_PCI_DEVICE(parent_obj.parent, OldWorldMacIOState),
35002635923SMark Cave-Ayland         VMSTATE_END_OF_LIST()
35102635923SMark Cave-Ayland     }
35202635923SMark Cave-Ayland };
35302635923SMark Cave-Ayland 
354d037834aSAndreas Färber static void macio_oldworld_class_init(ObjectClass *oc, void *data)
355d037834aSAndreas Färber {
356d037834aSAndreas Färber     PCIDeviceClass *pdc = PCI_DEVICE_CLASS(oc);
35702635923SMark Cave-Ayland     DeviceClass *dc = DEVICE_CLASS(oc);
358d037834aSAndreas Färber 
35962e9cd77SMarkus Armbruster     pdc->realize = macio_oldworld_realize;
360d037834aSAndreas Färber     pdc->device_id = PCI_DEVICE_ID_APPLE_343S1201;
36102635923SMark Cave-Ayland     dc->vmsd = &vmstate_macio_oldworld;
362d037834aSAndreas Färber }
363d037834aSAndreas Färber 
36402635923SMark Cave-Ayland static const VMStateDescription vmstate_macio_newworld = {
36502635923SMark Cave-Ayland     .name = "macio-newworld",
36602635923SMark Cave-Ayland     .version_id = 0,
36702635923SMark Cave-Ayland     .minimum_version_id = 0,
36802635923SMark Cave-Ayland     .fields = (VMStateField[]) {
36902635923SMark Cave-Ayland         VMSTATE_PCI_DEVICE(parent_obj.parent, NewWorldMacIOState),
37002635923SMark Cave-Ayland         VMSTATE_END_OF_LIST()
37102635923SMark Cave-Ayland     }
37202635923SMark Cave-Ayland };
37302635923SMark Cave-Ayland 
374d037834aSAndreas Färber static void macio_newworld_class_init(ObjectClass *oc, void *data)
375d037834aSAndreas Färber {
376d037834aSAndreas Färber     PCIDeviceClass *pdc = PCI_DEVICE_CLASS(oc);
37702635923SMark Cave-Ayland     DeviceClass *dc = DEVICE_CLASS(oc);
378d037834aSAndreas Färber 
37962e9cd77SMarkus Armbruster     pdc->realize = macio_newworld_realize;
380d037834aSAndreas Färber     pdc->device_id = PCI_DEVICE_ID_APPLE_UNI_N_KEYL;
38102635923SMark Cave-Ayland     dc->vmsd = &vmstate_macio_newworld;
382d037834aSAndreas Färber }
383d037834aSAndreas Färber 
384b981289cSAlexander Graf static Property macio_properties[] = {
385b981289cSAlexander Graf     DEFINE_PROP_UINT64("frequency", MacIOState, frequency, 0),
386b981289cSAlexander Graf     DEFINE_PROP_END_OF_LIST()
387b981289cSAlexander Graf };
388b981289cSAlexander Graf 
38940021f08SAnthony Liguori static void macio_class_init(ObjectClass *klass, void *data)
39040021f08SAnthony Liguori {
39140021f08SAnthony Liguori     PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
392b981289cSAlexander Graf     DeviceClass *dc = DEVICE_CLASS(klass);
39340021f08SAnthony Liguori 
39440021f08SAnthony Liguori     k->vendor_id = PCI_VENDOR_ID_APPLE;
39540021f08SAnthony Liguori     k->class_id = PCI_CLASS_OTHERS << 8;
396b981289cSAlexander Graf     dc->props = macio_properties;
397f9f2a9f2SLaurent Vivier     set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
39840021f08SAnthony Liguori }
39940021f08SAnthony Liguori 
400d037834aSAndreas Färber static const TypeInfo macio_oldworld_type_info = {
401d037834aSAndreas Färber     .name          = TYPE_OLDWORLD_MACIO,
402d037834aSAndreas Färber     .parent        = TYPE_MACIO,
40395ed3b7cSAndreas Färber     .instance_size = sizeof(OldWorldMacIOState),
40495ed3b7cSAndreas Färber     .instance_init = macio_oldworld_init,
405d037834aSAndreas Färber     .class_init    = macio_oldworld_class_init,
406d037834aSAndreas Färber };
407d037834aSAndreas Färber 
408d037834aSAndreas Färber static const TypeInfo macio_newworld_type_info = {
409d037834aSAndreas Färber     .name          = TYPE_NEWWORLD_MACIO,
410d037834aSAndreas Färber     .parent        = TYPE_MACIO,
41107a7484eSAndreas Färber     .instance_size = sizeof(NewWorldMacIOState),
41207a7484eSAndreas Färber     .instance_init = macio_newworld_init,
413d037834aSAndreas Färber     .class_init    = macio_newworld_class_init,
414d037834aSAndreas Färber };
415d037834aSAndreas Färber 
416fcf1bbabSAndreas Färber static const TypeInfo macio_type_info = {
417fcf1bbabSAndreas Färber     .name          = TYPE_MACIO,
41839bffca2SAnthony Liguori     .parent        = TYPE_PCI_DEVICE,
41939bffca2SAnthony Liguori     .instance_size = sizeof(MacIOState),
420fcf1bbabSAndreas Färber     .instance_init = macio_instance_init,
421d037834aSAndreas Färber     .abstract      = true,
42240021f08SAnthony Liguori     .class_init    = macio_class_init,
423d8c51b05SAnthony Liguori };
424d8c51b05SAnthony Liguori 
42583f7d43aSAndreas Färber static void macio_register_types(void)
426d8c51b05SAnthony Liguori {
427fcf1bbabSAndreas Färber     type_register_static(&macio_type_info);
428d037834aSAndreas Färber     type_register_static(&macio_oldworld_type_info);
429d037834aSAndreas Färber     type_register_static(&macio_newworld_type_info);
430d8c51b05SAnthony Liguori }
431d8c51b05SAnthony Liguori 
43283f7d43aSAndreas Färber type_init(macio_register_types)
433d8c51b05SAnthony Liguori 
434d037834aSAndreas Färber void macio_init(PCIDevice *d,
43507a7484eSAndreas Färber                 MemoryRegion *pic_mem,
43623c5e4caSAvi Kivity                 MemoryRegion *escc_mem)
4373cbee15bSj_mayer {
438d037834aSAndreas Färber     MacIOState *macio_state = MACIO(d);
4393cbee15bSj_mayer 
44023c5e4caSAvi Kivity     macio_state->pic_mem = pic_mem;
44123c5e4caSAvi Kivity     macio_state->escc_mem = escc_mem;
4423cbee15bSj_mayer     /* Note: this code is strongly inspirated from the corresponding code
4433cbee15bSj_mayer        in PearPC */
444b981289cSAlexander Graf     qdev_prop_set_uint64(DEVICE(&macio_state->cuda), "frequency",
445b981289cSAlexander Graf                          macio_state->frequency);
446deb54399Saliguori 
4477b925079SAndreas Färber     qdev_init_nofail(DEVICE(d));
4483cbee15bSj_mayer }
449