xref: /qemu/hw/misc/macio/macio.c (revision c7104402353bf32ac1d3a276e3619a20e910506b)
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  */
2583c9f4caSPaolo Bonzini #include "hw/hw.h"
2683c9f4caSPaolo Bonzini #include "hw/ppc/mac.h"
2783c9f4caSPaolo Bonzini #include "hw/pci/pci.h"
280d09e41aSPaolo Bonzini #include "hw/ppc/mac_dbdma.h"
290d09e41aSPaolo Bonzini #include "hw/char/escc.h"
303cbee15bSj_mayer 
31fcf1bbabSAndreas Färber #define TYPE_MACIO "macio"
32fcf1bbabSAndreas Färber #define MACIO(obj) OBJECT_CHECK(MacIOState, (obj), TYPE_MACIO)
33fcf1bbabSAndreas Färber 
34d8c51b05SAnthony Liguori typedef struct MacIOState
35d8c51b05SAnthony Liguori {
36fcf1bbabSAndreas Färber     /*< private >*/
37d8c51b05SAnthony Liguori     PCIDevice parent;
38fcf1bbabSAndreas Färber     /*< public >*/
39fcf1bbabSAndreas Färber 
4023c5e4caSAvi Kivity     MemoryRegion bar;
4145fa67fbSAndreas Färber     CUDAState cuda;
4207a7484eSAndreas Färber     void *dbdma;
4323c5e4caSAvi Kivity     MemoryRegion *pic_mem;
4423c5e4caSAvi Kivity     MemoryRegion *escc_mem;
45b981289cSAlexander Graf     uint64_t frequency;
46d8c51b05SAnthony Liguori } MacIOState;
473cbee15bSj_mayer 
4895ed3b7cSAndreas Färber #define OLDWORLD_MACIO(obj) \
4995ed3b7cSAndreas Färber     OBJECT_CHECK(OldWorldMacIOState, (obj), TYPE_OLDWORLD_MACIO)
5095ed3b7cSAndreas Färber 
5195ed3b7cSAndreas Färber typedef struct OldWorldMacIOState {
5295ed3b7cSAndreas Färber     /*< private >*/
5395ed3b7cSAndreas Färber     MacIOState parent_obj;
5495ed3b7cSAndreas Färber     /*< public >*/
5595ed3b7cSAndreas Färber 
5614eefd0eSAlexander Graf     qemu_irq irqs[5];
5707a7484eSAndreas Färber 
5895ed3b7cSAndreas Färber     MacIONVRAMState nvram;
5914eefd0eSAlexander Graf     MACIOIDEState ide[2];
6095ed3b7cSAndreas Färber } OldWorldMacIOState;
6195ed3b7cSAndreas Färber 
6207a7484eSAndreas Färber #define NEWWORLD_MACIO(obj) \
6307a7484eSAndreas Färber     OBJECT_CHECK(NewWorldMacIOState, (obj), TYPE_NEWWORLD_MACIO)
6407a7484eSAndreas Färber 
6507a7484eSAndreas Färber typedef struct NewWorldMacIOState {
6607a7484eSAndreas Färber     /*< private >*/
6707a7484eSAndreas Färber     MacIOState parent_obj;
6807a7484eSAndreas Färber     /*< public >*/
6945fa67fbSAndreas Färber     qemu_irq irqs[5];
7007a7484eSAndreas Färber     MACIOIDEState ide[2];
7107a7484eSAndreas Färber } NewWorldMacIOState;
7207a7484eSAndreas Färber 
730d54a502SAlexander Graf /*
740d54a502SAlexander Graf  * The mac-io has two interfaces to the ESCC. One is called "escc-legacy",
750d54a502SAlexander Graf  * while the other one is the normal, current ESCC interface.
760d54a502SAlexander Graf  *
770d54a502SAlexander Graf  * The magic below creates memory aliases to spawn the escc-legacy device
780d54a502SAlexander Graf  * purely by rerouting the respective registers to our escc region. This
790d54a502SAlexander Graf  * works because the only difference between the two memory regions is the
800d54a502SAlexander Graf  * register layout, not their semantics.
810d54a502SAlexander Graf  *
820d54a502SAlexander Graf  * Reference: ftp://ftp.software.ibm.com/rs6000/technology/spec/chrp/inwork/CHRP_IORef_1.0.pdf
830d54a502SAlexander Graf  */
840d54a502SAlexander Graf static void macio_escc_legacy_setup(MacIOState *macio_state)
850d54a502SAlexander Graf {
860d54a502SAlexander Graf     MemoryRegion *escc_legacy = g_new(MemoryRegion, 1);
870d54a502SAlexander Graf     MemoryRegion *bar = &macio_state->bar;
880d54a502SAlexander Graf     int i;
890d54a502SAlexander Graf     static const int maps[] = {
900d54a502SAlexander Graf         0x00, 0x00,
910d54a502SAlexander Graf         0x02, 0x20,
920d54a502SAlexander Graf         0x04, 0x10,
930d54a502SAlexander Graf         0x06, 0x30,
940d54a502SAlexander Graf         0x08, 0x40,
950d54a502SAlexander Graf         0x0A, 0x50,
960d54a502SAlexander Graf         0x60, 0x60,
970d54a502SAlexander Graf         0x70, 0x70,
980d54a502SAlexander Graf         0x80, 0x70,
990d54a502SAlexander Graf         0x90, 0x80,
1000d54a502SAlexander Graf         0xA0, 0x90,
1010d54a502SAlexander Graf         0xB0, 0xA0,
1020d54a502SAlexander Graf         0xC0, 0xB0,
1030d54a502SAlexander Graf         0xD0, 0xC0,
1040d54a502SAlexander Graf         0xE0, 0xD0,
1050d54a502SAlexander Graf         0xF0, 0xE0,
1060d54a502SAlexander Graf     };
1070d54a502SAlexander Graf 
10881e0ab48SPaolo Bonzini     memory_region_init(escc_legacy, OBJECT(macio_state), "escc-legacy", 256);
1090d54a502SAlexander Graf     for (i = 0; i < ARRAY_SIZE(maps); i += 2) {
1100d54a502SAlexander Graf         MemoryRegion *port = g_new(MemoryRegion, 1);
11181e0ab48SPaolo Bonzini         memory_region_init_alias(port, OBJECT(macio_state), "escc-legacy-port",
1122c9b15caSPaolo Bonzini                                  macio_state->escc_mem, maps[i+1], 0x2);
1130d54a502SAlexander Graf         memory_region_add_subregion(escc_legacy, maps[i], port);
1140d54a502SAlexander Graf     }
1150d54a502SAlexander Graf 
1160d54a502SAlexander Graf     memory_region_add_subregion(bar, 0x12000, escc_legacy);
1170d54a502SAlexander Graf }
1180d54a502SAlexander Graf 
119d8c51b05SAnthony Liguori static void macio_bar_setup(MacIOState *macio_state)
1203cbee15bSj_mayer {
12123c5e4caSAvi Kivity     MemoryRegion *bar = &macio_state->bar;
1223cbee15bSj_mayer 
12323c5e4caSAvi Kivity     if (macio_state->escc_mem) {
12423c5e4caSAvi Kivity         memory_region_add_subregion(bar, 0x13000, macio_state->escc_mem);
1250d54a502SAlexander Graf         macio_escc_legacy_setup(macio_state);
1267fa9ae1aSblueswir1     }
1273cbee15bSj_mayer }
1283cbee15bSj_mayer 
12962e9cd77SMarkus Armbruster static void macio_common_realize(PCIDevice *d, Error **errp)
130d8c51b05SAnthony Liguori {
1317b925079SAndreas Färber     MacIOState *s = MACIO(d);
13245fa67fbSAndreas Färber     SysBusDevice *sysbus_dev;
13362e9cd77SMarkus Armbruster     Error *err = NULL;
134*c7104402SPaolo Bonzini     MemoryRegion *dbdma_mem;
135*c7104402SPaolo Bonzini 
136*c7104402SPaolo Bonzini     s->dbdma = DBDMA_init(&dbdma_mem);
137*c7104402SPaolo Bonzini     memory_region_add_subregion(&s->bar, 0x08000, dbdma_mem);
1387b925079SAndreas Färber 
13962e9cd77SMarkus Armbruster     object_property_set_bool(OBJECT(&s->cuda), true, "realized", &err);
14062e9cd77SMarkus Armbruster     if (err) {
14162e9cd77SMarkus Armbruster         error_propagate(errp, err);
14262e9cd77SMarkus Armbruster         return;
14345fa67fbSAndreas Färber     }
14445fa67fbSAndreas Färber     sysbus_dev = SYS_BUS_DEVICE(&s->cuda);
14545fa67fbSAndreas Färber     memory_region_add_subregion(&s->bar, 0x16000,
14645fa67fbSAndreas Färber                                 sysbus_mmio_get_region(sysbus_dev, 0));
14745fa67fbSAndreas Färber 
1487b925079SAndreas Färber     macio_bar_setup(s);
1497b925079SAndreas Färber     pci_register_bar(d, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->bar);
150d8c51b05SAnthony Liguori }
151d8c51b05SAnthony Liguori 
15262e9cd77SMarkus Armbruster static void macio_realize_ide(MacIOState *s, MACIOIDEState *ide,
15362e9cd77SMarkus Armbruster                               qemu_irq irq0, qemu_irq irq1, int dmaid,
15462e9cd77SMarkus Armbruster                               Error **errp)
15514eefd0eSAlexander Graf {
15614eefd0eSAlexander Graf     SysBusDevice *sysbus_dev;
15714eefd0eSAlexander Graf 
15814eefd0eSAlexander Graf     sysbus_dev = SYS_BUS_DEVICE(ide);
15914eefd0eSAlexander Graf     sysbus_connect_irq(sysbus_dev, 0, irq0);
16014eefd0eSAlexander Graf     sysbus_connect_irq(sysbus_dev, 1, irq1);
16114eefd0eSAlexander Graf     macio_ide_register_dma(ide, s->dbdma, dmaid);
16262e9cd77SMarkus Armbruster     object_property_set_bool(OBJECT(ide), true, "realized", errp);
16314eefd0eSAlexander Graf }
16414eefd0eSAlexander Graf 
16562e9cd77SMarkus Armbruster static void macio_oldworld_realize(PCIDevice *d, Error **errp)
166d037834aSAndreas Färber {
167d037834aSAndreas Färber     MacIOState *s = MACIO(d);
16895ed3b7cSAndreas Färber     OldWorldMacIOState *os = OLDWORLD_MACIO(d);
16962e9cd77SMarkus Armbruster     Error *err = NULL;
17095ed3b7cSAndreas Färber     SysBusDevice *sysbus_dev;
17114eefd0eSAlexander Graf     int i;
17214eefd0eSAlexander Graf     int cur_irq = 0;
17362e9cd77SMarkus Armbruster 
17462e9cd77SMarkus Armbruster     macio_common_realize(d, &err);
17562e9cd77SMarkus Armbruster     if (err) {
17662e9cd77SMarkus Armbruster         error_propagate(errp, err);
17762e9cd77SMarkus Armbruster         return;
178d037834aSAndreas Färber     }
179d037834aSAndreas Färber 
18045fa67fbSAndreas Färber     sysbus_dev = SYS_BUS_DEVICE(&s->cuda);
18114eefd0eSAlexander Graf     sysbus_connect_irq(sysbus_dev, 0, os->irqs[cur_irq++]);
18245fa67fbSAndreas Färber 
18362e9cd77SMarkus Armbruster     object_property_set_bool(OBJECT(&os->nvram), true, "realized", &err);
18462e9cd77SMarkus Armbruster     if (err) {
18562e9cd77SMarkus Armbruster         error_propagate(errp, err);
18662e9cd77SMarkus Armbruster         return;
18795ed3b7cSAndreas Färber     }
18895ed3b7cSAndreas Färber     sysbus_dev = SYS_BUS_DEVICE(&os->nvram);
18995ed3b7cSAndreas Färber     memory_region_add_subregion(&s->bar, 0x60000,
19095ed3b7cSAndreas Färber                                 sysbus_mmio_get_region(sysbus_dev, 0));
19195ed3b7cSAndreas Färber     pmac_format_nvram_partition(&os->nvram, os->nvram.size);
19295ed3b7cSAndreas Färber 
193d037834aSAndreas Färber     if (s->pic_mem) {
194d037834aSAndreas Färber         /* Heathrow PIC */
195d037834aSAndreas Färber         memory_region_add_subregion(&s->bar, 0x00000, s->pic_mem);
196d037834aSAndreas Färber     }
197d037834aSAndreas Färber 
19814eefd0eSAlexander Graf     /* IDE buses */
19914eefd0eSAlexander Graf     for (i = 0; i < ARRAY_SIZE(os->ide); i++) {
20014eefd0eSAlexander Graf         qemu_irq irq0 = os->irqs[cur_irq++];
20114eefd0eSAlexander Graf         qemu_irq irq1 = os->irqs[cur_irq++];
20214eefd0eSAlexander Graf 
20362e9cd77SMarkus Armbruster         macio_realize_ide(s, &os->ide[i], irq0, irq1, 0x16 + (i * 4), &err);
20462e9cd77SMarkus Armbruster         if (err) {
20562e9cd77SMarkus Armbruster             error_propagate(errp, err);
20662e9cd77SMarkus Armbruster             return;
20707a7484eSAndreas Färber         }
20814eefd0eSAlexander Graf     }
209d037834aSAndreas Färber }
210d037834aSAndreas Färber 
211213f0c4fSAndreas Färber static void macio_init_ide(MacIOState *s, MACIOIDEState *ide, size_t ide_size,
212213f0c4fSAndreas Färber                            int index)
21314eefd0eSAlexander Graf {
21414eefd0eSAlexander Graf     gchar *name;
21514eefd0eSAlexander Graf 
216213f0c4fSAndreas Färber     object_initialize(ide, ide_size, TYPE_MACIO_IDE);
21714eefd0eSAlexander Graf     qdev_set_parent_bus(DEVICE(ide), sysbus_get_default());
21814eefd0eSAlexander Graf     memory_region_add_subregion(&s->bar, 0x1f000 + ((index + 1) * 0x1000),
21914eefd0eSAlexander Graf                                 &ide->mem);
22014eefd0eSAlexander Graf     name = g_strdup_printf("ide[%i]", index);
22114eefd0eSAlexander Graf     object_property_add_child(OBJECT(s), name, OBJECT(ide), NULL);
22214eefd0eSAlexander Graf     g_free(name);
22314eefd0eSAlexander Graf }
22414eefd0eSAlexander Graf 
22595ed3b7cSAndreas Färber static void macio_oldworld_init(Object *obj)
22695ed3b7cSAndreas Färber {
22707a7484eSAndreas Färber     MacIOState *s = MACIO(obj);
22895ed3b7cSAndreas Färber     OldWorldMacIOState *os = OLDWORLD_MACIO(obj);
22995ed3b7cSAndreas Färber     DeviceState *dev;
23014eefd0eSAlexander Graf     int i;
23195ed3b7cSAndreas Färber 
23207a7484eSAndreas Färber     qdev_init_gpio_out(DEVICE(obj), os->irqs, ARRAY_SIZE(os->irqs));
23307a7484eSAndreas Färber 
234213f0c4fSAndreas Färber     object_initialize(&os->nvram, sizeof(os->nvram), TYPE_MACIO_NVRAM);
23595ed3b7cSAndreas Färber     dev = DEVICE(&os->nvram);
23695ed3b7cSAndreas Färber     qdev_prop_set_uint32(dev, "size", 0x2000);
23795ed3b7cSAndreas Färber     qdev_prop_set_uint32(dev, "it_shift", 4);
23807a7484eSAndreas Färber 
23914eefd0eSAlexander Graf     for (i = 0; i < 2; i++) {
240213f0c4fSAndreas Färber         macio_init_ide(s, &os->ide[i], sizeof(os->ide[i]), i);
24114eefd0eSAlexander Graf     }
24295ed3b7cSAndreas Färber }
24395ed3b7cSAndreas Färber 
244a0f9fdfdSAlexander Graf static void timer_write(void *opaque, hwaddr addr, uint64_t value,
245a0f9fdfdSAlexander Graf                        unsigned size)
246a0f9fdfdSAlexander Graf {
247a0f9fdfdSAlexander Graf }
248a0f9fdfdSAlexander Graf 
249a0f9fdfdSAlexander Graf static uint64_t timer_read(void *opaque, hwaddr addr, unsigned size)
250a0f9fdfdSAlexander Graf {
251a0f9fdfdSAlexander Graf     uint32_t value = 0;
252d696760bSAlexander Graf     uint64_t systime = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
253d696760bSAlexander Graf     uint64_t kltime;
254d696760bSAlexander Graf 
255d696760bSAlexander Graf     kltime = muldiv64(systime, 4194300, get_ticks_per_sec() * 4);
256d696760bSAlexander Graf     kltime = muldiv64(kltime, 18432000, 1048575);
257a0f9fdfdSAlexander Graf 
258a0f9fdfdSAlexander Graf     switch (addr) {
259a0f9fdfdSAlexander Graf     case 0x38:
260d696760bSAlexander Graf         value = kltime;
261a0f9fdfdSAlexander Graf         break;
262a0f9fdfdSAlexander Graf     case 0x3c:
263d696760bSAlexander Graf         value = kltime >> 32;
264a0f9fdfdSAlexander Graf         break;
265a0f9fdfdSAlexander Graf     }
266a0f9fdfdSAlexander Graf 
267a0f9fdfdSAlexander Graf     return value;
268a0f9fdfdSAlexander Graf }
269a0f9fdfdSAlexander Graf 
270a0f9fdfdSAlexander Graf static const MemoryRegionOps timer_ops = {
271a0f9fdfdSAlexander Graf     .read = timer_read,
272a0f9fdfdSAlexander Graf     .write = timer_write,
2739397a7c8SAlexander Graf     .endianness = DEVICE_LITTLE_ENDIAN,
274a0f9fdfdSAlexander Graf };
275a0f9fdfdSAlexander Graf 
27662e9cd77SMarkus Armbruster static void macio_newworld_realize(PCIDevice *d, Error **errp)
277d037834aSAndreas Färber {
278d037834aSAndreas Färber     MacIOState *s = MACIO(d);
27907a7484eSAndreas Färber     NewWorldMacIOState *ns = NEWWORLD_MACIO(d);
28062e9cd77SMarkus Armbruster     Error *err = NULL;
28107a7484eSAndreas Färber     SysBusDevice *sysbus_dev;
2826c5819c4SGonglei     MemoryRegion *timer_memory = NULL;
28314eefd0eSAlexander Graf     int i;
28414eefd0eSAlexander Graf     int cur_irq = 0;
28562e9cd77SMarkus Armbruster 
28662e9cd77SMarkus Armbruster     macio_common_realize(d, &err);
28762e9cd77SMarkus Armbruster     if (err) {
28862e9cd77SMarkus Armbruster         error_propagate(errp, err);
28962e9cd77SMarkus Armbruster         return;
290d037834aSAndreas Färber     }
291d037834aSAndreas Färber 
29245fa67fbSAndreas Färber     sysbus_dev = SYS_BUS_DEVICE(&s->cuda);
29314eefd0eSAlexander Graf     sysbus_connect_irq(sysbus_dev, 0, ns->irqs[cur_irq++]);
29445fa67fbSAndreas Färber 
295d037834aSAndreas Färber     if (s->pic_mem) {
296d037834aSAndreas Färber         /* OpenPIC */
297d037834aSAndreas Färber         memory_region_add_subregion(&s->bar, 0x40000, s->pic_mem);
298d037834aSAndreas Färber     }
299d037834aSAndreas Färber 
30014eefd0eSAlexander Graf     /* IDE buses */
30114eefd0eSAlexander Graf     for (i = 0; i < ARRAY_SIZE(ns->ide); i++) {
30214eefd0eSAlexander Graf         qemu_irq irq0 = ns->irqs[cur_irq++];
30314eefd0eSAlexander Graf         qemu_irq irq1 = ns->irqs[cur_irq++];
30414eefd0eSAlexander Graf 
30562e9cd77SMarkus Armbruster         macio_realize_ide(s, &ns->ide[i], irq0, irq1, 0x16 + (i * 4), &err);
30662e9cd77SMarkus Armbruster         if (err) {
30762e9cd77SMarkus Armbruster             error_propagate(errp, err);
30862e9cd77SMarkus Armbruster             return;
30907a7484eSAndreas Färber         }
31007a7484eSAndreas Färber     }
31107a7484eSAndreas Färber 
312a0f9fdfdSAlexander Graf     /* Timer */
3136c5819c4SGonglei     timer_memory = g_new(MemoryRegion, 1);
314a0f9fdfdSAlexander Graf     memory_region_init_io(timer_memory, OBJECT(s), &timer_ops, NULL, "timer",
315a0f9fdfdSAlexander Graf                           0x1000);
316a0f9fdfdSAlexander Graf     memory_region_add_subregion(&s->bar, 0x15000, timer_memory);
317d037834aSAndreas Färber }
318d037834aSAndreas Färber 
31907a7484eSAndreas Färber static void macio_newworld_init(Object *obj)
32007a7484eSAndreas Färber {
32107a7484eSAndreas Färber     MacIOState *s = MACIO(obj);
32207a7484eSAndreas Färber     NewWorldMacIOState *ns = NEWWORLD_MACIO(obj);
32307a7484eSAndreas Färber     int i;
32407a7484eSAndreas Färber 
32507a7484eSAndreas Färber     qdev_init_gpio_out(DEVICE(obj), ns->irqs, ARRAY_SIZE(ns->irqs));
32607a7484eSAndreas Färber 
32707a7484eSAndreas Färber     for (i = 0; i < 2; i++) {
328213f0c4fSAndreas Färber         macio_init_ide(s, &ns->ide[i], sizeof(ns->ide[i]), i);
32907a7484eSAndreas Färber     }
33007a7484eSAndreas Färber }
33107a7484eSAndreas Färber 
332fcf1bbabSAndreas Färber static void macio_instance_init(Object *obj)
333fcf1bbabSAndreas Färber {
334fcf1bbabSAndreas Färber     MacIOState *s = MACIO(obj);
335fcf1bbabSAndreas Färber 
33681e0ab48SPaolo Bonzini     memory_region_init(&s->bar, obj, "macio", 0x80000);
33707a7484eSAndreas Färber 
338213f0c4fSAndreas Färber     object_initialize(&s->cuda, sizeof(s->cuda), TYPE_CUDA);
33945fa67fbSAndreas Färber     qdev_set_parent_bus(DEVICE(&s->cuda), sysbus_get_default());
34045fa67fbSAndreas Färber     object_property_add_child(obj, "cuda", OBJECT(&s->cuda), NULL);
341fcf1bbabSAndreas Färber }
342fcf1bbabSAndreas Färber 
34302635923SMark Cave-Ayland static const VMStateDescription vmstate_macio_oldworld = {
34402635923SMark Cave-Ayland     .name = "macio-oldworld",
34502635923SMark Cave-Ayland     .version_id = 0,
34602635923SMark Cave-Ayland     .minimum_version_id = 0,
34702635923SMark Cave-Ayland     .fields = (VMStateField[]) {
34802635923SMark Cave-Ayland         VMSTATE_PCI_DEVICE(parent_obj.parent, OldWorldMacIOState),
34902635923SMark Cave-Ayland         VMSTATE_END_OF_LIST()
35002635923SMark Cave-Ayland     }
35102635923SMark Cave-Ayland };
35202635923SMark Cave-Ayland 
353d037834aSAndreas Färber static void macio_oldworld_class_init(ObjectClass *oc, void *data)
354d037834aSAndreas Färber {
355d037834aSAndreas Färber     PCIDeviceClass *pdc = PCI_DEVICE_CLASS(oc);
35602635923SMark Cave-Ayland     DeviceClass *dc = DEVICE_CLASS(oc);
357d037834aSAndreas Färber 
35862e9cd77SMarkus Armbruster     pdc->realize = macio_oldworld_realize;
359d037834aSAndreas Färber     pdc->device_id = PCI_DEVICE_ID_APPLE_343S1201;
36002635923SMark Cave-Ayland     dc->vmsd = &vmstate_macio_oldworld;
361d037834aSAndreas Färber }
362d037834aSAndreas Färber 
36302635923SMark Cave-Ayland static const VMStateDescription vmstate_macio_newworld = {
36402635923SMark Cave-Ayland     .name = "macio-newworld",
36502635923SMark Cave-Ayland     .version_id = 0,
36602635923SMark Cave-Ayland     .minimum_version_id = 0,
36702635923SMark Cave-Ayland     .fields = (VMStateField[]) {
36802635923SMark Cave-Ayland         VMSTATE_PCI_DEVICE(parent_obj.parent, NewWorldMacIOState),
36902635923SMark Cave-Ayland         VMSTATE_END_OF_LIST()
37002635923SMark Cave-Ayland     }
37102635923SMark Cave-Ayland };
37202635923SMark Cave-Ayland 
373d037834aSAndreas Färber static void macio_newworld_class_init(ObjectClass *oc, void *data)
374d037834aSAndreas Färber {
375d037834aSAndreas Färber     PCIDeviceClass *pdc = PCI_DEVICE_CLASS(oc);
37602635923SMark Cave-Ayland     DeviceClass *dc = DEVICE_CLASS(oc);
377d037834aSAndreas Färber 
37862e9cd77SMarkus Armbruster     pdc->realize = macio_newworld_realize;
379d037834aSAndreas Färber     pdc->device_id = PCI_DEVICE_ID_APPLE_UNI_N_KEYL;
38002635923SMark Cave-Ayland     dc->vmsd = &vmstate_macio_newworld;
381d037834aSAndreas Färber }
382d037834aSAndreas Färber 
383b981289cSAlexander Graf static Property macio_properties[] = {
384b981289cSAlexander Graf     DEFINE_PROP_UINT64("frequency", MacIOState, frequency, 0),
385b981289cSAlexander Graf     DEFINE_PROP_END_OF_LIST()
386b981289cSAlexander Graf };
387b981289cSAlexander Graf 
38840021f08SAnthony Liguori static void macio_class_init(ObjectClass *klass, void *data)
38940021f08SAnthony Liguori {
39040021f08SAnthony Liguori     PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
391b981289cSAlexander Graf     DeviceClass *dc = DEVICE_CLASS(klass);
39240021f08SAnthony Liguori 
39340021f08SAnthony Liguori     k->vendor_id = PCI_VENDOR_ID_APPLE;
39440021f08SAnthony Liguori     k->class_id = PCI_CLASS_OTHERS << 8;
395b981289cSAlexander Graf     dc->props = macio_properties;
39640021f08SAnthony Liguori }
39740021f08SAnthony Liguori 
398d037834aSAndreas Färber static const TypeInfo macio_oldworld_type_info = {
399d037834aSAndreas Färber     .name          = TYPE_OLDWORLD_MACIO,
400d037834aSAndreas Färber     .parent        = TYPE_MACIO,
40195ed3b7cSAndreas Färber     .instance_size = sizeof(OldWorldMacIOState),
40295ed3b7cSAndreas Färber     .instance_init = macio_oldworld_init,
403d037834aSAndreas Färber     .class_init    = macio_oldworld_class_init,
404d037834aSAndreas Färber };
405d037834aSAndreas Färber 
406d037834aSAndreas Färber static const TypeInfo macio_newworld_type_info = {
407d037834aSAndreas Färber     .name          = TYPE_NEWWORLD_MACIO,
408d037834aSAndreas Färber     .parent        = TYPE_MACIO,
40907a7484eSAndreas Färber     .instance_size = sizeof(NewWorldMacIOState),
41007a7484eSAndreas Färber     .instance_init = macio_newworld_init,
411d037834aSAndreas Färber     .class_init    = macio_newworld_class_init,
412d037834aSAndreas Färber };
413d037834aSAndreas Färber 
414fcf1bbabSAndreas Färber static const TypeInfo macio_type_info = {
415fcf1bbabSAndreas Färber     .name          = TYPE_MACIO,
41639bffca2SAnthony Liguori     .parent        = TYPE_PCI_DEVICE,
41739bffca2SAnthony Liguori     .instance_size = sizeof(MacIOState),
418fcf1bbabSAndreas Färber     .instance_init = macio_instance_init,
419d037834aSAndreas Färber     .abstract      = true,
42040021f08SAnthony Liguori     .class_init    = macio_class_init,
421d8c51b05SAnthony Liguori };
422d8c51b05SAnthony Liguori 
42383f7d43aSAndreas Färber static void macio_register_types(void)
424d8c51b05SAnthony Liguori {
425fcf1bbabSAndreas Färber     type_register_static(&macio_type_info);
426d037834aSAndreas Färber     type_register_static(&macio_oldworld_type_info);
427d037834aSAndreas Färber     type_register_static(&macio_newworld_type_info);
428d8c51b05SAnthony Liguori }
429d8c51b05SAnthony Liguori 
43083f7d43aSAndreas Färber type_init(macio_register_types)
431d8c51b05SAnthony Liguori 
432d037834aSAndreas Färber void macio_init(PCIDevice *d,
43307a7484eSAndreas Färber                 MemoryRegion *pic_mem,
43423c5e4caSAvi Kivity                 MemoryRegion *escc_mem)
4353cbee15bSj_mayer {
436d037834aSAndreas Färber     MacIOState *macio_state = MACIO(d);
4373cbee15bSj_mayer 
43823c5e4caSAvi Kivity     macio_state->pic_mem = pic_mem;
43923c5e4caSAvi Kivity     macio_state->escc_mem = escc_mem;
4403cbee15bSj_mayer     /* Note: this code is strongly inspirated from the corresponding code
4413cbee15bSj_mayer        in PearPC */
442b981289cSAlexander Graf     qdev_prop_set_uint64(DEVICE(&macio_state->cuda), "frequency",
443b981289cSAlexander Graf                          macio_state->frequency);
444deb54399Saliguori 
4457b925079SAndreas Färber     qdev_init_nofail(DEVICE(d));
4463cbee15bSj_mayer }
447