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