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