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 */ 250d75590dSPeter Maydell #include "qemu/osdep.h" 26da34e65cSMarkus Armbruster #include "qapi/error.h" 2783c9f4caSPaolo Bonzini #include "hw/hw.h" 2883c9f4caSPaolo Bonzini #include "hw/ppc/mac.h" 2983c9f4caSPaolo Bonzini #include "hw/pci/pci.h" 300d09e41aSPaolo Bonzini #include "hw/ppc/mac_dbdma.h" 310d09e41aSPaolo Bonzini #include "hw/char/escc.h" 323cbee15bSj_mayer 33fcf1bbabSAndreas Färber #define TYPE_MACIO "macio" 34fcf1bbabSAndreas Färber #define MACIO(obj) OBJECT_CHECK(MacIOState, (obj), TYPE_MACIO) 35fcf1bbabSAndreas Färber 36d8c51b05SAnthony Liguori typedef struct MacIOState 37d8c51b05SAnthony Liguori { 38fcf1bbabSAndreas Färber /*< private >*/ 39d8c51b05SAnthony Liguori PCIDevice parent; 40fcf1bbabSAndreas Färber /*< public >*/ 41fcf1bbabSAndreas Färber 4223c5e4caSAvi Kivity MemoryRegion bar; 4345fa67fbSAndreas Färber CUDAState cuda; 4407a7484eSAndreas Färber void *dbdma; 4523c5e4caSAvi Kivity MemoryRegion *pic_mem; 4623c5e4caSAvi Kivity MemoryRegion *escc_mem; 47b981289cSAlexander Graf uint64_t frequency; 48d8c51b05SAnthony Liguori } MacIOState; 493cbee15bSj_mayer 5095ed3b7cSAndreas Färber #define OLDWORLD_MACIO(obj) \ 5195ed3b7cSAndreas Färber OBJECT_CHECK(OldWorldMacIOState, (obj), TYPE_OLDWORLD_MACIO) 5295ed3b7cSAndreas Färber 5395ed3b7cSAndreas Färber typedef struct OldWorldMacIOState { 5495ed3b7cSAndreas Färber /*< private >*/ 5595ed3b7cSAndreas Färber MacIOState parent_obj; 5695ed3b7cSAndreas Färber /*< public >*/ 5795ed3b7cSAndreas Färber 5814eefd0eSAlexander Graf qemu_irq irqs[5]; 5907a7484eSAndreas Färber 6095ed3b7cSAndreas Färber MacIONVRAMState nvram; 6114eefd0eSAlexander Graf MACIOIDEState ide[2]; 6295ed3b7cSAndreas Färber } OldWorldMacIOState; 6395ed3b7cSAndreas Färber 6407a7484eSAndreas Färber #define NEWWORLD_MACIO(obj) \ 6507a7484eSAndreas Färber OBJECT_CHECK(NewWorldMacIOState, (obj), TYPE_NEWWORLD_MACIO) 6607a7484eSAndreas Färber 6707a7484eSAndreas Färber typedef struct NewWorldMacIOState { 6807a7484eSAndreas Färber /*< private >*/ 6907a7484eSAndreas Färber MacIOState parent_obj; 7007a7484eSAndreas Färber /*< public >*/ 7145fa67fbSAndreas Färber qemu_irq irqs[5]; 7207a7484eSAndreas Färber MACIOIDEState ide[2]; 7307a7484eSAndreas Färber } NewWorldMacIOState; 7407a7484eSAndreas Färber 750d54a502SAlexander Graf /* 760d54a502SAlexander Graf * The mac-io has two interfaces to the ESCC. One is called "escc-legacy", 770d54a502SAlexander Graf * while the other one is the normal, current ESCC interface. 780d54a502SAlexander Graf * 790d54a502SAlexander Graf * The magic below creates memory aliases to spawn the escc-legacy device 800d54a502SAlexander Graf * purely by rerouting the respective registers to our escc region. This 810d54a502SAlexander Graf * works because the only difference between the two memory regions is the 820d54a502SAlexander Graf * register layout, not their semantics. 830d54a502SAlexander Graf * 840d54a502SAlexander Graf * Reference: ftp://ftp.software.ibm.com/rs6000/technology/spec/chrp/inwork/CHRP_IORef_1.0.pdf 850d54a502SAlexander Graf */ 860d54a502SAlexander Graf static void macio_escc_legacy_setup(MacIOState *macio_state) 870d54a502SAlexander Graf { 880d54a502SAlexander Graf MemoryRegion *escc_legacy = g_new(MemoryRegion, 1); 890d54a502SAlexander Graf MemoryRegion *bar = &macio_state->bar; 900d54a502SAlexander Graf int i; 910d54a502SAlexander Graf static const int maps[] = { 920d54a502SAlexander Graf 0x00, 0x00, 930d54a502SAlexander Graf 0x02, 0x20, 940d54a502SAlexander Graf 0x04, 0x10, 950d54a502SAlexander Graf 0x06, 0x30, 960d54a502SAlexander Graf 0x08, 0x40, 970d54a502SAlexander Graf 0x0A, 0x50, 980d54a502SAlexander Graf 0x60, 0x60, 990d54a502SAlexander Graf 0x70, 0x70, 1000d54a502SAlexander Graf 0x80, 0x70, 1010d54a502SAlexander Graf 0x90, 0x80, 1020d54a502SAlexander Graf 0xA0, 0x90, 1030d54a502SAlexander Graf 0xB0, 0xA0, 1040d54a502SAlexander Graf 0xC0, 0xB0, 1050d54a502SAlexander Graf 0xD0, 0xC0, 1060d54a502SAlexander Graf 0xE0, 0xD0, 1070d54a502SAlexander Graf 0xF0, 0xE0, 1080d54a502SAlexander Graf }; 1090d54a502SAlexander Graf 11081e0ab48SPaolo Bonzini memory_region_init(escc_legacy, OBJECT(macio_state), "escc-legacy", 256); 1110d54a502SAlexander Graf for (i = 0; i < ARRAY_SIZE(maps); i += 2) { 1120d54a502SAlexander Graf MemoryRegion *port = g_new(MemoryRegion, 1); 11381e0ab48SPaolo Bonzini memory_region_init_alias(port, OBJECT(macio_state), "escc-legacy-port", 1142c9b15caSPaolo Bonzini macio_state->escc_mem, maps[i+1], 0x2); 1150d54a502SAlexander Graf memory_region_add_subregion(escc_legacy, maps[i], port); 1160d54a502SAlexander Graf } 1170d54a502SAlexander Graf 1180d54a502SAlexander Graf memory_region_add_subregion(bar, 0x12000, escc_legacy); 1190d54a502SAlexander Graf } 1200d54a502SAlexander Graf 121d8c51b05SAnthony Liguori static void macio_bar_setup(MacIOState *macio_state) 1223cbee15bSj_mayer { 12323c5e4caSAvi Kivity MemoryRegion *bar = &macio_state->bar; 1243cbee15bSj_mayer 12523c5e4caSAvi Kivity if (macio_state->escc_mem) { 12623c5e4caSAvi Kivity memory_region_add_subregion(bar, 0x13000, macio_state->escc_mem); 1270d54a502SAlexander Graf macio_escc_legacy_setup(macio_state); 1287fa9ae1aSblueswir1 } 1293cbee15bSj_mayer } 1303cbee15bSj_mayer 13162e9cd77SMarkus Armbruster static void macio_common_realize(PCIDevice *d, Error **errp) 132d8c51b05SAnthony Liguori { 1337b925079SAndreas Färber MacIOState *s = MACIO(d); 13445fa67fbSAndreas Färber SysBusDevice *sysbus_dev; 13562e9cd77SMarkus Armbruster Error *err = NULL; 136c7104402SPaolo Bonzini MemoryRegion *dbdma_mem; 137c7104402SPaolo Bonzini 138c7104402SPaolo Bonzini s->dbdma = DBDMA_init(&dbdma_mem); 139c7104402SPaolo Bonzini memory_region_add_subregion(&s->bar, 0x08000, dbdma_mem); 1407b925079SAndreas Färber 14162e9cd77SMarkus Armbruster object_property_set_bool(OBJECT(&s->cuda), true, "realized", &err); 14262e9cd77SMarkus Armbruster if (err) { 14362e9cd77SMarkus Armbruster error_propagate(errp, err); 14462e9cd77SMarkus Armbruster return; 14545fa67fbSAndreas Färber } 14645fa67fbSAndreas Färber sysbus_dev = SYS_BUS_DEVICE(&s->cuda); 14745fa67fbSAndreas Färber memory_region_add_subregion(&s->bar, 0x16000, 14845fa67fbSAndreas Färber sysbus_mmio_get_region(sysbus_dev, 0)); 14945fa67fbSAndreas Färber 1507b925079SAndreas Färber macio_bar_setup(s); 1517b925079SAndreas Färber pci_register_bar(d, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->bar); 152d8c51b05SAnthony Liguori } 153d8c51b05SAnthony Liguori 15462e9cd77SMarkus Armbruster static void macio_realize_ide(MacIOState *s, MACIOIDEState *ide, 15562e9cd77SMarkus Armbruster qemu_irq irq0, qemu_irq irq1, int dmaid, 15662e9cd77SMarkus Armbruster Error **errp) 15714eefd0eSAlexander Graf { 15814eefd0eSAlexander Graf SysBusDevice *sysbus_dev; 15914eefd0eSAlexander Graf 16014eefd0eSAlexander Graf sysbus_dev = SYS_BUS_DEVICE(ide); 16114eefd0eSAlexander Graf sysbus_connect_irq(sysbus_dev, 0, irq0); 16214eefd0eSAlexander Graf sysbus_connect_irq(sysbus_dev, 1, irq1); 16314eefd0eSAlexander Graf macio_ide_register_dma(ide, s->dbdma, dmaid); 16462e9cd77SMarkus Armbruster object_property_set_bool(OBJECT(ide), true, "realized", errp); 16514eefd0eSAlexander Graf } 16614eefd0eSAlexander Graf 16762e9cd77SMarkus Armbruster static void macio_oldworld_realize(PCIDevice *d, Error **errp) 168d037834aSAndreas Färber { 169d037834aSAndreas Färber MacIOState *s = MACIO(d); 17095ed3b7cSAndreas Färber OldWorldMacIOState *os = OLDWORLD_MACIO(d); 17162e9cd77SMarkus Armbruster Error *err = NULL; 17295ed3b7cSAndreas Färber SysBusDevice *sysbus_dev; 17314eefd0eSAlexander Graf int i; 17414eefd0eSAlexander Graf int cur_irq = 0; 17562e9cd77SMarkus Armbruster 17662e9cd77SMarkus Armbruster macio_common_realize(d, &err); 17762e9cd77SMarkus Armbruster if (err) { 17862e9cd77SMarkus Armbruster error_propagate(errp, err); 17962e9cd77SMarkus Armbruster return; 180d037834aSAndreas Färber } 181d037834aSAndreas Färber 18245fa67fbSAndreas Färber sysbus_dev = SYS_BUS_DEVICE(&s->cuda); 18314eefd0eSAlexander Graf sysbus_connect_irq(sysbus_dev, 0, os->irqs[cur_irq++]); 18445fa67fbSAndreas Färber 18562e9cd77SMarkus Armbruster object_property_set_bool(OBJECT(&os->nvram), true, "realized", &err); 18662e9cd77SMarkus Armbruster if (err) { 18762e9cd77SMarkus Armbruster error_propagate(errp, err); 18862e9cd77SMarkus Armbruster return; 18995ed3b7cSAndreas Färber } 19095ed3b7cSAndreas Färber sysbus_dev = SYS_BUS_DEVICE(&os->nvram); 19195ed3b7cSAndreas Färber memory_region_add_subregion(&s->bar, 0x60000, 19295ed3b7cSAndreas Färber sysbus_mmio_get_region(sysbus_dev, 0)); 19395ed3b7cSAndreas Färber pmac_format_nvram_partition(&os->nvram, os->nvram.size); 19495ed3b7cSAndreas Färber 195d037834aSAndreas Färber if (s->pic_mem) { 196d037834aSAndreas Färber /* Heathrow PIC */ 197d037834aSAndreas Färber memory_region_add_subregion(&s->bar, 0x00000, s->pic_mem); 198d037834aSAndreas Färber } 199d037834aSAndreas Färber 20014eefd0eSAlexander Graf /* IDE buses */ 20114eefd0eSAlexander Graf for (i = 0; i < ARRAY_SIZE(os->ide); i++) { 20214eefd0eSAlexander Graf qemu_irq irq0 = os->irqs[cur_irq++]; 20314eefd0eSAlexander Graf qemu_irq irq1 = os->irqs[cur_irq++]; 20414eefd0eSAlexander Graf 20562e9cd77SMarkus Armbruster macio_realize_ide(s, &os->ide[i], irq0, irq1, 0x16 + (i * 4), &err); 20662e9cd77SMarkus Armbruster if (err) { 20762e9cd77SMarkus Armbruster error_propagate(errp, err); 20862e9cd77SMarkus Armbruster return; 20907a7484eSAndreas Färber } 21014eefd0eSAlexander Graf } 211d037834aSAndreas Färber } 212d037834aSAndreas Färber 213213f0c4fSAndreas Färber static void macio_init_ide(MacIOState *s, MACIOIDEState *ide, size_t ide_size, 214213f0c4fSAndreas Färber int index) 21514eefd0eSAlexander Graf { 21614eefd0eSAlexander Graf gchar *name; 21714eefd0eSAlexander Graf 218213f0c4fSAndreas Färber object_initialize(ide, ide_size, TYPE_MACIO_IDE); 21914eefd0eSAlexander Graf qdev_set_parent_bus(DEVICE(ide), sysbus_get_default()); 22014eefd0eSAlexander Graf memory_region_add_subregion(&s->bar, 0x1f000 + ((index + 1) * 0x1000), 22114eefd0eSAlexander Graf &ide->mem); 22214eefd0eSAlexander Graf name = g_strdup_printf("ide[%i]", index); 22314eefd0eSAlexander Graf object_property_add_child(OBJECT(s), name, OBJECT(ide), NULL); 22414eefd0eSAlexander Graf g_free(name); 22514eefd0eSAlexander Graf } 22614eefd0eSAlexander Graf 22795ed3b7cSAndreas Färber static void macio_oldworld_init(Object *obj) 22895ed3b7cSAndreas Färber { 22907a7484eSAndreas Färber MacIOState *s = MACIO(obj); 23095ed3b7cSAndreas Färber OldWorldMacIOState *os = OLDWORLD_MACIO(obj); 23195ed3b7cSAndreas Färber DeviceState *dev; 23214eefd0eSAlexander Graf int i; 23395ed3b7cSAndreas Färber 23407a7484eSAndreas Färber qdev_init_gpio_out(DEVICE(obj), os->irqs, ARRAY_SIZE(os->irqs)); 23507a7484eSAndreas Färber 236213f0c4fSAndreas Färber object_initialize(&os->nvram, sizeof(os->nvram), TYPE_MACIO_NVRAM); 23795ed3b7cSAndreas Färber dev = DEVICE(&os->nvram); 23895ed3b7cSAndreas Färber qdev_prop_set_uint32(dev, "size", 0x2000); 23995ed3b7cSAndreas Färber qdev_prop_set_uint32(dev, "it_shift", 4); 24007a7484eSAndreas Färber 24114eefd0eSAlexander Graf for (i = 0; i < 2; i++) { 242213f0c4fSAndreas Färber macio_init_ide(s, &os->ide[i], sizeof(os->ide[i]), i); 24314eefd0eSAlexander Graf } 24495ed3b7cSAndreas Färber } 24595ed3b7cSAndreas Färber 246a0f9fdfdSAlexander Graf static void timer_write(void *opaque, hwaddr addr, uint64_t value, 247a0f9fdfdSAlexander Graf unsigned size) 248a0f9fdfdSAlexander Graf { 249a0f9fdfdSAlexander Graf } 250a0f9fdfdSAlexander Graf 251a0f9fdfdSAlexander Graf static uint64_t timer_read(void *opaque, hwaddr addr, unsigned size) 252a0f9fdfdSAlexander Graf { 253a0f9fdfdSAlexander Graf uint32_t value = 0; 254d696760bSAlexander Graf uint64_t systime = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); 255d696760bSAlexander Graf uint64_t kltime; 256d696760bSAlexander Graf 257*73bcb24dSRutuja Shah kltime = muldiv64(systime, 4194300, NANOSECONDS_PER_SECOND * 4); 258d696760bSAlexander Graf kltime = muldiv64(kltime, 18432000, 1048575); 259a0f9fdfdSAlexander Graf 260a0f9fdfdSAlexander Graf switch (addr) { 261a0f9fdfdSAlexander Graf case 0x38: 262d696760bSAlexander Graf value = kltime; 263a0f9fdfdSAlexander Graf break; 264a0f9fdfdSAlexander Graf case 0x3c: 265d696760bSAlexander Graf value = kltime >> 32; 266a0f9fdfdSAlexander Graf break; 267a0f9fdfdSAlexander Graf } 268a0f9fdfdSAlexander Graf 269a0f9fdfdSAlexander Graf return value; 270a0f9fdfdSAlexander Graf } 271a0f9fdfdSAlexander Graf 272a0f9fdfdSAlexander Graf static const MemoryRegionOps timer_ops = { 273a0f9fdfdSAlexander Graf .read = timer_read, 274a0f9fdfdSAlexander Graf .write = timer_write, 2759397a7c8SAlexander Graf .endianness = DEVICE_LITTLE_ENDIAN, 276a0f9fdfdSAlexander Graf }; 277a0f9fdfdSAlexander Graf 27862e9cd77SMarkus Armbruster static void macio_newworld_realize(PCIDevice *d, Error **errp) 279d037834aSAndreas Färber { 280d037834aSAndreas Färber MacIOState *s = MACIO(d); 28107a7484eSAndreas Färber NewWorldMacIOState *ns = NEWWORLD_MACIO(d); 28262e9cd77SMarkus Armbruster Error *err = NULL; 28307a7484eSAndreas Färber SysBusDevice *sysbus_dev; 2846c5819c4SGonglei MemoryRegion *timer_memory = NULL; 28514eefd0eSAlexander Graf int i; 28614eefd0eSAlexander Graf int cur_irq = 0; 28762e9cd77SMarkus Armbruster 28862e9cd77SMarkus Armbruster macio_common_realize(d, &err); 28962e9cd77SMarkus Armbruster if (err) { 29062e9cd77SMarkus Armbruster error_propagate(errp, err); 29162e9cd77SMarkus Armbruster return; 292d037834aSAndreas Färber } 293d037834aSAndreas Färber 29445fa67fbSAndreas Färber sysbus_dev = SYS_BUS_DEVICE(&s->cuda); 29514eefd0eSAlexander Graf sysbus_connect_irq(sysbus_dev, 0, ns->irqs[cur_irq++]); 29645fa67fbSAndreas Färber 297d037834aSAndreas Färber if (s->pic_mem) { 298d037834aSAndreas Färber /* OpenPIC */ 299d037834aSAndreas Färber memory_region_add_subregion(&s->bar, 0x40000, s->pic_mem); 300d037834aSAndreas Färber } 301d037834aSAndreas Färber 30214eefd0eSAlexander Graf /* IDE buses */ 30314eefd0eSAlexander Graf for (i = 0; i < ARRAY_SIZE(ns->ide); i++) { 30414eefd0eSAlexander Graf qemu_irq irq0 = ns->irqs[cur_irq++]; 30514eefd0eSAlexander Graf qemu_irq irq1 = ns->irqs[cur_irq++]; 30614eefd0eSAlexander Graf 30762e9cd77SMarkus Armbruster macio_realize_ide(s, &ns->ide[i], irq0, irq1, 0x16 + (i * 4), &err); 30862e9cd77SMarkus Armbruster if (err) { 30962e9cd77SMarkus Armbruster error_propagate(errp, err); 31062e9cd77SMarkus Armbruster return; 31107a7484eSAndreas Färber } 31207a7484eSAndreas Färber } 31307a7484eSAndreas Färber 314a0f9fdfdSAlexander Graf /* Timer */ 3156c5819c4SGonglei timer_memory = g_new(MemoryRegion, 1); 316a0f9fdfdSAlexander Graf memory_region_init_io(timer_memory, OBJECT(s), &timer_ops, NULL, "timer", 317a0f9fdfdSAlexander Graf 0x1000); 318a0f9fdfdSAlexander Graf memory_region_add_subregion(&s->bar, 0x15000, timer_memory); 319d037834aSAndreas Färber } 320d037834aSAndreas Färber 32107a7484eSAndreas Färber static void macio_newworld_init(Object *obj) 32207a7484eSAndreas Färber { 32307a7484eSAndreas Färber MacIOState *s = MACIO(obj); 32407a7484eSAndreas Färber NewWorldMacIOState *ns = NEWWORLD_MACIO(obj); 32507a7484eSAndreas Färber int i; 32607a7484eSAndreas Färber 32707a7484eSAndreas Färber qdev_init_gpio_out(DEVICE(obj), ns->irqs, ARRAY_SIZE(ns->irqs)); 32807a7484eSAndreas Färber 32907a7484eSAndreas Färber for (i = 0; i < 2; i++) { 330213f0c4fSAndreas Färber macio_init_ide(s, &ns->ide[i], sizeof(ns->ide[i]), i); 33107a7484eSAndreas Färber } 33207a7484eSAndreas Färber } 33307a7484eSAndreas Färber 334fcf1bbabSAndreas Färber static void macio_instance_init(Object *obj) 335fcf1bbabSAndreas Färber { 336fcf1bbabSAndreas Färber MacIOState *s = MACIO(obj); 337fcf1bbabSAndreas Färber 33881e0ab48SPaolo Bonzini memory_region_init(&s->bar, obj, "macio", 0x80000); 33907a7484eSAndreas Färber 340213f0c4fSAndreas Färber object_initialize(&s->cuda, sizeof(s->cuda), TYPE_CUDA); 34145fa67fbSAndreas Färber qdev_set_parent_bus(DEVICE(&s->cuda), sysbus_get_default()); 34245fa67fbSAndreas Färber object_property_add_child(obj, "cuda", OBJECT(&s->cuda), NULL); 343fcf1bbabSAndreas Färber } 344fcf1bbabSAndreas Färber 34502635923SMark Cave-Ayland static const VMStateDescription vmstate_macio_oldworld = { 34602635923SMark Cave-Ayland .name = "macio-oldworld", 34702635923SMark Cave-Ayland .version_id = 0, 34802635923SMark Cave-Ayland .minimum_version_id = 0, 34902635923SMark Cave-Ayland .fields = (VMStateField[]) { 35002635923SMark Cave-Ayland VMSTATE_PCI_DEVICE(parent_obj.parent, OldWorldMacIOState), 35102635923SMark Cave-Ayland VMSTATE_END_OF_LIST() 35202635923SMark Cave-Ayland } 35302635923SMark Cave-Ayland }; 35402635923SMark Cave-Ayland 355d037834aSAndreas Färber static void macio_oldworld_class_init(ObjectClass *oc, void *data) 356d037834aSAndreas Färber { 357d037834aSAndreas Färber PCIDeviceClass *pdc = PCI_DEVICE_CLASS(oc); 35802635923SMark Cave-Ayland DeviceClass *dc = DEVICE_CLASS(oc); 359d037834aSAndreas Färber 36062e9cd77SMarkus Armbruster pdc->realize = macio_oldworld_realize; 361d037834aSAndreas Färber pdc->device_id = PCI_DEVICE_ID_APPLE_343S1201; 36202635923SMark Cave-Ayland dc->vmsd = &vmstate_macio_oldworld; 363d037834aSAndreas Färber } 364d037834aSAndreas Färber 36502635923SMark Cave-Ayland static const VMStateDescription vmstate_macio_newworld = { 36602635923SMark Cave-Ayland .name = "macio-newworld", 36702635923SMark Cave-Ayland .version_id = 0, 36802635923SMark Cave-Ayland .minimum_version_id = 0, 36902635923SMark Cave-Ayland .fields = (VMStateField[]) { 37002635923SMark Cave-Ayland VMSTATE_PCI_DEVICE(parent_obj.parent, NewWorldMacIOState), 37102635923SMark Cave-Ayland VMSTATE_END_OF_LIST() 37202635923SMark Cave-Ayland } 37302635923SMark Cave-Ayland }; 37402635923SMark Cave-Ayland 375d037834aSAndreas Färber static void macio_newworld_class_init(ObjectClass *oc, void *data) 376d037834aSAndreas Färber { 377d037834aSAndreas Färber PCIDeviceClass *pdc = PCI_DEVICE_CLASS(oc); 37802635923SMark Cave-Ayland DeviceClass *dc = DEVICE_CLASS(oc); 379d037834aSAndreas Färber 38062e9cd77SMarkus Armbruster pdc->realize = macio_newworld_realize; 381d037834aSAndreas Färber pdc->device_id = PCI_DEVICE_ID_APPLE_UNI_N_KEYL; 38202635923SMark Cave-Ayland dc->vmsd = &vmstate_macio_newworld; 383d037834aSAndreas Färber } 384d037834aSAndreas Färber 385b981289cSAlexander Graf static Property macio_properties[] = { 386b981289cSAlexander Graf DEFINE_PROP_UINT64("frequency", MacIOState, frequency, 0), 387b981289cSAlexander Graf DEFINE_PROP_END_OF_LIST() 388b981289cSAlexander Graf }; 389b981289cSAlexander Graf 39040021f08SAnthony Liguori static void macio_class_init(ObjectClass *klass, void *data) 39140021f08SAnthony Liguori { 39240021f08SAnthony Liguori PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); 393b981289cSAlexander Graf DeviceClass *dc = DEVICE_CLASS(klass); 39440021f08SAnthony Liguori 39540021f08SAnthony Liguori k->vendor_id = PCI_VENDOR_ID_APPLE; 39640021f08SAnthony Liguori k->class_id = PCI_CLASS_OTHERS << 8; 397b981289cSAlexander Graf dc->props = macio_properties; 398f9f2a9f2SLaurent Vivier set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); 39940021f08SAnthony Liguori } 40040021f08SAnthony Liguori 401d037834aSAndreas Färber static const TypeInfo macio_oldworld_type_info = { 402d037834aSAndreas Färber .name = TYPE_OLDWORLD_MACIO, 403d037834aSAndreas Färber .parent = TYPE_MACIO, 40495ed3b7cSAndreas Färber .instance_size = sizeof(OldWorldMacIOState), 40595ed3b7cSAndreas Färber .instance_init = macio_oldworld_init, 406d037834aSAndreas Färber .class_init = macio_oldworld_class_init, 407d037834aSAndreas Färber }; 408d037834aSAndreas Färber 409d037834aSAndreas Färber static const TypeInfo macio_newworld_type_info = { 410d037834aSAndreas Färber .name = TYPE_NEWWORLD_MACIO, 411d037834aSAndreas Färber .parent = TYPE_MACIO, 41207a7484eSAndreas Färber .instance_size = sizeof(NewWorldMacIOState), 41307a7484eSAndreas Färber .instance_init = macio_newworld_init, 414d037834aSAndreas Färber .class_init = macio_newworld_class_init, 415d037834aSAndreas Färber }; 416d037834aSAndreas Färber 417fcf1bbabSAndreas Färber static const TypeInfo macio_type_info = { 418fcf1bbabSAndreas Färber .name = TYPE_MACIO, 41939bffca2SAnthony Liguori .parent = TYPE_PCI_DEVICE, 42039bffca2SAnthony Liguori .instance_size = sizeof(MacIOState), 421fcf1bbabSAndreas Färber .instance_init = macio_instance_init, 422d037834aSAndreas Färber .abstract = true, 42340021f08SAnthony Liguori .class_init = macio_class_init, 424d8c51b05SAnthony Liguori }; 425d8c51b05SAnthony Liguori 42683f7d43aSAndreas Färber static void macio_register_types(void) 427d8c51b05SAnthony Liguori { 428fcf1bbabSAndreas Färber type_register_static(&macio_type_info); 429d037834aSAndreas Färber type_register_static(&macio_oldworld_type_info); 430d037834aSAndreas Färber type_register_static(&macio_newworld_type_info); 431d8c51b05SAnthony Liguori } 432d8c51b05SAnthony Liguori 43383f7d43aSAndreas Färber type_init(macio_register_types) 434d8c51b05SAnthony Liguori 435d037834aSAndreas Färber void macio_init(PCIDevice *d, 43607a7484eSAndreas Färber MemoryRegion *pic_mem, 43723c5e4caSAvi Kivity MemoryRegion *escc_mem) 4383cbee15bSj_mayer { 439d037834aSAndreas Färber MacIOState *macio_state = MACIO(d); 4403cbee15bSj_mayer 44123c5e4caSAvi Kivity macio_state->pic_mem = pic_mem; 44223c5e4caSAvi Kivity macio_state->escc_mem = escc_mem; 4433cbee15bSj_mayer /* Note: this code is strongly inspirated from the corresponding code 4443cbee15bSj_mayer in PearPC */ 445b981289cSAlexander Graf qdev_prop_set_uint64(DEVICE(&macio_state->cuda), "frequency", 446b981289cSAlexander Graf macio_state->frequency); 447deb54399Saliguori 4487b925079SAndreas Färber qdev_init_nofail(DEVICE(d)); 4493cbee15bSj_mayer } 450