xref: /qemu/hw/misc/macio/macio.c (revision 026359238b50f56a90961d9aa62ef303371eca8c)
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 
1082c9b15caSPaolo Bonzini     memory_region_init(escc_legacy, NULL, "escc-legacy", 256);
1090d54a502SAlexander Graf     for (i = 0; i < ARRAY_SIZE(maps); i += 2) {
1100d54a502SAlexander Graf         MemoryRegion *port = g_new(MemoryRegion, 1);
1112c9b15caSPaolo Bonzini         memory_region_init_alias(port, NULL, "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 
129d037834aSAndreas Färber static int macio_common_initfn(PCIDevice *d)
130d8c51b05SAnthony Liguori {
1317b925079SAndreas Färber     MacIOState *s = MACIO(d);
13245fa67fbSAndreas Färber     SysBusDevice *sysbus_dev;
13345fa67fbSAndreas Färber     int ret;
1347b925079SAndreas Färber 
135d8c51b05SAnthony Liguori     d->config[0x3d] = 0x01; // interrupt on pin 1
1367b925079SAndreas Färber 
13745fa67fbSAndreas Färber     ret = qdev_init(DEVICE(&s->cuda));
13845fa67fbSAndreas Färber     if (ret < 0) {
13945fa67fbSAndreas Färber         return ret;
14045fa67fbSAndreas Färber     }
14145fa67fbSAndreas Färber     sysbus_dev = SYS_BUS_DEVICE(&s->cuda);
14245fa67fbSAndreas Färber     memory_region_add_subregion(&s->bar, 0x16000,
14345fa67fbSAndreas Färber                                 sysbus_mmio_get_region(sysbus_dev, 0));
14445fa67fbSAndreas Färber 
1457b925079SAndreas Färber     macio_bar_setup(s);
1467b925079SAndreas Färber     pci_register_bar(d, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->bar);
1477b925079SAndreas Färber 
148d8c51b05SAnthony Liguori     return 0;
149d8c51b05SAnthony Liguori }
150d8c51b05SAnthony Liguori 
15114eefd0eSAlexander Graf static int macio_initfn_ide(MacIOState *s, MACIOIDEState *ide, qemu_irq irq0,
15214eefd0eSAlexander Graf                             qemu_irq irq1, int dmaid)
15314eefd0eSAlexander Graf {
15414eefd0eSAlexander Graf     SysBusDevice *sysbus_dev;
15514eefd0eSAlexander Graf 
15614eefd0eSAlexander Graf     sysbus_dev = SYS_BUS_DEVICE(ide);
15714eefd0eSAlexander Graf     sysbus_connect_irq(sysbus_dev, 0, irq0);
15814eefd0eSAlexander Graf     sysbus_connect_irq(sysbus_dev, 1, irq1);
15914eefd0eSAlexander Graf     macio_ide_register_dma(ide, s->dbdma, dmaid);
16014eefd0eSAlexander Graf     return qdev_init(DEVICE(ide));
16114eefd0eSAlexander Graf }
16214eefd0eSAlexander Graf 
163d037834aSAndreas Färber static int macio_oldworld_initfn(PCIDevice *d)
164d037834aSAndreas Färber {
165d037834aSAndreas Färber     MacIOState *s = MACIO(d);
16695ed3b7cSAndreas Färber     OldWorldMacIOState *os = OLDWORLD_MACIO(d);
16795ed3b7cSAndreas Färber     SysBusDevice *sysbus_dev;
16814eefd0eSAlexander Graf     int i;
16914eefd0eSAlexander Graf     int cur_irq = 0;
170d037834aSAndreas Färber     int ret = macio_common_initfn(d);
171d037834aSAndreas Färber     if (ret < 0) {
172d037834aSAndreas Färber         return ret;
173d037834aSAndreas Färber     }
174d037834aSAndreas Färber 
17545fa67fbSAndreas Färber     sysbus_dev = SYS_BUS_DEVICE(&s->cuda);
17614eefd0eSAlexander Graf     sysbus_connect_irq(sysbus_dev, 0, os->irqs[cur_irq++]);
17745fa67fbSAndreas Färber 
17895ed3b7cSAndreas Färber     ret = qdev_init(DEVICE(&os->nvram));
17995ed3b7cSAndreas Färber     if (ret < 0) {
18095ed3b7cSAndreas Färber         return ret;
18195ed3b7cSAndreas Färber     }
18295ed3b7cSAndreas Färber     sysbus_dev = SYS_BUS_DEVICE(&os->nvram);
18395ed3b7cSAndreas Färber     memory_region_add_subregion(&s->bar, 0x60000,
18495ed3b7cSAndreas Färber                                 sysbus_mmio_get_region(sysbus_dev, 0));
18595ed3b7cSAndreas Färber     pmac_format_nvram_partition(&os->nvram, os->nvram.size);
18695ed3b7cSAndreas Färber 
187d037834aSAndreas Färber     if (s->pic_mem) {
188d037834aSAndreas Färber         /* Heathrow PIC */
189d037834aSAndreas Färber         memory_region_add_subregion(&s->bar, 0x00000, s->pic_mem);
190d037834aSAndreas Färber     }
191d037834aSAndreas Färber 
19214eefd0eSAlexander Graf     /* IDE buses */
19314eefd0eSAlexander Graf     for (i = 0; i < ARRAY_SIZE(os->ide); i++) {
19414eefd0eSAlexander Graf         qemu_irq irq0 = os->irqs[cur_irq++];
19514eefd0eSAlexander Graf         qemu_irq irq1 = os->irqs[cur_irq++];
19614eefd0eSAlexander Graf 
19714eefd0eSAlexander Graf         ret = macio_initfn_ide(s, &os->ide[i], irq0, irq1, 0x16 + (i * 4));
19807a7484eSAndreas Färber         if (ret < 0) {
19907a7484eSAndreas Färber             return ret;
20007a7484eSAndreas Färber         }
20114eefd0eSAlexander Graf     }
20207a7484eSAndreas Färber 
203d037834aSAndreas Färber     return 0;
204d037834aSAndreas Färber }
205d037834aSAndreas Färber 
206213f0c4fSAndreas Färber static void macio_init_ide(MacIOState *s, MACIOIDEState *ide, size_t ide_size,
207213f0c4fSAndreas Färber                            int index)
20814eefd0eSAlexander Graf {
20914eefd0eSAlexander Graf     gchar *name;
21014eefd0eSAlexander Graf 
211213f0c4fSAndreas Färber     object_initialize(ide, ide_size, TYPE_MACIO_IDE);
21214eefd0eSAlexander Graf     qdev_set_parent_bus(DEVICE(ide), sysbus_get_default());
21314eefd0eSAlexander Graf     memory_region_add_subregion(&s->bar, 0x1f000 + ((index + 1) * 0x1000),
21414eefd0eSAlexander Graf                                 &ide->mem);
21514eefd0eSAlexander Graf     name = g_strdup_printf("ide[%i]", index);
21614eefd0eSAlexander Graf     object_property_add_child(OBJECT(s), name, OBJECT(ide), NULL);
21714eefd0eSAlexander Graf     g_free(name);
21814eefd0eSAlexander Graf }
21914eefd0eSAlexander Graf 
22095ed3b7cSAndreas Färber static void macio_oldworld_init(Object *obj)
22195ed3b7cSAndreas Färber {
22207a7484eSAndreas Färber     MacIOState *s = MACIO(obj);
22395ed3b7cSAndreas Färber     OldWorldMacIOState *os = OLDWORLD_MACIO(obj);
22495ed3b7cSAndreas Färber     DeviceState *dev;
22514eefd0eSAlexander Graf     int i;
22695ed3b7cSAndreas Färber 
22707a7484eSAndreas Färber     qdev_init_gpio_out(DEVICE(obj), os->irqs, ARRAY_SIZE(os->irqs));
22807a7484eSAndreas Färber 
229213f0c4fSAndreas Färber     object_initialize(&os->nvram, sizeof(os->nvram), TYPE_MACIO_NVRAM);
23095ed3b7cSAndreas Färber     dev = DEVICE(&os->nvram);
23195ed3b7cSAndreas Färber     qdev_prop_set_uint32(dev, "size", 0x2000);
23295ed3b7cSAndreas Färber     qdev_prop_set_uint32(dev, "it_shift", 4);
23307a7484eSAndreas Färber 
23414eefd0eSAlexander Graf     for (i = 0; i < 2; i++) {
235213f0c4fSAndreas Färber         macio_init_ide(s, &os->ide[i], sizeof(os->ide[i]), i);
23614eefd0eSAlexander Graf     }
23795ed3b7cSAndreas Färber }
23895ed3b7cSAndreas Färber 
239a0f9fdfdSAlexander Graf static void timer_write(void *opaque, hwaddr addr, uint64_t value,
240a0f9fdfdSAlexander Graf                        unsigned size)
241a0f9fdfdSAlexander Graf {
242a0f9fdfdSAlexander Graf }
243a0f9fdfdSAlexander Graf 
244a0f9fdfdSAlexander Graf static uint64_t timer_read(void *opaque, hwaddr addr, unsigned size)
245a0f9fdfdSAlexander Graf {
246a0f9fdfdSAlexander Graf     uint32_t value = 0;
247d696760bSAlexander Graf     uint64_t systime = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
248d696760bSAlexander Graf     uint64_t kltime;
249d696760bSAlexander Graf 
250d696760bSAlexander Graf     kltime = muldiv64(systime, 4194300, get_ticks_per_sec() * 4);
251d696760bSAlexander Graf     kltime = muldiv64(kltime, 18432000, 1048575);
252a0f9fdfdSAlexander Graf 
253a0f9fdfdSAlexander Graf     switch (addr) {
254a0f9fdfdSAlexander Graf     case 0x38:
255d696760bSAlexander Graf         value = kltime;
256a0f9fdfdSAlexander Graf         break;
257a0f9fdfdSAlexander Graf     case 0x3c:
258d696760bSAlexander Graf         value = kltime >> 32;
259a0f9fdfdSAlexander Graf         break;
260a0f9fdfdSAlexander Graf     }
261a0f9fdfdSAlexander Graf 
262a0f9fdfdSAlexander Graf     return value;
263a0f9fdfdSAlexander Graf }
264a0f9fdfdSAlexander Graf 
265a0f9fdfdSAlexander Graf static const MemoryRegionOps timer_ops = {
266a0f9fdfdSAlexander Graf     .read = timer_read,
267a0f9fdfdSAlexander Graf     .write = timer_write,
2689397a7c8SAlexander Graf     .endianness = DEVICE_LITTLE_ENDIAN,
269a0f9fdfdSAlexander Graf };
270a0f9fdfdSAlexander Graf 
271d037834aSAndreas Färber static int macio_newworld_initfn(PCIDevice *d)
272d037834aSAndreas Färber {
273d037834aSAndreas Färber     MacIOState *s = MACIO(d);
27407a7484eSAndreas Färber     NewWorldMacIOState *ns = NEWWORLD_MACIO(d);
27507a7484eSAndreas Färber     SysBusDevice *sysbus_dev;
276a0f9fdfdSAlexander Graf     MemoryRegion *timer_memory = g_new(MemoryRegion, 1);
27714eefd0eSAlexander Graf     int i;
27814eefd0eSAlexander Graf     int cur_irq = 0;
279d037834aSAndreas Färber     int ret = macio_common_initfn(d);
280d037834aSAndreas Färber     if (ret < 0) {
281d037834aSAndreas Färber         return ret;
282d037834aSAndreas Färber     }
283d037834aSAndreas Färber 
28445fa67fbSAndreas Färber     sysbus_dev = SYS_BUS_DEVICE(&s->cuda);
28514eefd0eSAlexander Graf     sysbus_connect_irq(sysbus_dev, 0, ns->irqs[cur_irq++]);
28645fa67fbSAndreas Färber 
287d037834aSAndreas Färber     if (s->pic_mem) {
288d037834aSAndreas Färber         /* OpenPIC */
289d037834aSAndreas Färber         memory_region_add_subregion(&s->bar, 0x40000, s->pic_mem);
290d037834aSAndreas Färber     }
291d037834aSAndreas Färber 
29214eefd0eSAlexander Graf     /* IDE buses */
29314eefd0eSAlexander Graf     for (i = 0; i < ARRAY_SIZE(ns->ide); i++) {
29414eefd0eSAlexander Graf         qemu_irq irq0 = ns->irqs[cur_irq++];
29514eefd0eSAlexander Graf         qemu_irq irq1 = ns->irqs[cur_irq++];
29614eefd0eSAlexander Graf 
29714eefd0eSAlexander Graf         ret = macio_initfn_ide(s, &ns->ide[i], irq0, irq1, 0x16 + (i * 4));
29807a7484eSAndreas Färber         if (ret < 0) {
29907a7484eSAndreas Färber             return ret;
30007a7484eSAndreas Färber         }
30107a7484eSAndreas Färber     }
30207a7484eSAndreas Färber 
303a0f9fdfdSAlexander Graf     /* Timer */
304a0f9fdfdSAlexander Graf     memory_region_init_io(timer_memory, OBJECT(s), &timer_ops, NULL, "timer",
305a0f9fdfdSAlexander Graf                           0x1000);
306a0f9fdfdSAlexander Graf     memory_region_add_subregion(&s->bar, 0x15000, timer_memory);
307a0f9fdfdSAlexander Graf 
308d037834aSAndreas Färber     return 0;
309d037834aSAndreas Färber }
310d037834aSAndreas Färber 
31107a7484eSAndreas Färber static void macio_newworld_init(Object *obj)
31207a7484eSAndreas Färber {
31307a7484eSAndreas Färber     MacIOState *s = MACIO(obj);
31407a7484eSAndreas Färber     NewWorldMacIOState *ns = NEWWORLD_MACIO(obj);
31507a7484eSAndreas Färber     int i;
31607a7484eSAndreas Färber 
31707a7484eSAndreas Färber     qdev_init_gpio_out(DEVICE(obj), ns->irqs, ARRAY_SIZE(ns->irqs));
31807a7484eSAndreas Färber 
31907a7484eSAndreas Färber     for (i = 0; i < 2; i++) {
320213f0c4fSAndreas Färber         macio_init_ide(s, &ns->ide[i], sizeof(ns->ide[i]), i);
32107a7484eSAndreas Färber     }
32207a7484eSAndreas Färber }
32307a7484eSAndreas Färber 
324fcf1bbabSAndreas Färber static void macio_instance_init(Object *obj)
325fcf1bbabSAndreas Färber {
326fcf1bbabSAndreas Färber     MacIOState *s = MACIO(obj);
32707a7484eSAndreas Färber     MemoryRegion *dbdma_mem;
328fcf1bbabSAndreas Färber 
3292c9b15caSPaolo Bonzini     memory_region_init(&s->bar, NULL, "macio", 0x80000);
33007a7484eSAndreas Färber 
331213f0c4fSAndreas Färber     object_initialize(&s->cuda, sizeof(s->cuda), TYPE_CUDA);
33245fa67fbSAndreas Färber     qdev_set_parent_bus(DEVICE(&s->cuda), sysbus_get_default());
33345fa67fbSAndreas Färber     object_property_add_child(obj, "cuda", OBJECT(&s->cuda), NULL);
33445fa67fbSAndreas Färber 
33507a7484eSAndreas Färber     s->dbdma = DBDMA_init(&dbdma_mem);
33607a7484eSAndreas Färber     memory_region_add_subregion(&s->bar, 0x08000, dbdma_mem);
337fcf1bbabSAndreas Färber }
338fcf1bbabSAndreas Färber 
339*02635923SMark Cave-Ayland static const VMStateDescription vmstate_macio_oldworld = {
340*02635923SMark Cave-Ayland     .name = "macio-oldworld",
341*02635923SMark Cave-Ayland     .version_id = 0,
342*02635923SMark Cave-Ayland     .minimum_version_id = 0,
343*02635923SMark Cave-Ayland     .fields = (VMStateField[]) {
344*02635923SMark Cave-Ayland         VMSTATE_PCI_DEVICE(parent_obj.parent, OldWorldMacIOState),
345*02635923SMark Cave-Ayland         VMSTATE_END_OF_LIST()
346*02635923SMark Cave-Ayland     }
347*02635923SMark Cave-Ayland };
348*02635923SMark Cave-Ayland 
349d037834aSAndreas Färber static void macio_oldworld_class_init(ObjectClass *oc, void *data)
350d037834aSAndreas Färber {
351d037834aSAndreas Färber     PCIDeviceClass *pdc = PCI_DEVICE_CLASS(oc);
352*02635923SMark Cave-Ayland     DeviceClass *dc = DEVICE_CLASS(oc);
353d037834aSAndreas Färber 
354d037834aSAndreas Färber     pdc->init = macio_oldworld_initfn;
355d037834aSAndreas Färber     pdc->device_id = PCI_DEVICE_ID_APPLE_343S1201;
356*02635923SMark Cave-Ayland     dc->vmsd = &vmstate_macio_oldworld;
357d037834aSAndreas Färber }
358d037834aSAndreas Färber 
359*02635923SMark Cave-Ayland static const VMStateDescription vmstate_macio_newworld = {
360*02635923SMark Cave-Ayland     .name = "macio-newworld",
361*02635923SMark Cave-Ayland     .version_id = 0,
362*02635923SMark Cave-Ayland     .minimum_version_id = 0,
363*02635923SMark Cave-Ayland     .fields = (VMStateField[]) {
364*02635923SMark Cave-Ayland         VMSTATE_PCI_DEVICE(parent_obj.parent, NewWorldMacIOState),
365*02635923SMark Cave-Ayland         VMSTATE_END_OF_LIST()
366*02635923SMark Cave-Ayland     }
367*02635923SMark Cave-Ayland };
368*02635923SMark Cave-Ayland 
369d037834aSAndreas Färber static void macio_newworld_class_init(ObjectClass *oc, void *data)
370d037834aSAndreas Färber {
371d037834aSAndreas Färber     PCIDeviceClass *pdc = PCI_DEVICE_CLASS(oc);
372*02635923SMark Cave-Ayland     DeviceClass *dc = DEVICE_CLASS(oc);
373d037834aSAndreas Färber 
374d037834aSAndreas Färber     pdc->init = macio_newworld_initfn;
375d037834aSAndreas Färber     pdc->device_id = PCI_DEVICE_ID_APPLE_UNI_N_KEYL;
376*02635923SMark Cave-Ayland     dc->vmsd = &vmstate_macio_newworld;
377d037834aSAndreas Färber }
378d037834aSAndreas Färber 
379b981289cSAlexander Graf static Property macio_properties[] = {
380b981289cSAlexander Graf     DEFINE_PROP_UINT64("frequency", MacIOState, frequency, 0),
381b981289cSAlexander Graf     DEFINE_PROP_END_OF_LIST()
382b981289cSAlexander Graf };
383b981289cSAlexander Graf 
38440021f08SAnthony Liguori static void macio_class_init(ObjectClass *klass, void *data)
38540021f08SAnthony Liguori {
38640021f08SAnthony Liguori     PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
387b981289cSAlexander Graf     DeviceClass *dc = DEVICE_CLASS(klass);
38840021f08SAnthony Liguori 
38940021f08SAnthony Liguori     k->vendor_id = PCI_VENDOR_ID_APPLE;
39040021f08SAnthony Liguori     k->class_id = PCI_CLASS_OTHERS << 8;
391b981289cSAlexander Graf     dc->props = macio_properties;
39240021f08SAnthony Liguori }
39340021f08SAnthony Liguori 
394d037834aSAndreas Färber static const TypeInfo macio_oldworld_type_info = {
395d037834aSAndreas Färber     .name          = TYPE_OLDWORLD_MACIO,
396d037834aSAndreas Färber     .parent        = TYPE_MACIO,
39795ed3b7cSAndreas Färber     .instance_size = sizeof(OldWorldMacIOState),
39895ed3b7cSAndreas Färber     .instance_init = macio_oldworld_init,
399d037834aSAndreas Färber     .class_init    = macio_oldworld_class_init,
400d037834aSAndreas Färber };
401d037834aSAndreas Färber 
402d037834aSAndreas Färber static const TypeInfo macio_newworld_type_info = {
403d037834aSAndreas Färber     .name          = TYPE_NEWWORLD_MACIO,
404d037834aSAndreas Färber     .parent        = TYPE_MACIO,
40507a7484eSAndreas Färber     .instance_size = sizeof(NewWorldMacIOState),
40607a7484eSAndreas Färber     .instance_init = macio_newworld_init,
407d037834aSAndreas Färber     .class_init    = macio_newworld_class_init,
408d037834aSAndreas Färber };
409d037834aSAndreas Färber 
410fcf1bbabSAndreas Färber static const TypeInfo macio_type_info = {
411fcf1bbabSAndreas Färber     .name          = TYPE_MACIO,
41239bffca2SAnthony Liguori     .parent        = TYPE_PCI_DEVICE,
41339bffca2SAnthony Liguori     .instance_size = sizeof(MacIOState),
414fcf1bbabSAndreas Färber     .instance_init = macio_instance_init,
415d037834aSAndreas Färber     .abstract      = true,
41640021f08SAnthony Liguori     .class_init    = macio_class_init,
417d8c51b05SAnthony Liguori };
418d8c51b05SAnthony Liguori 
41983f7d43aSAndreas Färber static void macio_register_types(void)
420d8c51b05SAnthony Liguori {
421fcf1bbabSAndreas Färber     type_register_static(&macio_type_info);
422d037834aSAndreas Färber     type_register_static(&macio_oldworld_type_info);
423d037834aSAndreas Färber     type_register_static(&macio_newworld_type_info);
424d8c51b05SAnthony Liguori }
425d8c51b05SAnthony Liguori 
42683f7d43aSAndreas Färber type_init(macio_register_types)
427d8c51b05SAnthony Liguori 
428d037834aSAndreas Färber void macio_init(PCIDevice *d,
42907a7484eSAndreas Färber                 MemoryRegion *pic_mem,
43023c5e4caSAvi Kivity                 MemoryRegion *escc_mem)
4313cbee15bSj_mayer {
432d037834aSAndreas Färber     MacIOState *macio_state = MACIO(d);
4333cbee15bSj_mayer 
43423c5e4caSAvi Kivity     macio_state->pic_mem = pic_mem;
43523c5e4caSAvi Kivity     macio_state->escc_mem = escc_mem;
4363cbee15bSj_mayer     /* Note: this code is strongly inspirated from the corresponding code
4373cbee15bSj_mayer        in PearPC */
438b981289cSAlexander Graf     qdev_prop_set_uint64(DEVICE(&macio_state->cuda), "frequency",
439b981289cSAlexander Graf                          macio_state->frequency);
440deb54399Saliguori 
4417b925079SAndreas Färber     qdev_init_nofail(DEVICE(d));
4423cbee15bSj_mayer }
443