xref: /qemu/hw/misc/macio/macio.c (revision 213f0c4f619dda7a56612353009e6f30d3348206)
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;
45d8c51b05SAnthony Liguori } MacIOState;
463cbee15bSj_mayer 
4795ed3b7cSAndreas Färber #define OLDWORLD_MACIO(obj) \
4895ed3b7cSAndreas Färber     OBJECT_CHECK(OldWorldMacIOState, (obj), TYPE_OLDWORLD_MACIO)
4995ed3b7cSAndreas Färber 
5095ed3b7cSAndreas Färber typedef struct OldWorldMacIOState {
5195ed3b7cSAndreas Färber     /*< private >*/
5295ed3b7cSAndreas Färber     MacIOState parent_obj;
5395ed3b7cSAndreas Färber     /*< public >*/
5495ed3b7cSAndreas Färber 
5514eefd0eSAlexander Graf     qemu_irq irqs[5];
5607a7484eSAndreas Färber 
5795ed3b7cSAndreas Färber     MacIONVRAMState nvram;
5814eefd0eSAlexander Graf     MACIOIDEState ide[2];
5995ed3b7cSAndreas Färber } OldWorldMacIOState;
6095ed3b7cSAndreas Färber 
6107a7484eSAndreas Färber #define NEWWORLD_MACIO(obj) \
6207a7484eSAndreas Färber     OBJECT_CHECK(NewWorldMacIOState, (obj), TYPE_NEWWORLD_MACIO)
6307a7484eSAndreas Färber 
6407a7484eSAndreas Färber typedef struct NewWorldMacIOState {
6507a7484eSAndreas Färber     /*< private >*/
6607a7484eSAndreas Färber     MacIOState parent_obj;
6707a7484eSAndreas Färber     /*< public >*/
6845fa67fbSAndreas Färber     qemu_irq irqs[5];
6907a7484eSAndreas Färber     MACIOIDEState ide[2];
7007a7484eSAndreas Färber } NewWorldMacIOState;
7107a7484eSAndreas Färber 
720d54a502SAlexander Graf /*
730d54a502SAlexander Graf  * The mac-io has two interfaces to the ESCC. One is called "escc-legacy",
740d54a502SAlexander Graf  * while the other one is the normal, current ESCC interface.
750d54a502SAlexander Graf  *
760d54a502SAlexander Graf  * The magic below creates memory aliases to spawn the escc-legacy device
770d54a502SAlexander Graf  * purely by rerouting the respective registers to our escc region. This
780d54a502SAlexander Graf  * works because the only difference between the two memory regions is the
790d54a502SAlexander Graf  * register layout, not their semantics.
800d54a502SAlexander Graf  *
810d54a502SAlexander Graf  * Reference: ftp://ftp.software.ibm.com/rs6000/technology/spec/chrp/inwork/CHRP_IORef_1.0.pdf
820d54a502SAlexander Graf  */
830d54a502SAlexander Graf static void macio_escc_legacy_setup(MacIOState *macio_state)
840d54a502SAlexander Graf {
850d54a502SAlexander Graf     MemoryRegion *escc_legacy = g_new(MemoryRegion, 1);
860d54a502SAlexander Graf     MemoryRegion *bar = &macio_state->bar;
870d54a502SAlexander Graf     int i;
880d54a502SAlexander Graf     static const int maps[] = {
890d54a502SAlexander Graf         0x00, 0x00,
900d54a502SAlexander Graf         0x02, 0x20,
910d54a502SAlexander Graf         0x04, 0x10,
920d54a502SAlexander Graf         0x06, 0x30,
930d54a502SAlexander Graf         0x08, 0x40,
940d54a502SAlexander Graf         0x0A, 0x50,
950d54a502SAlexander Graf         0x60, 0x60,
960d54a502SAlexander Graf         0x70, 0x70,
970d54a502SAlexander Graf         0x80, 0x70,
980d54a502SAlexander Graf         0x90, 0x80,
990d54a502SAlexander Graf         0xA0, 0x90,
1000d54a502SAlexander Graf         0xB0, 0xA0,
1010d54a502SAlexander Graf         0xC0, 0xB0,
1020d54a502SAlexander Graf         0xD0, 0xC0,
1030d54a502SAlexander Graf         0xE0, 0xD0,
1040d54a502SAlexander Graf         0xF0, 0xE0,
1050d54a502SAlexander Graf     };
1060d54a502SAlexander Graf 
1072c9b15caSPaolo Bonzini     memory_region_init(escc_legacy, NULL, "escc-legacy", 256);
1080d54a502SAlexander Graf     for (i = 0; i < ARRAY_SIZE(maps); i += 2) {
1090d54a502SAlexander Graf         MemoryRegion *port = g_new(MemoryRegion, 1);
1102c9b15caSPaolo Bonzini         memory_region_init_alias(port, NULL, "escc-legacy-port",
1112c9b15caSPaolo Bonzini                                  macio_state->escc_mem, maps[i+1], 0x2);
1120d54a502SAlexander Graf         memory_region_add_subregion(escc_legacy, maps[i], port);
1130d54a502SAlexander Graf     }
1140d54a502SAlexander Graf 
1150d54a502SAlexander Graf     memory_region_add_subregion(bar, 0x12000, escc_legacy);
1160d54a502SAlexander Graf }
1170d54a502SAlexander Graf 
118d8c51b05SAnthony Liguori static void macio_bar_setup(MacIOState *macio_state)
1193cbee15bSj_mayer {
12023c5e4caSAvi Kivity     MemoryRegion *bar = &macio_state->bar;
1213cbee15bSj_mayer 
12223c5e4caSAvi Kivity     if (macio_state->escc_mem) {
12323c5e4caSAvi Kivity         memory_region_add_subregion(bar, 0x13000, macio_state->escc_mem);
1240d54a502SAlexander Graf         macio_escc_legacy_setup(macio_state);
1257fa9ae1aSblueswir1     }
1263cbee15bSj_mayer }
1273cbee15bSj_mayer 
128d037834aSAndreas Färber static int macio_common_initfn(PCIDevice *d)
129d8c51b05SAnthony Liguori {
1307b925079SAndreas Färber     MacIOState *s = MACIO(d);
13145fa67fbSAndreas Färber     SysBusDevice *sysbus_dev;
13245fa67fbSAndreas Färber     int ret;
1337b925079SAndreas Färber 
134d8c51b05SAnthony Liguori     d->config[0x3d] = 0x01; // interrupt on pin 1
1357b925079SAndreas Färber 
13645fa67fbSAndreas Färber     ret = qdev_init(DEVICE(&s->cuda));
13745fa67fbSAndreas Färber     if (ret < 0) {
13845fa67fbSAndreas Färber         return ret;
13945fa67fbSAndreas Färber     }
14045fa67fbSAndreas Färber     sysbus_dev = SYS_BUS_DEVICE(&s->cuda);
14145fa67fbSAndreas Färber     memory_region_add_subregion(&s->bar, 0x16000,
14245fa67fbSAndreas Färber                                 sysbus_mmio_get_region(sysbus_dev, 0));
14345fa67fbSAndreas Färber 
1447b925079SAndreas Färber     macio_bar_setup(s);
1457b925079SAndreas Färber     pci_register_bar(d, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->bar);
1467b925079SAndreas Färber 
147d8c51b05SAnthony Liguori     return 0;
148d8c51b05SAnthony Liguori }
149d8c51b05SAnthony Liguori 
15014eefd0eSAlexander Graf static int macio_initfn_ide(MacIOState *s, MACIOIDEState *ide, qemu_irq irq0,
15114eefd0eSAlexander Graf                             qemu_irq irq1, int dmaid)
15214eefd0eSAlexander Graf {
15314eefd0eSAlexander Graf     SysBusDevice *sysbus_dev;
15414eefd0eSAlexander Graf 
15514eefd0eSAlexander Graf     sysbus_dev = SYS_BUS_DEVICE(ide);
15614eefd0eSAlexander Graf     sysbus_connect_irq(sysbus_dev, 0, irq0);
15714eefd0eSAlexander Graf     sysbus_connect_irq(sysbus_dev, 1, irq1);
15814eefd0eSAlexander Graf     macio_ide_register_dma(ide, s->dbdma, dmaid);
15914eefd0eSAlexander Graf     return qdev_init(DEVICE(ide));
16014eefd0eSAlexander Graf }
16114eefd0eSAlexander Graf 
162d037834aSAndreas Färber static int macio_oldworld_initfn(PCIDevice *d)
163d037834aSAndreas Färber {
164d037834aSAndreas Färber     MacIOState *s = MACIO(d);
16595ed3b7cSAndreas Färber     OldWorldMacIOState *os = OLDWORLD_MACIO(d);
16695ed3b7cSAndreas Färber     SysBusDevice *sysbus_dev;
16714eefd0eSAlexander Graf     int i;
16814eefd0eSAlexander Graf     int cur_irq = 0;
169d037834aSAndreas Färber     int ret = macio_common_initfn(d);
170d037834aSAndreas Färber     if (ret < 0) {
171d037834aSAndreas Färber         return ret;
172d037834aSAndreas Färber     }
173d037834aSAndreas Färber 
17445fa67fbSAndreas Färber     sysbus_dev = SYS_BUS_DEVICE(&s->cuda);
17514eefd0eSAlexander Graf     sysbus_connect_irq(sysbus_dev, 0, os->irqs[cur_irq++]);
17645fa67fbSAndreas Färber 
17795ed3b7cSAndreas Färber     ret = qdev_init(DEVICE(&os->nvram));
17895ed3b7cSAndreas Färber     if (ret < 0) {
17995ed3b7cSAndreas Färber         return ret;
18095ed3b7cSAndreas Färber     }
18195ed3b7cSAndreas Färber     sysbus_dev = SYS_BUS_DEVICE(&os->nvram);
18295ed3b7cSAndreas Färber     memory_region_add_subregion(&s->bar, 0x60000,
18395ed3b7cSAndreas Färber                                 sysbus_mmio_get_region(sysbus_dev, 0));
18495ed3b7cSAndreas Färber     pmac_format_nvram_partition(&os->nvram, os->nvram.size);
18595ed3b7cSAndreas Färber 
186d037834aSAndreas Färber     if (s->pic_mem) {
187d037834aSAndreas Färber         /* Heathrow PIC */
188d037834aSAndreas Färber         memory_region_add_subregion(&s->bar, 0x00000, s->pic_mem);
189d037834aSAndreas Färber     }
190d037834aSAndreas Färber 
19114eefd0eSAlexander Graf     /* IDE buses */
19214eefd0eSAlexander Graf     for (i = 0; i < ARRAY_SIZE(os->ide); i++) {
19314eefd0eSAlexander Graf         qemu_irq irq0 = os->irqs[cur_irq++];
19414eefd0eSAlexander Graf         qemu_irq irq1 = os->irqs[cur_irq++];
19514eefd0eSAlexander Graf 
19614eefd0eSAlexander Graf         ret = macio_initfn_ide(s, &os->ide[i], irq0, irq1, 0x16 + (i * 4));
19707a7484eSAndreas Färber         if (ret < 0) {
19807a7484eSAndreas Färber             return ret;
19907a7484eSAndreas Färber         }
20014eefd0eSAlexander Graf     }
20107a7484eSAndreas Färber 
202d037834aSAndreas Färber     return 0;
203d037834aSAndreas Färber }
204d037834aSAndreas Färber 
205*213f0c4fSAndreas Färber static void macio_init_ide(MacIOState *s, MACIOIDEState *ide, size_t ide_size,
206*213f0c4fSAndreas Färber                            int index)
20714eefd0eSAlexander Graf {
20814eefd0eSAlexander Graf     gchar *name;
20914eefd0eSAlexander Graf 
210*213f0c4fSAndreas Färber     object_initialize(ide, ide_size, TYPE_MACIO_IDE);
21114eefd0eSAlexander Graf     qdev_set_parent_bus(DEVICE(ide), sysbus_get_default());
21214eefd0eSAlexander Graf     memory_region_add_subregion(&s->bar, 0x1f000 + ((index + 1) * 0x1000),
21314eefd0eSAlexander Graf                                 &ide->mem);
21414eefd0eSAlexander Graf     name = g_strdup_printf("ide[%i]", index);
21514eefd0eSAlexander Graf     object_property_add_child(OBJECT(s), name, OBJECT(ide), NULL);
21614eefd0eSAlexander Graf     g_free(name);
21714eefd0eSAlexander Graf }
21814eefd0eSAlexander Graf 
21995ed3b7cSAndreas Färber static void macio_oldworld_init(Object *obj)
22095ed3b7cSAndreas Färber {
22107a7484eSAndreas Färber     MacIOState *s = MACIO(obj);
22295ed3b7cSAndreas Färber     OldWorldMacIOState *os = OLDWORLD_MACIO(obj);
22395ed3b7cSAndreas Färber     DeviceState *dev;
22414eefd0eSAlexander Graf     int i;
22595ed3b7cSAndreas Färber 
22607a7484eSAndreas Färber     qdev_init_gpio_out(DEVICE(obj), os->irqs, ARRAY_SIZE(os->irqs));
22707a7484eSAndreas Färber 
228*213f0c4fSAndreas Färber     object_initialize(&os->nvram, sizeof(os->nvram), TYPE_MACIO_NVRAM);
22995ed3b7cSAndreas Färber     dev = DEVICE(&os->nvram);
23095ed3b7cSAndreas Färber     qdev_prop_set_uint32(dev, "size", 0x2000);
23195ed3b7cSAndreas Färber     qdev_prop_set_uint32(dev, "it_shift", 4);
23207a7484eSAndreas Färber 
23314eefd0eSAlexander Graf     for (i = 0; i < 2; i++) {
234*213f0c4fSAndreas Färber         macio_init_ide(s, &os->ide[i], sizeof(os->ide[i]), i);
23514eefd0eSAlexander Graf     }
23695ed3b7cSAndreas Färber }
23795ed3b7cSAndreas Färber 
238a0f9fdfdSAlexander Graf static void timer_write(void *opaque, hwaddr addr, uint64_t value,
239a0f9fdfdSAlexander Graf                        unsigned size)
240a0f9fdfdSAlexander Graf {
241a0f9fdfdSAlexander Graf }
242a0f9fdfdSAlexander Graf 
243a0f9fdfdSAlexander Graf static uint64_t timer_read(void *opaque, hwaddr addr, unsigned size)
244a0f9fdfdSAlexander Graf {
245a0f9fdfdSAlexander Graf     uint32_t value = 0;
246a0f9fdfdSAlexander Graf 
247a0f9fdfdSAlexander Graf     switch (addr) {
248a0f9fdfdSAlexander Graf     case 0x38:
249bc72ad67SAlex Bligh         value = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
250a0f9fdfdSAlexander Graf         break;
251a0f9fdfdSAlexander Graf     case 0x3c:
252bc72ad67SAlex Bligh         value = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) >> 32;
253a0f9fdfdSAlexander Graf         break;
254a0f9fdfdSAlexander Graf     }
255a0f9fdfdSAlexander Graf 
256a0f9fdfdSAlexander Graf     return value;
257a0f9fdfdSAlexander Graf }
258a0f9fdfdSAlexander Graf 
259a0f9fdfdSAlexander Graf static const MemoryRegionOps timer_ops = {
260a0f9fdfdSAlexander Graf     .read = timer_read,
261a0f9fdfdSAlexander Graf     .write = timer_write,
262a0f9fdfdSAlexander Graf     .endianness = DEVICE_NATIVE_ENDIAN,
263a0f9fdfdSAlexander Graf };
264a0f9fdfdSAlexander Graf 
265d037834aSAndreas Färber static int macio_newworld_initfn(PCIDevice *d)
266d037834aSAndreas Färber {
267d037834aSAndreas Färber     MacIOState *s = MACIO(d);
26807a7484eSAndreas Färber     NewWorldMacIOState *ns = NEWWORLD_MACIO(d);
26907a7484eSAndreas Färber     SysBusDevice *sysbus_dev;
270a0f9fdfdSAlexander Graf     MemoryRegion *timer_memory = g_new(MemoryRegion, 1);
27114eefd0eSAlexander Graf     int i;
27214eefd0eSAlexander Graf     int cur_irq = 0;
273d037834aSAndreas Färber     int ret = macio_common_initfn(d);
274d037834aSAndreas Färber     if (ret < 0) {
275d037834aSAndreas Färber         return ret;
276d037834aSAndreas Färber     }
277d037834aSAndreas Färber 
27845fa67fbSAndreas Färber     sysbus_dev = SYS_BUS_DEVICE(&s->cuda);
27914eefd0eSAlexander Graf     sysbus_connect_irq(sysbus_dev, 0, ns->irqs[cur_irq++]);
28045fa67fbSAndreas Färber 
281d037834aSAndreas Färber     if (s->pic_mem) {
282d037834aSAndreas Färber         /* OpenPIC */
283d037834aSAndreas Färber         memory_region_add_subregion(&s->bar, 0x40000, s->pic_mem);
284d037834aSAndreas Färber     }
285d037834aSAndreas Färber 
28614eefd0eSAlexander Graf     /* IDE buses */
28714eefd0eSAlexander Graf     for (i = 0; i < ARRAY_SIZE(ns->ide); i++) {
28814eefd0eSAlexander Graf         qemu_irq irq0 = ns->irqs[cur_irq++];
28914eefd0eSAlexander Graf         qemu_irq irq1 = ns->irqs[cur_irq++];
29014eefd0eSAlexander Graf 
29114eefd0eSAlexander Graf         ret = macio_initfn_ide(s, &ns->ide[i], irq0, irq1, 0x16 + (i * 4));
29207a7484eSAndreas Färber         if (ret < 0) {
29307a7484eSAndreas Färber             return ret;
29407a7484eSAndreas Färber         }
29507a7484eSAndreas Färber     }
29607a7484eSAndreas Färber 
297a0f9fdfdSAlexander Graf     /* Timer */
298a0f9fdfdSAlexander Graf     memory_region_init_io(timer_memory, OBJECT(s), &timer_ops, NULL, "timer",
299a0f9fdfdSAlexander Graf                           0x1000);
300a0f9fdfdSAlexander Graf     memory_region_add_subregion(&s->bar, 0x15000, timer_memory);
301a0f9fdfdSAlexander Graf 
302d037834aSAndreas Färber     return 0;
303d037834aSAndreas Färber }
304d037834aSAndreas Färber 
30507a7484eSAndreas Färber static void macio_newworld_init(Object *obj)
30607a7484eSAndreas Färber {
30707a7484eSAndreas Färber     MacIOState *s = MACIO(obj);
30807a7484eSAndreas Färber     NewWorldMacIOState *ns = NEWWORLD_MACIO(obj);
30907a7484eSAndreas Färber     int i;
31007a7484eSAndreas Färber 
31107a7484eSAndreas Färber     qdev_init_gpio_out(DEVICE(obj), ns->irqs, ARRAY_SIZE(ns->irqs));
31207a7484eSAndreas Färber 
31307a7484eSAndreas Färber     for (i = 0; i < 2; i++) {
314*213f0c4fSAndreas Färber         macio_init_ide(s, &ns->ide[i], sizeof(ns->ide[i]), i);
31507a7484eSAndreas Färber     }
31607a7484eSAndreas Färber }
31707a7484eSAndreas Färber 
318fcf1bbabSAndreas Färber static void macio_instance_init(Object *obj)
319fcf1bbabSAndreas Färber {
320fcf1bbabSAndreas Färber     MacIOState *s = MACIO(obj);
32107a7484eSAndreas Färber     MemoryRegion *dbdma_mem;
322fcf1bbabSAndreas Färber 
3232c9b15caSPaolo Bonzini     memory_region_init(&s->bar, NULL, "macio", 0x80000);
32407a7484eSAndreas Färber 
325*213f0c4fSAndreas Färber     object_initialize(&s->cuda, sizeof(s->cuda), TYPE_CUDA);
32645fa67fbSAndreas Färber     qdev_set_parent_bus(DEVICE(&s->cuda), sysbus_get_default());
32745fa67fbSAndreas Färber     object_property_add_child(obj, "cuda", OBJECT(&s->cuda), NULL);
32845fa67fbSAndreas Färber 
32907a7484eSAndreas Färber     s->dbdma = DBDMA_init(&dbdma_mem);
33007a7484eSAndreas Färber     memory_region_add_subregion(&s->bar, 0x08000, dbdma_mem);
331fcf1bbabSAndreas Färber }
332fcf1bbabSAndreas Färber 
333d037834aSAndreas Färber static void macio_oldworld_class_init(ObjectClass *oc, void *data)
334d037834aSAndreas Färber {
335d037834aSAndreas Färber     PCIDeviceClass *pdc = PCI_DEVICE_CLASS(oc);
336d037834aSAndreas Färber 
337d037834aSAndreas Färber     pdc->init = macio_oldworld_initfn;
338d037834aSAndreas Färber     pdc->device_id = PCI_DEVICE_ID_APPLE_343S1201;
339d037834aSAndreas Färber }
340d037834aSAndreas Färber 
341d037834aSAndreas Färber static void macio_newworld_class_init(ObjectClass *oc, void *data)
342d037834aSAndreas Färber {
343d037834aSAndreas Färber     PCIDeviceClass *pdc = PCI_DEVICE_CLASS(oc);
344d037834aSAndreas Färber 
345d037834aSAndreas Färber     pdc->init = macio_newworld_initfn;
346d037834aSAndreas Färber     pdc->device_id = PCI_DEVICE_ID_APPLE_UNI_N_KEYL;
347d037834aSAndreas Färber }
348d037834aSAndreas Färber 
34940021f08SAnthony Liguori static void macio_class_init(ObjectClass *klass, void *data)
35040021f08SAnthony Liguori {
35140021f08SAnthony Liguori     PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
35240021f08SAnthony Liguori 
35340021f08SAnthony Liguori     k->vendor_id = PCI_VENDOR_ID_APPLE;
35440021f08SAnthony Liguori     k->class_id = PCI_CLASS_OTHERS << 8;
35540021f08SAnthony Liguori }
35640021f08SAnthony Liguori 
357d037834aSAndreas Färber static const TypeInfo macio_oldworld_type_info = {
358d037834aSAndreas Färber     .name          = TYPE_OLDWORLD_MACIO,
359d037834aSAndreas Färber     .parent        = TYPE_MACIO,
36095ed3b7cSAndreas Färber     .instance_size = sizeof(OldWorldMacIOState),
36195ed3b7cSAndreas Färber     .instance_init = macio_oldworld_init,
362d037834aSAndreas Färber     .class_init    = macio_oldworld_class_init,
363d037834aSAndreas Färber };
364d037834aSAndreas Färber 
365d037834aSAndreas Färber static const TypeInfo macio_newworld_type_info = {
366d037834aSAndreas Färber     .name          = TYPE_NEWWORLD_MACIO,
367d037834aSAndreas Färber     .parent        = TYPE_MACIO,
36807a7484eSAndreas Färber     .instance_size = sizeof(NewWorldMacIOState),
36907a7484eSAndreas Färber     .instance_init = macio_newworld_init,
370d037834aSAndreas Färber     .class_init    = macio_newworld_class_init,
371d037834aSAndreas Färber };
372d037834aSAndreas Färber 
373fcf1bbabSAndreas Färber static const TypeInfo macio_type_info = {
374fcf1bbabSAndreas Färber     .name          = TYPE_MACIO,
37539bffca2SAnthony Liguori     .parent        = TYPE_PCI_DEVICE,
37639bffca2SAnthony Liguori     .instance_size = sizeof(MacIOState),
377fcf1bbabSAndreas Färber     .instance_init = macio_instance_init,
378d037834aSAndreas Färber     .abstract      = true,
37940021f08SAnthony Liguori     .class_init    = macio_class_init,
380d8c51b05SAnthony Liguori };
381d8c51b05SAnthony Liguori 
38283f7d43aSAndreas Färber static void macio_register_types(void)
383d8c51b05SAnthony Liguori {
384fcf1bbabSAndreas Färber     type_register_static(&macio_type_info);
385d037834aSAndreas Färber     type_register_static(&macio_oldworld_type_info);
386d037834aSAndreas Färber     type_register_static(&macio_newworld_type_info);
387d8c51b05SAnthony Liguori }
388d8c51b05SAnthony Liguori 
38983f7d43aSAndreas Färber type_init(macio_register_types)
390d8c51b05SAnthony Liguori 
391d037834aSAndreas Färber void macio_init(PCIDevice *d,
39207a7484eSAndreas Färber                 MemoryRegion *pic_mem,
39323c5e4caSAvi Kivity                 MemoryRegion *escc_mem)
3943cbee15bSj_mayer {
395d037834aSAndreas Färber     MacIOState *macio_state = MACIO(d);
3963cbee15bSj_mayer 
39723c5e4caSAvi Kivity     macio_state->pic_mem = pic_mem;
39823c5e4caSAvi Kivity     macio_state->escc_mem = escc_mem;
3993cbee15bSj_mayer     /* Note: this code is strongly inspirated from the corresponding code
4003cbee15bSj_mayer        in PearPC */
401deb54399Saliguori 
4027b925079SAndreas Färber     qdev_init_nofail(DEVICE(d));
4033cbee15bSj_mayer }
404