From baec19105bb9824593bf6f37556302da2f67e583 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Wed, 23 Jan 2013 23:03:54 +0000 Subject: [PATCH 01/20] ppc: Move Mac machines to hw/ppc/ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Andreas Färber [agraf: squash in MAINTAINERS fix] Signed-off-by: Alexander Graf --- MAINTAINERS | 4 ++-- hw/cuda.c | 2 +- hw/grackle_pci.c | 2 +- hw/heathrow_pic.c | 2 +- hw/ide/macio.c | 6 ++--- hw/mac_nvram.c | 2 +- hw/macio.c | 2 +- hw/openpic.c | 2 +- hw/ppc/Makefile.objs | 9 ++++---- hw/{ppc_mac.h => ppc/mac.h} | 0 hw/{ppc_newworld.c => ppc/mac_newworld.c} | 28 +++++++++++------------ hw/{ppc_oldworld.c => ppc/mac_oldworld.c} | 26 ++++++++++----------- hw/unin_pci.c | 2 +- 13 files changed, 44 insertions(+), 43 deletions(-) rename hw/{ppc_mac.h => ppc/mac.h} (100%) rename hw/{ppc_newworld.c => ppc/mac_newworld.c} (98%) rename hw/{ppc_oldworld.c => ppc/mac_oldworld.c} (97%) diff --git a/MAINTAINERS b/MAINTAINERS index 35c260d54..9dd4c2079 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -380,7 +380,7 @@ New World M: Alexander Graf L: qemu-ppc@nongnu.org S: Maintained -F: hw/ppc_newworld.c +F: hw/ppc/mac_newworld.c F: hw/unin_pci.c F: hw/dec_pci.[hc] @@ -388,7 +388,7 @@ Old World M: Alexander Graf L: qemu-ppc@nongnu.org S: Maintained -F: hw/ppc_oldworld.c +F: hw/ppc/mac_oldworld.c F: hw/grackle_pci.c PReP diff --git a/hw/cuda.c b/hw/cuda.c index d59e0aeaa..bbd1fdaab 100644 --- a/hw/cuda.c +++ b/hw/cuda.c @@ -23,7 +23,7 @@ * THE SOFTWARE. */ #include "hw.h" -#include "ppc_mac.h" +#include "ppc/mac.h" #include "adb.h" #include "qemu/timer.h" #include "sysemu/sysemu.h" diff --git a/hw/grackle_pci.c b/hw/grackle_pci.c index 948416632..95639d573 100644 --- a/hw/grackle_pci.c +++ b/hw/grackle_pci.c @@ -24,7 +24,7 @@ */ #include "pci/pci_host.h" -#include "ppc_mac.h" +#include "ppc/mac.h" #include "pci/pci.h" /* debug Grackle */ diff --git a/hw/heathrow_pic.c b/hw/heathrow_pic.c index b9ec8e7b4..c0a71c3d5 100644 --- a/hw/heathrow_pic.c +++ b/hw/heathrow_pic.c @@ -23,7 +23,7 @@ * THE SOFTWARE. */ #include "hw.h" -#include "ppc_mac.h" +#include "ppc/mac.h" /* debug PIC */ //#define DEBUG_PIC diff --git a/hw/ide/macio.c b/hw/ide/macio.c index d8f9b4bce..e0f04dc33 100644 --- a/hw/ide/macio.c +++ b/hw/ide/macio.c @@ -22,9 +22,9 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -#include -#include -#include +#include "hw/hw.h" +#include "hw/ppc/mac.h" +#include "hw/mac_dbdma.h" #include "block/block.h" #include "sysemu/dma.h" diff --git a/hw/mac_nvram.c b/hw/mac_nvram.c index 71093c2b1..eec7ca430 100644 --- a/hw/mac_nvram.c +++ b/hw/mac_nvram.c @@ -25,7 +25,7 @@ #include "hw.h" #include "firmware_abi.h" #include "sysemu/sysemu.h" -#include "ppc_mac.h" +#include "ppc/mac.h" /* debug NVR */ //#define DEBUG_NVR diff --git a/hw/macio.c b/hw/macio.c index 675a71c05..f01fc5761 100644 --- a/hw/macio.c +++ b/hw/macio.c @@ -23,7 +23,7 @@ * THE SOFTWARE. */ #include "hw.h" -#include "ppc_mac.h" +#include "ppc/mac.h" #include "pci/pci.h" #include "escc.h" diff --git a/hw/openpic.c b/hw/openpic.c index d414f47b7..25aa9bf45 100644 --- a/hw/openpic.c +++ b/hw/openpic.c @@ -34,7 +34,7 @@ * */ #include "hw.h" -#include "ppc_mac.h" +#include "ppc/mac.h" #include "pci/pci.h" #include "openpic.h" #include "sysbus.h" diff --git a/hw/ppc/Makefile.objs b/hw/ppc/Makefile.objs index afdcc0e53..462146b0b 100644 --- a/hw/ppc/Makefile.objs +++ b/hw/ppc/Makefile.objs @@ -3,10 +3,6 @@ obj-y = ppc.o ppc_booke.o # PREP target obj-y += mc146818rtc.o obj-y += ppc_prep.o -# OldWorld PowerMac -obj-y += ppc_oldworld.o -# NewWorld PowerMac -obj-y += ppc_newworld.o # IBM pSeries (sPAPR) obj-$(CONFIG_PSERIES) += spapr.o spapr_hcall.o spapr_rtas.o spapr_vio.o obj-$(CONFIG_PSERIES) += xics.o spapr_vty.o spapr_llan.o spapr_vscsi.o @@ -28,4 +24,9 @@ obj-y += xilinx_ethlite.o obj-y := $(addprefix ../,$(obj-y)) +# OldWorld PowerMac +obj-y += mac_oldworld.o +# NewWorld PowerMac +obj-y += mac_newworld.o +# e500 obj-$(CONFIG_FDT) += e500.o mpc8544ds.o e500plat.o diff --git a/hw/ppc_mac.h b/hw/ppc/mac.h similarity index 100% rename from hw/ppc_mac.h rename to hw/ppc/mac.h diff --git a/hw/ppc_newworld.c b/hw/ppc/mac_newworld.c similarity index 98% rename from hw/ppc_newworld.c rename to hw/ppc/mac_newworld.c index b1973f18f..f3c01bfc5 100644 --- a/hw/ppc_newworld.c +++ b/hw/ppc/mac_newworld.c @@ -46,28 +46,28 @@ * 0001:05:0c.0 IDE interface [0101]: Broadcom K2 SATA [1166:0240] * */ -#include "hw.h" -#include "ppc.h" -#include "ppc_mac.h" -#include "adb.h" -#include "mac_dbdma.h" -#include "nvram.h" -#include "pci/pci.h" +#include "hw/hw.h" +#include "hw/ppc.h" +#include "hw/ppc/mac.h" +#include "hw/adb.h" +#include "hw/mac_dbdma.h" +#include "hw/nvram.h" +#include "hw/pci/pci.h" #include "net/net.h" #include "sysemu/sysemu.h" -#include "boards.h" -#include "fw_cfg.h" -#include "escc.h" -#include "openpic.h" -#include "ide.h" -#include "loader.h" +#include "hw/boards.h" +#include "hw/fw_cfg.h" +#include "hw/escc.h" +#include "hw/openpic.h" +#include "hw/ide.h" +#include "hw/loader.h" #include "elf.h" #include "sysemu/kvm.h" #include "kvm_ppc.h" #include "hw/usb.h" #include "sysemu/blockdev.h" #include "exec/address-spaces.h" -#include "sysbus.h" +#include "hw/sysbus.h" #define MAX_IDE_BUS 2 #define CFG_ADDR 0xf0000510 diff --git a/hw/ppc_oldworld.c b/hw/ppc/mac_oldworld.c similarity index 97% rename from hw/ppc_oldworld.c rename to hw/ppc/mac_oldworld.c index de34e7530..dfbfa546f 100644 --- a/hw/ppc_oldworld.c +++ b/hw/ppc/mac_oldworld.c @@ -23,21 +23,21 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -#include "hw.h" -#include "ppc.h" -#include "ppc_mac.h" -#include "adb.h" -#include "mac_dbdma.h" -#include "nvram.h" +#include "hw/hw.h" +#include "hw/ppc.h" +#include "mac.h" +#include "hw/adb.h" +#include "hw/mac_dbdma.h" +#include "hw/nvram.h" #include "sysemu/sysemu.h" #include "net/net.h" -#include "isa.h" -#include "pci/pci.h" -#include "boards.h" -#include "fw_cfg.h" -#include "escc.h" -#include "ide.h" -#include "loader.h" +#include "hw/isa.h" +#include "hw/pci/pci.h" +#include "hw/boards.h" +#include "hw/fw_cfg.h" +#include "hw/escc.h" +#include "hw/ide.h" +#include "hw/loader.h" #include "elf.h" #include "sysemu/kvm.h" #include "kvm_ppc.h" diff --git a/hw/unin_pci.c b/hw/unin_pci.c index 46757924b..f1c3c20f3 100644 --- a/hw/unin_pci.c +++ b/hw/unin_pci.c @@ -22,7 +22,7 @@ * THE SOFTWARE. */ #include "hw.h" -#include "ppc_mac.h" +#include "ppc/mac.h" #include "pci/pci.h" #include "pci/pci_host.h" From fcf1bbabf4de3bc125c4dff18ea1cb76d76f042a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Wed, 23 Jan 2013 23:03:55 +0000 Subject: [PATCH 02/20] macio: QOM'ify some more MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move bar MemoryRegion initialization to an instance_init. Signed-off-by: Andreas Färber Signed-off-by: Alexander Graf --- hw/macio.c | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/hw/macio.c b/hw/macio.c index f01fc5761..770e3bdb9 100644 --- a/hw/macio.c +++ b/hw/macio.c @@ -27,9 +27,15 @@ #include "pci/pci.h" #include "escc.h" +#define TYPE_MACIO "macio" +#define MACIO(obj) OBJECT_CHECK(MacIOState, (obj), TYPE_MACIO) + typedef struct MacIOState { + /*< private >*/ PCIDevice parent; + /*< public >*/ + int is_oldworld; MemoryRegion bar; MemoryRegion *pic_mem; @@ -46,7 +52,6 @@ static void macio_bar_setup(MacIOState *macio_state) int i; MemoryRegion *bar = &macio_state->bar; - memory_region_init(bar, "macio", 0x80000); if (macio_state->pic_mem) { if (macio_state->is_oldworld) { /* Heathrow PIC */ @@ -81,6 +86,13 @@ static int macio_initfn(PCIDevice *d) return 0; } +static void macio_instance_init(Object *obj) +{ + MacIOState *s = MACIO(obj); + + memory_region_init(&s->bar, "macio", 0x80000); +} + static void macio_class_init(ObjectClass *klass, void *data) { PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); @@ -90,16 +102,17 @@ static void macio_class_init(ObjectClass *klass, void *data) k->class_id = PCI_CLASS_OTHERS << 8; } -static const TypeInfo macio_info = { - .name = "macio", +static const TypeInfo macio_type_info = { + .name = TYPE_MACIO, .parent = TYPE_PCI_DEVICE, .instance_size = sizeof(MacIOState), + .instance_init = macio_instance_init, .class_init = macio_class_init, }; static void macio_register_types(void) { - type_register_static(&macio_info); + type_register_static(&macio_type_info); } type_init(macio_register_types) @@ -114,9 +127,9 @@ void macio_init (PCIBus *bus, int device_id, int is_oldworld, MacIOState *macio_state; int i; - d = pci_create_simple(bus, -1, "macio"); + d = pci_create_simple(bus, -1, TYPE_MACIO); - macio_state = DO_UPCAST(MacIOState, parent, d); + macio_state = MACIO(d); macio_state->is_oldworld = is_oldworld; macio_state->pic_mem = pic_mem; macio_state->dbdma_mem = dbdma_mem; From 7b925079e36cf26ca2e1f8db84b771ddc3d6340c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Wed, 23 Jan 2013 23:03:56 +0000 Subject: [PATCH 03/20] macio: Delay qdev init until all fields are initialized MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This turns macio_bar_setup() into an implementation detail of the qdev initfn, to be removed step by step. Signed-off-by: Andreas Färber Signed-off-by: Alexander Graf --- hw/macio.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/hw/macio.c b/hw/macio.c index 770e3bdb9..8b4b48d13 100644 --- a/hw/macio.c +++ b/hw/macio.c @@ -82,7 +82,13 @@ static void macio_bar_setup(MacIOState *macio_state) static int macio_initfn(PCIDevice *d) { + MacIOState *s = MACIO(d); + d->config[0x3d] = 0x01; // interrupt on pin 1 + + macio_bar_setup(s); + pci_register_bar(d, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->bar); + return 0; } @@ -127,7 +133,7 @@ void macio_init (PCIBus *bus, int device_id, int is_oldworld, MacIOState *macio_state; int i; - d = pci_create_simple(bus, -1, TYPE_MACIO); + d = pci_create(bus, -1, TYPE_MACIO); macio_state = MACIO(d); macio_state->is_oldworld = is_oldworld; @@ -148,6 +154,5 @@ void macio_init (PCIBus *bus, int device_id, int is_oldworld, pci_config_set_device_id(d->config, device_id); - macio_bar_setup(macio_state); - pci_register_bar(d, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &macio_state->bar); + qdev_init_nofail(DEVICE(d)); } From d037834a9d3847499e8a146bd1893a5c856411be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Wed, 23 Jan 2013 23:03:57 +0000 Subject: [PATCH 04/20] macio: Split MacIO in two MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Let the machines create two different types. This prepares to move knowledge about sub-devices from the machines into the devices. Signed-off-by: Andreas Färber Signed-off-by: Alexander Graf --- hw/macio.c | 97 +++++++++++++++++++++++++++++++------------ hw/ppc/mac.h | 10 +++-- hw/ppc/mac_newworld.c | 4 +- hw/ppc/mac_oldworld.c | 4 +- 4 files changed, 82 insertions(+), 33 deletions(-) diff --git a/hw/macio.c b/hw/macio.c index 8b4b48d13..0e6fc8d5f 100644 --- a/hw/macio.c +++ b/hw/macio.c @@ -36,7 +36,6 @@ typedef struct MacIOState PCIDevice parent; /*< public >*/ - int is_oldworld; MemoryRegion bar; MemoryRegion *pic_mem; MemoryRegion *dbdma_mem; @@ -52,15 +51,6 @@ static void macio_bar_setup(MacIOState *macio_state) int i; MemoryRegion *bar = &macio_state->bar; - if (macio_state->pic_mem) { - if (macio_state->is_oldworld) { - /* Heathrow PIC */ - memory_region_add_subregion(bar, 0x00000, macio_state->pic_mem); - } else { - /* OpenPIC */ - memory_region_add_subregion(bar, 0x40000, macio_state->pic_mem); - } - } if (macio_state->dbdma_mem) { memory_region_add_subregion(bar, 0x08000, macio_state->dbdma_mem); } @@ -80,7 +70,7 @@ static void macio_bar_setup(MacIOState *macio_state) macio_nvram_setup_bar(macio_state->nvram, bar, 0x60000); } -static int macio_initfn(PCIDevice *d) +static int macio_common_initfn(PCIDevice *d) { MacIOState *s = MACIO(d); @@ -92,6 +82,38 @@ static int macio_initfn(PCIDevice *d) return 0; } +static int macio_oldworld_initfn(PCIDevice *d) +{ + MacIOState *s = MACIO(d); + int ret = macio_common_initfn(d); + if (ret < 0) { + return ret; + } + + if (s->pic_mem) { + /* Heathrow PIC */ + memory_region_add_subregion(&s->bar, 0x00000, s->pic_mem); + } + + return 0; +} + +static int macio_newworld_initfn(PCIDevice *d) +{ + MacIOState *s = MACIO(d); + int ret = macio_common_initfn(d); + if (ret < 0) { + return ret; + } + + if (s->pic_mem) { + /* OpenPIC */ + memory_region_add_subregion(&s->bar, 0x40000, s->pic_mem); + } + + return 0; +} + static void macio_instance_init(Object *obj) { MacIOState *s = MACIO(obj); @@ -99,44 +121,69 @@ static void macio_instance_init(Object *obj) memory_region_init(&s->bar, "macio", 0x80000); } +static void macio_oldworld_class_init(ObjectClass *oc, void *data) +{ + PCIDeviceClass *pdc = PCI_DEVICE_CLASS(oc); + + pdc->init = macio_oldworld_initfn; + pdc->device_id = PCI_DEVICE_ID_APPLE_343S1201; +} + +static void macio_newworld_class_init(ObjectClass *oc, void *data) +{ + PCIDeviceClass *pdc = PCI_DEVICE_CLASS(oc); + + pdc->init = macio_newworld_initfn; + pdc->device_id = PCI_DEVICE_ID_APPLE_UNI_N_KEYL; +} + static void macio_class_init(ObjectClass *klass, void *data) { PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - k->init = macio_initfn; k->vendor_id = PCI_VENDOR_ID_APPLE; k->class_id = PCI_CLASS_OTHERS << 8; } +static const TypeInfo macio_oldworld_type_info = { + .name = TYPE_OLDWORLD_MACIO, + .parent = TYPE_MACIO, + .class_init = macio_oldworld_class_init, +}; + +static const TypeInfo macio_newworld_type_info = { + .name = TYPE_NEWWORLD_MACIO, + .parent = TYPE_MACIO, + .class_init = macio_newworld_class_init, +}; + static const TypeInfo macio_type_info = { .name = TYPE_MACIO, .parent = TYPE_PCI_DEVICE, .instance_size = sizeof(MacIOState), .instance_init = macio_instance_init, + .abstract = true, .class_init = macio_class_init, }; static void macio_register_types(void) { type_register_static(&macio_type_info); + type_register_static(&macio_oldworld_type_info); + type_register_static(&macio_newworld_type_info); } type_init(macio_register_types) -void macio_init (PCIBus *bus, int device_id, int is_oldworld, - MemoryRegion *pic_mem, MemoryRegion *dbdma_mem, - MemoryRegion *cuda_mem, void *nvram, - int nb_ide, MemoryRegion **ide_mem, - MemoryRegion *escc_mem) +void macio_init(PCIDevice *d, + MemoryRegion *pic_mem, MemoryRegion *dbdma_mem, + MemoryRegion *cuda_mem, void *nvram, + int nb_ide, MemoryRegion **ide_mem, + MemoryRegion *escc_mem) { - PCIDevice *d; - MacIOState *macio_state; + MacIOState *macio_state = MACIO(d); int i; - d = pci_create(bus, -1, TYPE_MACIO); - - macio_state = MACIO(d); - macio_state->is_oldworld = is_oldworld; macio_state->pic_mem = pic_mem; macio_state->dbdma_mem = dbdma_mem; macio_state->cuda_mem = cuda_mem; @@ -147,12 +194,8 @@ void macio_init (PCIBus *bus, int device_id, int is_oldworld, macio_state->nb_ide = nb_ide; for (i = 0; i < nb_ide; i++) macio_state->ide_mem[i] = ide_mem[i]; - for (; i < 4; i++) - macio_state->ide_mem[i] = NULL; /* Note: this code is strongly inspirated from the corresponding code in PearPC */ - pci_config_set_device_id(d->config, device_id); - qdev_init_nofail(DEVICE(d)); } diff --git a/hw/ppc/mac.h b/hw/ppc/mac.h index 89c7d6638..864a61086 100644 --- a/hw/ppc/mac.h +++ b/hw/ppc/mac.h @@ -45,10 +45,12 @@ void cuda_init (MemoryRegion **cuda_mem, qemu_irq irq); /* MacIO */ -void macio_init (PCIBus *bus, int device_id, int is_oldworld, - MemoryRegion *pic_mem, MemoryRegion *dbdma_mem, - MemoryRegion *cuda_mem, void *nvram, - int nb_ide, MemoryRegion **ide_mem, MemoryRegion *escc_mem); +#define TYPE_OLDWORLD_MACIO "macio-oldworld" +#define TYPE_NEWWORLD_MACIO "macio-newworld" +void macio_init(PCIDevice *dev, + MemoryRegion *pic_mem, MemoryRegion *dbdma_mem, + MemoryRegion *cuda_mem, void *nvram, + int nb_ide, MemoryRegion **ide_mem, MemoryRegion *escc_mem); /* Heathrow PIC */ qemu_irq *heathrow_pic_init(MemoryRegion **pmem, diff --git a/hw/ppc/mac_newworld.c b/hw/ppc/mac_newworld.c index f3c01bfc5..a62a6e9a3 100644 --- a/hw/ppc/mac_newworld.c +++ b/hw/ppc/mac_newworld.c @@ -147,6 +147,7 @@ static void ppc_core99_init(QEMUMachineInitArgs *args) hwaddr kernel_base, initrd_base, cmdline_base = 0; long kernel_size, initrd_size; PCIBus *pci_bus; + PCIDevice *macio; MacIONVRAMState *nvr; int bios_size; MemoryRegion *pic_mem, *dbdma_mem, *cuda_mem, *escc_mem; @@ -374,7 +375,8 @@ static void ppc_core99_init(QEMUMachineInitArgs *args) adb_kbd_init(&adb_bus); adb_mouse_init(&adb_bus); - macio_init(pci_bus, PCI_DEVICE_ID_APPLE_UNI_N_KEYL, 0, pic_mem, + macio = pci_create(pci_bus, -1, TYPE_NEWWORLD_MACIO); + macio_init(macio, pic_mem, dbdma_mem, cuda_mem, NULL, 3, ide_mem, escc_bar); if (usb_enabled(machine_arch == ARCH_MAC99_U3)) { diff --git a/hw/ppc/mac_oldworld.c b/hw/ppc/mac_oldworld.c index dfbfa546f..2801992b9 100644 --- a/hw/ppc/mac_oldworld.c +++ b/hw/ppc/mac_oldworld.c @@ -90,6 +90,7 @@ static void ppc_heathrow_init(QEMUMachineInitArgs *args) uint32_t kernel_base, initrd_base, cmdline_base = 0; int32_t kernel_size, initrd_size; PCIBus *pci_bus; + PCIDevice *macio; MacIONVRAMState *nvr; int bios_size; MemoryRegion *pic_mem, *dbdma_mem, *cuda_mem; @@ -283,7 +284,8 @@ static void ppc_heathrow_init(QEMUMachineInitArgs *args) nvr = macio_nvram_init(0x2000, 4); pmac_format_nvram_partition(nvr, 0x2000); - macio_init(pci_bus, PCI_DEVICE_ID_APPLE_343S1201, 1, pic_mem, + macio = pci_create(pci_bus, -1, TYPE_OLDWORLD_MACIO); + macio_init(macio, pic_mem, dbdma_mem, cuda_mem, nvr, 2, ide_mem, escc_bar); if (usb_enabled(false)) { From 3743cca7d55c700e727e958d4a0b0b5d6c15e2e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Wed, 23 Jan 2013 23:03:58 +0000 Subject: [PATCH 05/20] mac_nvram: Clean up public API MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The state data field is accessed in uint8_t quantities, so switch from uint32_t argument and return value to uint8_t. Fix debug format specifiers while at it. Signed-off-by: Andreas Färber Signed-off-by: Alexander Graf --- hw/mac_nvram.c | 21 ++++++++++----------- hw/ppc/mac.h | 4 ++-- 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/hw/mac_nvram.c b/hw/mac_nvram.c index eec7ca430..bcde07d06 100644 --- a/hw/mac_nvram.c +++ b/hw/mac_nvram.c @@ -47,27 +47,26 @@ struct MacIONVRAMState { #define DEF_SYSTEM_SIZE 0xc10 /* Direct access to NVRAM */ -uint32_t macio_nvram_read (void *opaque, uint32_t addr) +uint8_t macio_nvram_read(MacIONVRAMState *s, uint32_t addr) { - MacIONVRAMState *s = opaque; uint32_t ret; - if (addr < s->size) + if (addr < s->size) { ret = s->data[addr]; - else + } else { ret = -1; - NVR_DPRINTF("read addr %04x val %x\n", addr, ret); + } + NVR_DPRINTF("read addr %04" PRIx32 " val %" PRIx8 "\n", addr, ret); return ret; } -void macio_nvram_write (void *opaque, uint32_t addr, uint32_t val) +void macio_nvram_write(MacIONVRAMState *s, uint32_t addr, uint8_t val) { - MacIONVRAMState *s = opaque; - - NVR_DPRINTF("write addr %04x val %x\n", addr, val); - if (addr < s->size) + NVR_DPRINTF("write addr %04" PRIx32 " val %" PRIx8 "\n", addr, val); + if (addr < s->size) { s->data[addr] = val; + } } /* macio style NVRAM device */ @@ -78,7 +77,7 @@ static void macio_nvram_writeb(void *opaque, hwaddr addr, addr = (addr >> s->it_shift) & (s->size - 1); s->data[addr] = value; - NVR_DPRINTF("writeb addr %04x val %x\n", (int)addr, value); + NVR_DPRINTF("writeb addr %04" PHYS_PRIx " val %" PRIx64 "\n", addr, value); } static uint64_t macio_nvram_readb(void *opaque, hwaddr addr, diff --git a/hw/ppc/mac.h b/hw/ppc/mac.h index 864a61086..644179460 100644 --- a/hw/ppc/mac.h +++ b/hw/ppc/mac.h @@ -78,6 +78,6 @@ MacIONVRAMState *macio_nvram_init (hwaddr size, void macio_nvram_setup_bar(MacIONVRAMState *s, MemoryRegion *bar, hwaddr mem_base); void pmac_format_nvram_partition (MacIONVRAMState *nvr, int len); -uint32_t macio_nvram_read (void *opaque, uint32_t addr); -void macio_nvram_write (void *opaque, uint32_t addr, uint32_t val); +uint8_t macio_nvram_read(MacIONVRAMState *s, uint32_t addr); +void macio_nvram_write(MacIONVRAMState *s, uint32_t addr, uint8_t val); #endif /* !defined(__PPC_MAC_H__) */ From d8c6d07fdff2523ca78f95c7d8a7fe90ee7ea5a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Wed, 23 Jan 2013 23:03:59 +0000 Subject: [PATCH 06/20] mac_nvram: Mark as Big Endian MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Andreas Färber Signed-off-by: Alexander Graf --- hw/mac_nvram.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/mac_nvram.c b/hw/mac_nvram.c index bcde07d06..0a22e6605 100644 --- a/hw/mac_nvram.c +++ b/hw/mac_nvram.c @@ -96,7 +96,7 @@ static uint64_t macio_nvram_readb(void *opaque, hwaddr addr, static const MemoryRegionOps macio_nvram_ops = { .read = macio_nvram_readb, .write = macio_nvram_writeb, - .endianness = DEVICE_NATIVE_ENDIAN, + .endianness = DEVICE_BIG_ENDIAN, }; static const VMStateDescription vmstate_macio_nvram = { From 95ed3b7cf1677dc9f995a6e1fcc7bf377cf94a0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Wed, 23 Jan 2013 23:04:00 +0000 Subject: [PATCH 07/20] mac_nvram: QOM'ify MacIO NVRAM MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It was not qdev'ified before. Turn it into a SysBusDevice and initialize it via static properties. Prepare Old World specific MacIO state and embed the NVRAM state there. Drop macio_nvram_setup_bar() in favor of sysbus_mmio_map() or direct use of Memory API. Signed-off-by: Andreas Färber Signed-off-by: Alexander Graf --- hw/mac_nvram.c | 65 ++++++++++++++++++++++++++++--------------- hw/macio.c | 41 +++++++++++++++++++++++---- hw/ppc/mac.h | 23 +++++++++++---- hw/ppc/mac_newworld.c | 10 +++++-- hw/ppc/mac_oldworld.c | 6 +--- 5 files changed, 103 insertions(+), 42 deletions(-) diff --git a/hw/mac_nvram.c b/hw/mac_nvram.c index 0a22e6605..25121fa48 100644 --- a/hw/mac_nvram.c +++ b/hw/mac_nvram.c @@ -37,13 +37,6 @@ #define NVR_DPRINTF(fmt, ...) #endif -struct MacIONVRAMState { - uint32_t size; - MemoryRegion mem; - unsigned int it_shift; - uint8_t *data; -}; - #define DEF_SYSTEM_SIZE 0xc10 /* Direct access to NVRAM */ @@ -111,32 +104,56 @@ static const VMStateDescription vmstate_macio_nvram = { }; -static void macio_nvram_reset(void *opaque) +static void macio_nvram_reset(DeviceState *dev) { } -MacIONVRAMState *macio_nvram_init (hwaddr size, - unsigned int it_shift) +static void macio_nvram_realizefn(DeviceState *dev, Error **errp) { - MacIONVRAMState *s; + SysBusDevice *d = SYS_BUS_DEVICE(dev); + MacIONVRAMState *s = MACIO_NVRAM(dev); - s = g_malloc0(sizeof(MacIONVRAMState)); - s->data = g_malloc0(size); - s->size = size; - s->it_shift = it_shift; + s->data = g_malloc0(s->size); memory_region_init_io(&s->mem, &macio_nvram_ops, s, "macio-nvram", - size << it_shift); - vmstate_register(NULL, -1, &vmstate_macio_nvram, s); - qemu_register_reset(macio_nvram_reset, s); - - return s; + s->size << s->it_shift); + sysbus_init_mmio(d, &s->mem); } -void macio_nvram_setup_bar(MacIONVRAMState *s, MemoryRegion *bar, - hwaddr mem_base) +static void macio_nvram_unrealizefn(DeviceState *dev, Error **errp) { - memory_region_add_subregion(bar, mem_base, &s->mem); + MacIONVRAMState *s = MACIO_NVRAM(dev); + + g_free(s->data); +} + +static Property macio_nvram_properties[] = { + DEFINE_PROP_UINT32("size", MacIONVRAMState, size, 0), + DEFINE_PROP_UINT32("it_shift", MacIONVRAMState, it_shift, 0), + DEFINE_PROP_END_OF_LIST() +}; + +static void macio_nvram_class_init(ObjectClass *oc, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(oc); + + dc->realize = macio_nvram_realizefn; + dc->unrealize = macio_nvram_unrealizefn; + dc->reset = macio_nvram_reset; + dc->vmsd = &vmstate_macio_nvram; + dc->props = macio_nvram_properties; +} + +static const TypeInfo macio_nvram_type_info = { + .name = TYPE_MACIO_NVRAM, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(MacIONVRAMState), + .class_init = macio_nvram_class_init, +}; + +static void macio_nvram_register_types(void) +{ + type_register_static(&macio_nvram_type_info); } /* Set up a system OpenBIOS NVRAM partition */ @@ -175,3 +192,5 @@ void pmac_format_nvram_partition (MacIONVRAMState *nvr, int len) end = len; OpenBIOS_finish_partition(part_header, end - start); } + +type_init(macio_nvram_register_types) diff --git a/hw/macio.c b/hw/macio.c index 0e6fc8d5f..32f359cc7 100644 --- a/hw/macio.c +++ b/hw/macio.c @@ -41,11 +41,21 @@ typedef struct MacIOState MemoryRegion *dbdma_mem; MemoryRegion *cuda_mem; MemoryRegion *escc_mem; - void *nvram; int nb_ide; MemoryRegion *ide_mem[4]; } MacIOState; +#define OLDWORLD_MACIO(obj) \ + OBJECT_CHECK(OldWorldMacIOState, (obj), TYPE_OLDWORLD_MACIO) + +typedef struct OldWorldMacIOState { + /*< private >*/ + MacIOState parent_obj; + /*< public >*/ + + MacIONVRAMState nvram; +} OldWorldMacIOState; + static void macio_bar_setup(MacIOState *macio_state) { int i; @@ -66,8 +76,6 @@ static void macio_bar_setup(MacIOState *macio_state) macio_state->ide_mem[i]); } } - if (macio_state->nvram != NULL) - macio_nvram_setup_bar(macio_state->nvram, bar, 0x60000); } static int macio_common_initfn(PCIDevice *d) @@ -85,11 +93,22 @@ static int macio_common_initfn(PCIDevice *d) static int macio_oldworld_initfn(PCIDevice *d) { MacIOState *s = MACIO(d); + OldWorldMacIOState *os = OLDWORLD_MACIO(d); + SysBusDevice *sysbus_dev; int ret = macio_common_initfn(d); if (ret < 0) { return ret; } + ret = qdev_init(DEVICE(&os->nvram)); + if (ret < 0) { + return ret; + } + sysbus_dev = SYS_BUS_DEVICE(&os->nvram); + memory_region_add_subregion(&s->bar, 0x60000, + sysbus_mmio_get_region(sysbus_dev, 0)); + pmac_format_nvram_partition(&os->nvram, os->nvram.size); + if (s->pic_mem) { /* Heathrow PIC */ memory_region_add_subregion(&s->bar, 0x00000, s->pic_mem); @@ -98,6 +117,17 @@ static int macio_oldworld_initfn(PCIDevice *d) return 0; } +static void macio_oldworld_init(Object *obj) +{ + OldWorldMacIOState *os = OLDWORLD_MACIO(obj); + DeviceState *dev; + + object_initialize(&os->nvram, TYPE_MACIO_NVRAM); + dev = DEVICE(&os->nvram); + qdev_prop_set_uint32(dev, "size", 0x2000); + qdev_prop_set_uint32(dev, "it_shift", 4); +} + static int macio_newworld_initfn(PCIDevice *d) { MacIOState *s = MACIO(d); @@ -148,6 +178,8 @@ static void macio_class_init(ObjectClass *klass, void *data) static const TypeInfo macio_oldworld_type_info = { .name = TYPE_OLDWORLD_MACIO, .parent = TYPE_MACIO, + .instance_size = sizeof(OldWorldMacIOState), + .instance_init = macio_oldworld_init, .class_init = macio_oldworld_class_init, }; @@ -177,7 +209,7 @@ type_init(macio_register_types) void macio_init(PCIDevice *d, MemoryRegion *pic_mem, MemoryRegion *dbdma_mem, - MemoryRegion *cuda_mem, void *nvram, + MemoryRegion *cuda_mem, int nb_ide, MemoryRegion **ide_mem, MemoryRegion *escc_mem) { @@ -188,7 +220,6 @@ void macio_init(PCIDevice *d, macio_state->dbdma_mem = dbdma_mem; macio_state->cuda_mem = cuda_mem; macio_state->escc_mem = escc_mem; - macio_state->nvram = nvram; if (nb_ide > 4) nb_ide = 4; macio_state->nb_ide = nb_ide; diff --git a/hw/ppc/mac.h b/hw/ppc/mac.h index 644179460..581e95cf7 100644 --- a/hw/ppc/mac.h +++ b/hw/ppc/mac.h @@ -26,6 +26,7 @@ #define __PPC_MAC_H__ #include "exec/memory.h" +#include "hw/sysbus.h" /* SMP is not enabled, for now */ #define MAX_CPUS 1 @@ -49,7 +50,7 @@ void cuda_init (MemoryRegion **cuda_mem, qemu_irq irq); #define TYPE_NEWWORLD_MACIO "macio-newworld" void macio_init(PCIDevice *dev, MemoryRegion *pic_mem, MemoryRegion *dbdma_mem, - MemoryRegion *cuda_mem, void *nvram, + MemoryRegion *cuda_mem, int nb_ide, MemoryRegion **ide_mem, MemoryRegion *escc_mem); /* Heathrow PIC */ @@ -71,12 +72,22 @@ PCIBus *pci_pmac_u3_init(qemu_irq *pic, MemoryRegion *address_space_io); /* Mac NVRAM */ -typedef struct MacIONVRAMState MacIONVRAMState; +#define TYPE_MACIO_NVRAM "macio-nvram" +#define MACIO_NVRAM(obj) \ + OBJECT_CHECK(MacIONVRAMState, (obj), TYPE_MACIO_NVRAM) + +typedef struct MacIONVRAMState { + /*< private >*/ + SysBusDevice parent_obj; + /*< public >*/ + + uint32_t size; + uint32_t it_shift; + + MemoryRegion mem; + uint8_t *data; +} MacIONVRAMState; -MacIONVRAMState *macio_nvram_init (hwaddr size, - unsigned int it_shift); -void macio_nvram_setup_bar(MacIONVRAMState *s, MemoryRegion *bar, - hwaddr mem_base); void pmac_format_nvram_partition (MacIONVRAMState *nvr, int len); uint8_t macio_nvram_read(MacIONVRAMState *s, uint32_t addr); void macio_nvram_write(MacIONVRAMState *s, uint32_t addr, uint8_t val); diff --git a/hw/ppc/mac_newworld.c b/hw/ppc/mac_newworld.c index a62a6e9a3..a4b38fba1 100644 --- a/hw/ppc/mac_newworld.c +++ b/hw/ppc/mac_newworld.c @@ -377,7 +377,7 @@ static void ppc_core99_init(QEMUMachineInitArgs *args) macio = pci_create(pci_bus, -1, TYPE_NEWWORLD_MACIO); macio_init(macio, pic_mem, - dbdma_mem, cuda_mem, NULL, 3, ide_mem, escc_bar); + dbdma_mem, cuda_mem, 3, ide_mem, escc_bar); if (usb_enabled(machine_arch == ARCH_MAC99_U3)) { pci_create_simple(pci_bus, -1, "pci-ohci"); @@ -393,9 +393,13 @@ static void ppc_core99_init(QEMUMachineInitArgs *args) graphic_depth = 15; /* The NewWorld NVRAM is not located in the MacIO device */ - nvr = macio_nvram_init(0x2000, 1); + dev = qdev_create(NULL, TYPE_MACIO_NVRAM); + qdev_prop_set_uint32(dev, "size", 0x2000); + qdev_prop_set_uint32(dev, "it_shift", 1); + qdev_init_nofail(dev); + sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0xFFF04000); + nvr = MACIO_NVRAM(dev); pmac_format_nvram_partition(nvr, 0x2000); - macio_nvram_setup_bar(nvr, get_system_memory(), 0xFFF04000); /* No PCI init: the BIOS will do it */ fw_cfg = fw_cfg_init(0, 0, CFG_ADDR, CFG_ADDR + 2); diff --git a/hw/ppc/mac_oldworld.c b/hw/ppc/mac_oldworld.c index 2801992b9..29b3277df 100644 --- a/hw/ppc/mac_oldworld.c +++ b/hw/ppc/mac_oldworld.c @@ -91,7 +91,6 @@ static void ppc_heathrow_init(QEMUMachineInitArgs *args) int32_t kernel_size, initrd_size; PCIBus *pci_bus; PCIDevice *macio; - MacIONVRAMState *nvr; int bios_size; MemoryRegion *pic_mem, *dbdma_mem, *cuda_mem; MemoryRegion *escc_mem, *escc_bar = g_new(MemoryRegion, 1), *ide_mem[2]; @@ -281,12 +280,9 @@ static void ppc_heathrow_init(QEMUMachineInitArgs *args) adb_kbd_init(&adb_bus); adb_mouse_init(&adb_bus); - nvr = macio_nvram_init(0x2000, 4); - pmac_format_nvram_partition(nvr, 0x2000); - macio = pci_create(pci_bus, -1, TYPE_OLDWORLD_MACIO); macio_init(macio, pic_mem, - dbdma_mem, cuda_mem, nvr, 2, ide_mem, escc_bar); + dbdma_mem, cuda_mem, 2, ide_mem, escc_bar); if (usb_enabled(false)) { pci_create_simple(pci_bus, -1, "pci-ohci"); From 07a7484e5d713f1eb7c1c37b18a8ab0d56d88875 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Wed, 23 Jan 2013 23:04:01 +0000 Subject: [PATCH 08/20] ide/macio: QOM'ify MacIO IDE MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It was not qdev'ified before. Turn it into a SysBusDevice. Embed them into the MacIO devices. Signed-off-by: Andreas Färber Signed-off-by: Alexander Graf --- hw/ide.h | 4 -- hw/ide/macio.c | 84 +++++++++++++++++++++++----------- hw/macio.c | 102 +++++++++++++++++++++++++++++++++--------- hw/ppc/mac.h | 25 ++++++++++- hw/ppc/mac_newworld.c | 28 +++++++----- hw/ppc/mac_oldworld.c | 36 ++++++++------- 6 files changed, 198 insertions(+), 81 deletions(-) diff --git a/hw/ide.h b/hw/ide.h index 7e23cda8e..9b357c05a 100644 --- a/hw/ide.h +++ b/hw/ide.h @@ -19,10 +19,6 @@ PCIDevice *pci_piix3_ide_init(PCIBus *bus, DriveInfo **hd_table, int devfn); PCIDevice *pci_piix4_ide_init(PCIBus *bus, DriveInfo **hd_table, int devfn); void vt82c686b_ide_init(PCIBus *bus, DriveInfo **hd_table, int devfn); -/* ide-macio.c */ -MemoryRegion *pmac_ide_init (DriveInfo **hd_table, qemu_irq irq, - void *dbdma, int channel, qemu_irq dma_irq); - /* ide-mmio.c */ void mmio_ide_init (hwaddr membase, hwaddr membase2, MemoryRegion *address_space, diff --git a/hw/ide/macio.c b/hw/ide/macio.c index e0f04dc33..375c46f9d 100644 --- a/hw/ide/macio.c +++ b/hw/ide/macio.c @@ -33,12 +33,6 @@ /***********************************************************/ /* MacIO based PowerPC IDE */ -typedef struct MACIOIDEState { - MemoryRegion mem; - IDEBus bus; - BlockDriverAIOCB *aiocb; -} MACIOIDEState; - #define MACIO_PAGE_SIZE 4096 static void pmac_ide_atapi_transfer_cb(void *opaque, int ret) @@ -321,30 +315,70 @@ static const VMStateDescription vmstate_pmac = { } }; -static void pmac_ide_reset(void *opaque) +static void macio_ide_reset(DeviceState *dev) { - MACIOIDEState *d = opaque; + MACIOIDEState *d = MACIO_IDE(dev); ide_bus_reset(&d->bus); } -/* hd_table must contain 4 block drivers */ -/* PowerMac uses memory mapped registers, not I/O. Return the memory - I/O index to access the ide. */ -MemoryRegion *pmac_ide_init (DriveInfo **hd_table, qemu_irq irq, - void *dbdma, int channel, qemu_irq dma_irq) +static void macio_ide_realizefn(DeviceState *dev, Error **errp) { - MACIOIDEState *d; + MACIOIDEState *s = MACIO_IDE(dev); - d = g_malloc0(sizeof(MACIOIDEState)); - ide_init2_with_non_qdev_drives(&d->bus, hd_table[0], hd_table[1], irq); - - if (dbdma) - DBDMA_register_channel(dbdma, channel, dma_irq, pmac_ide_transfer, pmac_ide_flush, d); - - memory_region_init_io(&d->mem, &pmac_ide_ops, d, "pmac-ide", 0x1000); - vmstate_register(NULL, 0, &vmstate_pmac, d); - qemu_register_reset(pmac_ide_reset, d); - - return &d->mem; + ide_init2(&s->bus, s->irq); } + +static void macio_ide_initfn(Object *obj) +{ + SysBusDevice *d = SYS_BUS_DEVICE(obj); + MACIOIDEState *s = MACIO_IDE(obj); + + ide_bus_new(&s->bus, DEVICE(obj), 0); + memory_region_init_io(&s->mem, &pmac_ide_ops, s, "pmac-ide", 0x1000); + sysbus_init_mmio(d, &s->mem); + sysbus_init_irq(d, &s->irq); + sysbus_init_irq(d, &s->dma_irq); +} + +static void macio_ide_class_init(ObjectClass *oc, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(oc); + + dc->realize = macio_ide_realizefn; + dc->reset = macio_ide_reset; + dc->vmsd = &vmstate_pmac; +} + +static const TypeInfo macio_ide_type_info = { + .name = TYPE_MACIO_IDE, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(MACIOIDEState), + .instance_init = macio_ide_initfn, + .class_init = macio_ide_class_init, +}; + +static void macio_ide_register_types(void) +{ + type_register_static(&macio_ide_type_info); +} + +/* hd_table must contain 4 block drivers */ +void macio_ide_init_drives(MACIOIDEState *s, DriveInfo **hd_table) +{ + int i; + + for (i = 0; i < 2; i++) { + if (hd_table[i]) { + ide_create_drive(&s->bus, i, hd_table[i]); + } + } +} + +void macio_ide_register_dma(MACIOIDEState *s, void *dbdma, int channel) +{ + DBDMA_register_channel(dbdma, channel, s->dma_irq, + pmac_ide_transfer, pmac_ide_flush, s); +} + +type_init(macio_ide_register_types) diff --git a/hw/macio.c b/hw/macio.c index 32f359cc7..36c00e33a 100644 --- a/hw/macio.c +++ b/hw/macio.c @@ -25,6 +25,7 @@ #include "hw.h" #include "ppc/mac.h" #include "pci/pci.h" +#include "mac_dbdma.h" #include "escc.h" #define TYPE_MACIO "macio" @@ -37,12 +38,10 @@ typedef struct MacIOState /*< public >*/ MemoryRegion bar; + void *dbdma; MemoryRegion *pic_mem; - MemoryRegion *dbdma_mem; MemoryRegion *cuda_mem; MemoryRegion *escc_mem; - int nb_ide; - MemoryRegion *ide_mem[4]; } MacIOState; #define OLDWORLD_MACIO(obj) \ @@ -53,29 +52,33 @@ typedef struct OldWorldMacIOState { MacIOState parent_obj; /*< public >*/ + qemu_irq irqs[2]; + MacIONVRAMState nvram; + MACIOIDEState ide; } OldWorldMacIOState; +#define NEWWORLD_MACIO(obj) \ + OBJECT_CHECK(NewWorldMacIOState, (obj), TYPE_NEWWORLD_MACIO) + +typedef struct NewWorldMacIOState { + /*< private >*/ + MacIOState parent_obj; + /*< public >*/ + qemu_irq irqs[4]; + MACIOIDEState ide[2]; +} NewWorldMacIOState; + static void macio_bar_setup(MacIOState *macio_state) { - int i; MemoryRegion *bar = &macio_state->bar; - if (macio_state->dbdma_mem) { - memory_region_add_subregion(bar, 0x08000, macio_state->dbdma_mem); - } if (macio_state->escc_mem) { memory_region_add_subregion(bar, 0x13000, macio_state->escc_mem); } if (macio_state->cuda_mem) { memory_region_add_subregion(bar, 0x16000, macio_state->cuda_mem); } - for (i = 0; i < macio_state->nb_ide; i++) { - if (macio_state->ide_mem[i]) { - memory_region_add_subregion(bar, 0x1f000 + (i * 0x1000), - macio_state->ide_mem[i]); - } - } } static int macio_common_initfn(PCIDevice *d) @@ -114,23 +117,42 @@ static int macio_oldworld_initfn(PCIDevice *d) memory_region_add_subregion(&s->bar, 0x00000, s->pic_mem); } + sysbus_dev = SYS_BUS_DEVICE(&os->ide); + sysbus_connect_irq(sysbus_dev, 0, os->irqs[0]); + sysbus_connect_irq(sysbus_dev, 1, os->irqs[1]); + macio_ide_register_dma(&os->ide, s->dbdma, 0x16); + ret = qdev_init(DEVICE(&os->ide)); + if (ret < 0) { + return ret; + } + return 0; } static void macio_oldworld_init(Object *obj) { + MacIOState *s = MACIO(obj); OldWorldMacIOState *os = OLDWORLD_MACIO(obj); DeviceState *dev; + qdev_init_gpio_out(DEVICE(obj), os->irqs, ARRAY_SIZE(os->irqs)); + object_initialize(&os->nvram, TYPE_MACIO_NVRAM); dev = DEVICE(&os->nvram); qdev_prop_set_uint32(dev, "size", 0x2000); qdev_prop_set_uint32(dev, "it_shift", 4); + + object_initialize(&os->ide, TYPE_MACIO_IDE); + qdev_set_parent_bus(DEVICE(&os->ide), sysbus_get_default()); + memory_region_add_subregion(&s->bar, 0x1f000 + (1 * 0x1000), &os->ide.mem); + object_property_add_child(obj, "ide", OBJECT(&os->ide), NULL); } static int macio_newworld_initfn(PCIDevice *d) { MacIOState *s = MACIO(d); + NewWorldMacIOState *ns = NEWWORLD_MACIO(d); + SysBusDevice *sysbus_dev; int ret = macio_common_initfn(d); if (ret < 0) { return ret; @@ -141,14 +163,56 @@ static int macio_newworld_initfn(PCIDevice *d) memory_region_add_subregion(&s->bar, 0x40000, s->pic_mem); } + sysbus_dev = SYS_BUS_DEVICE(&ns->ide[0]); + sysbus_connect_irq(sysbus_dev, 0, ns->irqs[0]); + sysbus_connect_irq(sysbus_dev, 1, ns->irqs[1]); + macio_ide_register_dma(&ns->ide[0], s->dbdma, 0x16); + ret = qdev_init(DEVICE(&ns->ide[0])); + if (ret < 0) { + return ret; + } + + sysbus_dev = SYS_BUS_DEVICE(&ns->ide[1]); + sysbus_connect_irq(sysbus_dev, 0, ns->irqs[2]); + sysbus_connect_irq(sysbus_dev, 1, ns->irqs[3]); + macio_ide_register_dma(&ns->ide[0], s->dbdma, 0x1a); + ret = qdev_init(DEVICE(&ns->ide[1])); + if (ret < 0) { + return ret; + } + return 0; } +static void macio_newworld_init(Object *obj) +{ + MacIOState *s = MACIO(obj); + NewWorldMacIOState *ns = NEWWORLD_MACIO(obj); + int i; + gchar *name; + + qdev_init_gpio_out(DEVICE(obj), ns->irqs, ARRAY_SIZE(ns->irqs)); + + for (i = 0; i < 2; i++) { + object_initialize(&ns->ide[i], TYPE_MACIO_IDE); + qdev_set_parent_bus(DEVICE(&ns->ide[i]), sysbus_get_default()); + memory_region_add_subregion(&s->bar, 0x1f000 + ((i + 1) * 0x1000), + &ns->ide[i].mem); + name = g_strdup_printf("ide[%i]", i); + object_property_add_child(obj, name, OBJECT(&ns->ide[i]), NULL); + g_free(name); + } +} + static void macio_instance_init(Object *obj) { MacIOState *s = MACIO(obj); + MemoryRegion *dbdma_mem; memory_region_init(&s->bar, "macio", 0x80000); + + s->dbdma = DBDMA_init(&dbdma_mem); + memory_region_add_subregion(&s->bar, 0x08000, dbdma_mem); } static void macio_oldworld_class_init(ObjectClass *oc, void *data) @@ -186,6 +250,8 @@ static const TypeInfo macio_oldworld_type_info = { static const TypeInfo macio_newworld_type_info = { .name = TYPE_NEWWORLD_MACIO, .parent = TYPE_MACIO, + .instance_size = sizeof(NewWorldMacIOState), + .instance_init = macio_newworld_init, .class_init = macio_newworld_class_init, }; @@ -208,23 +274,15 @@ static void macio_register_types(void) type_init(macio_register_types) void macio_init(PCIDevice *d, - MemoryRegion *pic_mem, MemoryRegion *dbdma_mem, + MemoryRegion *pic_mem, MemoryRegion *cuda_mem, - int nb_ide, MemoryRegion **ide_mem, MemoryRegion *escc_mem) { MacIOState *macio_state = MACIO(d); - int i; macio_state->pic_mem = pic_mem; - macio_state->dbdma_mem = dbdma_mem; macio_state->cuda_mem = cuda_mem; macio_state->escc_mem = escc_mem; - if (nb_ide > 4) - nb_ide = 4; - macio_state->nb_ide = nb_ide; - for (i = 0; i < nb_ide; i++) - macio_state->ide_mem[i] = ide_mem[i]; /* Note: this code is strongly inspirated from the corresponding code in PearPC */ diff --git a/hw/ppc/mac.h b/hw/ppc/mac.h index 581e95cf7..3e390d3ee 100644 --- a/hw/ppc/mac.h +++ b/hw/ppc/mac.h @@ -27,6 +27,7 @@ #include "exec/memory.h" #include "hw/sysbus.h" +#include "hw/ide/internal.h" /* SMP is not enabled, for now */ #define MAX_CPUS 1 @@ -48,10 +49,30 @@ void cuda_init (MemoryRegion **cuda_mem, qemu_irq irq); /* MacIO */ #define TYPE_OLDWORLD_MACIO "macio-oldworld" #define TYPE_NEWWORLD_MACIO "macio-newworld" + +#define TYPE_MACIO_IDE "macio-ide" +#define MACIO_IDE(obj) OBJECT_CHECK(MACIOIDEState, (obj), TYPE_MACIO_IDE) + +typedef struct MACIOIDEState { + /*< private >*/ + SysBusDevice parent_obj; + /*< public >*/ + + qemu_irq irq; + qemu_irq dma_irq; + + MemoryRegion mem; + IDEBus bus; + BlockDriverAIOCB *aiocb; +} MACIOIDEState; + +void macio_ide_init_drives(MACIOIDEState *ide, DriveInfo **hd_table); +void macio_ide_register_dma(MACIOIDEState *ide, void *dbdma, int channel); + void macio_init(PCIDevice *dev, - MemoryRegion *pic_mem, MemoryRegion *dbdma_mem, + MemoryRegion *pic_mem, MemoryRegion *cuda_mem, - int nb_ide, MemoryRegion **ide_mem, MemoryRegion *escc_mem); + MemoryRegion *escc_mem); /* Heathrow PIC */ qemu_irq *heathrow_pic_init(MemoryRegion **pmem, diff --git a/hw/ppc/mac_newworld.c b/hw/ppc/mac_newworld.c index a4b38fba1..4fd86b042 100644 --- a/hw/ppc/mac_newworld.c +++ b/hw/ppc/mac_newworld.c @@ -148,15 +148,14 @@ static void ppc_core99_init(QEMUMachineInitArgs *args) long kernel_size, initrd_size; PCIBus *pci_bus; PCIDevice *macio; + MACIOIDEState *macio_ide; MacIONVRAMState *nvr; int bios_size; - MemoryRegion *pic_mem, *dbdma_mem, *cuda_mem, *escc_mem; + MemoryRegion *pic_mem, *cuda_mem, *escc_mem; MemoryRegion *escc_bar = g_new(MemoryRegion, 1); - MemoryRegion *ide_mem[3]; int ppc_boot_device; DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS]; void *fw_cfg; - void *dbdma; int machine_arch; SysBusDevice *s; DeviceState *dev; @@ -363,12 +362,6 @@ static void ppc_core99_init(QEMUMachineInitArgs *args) pci_nic_init_nofail(&nd_table[i], "ne2k_pci", NULL); ide_drive_get(hd, MAX_IDE_BUS); - dbdma = DBDMA_init(&dbdma_mem); - - /* We only emulate 2 out of 3 IDE controllers for now */ - ide_mem[0] = NULL; - ide_mem[1] = pmac_ide_init(hd, pic[0x0d], dbdma, 0x16, pic[0x02]); - ide_mem[2] = pmac_ide_init(&hd[MAX_IDE_DEVS], pic[0x0e], dbdma, 0x1a, pic[0x02]); cuda_init(&cuda_mem, pic[0x19]); @@ -376,8 +369,21 @@ static void ppc_core99_init(QEMUMachineInitArgs *args) adb_mouse_init(&adb_bus); macio = pci_create(pci_bus, -1, TYPE_NEWWORLD_MACIO); - macio_init(macio, pic_mem, - dbdma_mem, cuda_mem, 3, ide_mem, escc_bar); + dev = DEVICE(macio); + qdev_connect_gpio_out(dev, 0, pic[0x0d]); /* IDE */ + qdev_connect_gpio_out(dev, 1, pic[0x02]); /* IDE DMA */ + qdev_connect_gpio_out(dev, 2, pic[0x0e]); /* IDE */ + qdev_connect_gpio_out(dev, 3, pic[0x02]); /* IDE DMA */ + macio_init(macio, pic_mem, cuda_mem, escc_bar); + + /* We only emulate 2 out of 3 IDE controllers for now */ + macio_ide = MACIO_IDE(object_resolve_path_component(OBJECT(macio), + "ide[0]")); + macio_ide_init_drives(macio_ide, hd); + + macio_ide = MACIO_IDE(object_resolve_path_component(OBJECT(macio), + "ide[1]")); + macio_ide_init_drives(macio_ide, &hd[MAX_IDE_DEVS]); if (usb_enabled(machine_arch == ARCH_MAC99_U3)) { pci_create_simple(pci_bus, -1, "pci-ohci"); diff --git a/hw/ppc/mac_oldworld.c b/hw/ppc/mac_oldworld.c index 29b3277df..6039ea61f 100644 --- a/hw/ppc/mac_oldworld.c +++ b/hw/ppc/mac_oldworld.c @@ -27,7 +27,6 @@ #include "hw/ppc.h" #include "mac.h" #include "hw/adb.h" -#include "hw/mac_dbdma.h" #include "hw/nvram.h" #include "sysemu/sysemu.h" #include "net/net.h" @@ -91,13 +90,14 @@ static void ppc_heathrow_init(QEMUMachineInitArgs *args) int32_t kernel_size, initrd_size; PCIBus *pci_bus; PCIDevice *macio; + MACIOIDEState *macio_ide; + DeviceState *dev; int bios_size; - MemoryRegion *pic_mem, *dbdma_mem, *cuda_mem; - MemoryRegion *escc_mem, *escc_bar = g_new(MemoryRegion, 1), *ide_mem[2]; + MemoryRegion *pic_mem, *cuda_mem; + MemoryRegion *escc_mem, *escc_bar = g_new(MemoryRegion, 1); uint16_t ppc_boot_device; DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS]; void *fw_cfg; - void *dbdma; linux_boot = (kernel_filename != NULL); @@ -263,17 +263,6 @@ static void ppc_heathrow_init(QEMUMachineInitArgs *args) ide_drive_get(hd, MAX_IDE_BUS); - /* First IDE channel is a MAC IDE on the MacIO bus */ - dbdma = DBDMA_init(&dbdma_mem); - ide_mem[0] = NULL; - ide_mem[1] = pmac_ide_init(hd, pic[0x0D], dbdma, 0x16, pic[0x02]); - - /* Second IDE channel is a CMD646 on the PCI bus */ - hd[0] = hd[MAX_IDE_DEVS]; - hd[1] = hd[MAX_IDE_DEVS + 1]; - hd[3] = hd[2] = NULL; - pci_cmd646_ide_init(pci_bus, hd, 0); - /* cuda also initialize ADB */ cuda_init(&cuda_mem, pic[0x12]); @@ -281,8 +270,21 @@ static void ppc_heathrow_init(QEMUMachineInitArgs *args) adb_mouse_init(&adb_bus); macio = pci_create(pci_bus, -1, TYPE_OLDWORLD_MACIO); - macio_init(macio, pic_mem, - dbdma_mem, cuda_mem, 2, ide_mem, escc_bar); + dev = DEVICE(macio); + qdev_connect_gpio_out(dev, 0, pic[0x0D]); /* IDE */ + qdev_connect_gpio_out(dev, 1, pic[0x02]); /* IDE DMA */ + macio_init(macio, pic_mem, cuda_mem, escc_bar); + + /* First IDE channel is a MAC IDE on the MacIO bus */ + macio_ide = MACIO_IDE(object_resolve_path_component(OBJECT(macio), + "ide")); + macio_ide_init_drives(macio_ide, hd); + + /* Second IDE channel is a CMD646 on the PCI bus */ + hd[0] = hd[MAX_IDE_DEVS]; + hd[1] = hd[MAX_IDE_DEVS + 1]; + hd[3] = hd[2] = NULL; + pci_cmd646_ide_init(pci_bus, hd, 0); if (usb_enabled(false)) { pci_create_simple(pci_bus, -1, "pci-ohci"); From 45fa67fb68e73b395cd93ec97e45785944d4ee6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Wed, 23 Jan 2013 23:04:02 +0000 Subject: [PATCH 09/20] cuda: QOM'ify CUDA MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It was not qdev'ified before. Turn it into a SysBusDevice and embed it in MacIO. Signed-off-by: Andreas Färber Signed-off-by: Alexander Graf --- hw/cuda.c | 99 +++++++++++++++++++------------------------ hw/macio.c | 43 +++++++++++++------ hw/ppc/mac.h | 68 ++++++++++++++++++++++++++++- hw/ppc/mac_newworld.c | 21 +++++---- hw/ppc/mac_oldworld.c | 18 ++++---- 5 files changed, 156 insertions(+), 93 deletions(-) diff --git a/hw/cuda.c b/hw/cuda.c index bbd1fdaab..f863c38a8 100644 --- a/hw/cuda.c +++ b/hw/cuda.c @@ -108,48 +108,6 @@ /* CUDA returns time_t's offset from Jan 1, 1904, not 1970 */ #define RTC_OFFSET 2082844800 -typedef struct CUDATimer { - int index; - uint16_t latch; - uint16_t counter_value; /* counter value at load time */ - int64_t load_time; - int64_t next_irq_time; - QEMUTimer *timer; -} CUDATimer; - -typedef struct CUDAState { - MemoryRegion mem; - /* cuda registers */ - uint8_t b; /* B-side data */ - uint8_t a; /* A-side data */ - uint8_t dirb; /* B-side direction (1=output) */ - uint8_t dira; /* A-side direction (1=output) */ - uint8_t sr; /* Shift register */ - uint8_t acr; /* Auxiliary control register */ - uint8_t pcr; /* Peripheral control register */ - uint8_t ifr; /* Interrupt flag register */ - uint8_t ier; /* Interrupt enable register */ - uint8_t anh; /* A-side data, no handshake */ - - CUDATimer timers[2]; - - uint32_t tick_offset; - - uint8_t last_b; /* last value of B register */ - uint8_t last_acr; /* last value of B register */ - - int data_in_size; - int data_in_index; - int data_out_index; - - qemu_irq irq; - uint8_t autopoll; - uint8_t data_in[128]; - uint8_t data_out[16]; - QEMUTimer *adb_poll_timer; -} CUDAState; - -static CUDAState cuda_state; ADBBusState adb_bus; static void cuda_update(CUDAState *s); @@ -701,9 +659,9 @@ static const VMStateDescription vmstate_cuda = { } }; -static void cuda_reset(void *opaque) +static void cuda_reset(DeviceState *dev) { - CUDAState *s = opaque; + CUDAState *s = CUDA(dev); s->b = 0; s->a = 0; @@ -728,25 +686,54 @@ static void cuda_reset(void *opaque) set_counter(s, &s->timers[1], 0xffff); } -void cuda_init (MemoryRegion **cuda_mem, qemu_irq irq) +static void cuda_realizefn(DeviceState *dev, Error **errp) { + CUDAState *s = CUDA(dev); struct tm tm; - CUDAState *s = &cuda_state; - s->irq = irq; - - s->timers[0].index = 0; s->timers[0].timer = qemu_new_timer_ns(vm_clock, cuda_timer1, s); - s->timers[1].index = 1; - qemu_get_timedate(&tm, 0); s->tick_offset = (uint32_t)mktimegm(&tm) + RTC_OFFSET; s->adb_poll_timer = qemu_new_timer_ns(vm_clock, cuda_adb_poll, s); - memory_region_init_io(&s->mem, &cuda_ops, s, "cuda", 0x2000); - - *cuda_mem = &s->mem; - vmstate_register(NULL, -1, &vmstate_cuda, s); - qemu_register_reset(cuda_reset, s); } + +static void cuda_initfn(Object *obj) +{ + SysBusDevice *d = SYS_BUS_DEVICE(obj); + CUDAState *s = CUDA(obj); + int i; + + memory_region_init_io(&s->mem, &cuda_ops, s, "cuda", 0x2000); + sysbus_init_mmio(d, &s->mem); + sysbus_init_irq(d, &s->irq); + + for (i = 0; i < ARRAY_SIZE(s->timers); i++) { + s->timers[i].index = i; + } +} + +static void cuda_class_init(ObjectClass *oc, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(oc); + + dc->realize = cuda_realizefn; + dc->reset = cuda_reset; + dc->vmsd = &vmstate_cuda; +} + +static const TypeInfo cuda_type_info = { + .name = TYPE_CUDA, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(CUDAState), + .instance_init = cuda_initfn, + .class_init = cuda_class_init, +}; + +static void cuda_register_types(void) +{ + type_register_static(&cuda_type_info); +} + +type_init(cuda_register_types) diff --git a/hw/macio.c b/hw/macio.c index 36c00e33a..74bdcd103 100644 --- a/hw/macio.c +++ b/hw/macio.c @@ -38,9 +38,9 @@ typedef struct MacIOState /*< public >*/ MemoryRegion bar; + CUDAState cuda; void *dbdma; MemoryRegion *pic_mem; - MemoryRegion *cuda_mem; MemoryRegion *escc_mem; } MacIOState; @@ -52,7 +52,7 @@ typedef struct OldWorldMacIOState { MacIOState parent_obj; /*< public >*/ - qemu_irq irqs[2]; + qemu_irq irqs[3]; MacIONVRAMState nvram; MACIOIDEState ide; @@ -65,7 +65,7 @@ typedef struct NewWorldMacIOState { /*< private >*/ MacIOState parent_obj; /*< public >*/ - qemu_irq irqs[4]; + qemu_irq irqs[5]; MACIOIDEState ide[2]; } NewWorldMacIOState; @@ -76,17 +76,24 @@ static void macio_bar_setup(MacIOState *macio_state) if (macio_state->escc_mem) { memory_region_add_subregion(bar, 0x13000, macio_state->escc_mem); } - if (macio_state->cuda_mem) { - memory_region_add_subregion(bar, 0x16000, macio_state->cuda_mem); - } } static int macio_common_initfn(PCIDevice *d) { MacIOState *s = MACIO(d); + SysBusDevice *sysbus_dev; + int ret; d->config[0x3d] = 0x01; // interrupt on pin 1 + ret = qdev_init(DEVICE(&s->cuda)); + if (ret < 0) { + return ret; + } + sysbus_dev = SYS_BUS_DEVICE(&s->cuda); + memory_region_add_subregion(&s->bar, 0x16000, + sysbus_mmio_get_region(sysbus_dev, 0)); + macio_bar_setup(s); pci_register_bar(d, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->bar); @@ -103,6 +110,9 @@ static int macio_oldworld_initfn(PCIDevice *d) return ret; } + sysbus_dev = SYS_BUS_DEVICE(&s->cuda); + sysbus_connect_irq(sysbus_dev, 0, os->irqs[0]); + ret = qdev_init(DEVICE(&os->nvram)); if (ret < 0) { return ret; @@ -118,8 +128,8 @@ static int macio_oldworld_initfn(PCIDevice *d) } sysbus_dev = SYS_BUS_DEVICE(&os->ide); - sysbus_connect_irq(sysbus_dev, 0, os->irqs[0]); - sysbus_connect_irq(sysbus_dev, 1, os->irqs[1]); + sysbus_connect_irq(sysbus_dev, 0, os->irqs[1]); + sysbus_connect_irq(sysbus_dev, 1, os->irqs[2]); macio_ide_register_dma(&os->ide, s->dbdma, 0x16); ret = qdev_init(DEVICE(&os->ide)); if (ret < 0) { @@ -158,14 +168,17 @@ static int macio_newworld_initfn(PCIDevice *d) return ret; } + sysbus_dev = SYS_BUS_DEVICE(&s->cuda); + sysbus_connect_irq(sysbus_dev, 0, ns->irqs[0]); + if (s->pic_mem) { /* OpenPIC */ memory_region_add_subregion(&s->bar, 0x40000, s->pic_mem); } sysbus_dev = SYS_BUS_DEVICE(&ns->ide[0]); - sysbus_connect_irq(sysbus_dev, 0, ns->irqs[0]); - sysbus_connect_irq(sysbus_dev, 1, ns->irqs[1]); + sysbus_connect_irq(sysbus_dev, 0, ns->irqs[1]); + sysbus_connect_irq(sysbus_dev, 1, ns->irqs[2]); macio_ide_register_dma(&ns->ide[0], s->dbdma, 0x16); ret = qdev_init(DEVICE(&ns->ide[0])); if (ret < 0) { @@ -173,8 +186,8 @@ static int macio_newworld_initfn(PCIDevice *d) } sysbus_dev = SYS_BUS_DEVICE(&ns->ide[1]); - sysbus_connect_irq(sysbus_dev, 0, ns->irqs[2]); - sysbus_connect_irq(sysbus_dev, 1, ns->irqs[3]); + sysbus_connect_irq(sysbus_dev, 0, ns->irqs[3]); + sysbus_connect_irq(sysbus_dev, 1, ns->irqs[4]); macio_ide_register_dma(&ns->ide[0], s->dbdma, 0x1a); ret = qdev_init(DEVICE(&ns->ide[1])); if (ret < 0) { @@ -211,6 +224,10 @@ static void macio_instance_init(Object *obj) memory_region_init(&s->bar, "macio", 0x80000); + object_initialize(&s->cuda, TYPE_CUDA); + qdev_set_parent_bus(DEVICE(&s->cuda), sysbus_get_default()); + object_property_add_child(obj, "cuda", OBJECT(&s->cuda), NULL); + s->dbdma = DBDMA_init(&dbdma_mem); memory_region_add_subregion(&s->bar, 0x08000, dbdma_mem); } @@ -275,13 +292,11 @@ type_init(macio_register_types) void macio_init(PCIDevice *d, MemoryRegion *pic_mem, - MemoryRegion *cuda_mem, MemoryRegion *escc_mem) { MacIOState *macio_state = MACIO(d); macio_state->pic_mem = pic_mem; - macio_state->cuda_mem = cuda_mem; macio_state->escc_mem = escc_mem; /* Note: this code is strongly inspirated from the corresponding code in PearPC */ diff --git a/hw/ppc/mac.h b/hw/ppc/mac.h index 3e390d3ee..26cb497b2 100644 --- a/hw/ppc/mac.h +++ b/hw/ppc/mac.h @@ -44,7 +44,72 @@ #define ESCC_CLOCK 3686400 /* Cuda */ -void cuda_init (MemoryRegion **cuda_mem, qemu_irq irq); +#define TYPE_CUDA "cuda" +#define CUDA(obj) OBJECT_CHECK(CUDAState, (obj), TYPE_CUDA) + +/** + * CUDATimer: + * @counter_value: counter value at load time + */ +typedef struct CUDATimer { + int index; + uint16_t latch; + uint16_t counter_value; + int64_t load_time; + int64_t next_irq_time; + QEMUTimer *timer; +} CUDATimer; + +/** + * CUDAState: + * @b: B-side data + * @a: A-side data + * @dirb: B-side direction (1=output) + * @dira: A-side direction (1=output) + * @sr: Shift register + * @acr: Auxiliary control register + * @pcr: Peripheral control register + * @ifr: Interrupt flag register + * @ier: Interrupt enable register + * @anh: A-side data, no handshake + * @last_b: last value of B register + * @last_acr: last value of ACR register + */ +typedef struct CUDAState { + /*< private >*/ + SysBusDevice parent_obj; + /*< public >*/ + + MemoryRegion mem; + /* cuda registers */ + uint8_t b; + uint8_t a; + uint8_t dirb; + uint8_t dira; + uint8_t sr; + uint8_t acr; + uint8_t pcr; + uint8_t ifr; + uint8_t ier; + uint8_t anh; + + CUDATimer timers[2]; + + uint32_t tick_offset; + + uint8_t last_b; + uint8_t last_acr; + + int data_in_size; + int data_in_index; + int data_out_index; + + qemu_irq irq; + uint8_t autopoll; + uint8_t data_in[128]; + uint8_t data_out[16]; + QEMUTimer *adb_poll_timer; +} CUDAState; /* MacIO */ #define TYPE_OLDWORLD_MACIO "macio-oldworld" @@ -71,7 +136,6 @@ void macio_ide_register_dma(MACIOIDEState *ide, void *dbdma, int channel); void macio_init(PCIDevice *dev, MemoryRegion *pic_mem, - MemoryRegion *cuda_mem, MemoryRegion *escc_mem); /* Heathrow PIC */ diff --git a/hw/ppc/mac_newworld.c b/hw/ppc/mac_newworld.c index 4fd86b042..b9c58c188 100644 --- a/hw/ppc/mac_newworld.c +++ b/hw/ppc/mac_newworld.c @@ -151,7 +151,7 @@ static void ppc_core99_init(QEMUMachineInitArgs *args) MACIOIDEState *macio_ide; MacIONVRAMState *nvr; int bios_size; - MemoryRegion *pic_mem, *cuda_mem, *escc_mem; + MemoryRegion *pic_mem, *escc_mem; MemoryRegion *escc_bar = g_new(MemoryRegion, 1); int ppc_boot_device; DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS]; @@ -363,18 +363,14 @@ static void ppc_core99_init(QEMUMachineInitArgs *args) ide_drive_get(hd, MAX_IDE_BUS); - cuda_init(&cuda_mem, pic[0x19]); - - adb_kbd_init(&adb_bus); - adb_mouse_init(&adb_bus); - macio = pci_create(pci_bus, -1, TYPE_NEWWORLD_MACIO); dev = DEVICE(macio); - qdev_connect_gpio_out(dev, 0, pic[0x0d]); /* IDE */ - qdev_connect_gpio_out(dev, 1, pic[0x02]); /* IDE DMA */ - qdev_connect_gpio_out(dev, 2, pic[0x0e]); /* IDE */ - qdev_connect_gpio_out(dev, 3, pic[0x02]); /* IDE DMA */ - macio_init(macio, pic_mem, cuda_mem, escc_bar); + qdev_connect_gpio_out(dev, 0, pic[0x19]); /* CUDA */ + qdev_connect_gpio_out(dev, 1, pic[0x0d]); /* IDE */ + qdev_connect_gpio_out(dev, 2, pic[0x02]); /* IDE DMA */ + qdev_connect_gpio_out(dev, 3, pic[0x0e]); /* IDE */ + qdev_connect_gpio_out(dev, 4, pic[0x02]); /* IDE DMA */ + macio_init(macio, pic_mem, escc_bar); /* We only emulate 2 out of 3 IDE controllers for now */ macio_ide = MACIO_IDE(object_resolve_path_component(OBJECT(macio), @@ -385,6 +381,9 @@ static void ppc_core99_init(QEMUMachineInitArgs *args) "ide[1]")); macio_ide_init_drives(macio_ide, &hd[MAX_IDE_DEVS]); + adb_kbd_init(&adb_bus); + adb_mouse_init(&adb_bus); + if (usb_enabled(machine_arch == ARCH_MAC99_U3)) { pci_create_simple(pci_bus, -1, "pci-ohci"); /* U3 needs to use USB for input because Linux doesn't support via-cuda diff --git a/hw/ppc/mac_oldworld.c b/hw/ppc/mac_oldworld.c index 6039ea61f..9d9212a37 100644 --- a/hw/ppc/mac_oldworld.c +++ b/hw/ppc/mac_oldworld.c @@ -93,7 +93,7 @@ static void ppc_heathrow_init(QEMUMachineInitArgs *args) MACIOIDEState *macio_ide; DeviceState *dev; int bios_size; - MemoryRegion *pic_mem, *cuda_mem; + MemoryRegion *pic_mem; MemoryRegion *escc_mem, *escc_bar = g_new(MemoryRegion, 1); uint16_t ppc_boot_device; DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS]; @@ -263,17 +263,12 @@ static void ppc_heathrow_init(QEMUMachineInitArgs *args) ide_drive_get(hd, MAX_IDE_BUS); - /* cuda also initialize ADB */ - cuda_init(&cuda_mem, pic[0x12]); - - adb_kbd_init(&adb_bus); - adb_mouse_init(&adb_bus); - macio = pci_create(pci_bus, -1, TYPE_OLDWORLD_MACIO); dev = DEVICE(macio); - qdev_connect_gpio_out(dev, 0, pic[0x0D]); /* IDE */ - qdev_connect_gpio_out(dev, 1, pic[0x02]); /* IDE DMA */ - macio_init(macio, pic_mem, cuda_mem, escc_bar); + qdev_connect_gpio_out(dev, 0, pic[0x12]); /* CUDA */ + qdev_connect_gpio_out(dev, 1, pic[0x0D]); /* IDE */ + qdev_connect_gpio_out(dev, 2, pic[0x02]); /* IDE DMA */ + macio_init(macio, pic_mem, escc_bar); /* First IDE channel is a MAC IDE on the MacIO bus */ macio_ide = MACIO_IDE(object_resolve_path_component(OBJECT(macio), @@ -286,6 +281,9 @@ static void ppc_heathrow_init(QEMUMachineInitArgs *args) hd[3] = hd[2] = NULL; pci_cmd646_ide_init(pci_bus, hd, 0); + adb_kbd_init(&adb_bus); + adb_mouse_init(&adb_bus); + if (usb_enabled(false)) { pci_create_simple(pci_bus, -1, "pci-ohci"); } From 84ede329083b649c54f078276e7e06d48e910b9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Wed, 23 Jan 2013 23:04:03 +0000 Subject: [PATCH 10/20] adb: QOM'ify Apple Desktop Bus MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It was not a qbus before, turn it into a first-class bus and initialize it properly from CUDA. Leave it a global variable as long as devices are not QOM'ified yet. Signed-off-by: Andreas Färber Signed-off-by: Alexander Graf --- hw/adb.c | 14 ++++++++++++++ hw/adb.h | 16 +++++++++++++--- hw/cuda.c | 3 +++ 3 files changed, 30 insertions(+), 3 deletions(-) diff --git a/hw/adb.c b/hw/adb.c index cc8ad8e05..5d46f5969 100644 --- a/hw/adb.c +++ b/hw/adb.c @@ -126,6 +126,12 @@ static ADBDevice *adb_register_device(ADBBusState *s, int devaddr, return d; } +static const TypeInfo adb_bus_type_info = { + .name = TYPE_ADB_BUS, + .parent = TYPE_BUS, + .instance_size = sizeof(ADBBusState), +}; + /***************************************************************/ /* Keyboard ADB device */ @@ -453,3 +459,11 @@ void adb_mouse_init(ADBBusState *bus) qemu_add_mouse_event_handler(adb_mouse_event, d, 0, "QEMU ADB Mouse"); vmstate_register(NULL, -1, &vmstate_adb_mouse, s); } + + +static void adb_register_types(void) +{ + type_register_static(&adb_bus_type_info); +} + +type_init(adb_register_types) diff --git a/hw/adb.h b/hw/adb.h index 5b27da2dd..c23f804fe 100644 --- a/hw/adb.h +++ b/hw/adb.h @@ -26,10 +26,13 @@ #if !defined(__ADB_H__) #define __ADB_H__ +#include "qdev.h" + #define MAX_ADB_DEVICES 16 #define ADB_MAX_OUT_LEN 16 +typedef struct ADBBusState ADBBusState; typedef struct ADBDevice ADBDevice; /* buf = NULL means polling */ @@ -38,7 +41,7 @@ typedef int ADBDeviceRequest(ADBDevice *d, uint8_t *buf_out, typedef int ADBDeviceReset(ADBDevice *d); struct ADBDevice { - struct ADBBusState *bus; + ADBBusState *bus; int devaddr; int handler; ADBDeviceRequest *devreq; @@ -46,11 +49,18 @@ struct ADBDevice { void *opaque; }; -typedef struct ADBBusState { +#define TYPE_ADB_BUS "apple-desktop-bus" +#define ADB_BUS(obj) OBJECT_CHECK(ADBBusState, (obj), TYPE_ADB_BUS) + +struct ADBBusState { + /*< private >*/ + BusState parent_obj; + /*< public >*/ + ADBDevice devices[MAX_ADB_DEVICES]; int nb_devices; int poll_index; -} ADBBusState; +}; int adb_request(ADBBusState *s, uint8_t *buf_out, const uint8_t *buf, int len); diff --git a/hw/cuda.c b/hw/cuda.c index f863c38a8..b3a875c3b 100644 --- a/hw/cuda.c +++ b/hw/cuda.c @@ -712,6 +712,9 @@ static void cuda_initfn(Object *obj) for (i = 0; i < ARRAY_SIZE(s->timers); i++) { s->timers[i].index = i; } + + qbus_create_inplace((BusState *)&adb_bus, TYPE_ADB_BUS, DEVICE(obj), + "adb.0"); } static void cuda_class_init(ObjectClass *oc, void *data) From 2e4a7c9c5df442d4223e738f7e8f73192b8b2a65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Wed, 23 Jan 2013 23:04:04 +0000 Subject: [PATCH 11/20] adb: QOM'ify ADB devices MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit They were not qdev'ified before. Derive ADBDevice from DeviceState and convert reset callbacks to DeviceClass::reset, ADBDevice::opaque pointer to ADBDevice subtypes for mouse and keyboard and adb_{kbd,mouse}_init() to regular qdev functions. Fixing Coding Style issues and splitting keyboard and mouse off into their own files is left for a later point in time. Signed-off-by: Andreas Färber Signed-off-by: Alexander Graf --- hw/adb.c | 244 ++++++++++++++++++++++++++++++------------ hw/adb.h | 31 ++++-- hw/ppc/mac_newworld.c | 6 +- hw/ppc/mac_oldworld.c | 6 +- 4 files changed, 209 insertions(+), 78 deletions(-) diff --git a/hw/adb.c b/hw/adb.c index 5d46f5969..6cf54650c 100644 --- a/hw/adb.c +++ b/hw/adb.c @@ -48,16 +48,21 @@ do { printf("ADB: " fmt , ## __VA_ARGS__); } while (0) #define ADB_CMD_CHANGE_ID_AND_ENABLE 0x00 /* ADB default device IDs (upper 4 bits of ADB command byte) */ -#define ADB_DONGLE 1 -#define ADB_KEYBOARD 2 -#define ADB_MOUSE 3 -#define ADB_TABLET 4 -#define ADB_MODEM 5 -#define ADB_MISC 7 +#define ADB_DEVID_DONGLE 1 +#define ADB_DEVID_KEYBOARD 2 +#define ADB_DEVID_MOUSE 3 +#define ADB_DEVID_TABLET 4 +#define ADB_DEVID_MODEM 5 +#define ADB_DEVID_MISC 7 /* error codes */ #define ADB_RET_NOTPRESENT (-2) +static void adb_device_reset(ADBDevice *d) +{ + qdev_reset_all(DEVICE(d)); +} + int adb_request(ADBBusState *s, uint8_t *obuf, const uint8_t *buf, int len) { ADBDevice *d; @@ -66,18 +71,17 @@ int adb_request(ADBBusState *s, uint8_t *obuf, const uint8_t *buf, int len) cmd = buf[0] & 0xf; if (cmd == ADB_BUSRESET) { for(i = 0; i < s->nb_devices; i++) { - d = &s->devices[i]; - if (d->devreset) { - d->devreset(d); - } + d = s->devices[i]; + adb_device_reset(d); } return 0; } devaddr = buf[0] >> 4; for(i = 0; i < s->nb_devices; i++) { - d = &s->devices[i]; + d = s->devices[i]; if (d->devaddr == devaddr) { - return d->devreq(d, obuf, buf, len); + ADBDeviceClass *adc = ADB_DEVICE_GET_CLASS(d); + return adc->devreq(d, obuf, buf, len); } } return ADB_RET_NOTPRESENT; @@ -94,7 +98,7 @@ int adb_poll(ADBBusState *s, uint8_t *obuf) for(i = 0; i < s->nb_devices; i++) { if (s->poll_index >= s->nb_devices) s->poll_index = 0; - d = &s->devices[s->poll_index]; + d = s->devices[s->poll_index]; buf[0] = ADB_READREG | (d->devaddr << 4); olen = adb_request(s, obuf + 1, buf, 1); /* if there is data, we poll again the same device */ @@ -108,38 +112,67 @@ int adb_poll(ADBBusState *s, uint8_t *obuf) return olen; } -static ADBDevice *adb_register_device(ADBBusState *s, int devaddr, - ADBDeviceRequest *devreq, - ADBDeviceReset *devreset, - void *opaque) -{ - ADBDevice *d; - if (s->nb_devices >= MAX_ADB_DEVICES) - return NULL; - d = &s->devices[s->nb_devices++]; - d->bus = s; - d->devaddr = devaddr; - d->devreq = devreq; - d->devreset = devreset; - d->opaque = opaque; - qemu_register_reset((QEMUResetHandler *)devreset, d); - return d; -} - static const TypeInfo adb_bus_type_info = { .name = TYPE_ADB_BUS, .parent = TYPE_BUS, .instance_size = sizeof(ADBBusState), }; +static void adb_device_realizefn(DeviceState *dev, Error **errp) +{ + ADBDevice *d = ADB_DEVICE(dev); + ADBBusState *bus = ADB_BUS(qdev_get_parent_bus(dev)); + + if (bus->nb_devices >= MAX_ADB_DEVICES) { + return; + } + + bus->devices[bus->nb_devices++] = d; +} + +static void adb_device_class_init(ObjectClass *oc, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(oc); + + dc->realize = adb_device_realizefn; + dc->bus_type = TYPE_ADB_BUS; +} + +static const TypeInfo adb_device_type_info = { + .name = TYPE_ADB_DEVICE, + .parent = TYPE_DEVICE, + .instance_size = sizeof(ADBDevice), + .abstract = true, + .class_init = adb_device_class_init, +}; + /***************************************************************/ /* Keyboard ADB device */ +#define ADB_KEYBOARD(obj) OBJECT_CHECK(KBDState, (obj), TYPE_ADB_KEYBOARD) + typedef struct KBDState { + /*< private >*/ + ADBDevice parent_obj; + /*< public >*/ + uint8_t data[128]; int rptr, wptr, count; } KBDState; +#define ADB_KEYBOARD_CLASS(class) \ + OBJECT_CLASS_CHECK(ADBKeyboardClass, (class), TYPE_ADB_KEYBOARD) +#define ADB_KEYBOARD_GET_CLASS(obj) \ + OBJECT_GET_CLASS(ADBKeyboardClass, (obj), TYPE_ADB_KEYBOARD) + +typedef struct ADBKeyboardClass { + /*< private >*/ + ADBDeviceClass parent_class; + /*< public >*/ + + DeviceRealize parent_realize; +} ADBKeyboardClass; + static const uint8_t pc_to_adb_keycode[256] = { 0, 53, 18, 19, 20, 21, 23, 22, 26, 28, 25, 29, 27, 24, 51, 48, 12, 13, 14, 15, 17, 16, 32, 34, 31, 35, 33, 30, 36, 54, 0, 1, @@ -161,8 +194,7 @@ static const uint8_t pc_to_adb_keycode[256] = { static void adb_kbd_put_keycode(void *opaque, int keycode) { - ADBDevice *d = opaque; - KBDState *s = d->opaque; + KBDState *s = opaque; if (s->count < sizeof(s->data)) { s->data[s->wptr] = keycode; @@ -175,7 +207,7 @@ static void adb_kbd_put_keycode(void *opaque, int keycode) static int adb_kbd_poll(ADBDevice *d, uint8_t *obuf) { static int ext_keycode; - KBDState *s = d->opaque; + KBDState *s = ADB_KEYBOARD(d); int adb_keycode, keycode; int olen; @@ -209,7 +241,7 @@ static int adb_kbd_poll(ADBDevice *d, uint8_t *obuf) static int adb_kbd_request(ADBDevice *d, uint8_t *obuf, const uint8_t *buf, int len) { - KBDState *s = d->opaque; + KBDState *s = ADB_KEYBOARD(d); int cmd, reg, olen; if ((buf[0] & 0x0f) == ADB_FLUSH) { @@ -281,41 +313,90 @@ static const VMStateDescription vmstate_adb_kbd = { } }; -static int adb_kbd_reset(ADBDevice *d) +static void adb_kbd_reset(DeviceState *dev) { - KBDState *s = d->opaque; + ADBDevice *d = ADB_DEVICE(dev); + KBDState *s = ADB_KEYBOARD(dev); d->handler = 1; - d->devaddr = ADB_KEYBOARD; - memset(s, 0, sizeof(KBDState)); - - return 0; + d->devaddr = ADB_DEVID_KEYBOARD; + memset(s->data, 0, sizeof(s->data)); + s->rptr = 0; + s->wptr = 0; + s->count = 0; } -void adb_kbd_init(ADBBusState *bus) +static void adb_kbd_realizefn(DeviceState *dev, Error **errp) { - ADBDevice *d; - KBDState *s; - s = g_malloc0(sizeof(KBDState)); - d = adb_register_device(bus, ADB_KEYBOARD, adb_kbd_request, - adb_kbd_reset, s); + ADBDevice *d = ADB_DEVICE(dev); + ADBKeyboardClass *akc = ADB_KEYBOARD_GET_CLASS(dev); + + akc->parent_realize(dev, errp); + qemu_add_kbd_event_handler(adb_kbd_put_keycode, d); - vmstate_register(NULL, -1, &vmstate_adb_kbd, s); } +static void adb_kbd_initfn(Object *obj) +{ + ADBDevice *d = ADB_DEVICE(obj); + + d->devaddr = ADB_DEVID_KEYBOARD; +} + +static void adb_kbd_class_init(ObjectClass *oc, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(oc); + ADBDeviceClass *adc = ADB_DEVICE_CLASS(oc); + ADBKeyboardClass *akc = ADB_KEYBOARD_CLASS(oc); + + akc->parent_realize = dc->realize; + dc->realize = adb_kbd_realizefn; + + adc->devreq = adb_kbd_request; + dc->reset = adb_kbd_reset; + dc->vmsd = &vmstate_adb_kbd; +} + +static const TypeInfo adb_kbd_type_info = { + .name = TYPE_ADB_KEYBOARD, + .parent = TYPE_ADB_DEVICE, + .instance_size = sizeof(KBDState), + .instance_init = adb_kbd_initfn, + .class_init = adb_kbd_class_init, + .class_size = sizeof(ADBKeyboardClass), +}; + /***************************************************************/ /* Mouse ADB device */ +#define ADB_MOUSE(obj) OBJECT_CHECK(MouseState, (obj), TYPE_ADB_MOUSE) + typedef struct MouseState { + /*< public >*/ + ADBDevice parent_obj; + /*< private >*/ + int buttons_state, last_buttons_state; int dx, dy, dz; } MouseState; +#define ADB_MOUSE_CLASS(class) \ + OBJECT_CLASS_CHECK(ADBMouseClass, (class), TYPE_ADB_MOUSE) +#define ADB_MOUSE_GET_CLASS(obj) \ + OBJECT_GET_CLASS(ADBMouseClass, (obj), TYPE_ADB_MOUSE) + +typedef struct ADBMouseClass { + /*< public >*/ + ADBDeviceClass parent_class; + /*< private >*/ + + DeviceRealize parent_realize; +} ADBMouseClass; + static void adb_mouse_event(void *opaque, int dx1, int dy1, int dz1, int buttons_state) { - ADBDevice *d = opaque; - MouseState *s = d->opaque; + MouseState *s = opaque; s->dx += dx1; s->dy += dy1; @@ -326,7 +407,7 @@ static void adb_mouse_event(void *opaque, static int adb_mouse_poll(ADBDevice *d, uint8_t *obuf) { - MouseState *s = d->opaque; + MouseState *s = ADB_MOUSE(d); int dx, dy; if (s->last_buttons_state == s->buttons_state && @@ -365,7 +446,7 @@ static int adb_mouse_poll(ADBDevice *d, uint8_t *obuf) static int adb_mouse_request(ADBDevice *d, uint8_t *obuf, const uint8_t *buf, int len) { - MouseState *s = d->opaque; + MouseState *s = ADB_MOUSE(d); int cmd, reg, olen; if ((buf[0] & 0x0f) == ADB_FLUSH) { @@ -422,15 +503,15 @@ static int adb_mouse_request(ADBDevice *d, uint8_t *obuf, return olen; } -static int adb_mouse_reset(ADBDevice *d) +static void adb_mouse_reset(DeviceState *dev) { - MouseState *s = d->opaque; + ADBDevice *d = ADB_DEVICE(dev); + MouseState *s = ADB_MOUSE(dev); d->handler = 2; - d->devaddr = ADB_MOUSE; - memset(s, 0, sizeof(MouseState)); - - return 0; + d->devaddr = ADB_DEVID_MOUSE; + s->last_buttons_state = s->buttons_state = 0; + s->dx = s->dy = s->dz = 0; } static const VMStateDescription vmstate_adb_mouse = { @@ -448,22 +529,53 @@ static const VMStateDescription vmstate_adb_mouse = { } }; -void adb_mouse_init(ADBBusState *bus) +static void adb_mouse_realizefn(DeviceState *dev, Error **errp) { - ADBDevice *d; - MouseState *s; + MouseState *s = ADB_MOUSE(dev); + ADBMouseClass *amc = ADB_MOUSE_GET_CLASS(dev); - s = g_malloc0(sizeof(MouseState)); - d = adb_register_device(bus, ADB_MOUSE, adb_mouse_request, - adb_mouse_reset, s); - qemu_add_mouse_event_handler(adb_mouse_event, d, 0, "QEMU ADB Mouse"); - vmstate_register(NULL, -1, &vmstate_adb_mouse, s); + amc->parent_realize(dev, errp); + + qemu_add_mouse_event_handler(adb_mouse_event, s, 0, "QEMU ADB Mouse"); } +static void adb_mouse_initfn(Object *obj) +{ + ADBDevice *d = ADB_DEVICE(obj); + + d->devaddr = ADB_DEVID_MOUSE; +} + +static void adb_mouse_class_init(ObjectClass *oc, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(oc); + ADBDeviceClass *adc = ADB_DEVICE_CLASS(oc); + ADBMouseClass *amc = ADB_MOUSE_CLASS(oc); + + amc->parent_realize = dc->realize; + dc->realize = adb_mouse_realizefn; + + adc->devreq = adb_mouse_request; + dc->reset = adb_mouse_reset; + dc->vmsd = &vmstate_adb_mouse; +} + +static const TypeInfo adb_mouse_type_info = { + .name = TYPE_ADB_MOUSE, + .parent = TYPE_ADB_DEVICE, + .instance_size = sizeof(MouseState), + .instance_init = adb_mouse_initfn, + .class_init = adb_mouse_class_init, + .class_size = sizeof(ADBMouseClass), +}; + static void adb_register_types(void) { type_register_static(&adb_bus_type_info); + type_register_static(&adb_device_type_info); + type_register_static(&adb_kbd_type_info); + type_register_static(&adb_mouse_type_info); } type_init(adb_register_types) diff --git a/hw/adb.h b/hw/adb.h index c23f804fe..2fe981ffa 100644 --- a/hw/adb.h +++ b/hw/adb.h @@ -38,17 +38,32 @@ typedef struct ADBDevice ADBDevice; /* buf = NULL means polling */ typedef int ADBDeviceRequest(ADBDevice *d, uint8_t *buf_out, const uint8_t *buf, int len); -typedef int ADBDeviceReset(ADBDevice *d); + +#define TYPE_ADB_DEVICE "adb-device" +#define ADB_DEVICE(obj) OBJECT_CHECK(ADBDevice, (obj), TYPE_ADB_DEVICE) struct ADBDevice { - ADBBusState *bus; + /*< private >*/ + DeviceState parent_obj; + /*< public >*/ + int devaddr; int handler; - ADBDeviceRequest *devreq; - ADBDeviceReset *devreset; - void *opaque; }; +#define ADB_DEVICE_CLASS(cls) \ + OBJECT_CLASS_CHECK(ADBDeviceClass, (cls), TYPE_ADB_DEVICE) +#define ADB_DEVICE_GET_CLASS(obj) \ + OBJECT_GET_CLASS(ADBDeviceClass, (obj), TYPE_ADB_DEVICE) + +typedef struct ADBDeviceClass { + /*< private >*/ + DeviceClass parent_class; + /*< public >*/ + + ADBDeviceRequest *devreq; +} ADBDeviceClass; + #define TYPE_ADB_BUS "apple-desktop-bus" #define ADB_BUS(obj) OBJECT_CHECK(ADBBusState, (obj), TYPE_ADB_BUS) @@ -57,7 +72,7 @@ struct ADBBusState { BusState parent_obj; /*< public >*/ - ADBDevice devices[MAX_ADB_DEVICES]; + ADBDevice *devices[MAX_ADB_DEVICES]; int nb_devices; int poll_index; }; @@ -66,8 +81,8 @@ int adb_request(ADBBusState *s, uint8_t *buf_out, const uint8_t *buf, int len); int adb_poll(ADBBusState *s, uint8_t *buf_out); -void adb_kbd_init(ADBBusState *bus); -void adb_mouse_init(ADBBusState *bus); +#define TYPE_ADB_KEYBOARD "adb-keyboard" +#define TYPE_ADB_MOUSE "adb-mouse" extern ADBBusState adb_bus; #endif /* !defined(__ADB_H__) */ diff --git a/hw/ppc/mac_newworld.c b/hw/ppc/mac_newworld.c index b9c58c188..2892b362e 100644 --- a/hw/ppc/mac_newworld.c +++ b/hw/ppc/mac_newworld.c @@ -381,8 +381,10 @@ static void ppc_core99_init(QEMUMachineInitArgs *args) "ide[1]")); macio_ide_init_drives(macio_ide, &hd[MAX_IDE_DEVS]); - adb_kbd_init(&adb_bus); - adb_mouse_init(&adb_bus); + dev = qdev_create(BUS(&adb_bus), TYPE_ADB_KEYBOARD); + qdev_init_nofail(dev); + dev = qdev_create(BUS(&adb_bus), TYPE_ADB_MOUSE); + qdev_init_nofail(dev); if (usb_enabled(machine_arch == ARCH_MAC99_U3)) { pci_create_simple(pci_bus, -1, "pci-ohci"); diff --git a/hw/ppc/mac_oldworld.c b/hw/ppc/mac_oldworld.c index 9d9212a37..59b7199a9 100644 --- a/hw/ppc/mac_oldworld.c +++ b/hw/ppc/mac_oldworld.c @@ -281,8 +281,10 @@ static void ppc_heathrow_init(QEMUMachineInitArgs *args) hd[3] = hd[2] = NULL; pci_cmd646_ide_init(pci_bus, hd, 0); - adb_kbd_init(&adb_bus); - adb_mouse_init(&adb_bus); + dev = qdev_create(BUS(&adb_bus), TYPE_ADB_KEYBOARD); + qdev_init_nofail(dev); + dev = qdev_create(BUS(&adb_bus), TYPE_ADB_MOUSE); + qdev_init_nofail(dev); if (usb_enabled(false)) { pci_create_simple(pci_bus, -1, "pci-ohci"); From 293c867d8c7399d17e6b593053411a6515171f38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Wed, 23 Jan 2013 23:04:05 +0000 Subject: [PATCH 12/20] cuda: Move ADB bus into CUDA state MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace the global adb_bus with a CUDA-internal one, accessed using regular qdev child bus accessor. Signed-off-by: Andreas Färber Signed-off-by: Alexander Graf --- hw/adb.h | 1 - hw/cuda.c | 8 +++----- hw/ppc/mac.h | 2 ++ hw/ppc/mac_newworld.c | 7 +++++-- hw/ppc/mac_oldworld.c | 7 +++++-- 5 files changed, 15 insertions(+), 10 deletions(-) diff --git a/hw/adb.h b/hw/adb.h index 2fe981ffa..721f1ac43 100644 --- a/hw/adb.h +++ b/hw/adb.h @@ -84,5 +84,4 @@ int adb_poll(ADBBusState *s, uint8_t *buf_out); #define TYPE_ADB_KEYBOARD "adb-keyboard" #define TYPE_ADB_MOUSE "adb-mouse" -extern ADBBusState adb_bus; #endif /* !defined(__ADB_H__) */ diff --git a/hw/cuda.c b/hw/cuda.c index b3a875c3b..b36c53527 100644 --- a/hw/cuda.c +++ b/hw/cuda.c @@ -108,8 +108,6 @@ /* CUDA returns time_t's offset from Jan 1, 1904, not 1970 */ #define RTC_OFFSET 2082844800 -ADBBusState adb_bus; - static void cuda_update(CUDAState *s); static void cuda_receive_packet_from_host(CUDAState *s, const uint8_t *data, int len); @@ -459,7 +457,7 @@ static void cuda_adb_poll(void *opaque) uint8_t obuf[ADB_MAX_OUT_LEN + 2]; int olen; - olen = adb_poll(&adb_bus, obuf + 2); + olen = adb_poll(&s->adb_bus, obuf + 2); if (olen > 0) { obuf[0] = ADB_PACKET; obuf[1] = 0x40; /* polled data */ @@ -555,7 +553,7 @@ static void cuda_receive_packet_from_host(CUDAState *s, { uint8_t obuf[ADB_MAX_OUT_LEN + 2]; int olen; - olen = adb_request(&adb_bus, obuf + 2, data + 1, len - 1); + olen = adb_request(&s->adb_bus, obuf + 2, data + 1, len - 1); if (olen > 0) { obuf[0] = ADB_PACKET; obuf[1] = 0x00; @@ -713,7 +711,7 @@ static void cuda_initfn(Object *obj) s->timers[i].index = i; } - qbus_create_inplace((BusState *)&adb_bus, TYPE_ADB_BUS, DEVICE(obj), + qbus_create_inplace((BusState *)&s->adb_bus, TYPE_ADB_BUS, DEVICE(obj), "adb.0"); } diff --git a/hw/ppc/mac.h b/hw/ppc/mac.h index 26cb497b2..b17107b79 100644 --- a/hw/ppc/mac.h +++ b/hw/ppc/mac.h @@ -28,6 +28,7 @@ #include "exec/memory.h" #include "hw/sysbus.h" #include "hw/ide/internal.h" +#include "hw/adb.h" /* SMP is not enabled, for now */ #define MAX_CPUS 1 @@ -93,6 +94,7 @@ typedef struct CUDAState { uint8_t ier; uint8_t anh; + ADBBusState adb_bus; CUDATimer timers[2]; uint32_t tick_offset; diff --git a/hw/ppc/mac_newworld.c b/hw/ppc/mac_newworld.c index 2892b362e..6de810bde 100644 --- a/hw/ppc/mac_newworld.c +++ b/hw/ppc/mac_newworld.c @@ -149,6 +149,7 @@ static void ppc_core99_init(QEMUMachineInitArgs *args) PCIBus *pci_bus; PCIDevice *macio; MACIOIDEState *macio_ide; + BusState *adb_bus; MacIONVRAMState *nvr; int bios_size; MemoryRegion *pic_mem, *escc_mem; @@ -381,9 +382,11 @@ static void ppc_core99_init(QEMUMachineInitArgs *args) "ide[1]")); macio_ide_init_drives(macio_ide, &hd[MAX_IDE_DEVS]); - dev = qdev_create(BUS(&adb_bus), TYPE_ADB_KEYBOARD); + dev = DEVICE(object_resolve_path_component(OBJECT(macio), "cuda")); + adb_bus = qdev_get_child_bus(dev, "adb.0"); + dev = qdev_create(adb_bus, TYPE_ADB_KEYBOARD); qdev_init_nofail(dev); - dev = qdev_create(BUS(&adb_bus), TYPE_ADB_MOUSE); + dev = qdev_create(adb_bus, TYPE_ADB_MOUSE); qdev_init_nofail(dev); if (usb_enabled(machine_arch == ARCH_MAC99_U3)) { diff --git a/hw/ppc/mac_oldworld.c b/hw/ppc/mac_oldworld.c index 59b7199a9..9ed303a5e 100644 --- a/hw/ppc/mac_oldworld.c +++ b/hw/ppc/mac_oldworld.c @@ -92,6 +92,7 @@ static void ppc_heathrow_init(QEMUMachineInitArgs *args) PCIDevice *macio; MACIOIDEState *macio_ide; DeviceState *dev; + BusState *adb_bus; int bios_size; MemoryRegion *pic_mem; MemoryRegion *escc_mem, *escc_bar = g_new(MemoryRegion, 1); @@ -281,9 +282,11 @@ static void ppc_heathrow_init(QEMUMachineInitArgs *args) hd[3] = hd[2] = NULL; pci_cmd646_ide_init(pci_bus, hd, 0); - dev = qdev_create(BUS(&adb_bus), TYPE_ADB_KEYBOARD); + dev = DEVICE(object_resolve_path_component(OBJECT(macio), "cuda")); + adb_bus = qdev_get_child_bus(dev, "adb.0"); + dev = qdev_create(adb_bus, TYPE_ADB_KEYBOARD); qdev_init_nofail(dev); - dev = qdev_create(BUS(&adb_bus), TYPE_ADB_MOUSE); + dev = qdev_create(adb_bus, TYPE_ADB_MOUSE); qdev_init_nofail(dev); if (usb_enabled(false)) { From fe828a4d4b7a5617cda7b24e95e327bfb71d790e Mon Sep 17 00:00:00 2001 From: Mike Qiu Date: Wed, 23 Jan 2013 17:20:38 +0000 Subject: [PATCH 13/20] target-ppc: Give a meaningful error if too many threads are specified Currently the target-ppc tcg code only supports a single thread. You can specify more, but they're treated identically to multiple cores. On KVM we obviously can't support more threads than the hardware; if more are specified it will cause strange and cryptic errors. This patch clarifies the situation by giving a simple meaningful error if more threads are specified than we can support. Signed-off-by: Mike Qiu Signed-off-by: David Gibson Signed-off-by: Alexander Graf --- target-ppc/translate_init.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c index 2d7852927..4f767c975 100644 --- a/target-ppc/translate_init.c +++ b/target-ppc/translate_init.c @@ -28,6 +28,7 @@ #include #include "kvm_ppc.h" #include "sysemu/arch_init.h" +#include "sysemu/cpus.h" //#define PPC_DUMP_CPU //#define PPC_DEBUG_SPR @@ -10036,6 +10037,17 @@ static void ppc_cpu_realize(Object *obj, Error **errp) PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu); ppc_def_t *def = pcc->info; Error *local_err = NULL; +#if !defined(CONFIG_USER_ONLY) + int max_smt = kvm_enabled() ? kvmppc_smt_threads() : 1; +#endif + +#if !defined(CONFIG_USER_ONLY) + if (smp_threads > max_smt) { + fprintf(stderr, "Cannot support more than %d threads on PPC with %s\n", + max_smt, kvm_enabled() ? "KVM" : "TCG"); + exit(1); + } +#endif if (kvm_enabled()) { if (kvmppc_fixup_cpu(cpu) != 0) { From caae58cba07efec5f0616f568531c9dfaf1e9179 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 23 Jan 2013 17:20:39 +0000 Subject: [PATCH 14/20] pseries: Improve handling of multiple PCI host bridges Multiple - even many - PCI host bridges (i.e. PCI domains) are very common on real PAPR compliant hardware. For reasons related to the PAPR specified IOMMU interfaces, PCI device assignment with VFIO will generally require at least two (virtual) PHBs and possibly more depending on which devices are assigned. At the moment the qemu PAPR PCI code will not deal with this well, leaving several crucial parameters of PHBs other than the default one uninitialized. This patch reworks the code to allow this. Every PHB needs a unique BUID (Bus Unit Identifier, the id used for the PAPR PCI related interfaces) and a unique LIOBN (Logical IO Bus Number, the id used for the PAPR IOMMU related interfaces). In addition they need windows in CPU real address space to access PCI memory space, PCI IO space and MSIs. Properties are added to the PCI host bridge qdevice to allow configuration of all these. To simplify configuration of multiple PHBs for common cases, a convenience "index" property is also added. This can be set instead of the low-level properties, and will generate suitable values for the other parameters, different for each index value. Signed-off-by: David Gibson Signed-off-by: Alexander Graf --- hw/spapr.c | 13 +------ hw/spapr_pci.c | 102 +++++++++++++++++++++++++++++++++++++------------ hw/spapr_pci.h | 22 +++++++---- 3 files changed, 94 insertions(+), 43 deletions(-) diff --git a/hw/spapr.c b/hw/spapr.c index d80b792b3..e88a27aa7 100644 --- a/hw/spapr.c +++ b/hw/spapr.c @@ -77,12 +77,6 @@ #define MAX_CPUS 256 #define XICS_IRQS 1024 -#define SPAPR_PCI_BUID 0x800000020000001ULL -#define SPAPR_PCI_MEM_WIN_ADDR (0x10000000000ULL + 0xA0000000) -#define SPAPR_PCI_MEM_WIN_SIZE 0x20000000 -#define SPAPR_PCI_IO_WIN_ADDR (0x10000000000ULL + 0x80000000) -#define SPAPR_PCI_MSI_WIN_ADDR (0x10000000000ULL + 0x90000000) - #define PHANDLE_XICP 0x00001111 #define HTAB_SIZE(spapr) (1ULL << ((spapr)->htab_shift)) @@ -857,12 +851,7 @@ static void ppc_spapr_init(QEMUMachineInitArgs *args) /* Set up PCI */ spapr_pci_rtas_init(); - spapr_create_phb(spapr, "pci", SPAPR_PCI_BUID, - SPAPR_PCI_MEM_WIN_ADDR, - SPAPR_PCI_MEM_WIN_SIZE, - SPAPR_PCI_IO_WIN_ADDR, - SPAPR_PCI_MSI_WIN_ADDR); - phb = PCI_HOST_BRIDGE(QLIST_FIRST(&spapr->phbs)); + phb = spapr_create_phb(spapr, 0, "pci"); for (i = 0; i < nb_nics; i++) { NICInfo *nd = &nd_table[i]; diff --git a/hw/spapr_pci.c b/hw/spapr_pci.c index bbcc9fc96..4eacbcfd5 100644 --- a/hw/spapr_pci.c +++ b/hw/spapr_pci.c @@ -435,7 +435,7 @@ static void pci_spapr_set_irq(void *opaque, int irq_num, int level) */ sPAPRPHBState *phb = opaque; - trace_spapr_pci_lsi_set(phb->busname, irq_num, phb->lsi_table[irq_num].irq); + trace_spapr_pci_lsi_set(phb->dtbusname, irq_num, phb->lsi_table[irq_num].irq); qemu_set_irq(spapr_phb_lsi_qirq(phb, irq_num), level); } @@ -522,7 +522,63 @@ static int spapr_phb_init(SysBusDevice *s) int i; PCIBus *bus; + if (sphb->index != -1) { + hwaddr windows_base; + + if ((sphb->buid != -1) || (sphb->dma_liobn != -1) + || (sphb->mem_win_addr != -1) + || (sphb->io_win_addr != -1) + || (sphb->msi_win_addr != -1)) { + fprintf(stderr, "Either \"index\" or other parameters must" + " be specified for PAPR PHB, not both\n"); + return -1; + } + + sphb->buid = SPAPR_PCI_BASE_BUID + sphb->index; + sphb->dma_liobn = SPAPR_PCI_BASE_LIOBN + sphb->index; + + windows_base = SPAPR_PCI_WINDOW_BASE + + sphb->index * SPAPR_PCI_WINDOW_SPACING; + sphb->mem_win_addr = windows_base + SPAPR_PCI_MMIO_WIN_OFF; + sphb->io_win_addr = windows_base + SPAPR_PCI_IO_WIN_OFF; + sphb->msi_win_addr = windows_base + SPAPR_PCI_MSI_WIN_OFF; + } + + if (sphb->buid == -1) { + fprintf(stderr, "BUID not specified for PHB\n"); + return -1; + } + + if (sphb->dma_liobn == -1) { + fprintf(stderr, "LIOBN not specified for PHB\n"); + return -1; + } + + if (sphb->mem_win_addr == -1) { + fprintf(stderr, "Memory window address not specified for PHB\n"); + return -1; + } + + if (sphb->io_win_addr == -1) { + fprintf(stderr, "IO window address not specified for PHB\n"); + return -1; + } + + if (sphb->msi_win_addr == -1) { + fprintf(stderr, "MSI window address not specified for PHB\n"); + return -1; + } + + if (find_phb(spapr, sphb->buid)) { + fprintf(stderr, "PCI host bridges must have unique BUIDs\n"); + return -1; + } + sphb->dtbusname = g_strdup_printf("pci@%" PRIx64, sphb->buid); + if (!sphb->busname) { + sphb->busname = sphb->dtbusname; + } + namebuf = alloca(strlen(sphb->dtbusname) + 32); /* Initialize memory regions */ @@ -565,17 +621,19 @@ static int spapr_phb_init(SysBusDevice *s) &sphb->msiwindow); } - bus = pci_register_bus(DEVICE(s), - sphb->busname ? sphb->busname : sphb->dtbusname, + bus = pci_register_bus(DEVICE(s), sphb->busname, pci_spapr_set_irq, pci_spapr_map_irq, sphb, &sphb->memspace, &sphb->iospace, PCI_DEVFN(0, 0), PCI_NUM_PINS); phb->bus = bus; - sphb->dma_liobn = SPAPR_PCI_BASE_LIOBN | (pci_find_domain(bus) << 16); sphb->dma_window_start = 0; sphb->dma_window_size = 0x40000000; sphb->dma = spapr_tce_new_dma_context(sphb->dma_liobn, sphb->dma_window_size); + if (!sphb->dma) { + fprintf(stderr, "Unable to create TCE table for %s\n", sphb->dtbusname); + return -1; + } pci_setup_iommu(bus, spapr_pci_dma_context_fn, sphb); QLIST_INSERT_HEAD(&spapr->phbs, sphb, list); @@ -605,13 +663,17 @@ static void spapr_phb_reset(DeviceState *qdev) } static Property spapr_phb_properties[] = { - DEFINE_PROP_HEX64("buid", sPAPRPHBState, buid, 0), DEFINE_PROP_STRING("busname", sPAPRPHBState, busname), - DEFINE_PROP_HEX64("mem_win_addr", sPAPRPHBState, mem_win_addr, 0), - DEFINE_PROP_HEX64("mem_win_size", sPAPRPHBState, mem_win_size, 0x20000000), - DEFINE_PROP_HEX64("io_win_addr", sPAPRPHBState, io_win_addr, 0), - DEFINE_PROP_HEX64("io_win_size", sPAPRPHBState, io_win_size, 0x10000), - DEFINE_PROP_HEX64("msi_win_addr", sPAPRPHBState, msi_win_addr, 0), + DEFINE_PROP_INT32("index", sPAPRPHBState, index, -1), + DEFINE_PROP_HEX64("buid", sPAPRPHBState, buid, -1), + DEFINE_PROP_HEX32("liobn", sPAPRPHBState, dma_liobn, -1), + DEFINE_PROP_HEX64("mem_win_addr", sPAPRPHBState, mem_win_addr, -1), + DEFINE_PROP_HEX64("mem_win_size", sPAPRPHBState, mem_win_size, + SPAPR_PCI_MMIO_WIN_SIZE), + DEFINE_PROP_HEX64("io_win_addr", sPAPRPHBState, io_win_addr, -1), + DEFINE_PROP_HEX64("io_win_size", sPAPRPHBState, io_win_size, + SPAPR_PCI_IO_WIN_SIZE), + DEFINE_PROP_HEX64("msi_win_addr", sPAPRPHBState, msi_win_addr, -1), DEFINE_PROP_END_OF_LIST(), }; @@ -632,25 +694,17 @@ static const TypeInfo spapr_phb_info = { .class_init = spapr_phb_class_init, }; -void spapr_create_phb(sPAPREnvironment *spapr, - const char *busname, uint64_t buid, - uint64_t mem_win_addr, uint64_t mem_win_size, - uint64_t io_win_addr, uint64_t msi_win_addr) +PCIHostState *spapr_create_phb(sPAPREnvironment *spapr, int index, + const char *busname) { DeviceState *dev; dev = qdev_create(NULL, TYPE_SPAPR_PCI_HOST_BRIDGE); - - if (busname) { - qdev_prop_set_string(dev, "busname", g_strdup(busname)); - } - qdev_prop_set_uint64(dev, "buid", buid); - qdev_prop_set_uint64(dev, "mem_win_addr", mem_win_addr); - qdev_prop_set_uint64(dev, "mem_win_size", mem_win_size); - qdev_prop_set_uint64(dev, "io_win_addr", io_win_addr); - qdev_prop_set_uint64(dev, "msi_win_addr", msi_win_addr); - + qdev_prop_set_uint32(dev, "index", index); + qdev_prop_set_string(dev, "busname", busname); qdev_init_nofail(dev); + + return PCI_HOST_BRIDGE(dev); } /* Macros to operate with address in OF binding to PCI */ diff --git a/hw/spapr_pci.h b/hw/spapr_pci.h index 7b26ba156..8bb3c62c3 100644 --- a/hw/spapr_pci.h +++ b/hw/spapr_pci.h @@ -37,6 +37,7 @@ typedef struct sPAPRPHBState { PCIHostState parent_obj; + int32_t index; uint64_t buid; char *busname; char *dtbusname; @@ -64,18 +65,25 @@ typedef struct sPAPRPHBState { QLIST_ENTRY(sPAPRPHBState) list; } sPAPRPHBState; +#define SPAPR_PCI_BASE_BUID 0x800000020000000ULL + +#define SPAPR_PCI_WINDOW_BASE 0x10000000000ULL +#define SPAPR_PCI_WINDOW_SPACING 0x1000000000ULL +#define SPAPR_PCI_MMIO_WIN_OFF 0xA0000000 +#define SPAPR_PCI_MMIO_WIN_SIZE 0x20000000 +#define SPAPR_PCI_IO_WIN_OFF 0x80000000 +#define SPAPR_PCI_IO_WIN_SIZE 0x10000 +#define SPAPR_PCI_MSI_WIN_OFF 0x90000000 + +#define SPAPR_PCI_MEM_WIN_BUS_OFFSET 0x80000000ULL + static inline qemu_irq spapr_phb_lsi_qirq(struct sPAPRPHBState *phb, int pin) { return xics_get_qirq(spapr->icp, phb->lsi_table[pin].irq); } -#define SPAPR_PCI_MEM_WIN_BUS_OFFSET 0x80000000ULL -#define SPAPR_PCI_IO_WIN_SIZE 0x10000 - -void spapr_create_phb(sPAPREnvironment *spapr, - const char *busname, uint64_t buid, - uint64_t mem_win_addr, uint64_t mem_win_size, - uint64_t io_win_addr, uint64_t msi_win_addr); +PCIHostState *spapr_create_phb(sPAPREnvironment *spapr, int index, + const char *busname); int spapr_populate_pci_dt(sPAPRPHBState *phb, uint32_t xics_phandle, From 1ea1ce8ac305d9e006bc8b0f5f3554793fd2fa43 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 23 Jan 2013 17:20:43 +0000 Subject: [PATCH 15/20] pseries: Adjust default VIO address allocations to play better with libvirt Currently, if VIO devices for pseries don't have addresses explicitly allocated, they get automatically numbered from 0x1000. This is in the same general range that libvirt will typically assign VIO device addresses. That means that if there is a device libvirt doesn't know about, and it gets an address assigned before the libvirt assigned devices are processed, we can end up with an address conflict (qemu will abort with an error). While the real solution is to teach libvirt about the other devices, so it can correctly manage the whole allocation, this patch reduces the interim inconvenience by moving qemu allocations to a range that libvirt is less likely to conflict with. Because the guest gets the device addresses through the device tree, these addresses are truly arbitrary and can be changed without breaking guests. Signed-off-by: David Gibson Signed-off-by: Alexander Graf --- hw/spapr_vio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/spapr_vio.c b/hw/spapr_vio.c index 2054219c9..34c9ca6b6 100644 --- a/hw/spapr_vio.c +++ b/hw/spapr_vio.c @@ -492,7 +492,7 @@ VIOsPAPRBus *spapr_vio_bus_init(void) qbus = qbus_create(TYPE_SPAPR_VIO_BUS, dev, "spapr-vio"); bus = DO_UPCAST(VIOsPAPRBus, bus, qbus); - bus->next_reg = 0x1000; + bus->next_reg = 0x71000000; /* hcall-vio */ spapr_register_hypercall(H_VIO_SIGNAL, h_vio_signal); From f40c360c0da020a1a478f8e60dd205d7412bc315 Mon Sep 17 00:00:00 2001 From: Scott Wood Date: Mon, 21 Jan 2013 15:53:51 +0000 Subject: [PATCH 16/20] openpic: fix remaining issues from idr-to-destmask conversion openpic_update_irq() was checking idr rather than destmask, treating it as if it were a simple bitmap of cpus. Changed to use destmask. IPI delivery was removing bits directly from .idr, without calling write_IRQreg_idr so that the change could be conveyed to destmask. Changed to use destmask directly. Save/restore destmask when serializing, as due to the IPI change it cannot be reproduced from idr. Signed-off-by: Scott Wood Signed-off-by: Alexander Graf --- hw/openpic.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/hw/openpic.c b/hw/openpic.c index 25aa9bf45..a4488c2d4 100644 --- a/hw/openpic.c +++ b/hw/openpic.c @@ -436,13 +436,13 @@ static void openpic_update_irq(OpenPICState *opp, int n_IRQ) src->ivpr &= ~IVPR_ACTIVITY_MASK; } - if (src->idr == 0) { + if (src->destmask == 0) { /* No target */ DPRINTF("%s: IRQ %d has no target\n", __func__, n_IRQ); return; } - if (src->idr == (1 << src->last_cpu)) { + if (src->destmask == (1 << src->last_cpu)) { /* Only one CPU is allowed to receive this IRQ */ IRQ_local_pipe(opp, src->last_cpu, n_IRQ, active, was_active); } else if (!(src->ivpr & IVPR_MODE_MASK)) { @@ -1000,8 +1000,7 @@ static void openpic_cpu_write_internal(void *opaque, hwaddr addr, case 0x70: idx = (addr - 0x40) >> 4; /* we use IDE as mask which CPUs to deliver the IPI to still. */ - write_IRQreg_idr(opp, opp->irq_ipi0 + idx, - opp->src[opp->irq_ipi0 + idx].idr | val); + opp->src[opp->irq_ipi0 + idx].destmask |= val; openpic_set_irq(opp, opp->irq_ipi0 + idx, 1); openpic_set_irq(opp, opp->irq_ipi0 + idx, 0); break; @@ -1101,8 +1100,8 @@ static uint32_t openpic_iack(OpenPICState *opp, IRQDest *dst, int cpu) } if ((irq >= opp->irq_ipi0) && (irq < (opp->irq_ipi0 + MAX_IPI))) { - src->idr &= ~(1 << cpu); - if (src->idr && !src->level) { + src->destmask &= ~(1 << cpu); + if (src->destmask && !src->level) { /* trigger on CPUs that didn't know about it yet */ openpic_set_irq(opp, irq, 1); openpic_set_irq(opp, irq, 0); @@ -1307,6 +1306,7 @@ static void openpic_save(QEMUFile* f, void *opaque) for (i = 0; i < opp->max_irq; i++) { qemu_put_be32s(f, &opp->src[i].ivpr); qemu_put_be32s(f, &opp->src[i].idr); + qemu_get_be32s(f, &opp->src[i].destmask); qemu_put_sbe32s(f, &opp->src[i].last_cpu); qemu_put_sbe32s(f, &opp->src[i].pending); } @@ -1372,6 +1372,7 @@ static int openpic_load(QEMUFile* f, void *opaque, int version_id) qemu_get_be32s(f, &opp->src[i].ivpr); qemu_get_be32s(f, &opp->src[i].idr); + qemu_get_be32s(f, &opp->src[i].destmask); qemu_get_sbe32s(f, &opp->src[i].last_cpu); qemu_get_sbe32s(f, &opp->src[i].pending); } From 03274d44f655f7b822e845e79fa32b261cdb0774 Mon Sep 17 00:00:00 2001 From: Scott Wood Date: Mon, 21 Jan 2013 15:53:52 +0000 Subject: [PATCH 17/20] openpic: fix timer address decoding The timer memory range begins at 0x10f0, so that address 0x1120 shows up as 0x30, 0x1130 shows up as 0x40, etc. However, the address decoding (other than TFRR) is not adjusted for this, causing the wrong registers to be accessed. Signed-off-by: Scott Wood Signed-off-by: Alexander Graf --- hw/openpic.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/hw/openpic.c b/hw/openpic.c index a4488c2d4..0a4379ff5 100644 --- a/hw/openpic.c +++ b/hw/openpic.c @@ -792,19 +792,23 @@ static void openpic_tmr_write(void *opaque, hwaddr addr, uint64_t val, OpenPICState *opp = opaque; int idx; + addr += 0x10f0; + DPRINTF("%s: addr %#" HWADDR_PRIx " <= %08" PRIx64 "\n", __func__, addr, val); if (addr & 0xF) { return; } - idx = (addr >> 6) & 0x3; - addr = addr & 0x30; - if (addr == 0x0) { + if (addr == 0x10f0) { /* TFRR */ opp->tfrr = val; return; } + + idx = (addr >> 6) & 0x3; + addr = addr & 0x30; + switch (addr & 0x30) { case 0x00: /* TCCR */ break; From e0dfe5b18919a6a4deb841dcf3212e3e998c95e5 Mon Sep 17 00:00:00 2001 From: Scott Wood Date: Mon, 21 Jan 2013 15:53:53 +0000 Subject: [PATCH 18/20] openpic: add basic support for MPIC v4.2 Besides the new value in the version register, this provides: - ILR support, which includes: - IDR becoming a pure CPU bitmap, allowing 32 CPUs - machine check output support (though other parts of QEMU need to be fixed for it to do something other than immediately reboot the guest) - dummy error interrupt support (EISR0/EIMR0 read as zero) - actually all FSL MPICs get all summary registers returning zero for now, which includes EISR0/EIMR0 Various refactoring is done to support these changes and to ease new functionality (e.g. a more flexible way of declaring regions). Just as the code was already not a full implementation of MPIC v2.0, this is not a full implementation of MPIC v4.2 -- e.g. it still has only one bank of MSIs. Signed-off-by: Scott Wood Signed-off-by: Alexander Graf --- hw/openpic.c | 348 ++++++++++++++++++++++++++++++++++----------------- hw/openpic.h | 1 + 2 files changed, 232 insertions(+), 117 deletions(-) diff --git a/hw/openpic.c b/hw/openpic.c index 0a4379ff5..20a479c79 100644 --- a/hw/openpic.c +++ b/hw/openpic.c @@ -56,7 +56,7 @@ static const int debug_openpic = 0; } \ } while (0) -#define MAX_CPU 15 +#define MAX_CPU 32 #define MAX_SRC 256 #define MAX_TMR 4 #define MAX_IPI 4 @@ -66,6 +66,7 @@ static const int debug_openpic = 0; /* OpenPIC capability flags */ #define OPENPIC_FLAG_IDR_CRIT (1 << 0) +#define OPENPIC_FLAG_ILR (2 << 0) /* OpenPIC address map */ #define OPENPIC_GLB_REG_START 0x0 @@ -74,6 +75,8 @@ static const int debug_openpic = 0; #define OPENPIC_TMR_REG_SIZE 0x220 #define OPENPIC_MSI_REG_START 0x1600 #define OPENPIC_MSI_REG_SIZE 0x200 +#define OPENPIC_SUMMARY_REG_START 0x3800 +#define OPENPIC_SUMMARY_REG_SIZE 0x800 #define OPENPIC_SRC_REG_START 0x10000 #define OPENPIC_SRC_REG_SIZE (MAX_SRC * 0x20) #define OPENPIC_CPU_REG_START 0x20000 @@ -94,33 +97,17 @@ static const int debug_openpic = 0; /* First doorbell IRQ */ #define RAVEN_DBL_IRQ (RAVEN_IPI_IRQ + (RAVEN_MAX_CPU * RAVEN_MAX_IPI)) -/* FSL_MPIC_20 */ -#define FSL_MPIC_20_MAX_CPU 1 -#define FSL_MPIC_20_MAX_EXT 12 -#define FSL_MPIC_20_MAX_INT 64 -#define FSL_MPIC_20_MAX_IRQ MAX_IRQ +typedef struct FslMpicInfo { + int max_ext; +} FslMpicInfo; -/* Interrupt definitions */ -/* IRQs, accessible through the IRQ region */ -#define FSL_MPIC_20_EXT_IRQ 0x00 -#define FSL_MPIC_20_INT_IRQ 0x10 -#define FSL_MPIC_20_MSG_IRQ 0xb0 -#define FSL_MPIC_20_MSI_IRQ 0xe0 -/* These are available through separate regions, but - for simplicity's sake mapped into the same number space */ -#define FSL_MPIC_20_TMR_IRQ 0x100 -#define FSL_MPIC_20_IPI_IRQ 0x104 +static FslMpicInfo fsl_mpic_20 = { + .max_ext = 12, +}; -/* - * Block Revision Register1 (BRR1): QEMU does not fully emulate - * any version on MPIC. So to start with, set the IP version to 0. - * - * NOTE: This is Freescale MPIC specific register. Keep it here till - * this code is refactored for different variants of OPENPIC and MPIC. - */ -#define FSL_BRR1_IPID (0x0040 << 16) /* 16 bit IP-block ID */ -#define FSL_BRR1_IPMJ (0x00 << 8) /* 8 bit IP major number */ -#define FSL_BRR1_IPMN 0x00 /* 8 bit IP minor number */ +static FslMpicInfo fsl_mpic_42 = { + .max_ext = 12, +}; #define FRR_NIRQ_SHIFT 16 #define FRR_NCPU_SHIFT 8 @@ -146,6 +133,49 @@ static const int debug_openpic = 0; #define IDR_P1_SHIFT 1 #define IDR_P0_SHIFT 0 +#define ILR_INTTGT_MASK 0x000000ff +#define ILR_INTTGT_INT 0x00 +#define ILR_INTTGT_CINT 0x01 /* critical */ +#define ILR_INTTGT_MCP 0x02 /* machine check */ + +/* The currently supported INTTGT values happen to be the same as QEMU's + * openpic output codes, but don't depend on this. The output codes + * could change (unlikely, but...) or support could be added for + * more INTTGT values. + */ +static const int inttgt_output[][2] = { + { ILR_INTTGT_INT, OPENPIC_OUTPUT_INT }, + { ILR_INTTGT_CINT, OPENPIC_OUTPUT_CINT }, + { ILR_INTTGT_MCP, OPENPIC_OUTPUT_MCK }, +}; + +static int inttgt_to_output(int inttgt) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(inttgt_output); i++) { + if (inttgt_output[i][0] == inttgt) { + return inttgt_output[i][1]; + } + } + + fprintf(stderr, "%s: unsupported inttgt %d\n", __func__, inttgt); + return OPENPIC_OUTPUT_INT; +} + +static int output_to_inttgt(int output) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(inttgt_output); i++) { + if (inttgt_output[i][1] == output) { + return inttgt_output[i][0]; + } + } + + abort(); +} + #define MSIIR_OFFSET 0x140 #define MSIIR_SRS_SHIFT 29 #define MSIIR_SRS_MASK (0x7 << MSIIR_SRS_SHIFT) @@ -230,6 +260,7 @@ typedef struct OpenPICState { MemoryRegion mem; /* Behavior control */ + FslMpicInfo *fsl; uint32_t model; uint32_t flags; uint32_t nb_irqs; @@ -243,7 +274,7 @@ typedef struct OpenPICState { uint32_t mpic_mode_mask; /* Sub-regions */ - MemoryRegion sub_io_mem[5]; + MemoryRegion sub_io_mem[6]; /* Global registers */ uint32_t frr; /* Feature reporting register */ @@ -558,6 +589,15 @@ static inline uint32_t read_IRQreg_idr(OpenPICState *opp, int n_IRQ) return opp->src[n_IRQ].idr; } +static inline uint32_t read_IRQreg_ilr(OpenPICState *opp, int n_IRQ) +{ + if (opp->flags & OPENPIC_FLAG_ILR) { + return output_to_inttgt(opp->src[n_IRQ].output); + } + + return 0xffffffff; +} + static inline uint32_t read_IRQreg_ivpr(OpenPICState *opp, int n_IRQ) { return opp->src[n_IRQ].ivpr; @@ -608,6 +648,19 @@ static inline void write_IRQreg_idr(OpenPICState *opp, int n_IRQ, uint32_t val) } } +static inline void write_IRQreg_ilr(OpenPICState *opp, int n_IRQ, uint32_t val) +{ + if (opp->flags & OPENPIC_FLAG_ILR) { + IRQSource *src = &opp->src[n_IRQ]; + + src->output = inttgt_to_output(val & ILR_INTTGT_MASK); + DPRINTF("Set ILR %d to 0x%08x, output %d\n", n_IRQ, src->idr, + src->output); + + /* TODO: on MPIC v4.0 only, set nomask for non-INT */ + } +} + static inline void write_IRQreg_ivpr(OpenPICState *opp, int n_IRQ, uint32_t val) { uint32_t mask; @@ -874,17 +927,20 @@ static void openpic_src_write(void *opaque, hwaddr addr, uint64_t val, DPRINTF("%s: addr %#" HWADDR_PRIx " <= %08" PRIx64 "\n", __func__, addr, val); - if (addr & 0xF) { - return; - } - addr = addr & 0xFFF0; + + addr = addr & 0xffff; idx = addr >> 5; - if (addr & 0x10) { - /* EXDE / IFEDE / IEEDE */ - write_IRQreg_idr(opp, idx, val); - } else { - /* EXVP / IFEVP / IEEVP */ + + switch (addr & 0x1f) { + case 0x00: write_IRQreg_ivpr(opp, idx, val); + break; + case 0x10: + write_IRQreg_idr(opp, idx, val); + break; + case 0x18: + write_IRQreg_ilr(opp, idx, val); + break; } } @@ -896,20 +952,23 @@ static uint64_t openpic_src_read(void *opaque, uint64_t addr, unsigned len) DPRINTF("%s: addr %#" HWADDR_PRIx "\n", __func__, addr); retval = 0xFFFFFFFF; - if (addr & 0xF) { - return retval; - } - addr = addr & 0xFFF0; - idx = addr >> 5; - if (addr & 0x10) { - /* EXDE / IFEDE / IEEDE */ - retval = read_IRQreg_idr(opp, idx); - } else { - /* EXVP / IFEVP / IEEVP */ - retval = read_IRQreg_ivpr(opp, idx); - } - DPRINTF("%s: => 0x%08x\n", __func__, retval); + addr = addr & 0xffff; + idx = addr >> 5; + + switch (addr & 0x1f) { + case 0x00: + retval = read_IRQreg_ivpr(opp, idx); + break; + case 0x10: + retval = read_IRQreg_idr(opp, idx); + break; + case 0x18: + retval = read_IRQreg_ilr(opp, idx); + break; + } + + DPRINTF("%s: => 0x%08x\n", __func__, retval); return retval; } @@ -977,6 +1036,26 @@ static uint64_t openpic_msi_read(void *opaque, hwaddr addr, unsigned size) return r; } +static uint64_t openpic_summary_read(void *opaque, hwaddr addr, unsigned size) +{ + uint64_t r = 0; + + DPRINTF("%s: addr %#" HWADDR_PRIx "\n", __func__, addr); + + /* TODO: EISR/EIMR */ + + return r; +} + +static void openpic_summary_write(void *opaque, hwaddr addr, uint64_t val, + unsigned size) +{ + DPRINTF("%s: addr %#" HWADDR_PRIx " <= 0x%08" PRIx64 "\n", + __func__, addr, val); + + /* TODO: EISR/EIMR */ +} + static void openpic_cpu_write_internal(void *opaque, hwaddr addr, uint32_t val, int idx) { @@ -1242,19 +1321,19 @@ static const MemoryRegionOps openpic_src_ops_be = { }, }; -static const MemoryRegionOps openpic_msi_ops_le = { +static const MemoryRegionOps openpic_msi_ops_be = { .read = openpic_msi_read, .write = openpic_msi_write, - .endianness = DEVICE_LITTLE_ENDIAN, + .endianness = DEVICE_BIG_ENDIAN, .impl = { .min_access_size = 4, .max_access_size = 4, }, }; -static const MemoryRegionOps openpic_msi_ops_be = { - .read = openpic_msi_read, - .write = openpic_msi_write, +static const MemoryRegionOps openpic_summary_ops_be = { + .read = openpic_summary_read, + .write = openpic_summary_write, .endianness = DEVICE_BIG_ENDIAN, .impl = { .min_access_size = 4, @@ -1387,78 +1466,128 @@ static int openpic_load(QEMUFile* f, void *opaque, int version_id) typedef struct MemReg { const char *name; MemoryRegionOps const *ops; - bool map; hwaddr start_addr; ram_addr_t size; } MemReg; +static void fsl_common_init(OpenPICState *opp) +{ + int i; + int virq = MAX_SRC; + + opp->vid = VID_REVISION_1_2; + opp->vir = VIR_GENERIC; + opp->vector_mask = 0xFFFF; + opp->tfrr_reset = 0; + opp->ivpr_reset = IVPR_MASK_MASK; + opp->idr_reset = 1 << 0; + opp->max_irq = MAX_IRQ; + + opp->irq_ipi0 = virq; + virq += MAX_IPI; + opp->irq_tim0 = virq; + virq += MAX_TMR; + + assert(virq <= MAX_IRQ); + + opp->irq_msi = 224; + + msi_supported = true; + for (i = 0; i < opp->fsl->max_ext; i++) { + opp->src[i].level = false; + } + + /* Internal interrupts, including message and MSI */ + for (i = 16; i < MAX_SRC; i++) { + opp->src[i].type = IRQ_TYPE_FSLINT; + opp->src[i].level = true; + } + + /* timers and IPIs */ + for (i = MAX_SRC; i < virq; i++) { + opp->src[i].type = IRQ_TYPE_FSLSPECIAL; + opp->src[i].level = false; + } +} + +static void map_list(OpenPICState *opp, const MemReg *list, int *count) +{ + while (list->name) { + assert(*count < ARRAY_SIZE(opp->sub_io_mem)); + + memory_region_init_io(&opp->sub_io_mem[*count], list->ops, opp, + list->name, list->size); + + memory_region_add_subregion(&opp->mem, list->start_addr, + &opp->sub_io_mem[*count]); + + (*count)++; + list++; + } +} + static int openpic_init(SysBusDevice *dev) { OpenPICState *opp = FROM_SYSBUS(typeof (*opp), dev); int i, j; - MemReg list_le[] = { - {"glb", &openpic_glb_ops_le, true, + int list_count = 0; + static const MemReg list_le[] = { + {"glb", &openpic_glb_ops_le, OPENPIC_GLB_REG_START, OPENPIC_GLB_REG_SIZE}, - {"tmr", &openpic_tmr_ops_le, true, + {"tmr", &openpic_tmr_ops_le, OPENPIC_TMR_REG_START, OPENPIC_TMR_REG_SIZE}, - {"msi", &openpic_msi_ops_le, true, - OPENPIC_MSI_REG_START, OPENPIC_MSI_REG_SIZE}, - {"src", &openpic_src_ops_le, true, + {"src", &openpic_src_ops_le, OPENPIC_SRC_REG_START, OPENPIC_SRC_REG_SIZE}, - {"cpu", &openpic_cpu_ops_le, true, + {"cpu", &openpic_cpu_ops_le, OPENPIC_CPU_REG_START, OPENPIC_CPU_REG_SIZE}, + {NULL} }; - MemReg list_be[] = { - {"glb", &openpic_glb_ops_be, true, + static const MemReg list_be[] = { + {"glb", &openpic_glb_ops_be, OPENPIC_GLB_REG_START, OPENPIC_GLB_REG_SIZE}, - {"tmr", &openpic_tmr_ops_be, true, + {"tmr", &openpic_tmr_ops_be, OPENPIC_TMR_REG_START, OPENPIC_TMR_REG_SIZE}, - {"msi", &openpic_msi_ops_be, true, - OPENPIC_MSI_REG_START, OPENPIC_MSI_REG_SIZE}, - {"src", &openpic_src_ops_be, true, + {"src", &openpic_src_ops_be, OPENPIC_SRC_REG_START, OPENPIC_SRC_REG_SIZE}, - {"cpu", &openpic_cpu_ops_be, true, + {"cpu", &openpic_cpu_ops_be, OPENPIC_CPU_REG_START, OPENPIC_CPU_REG_SIZE}, + {NULL} }; - MemReg *list; + static const MemReg list_fsl[] = { + {"msi", &openpic_msi_ops_be, + OPENPIC_MSI_REG_START, OPENPIC_MSI_REG_SIZE}, + {"summary", &openpic_summary_ops_be, + OPENPIC_SUMMARY_REG_START, OPENPIC_SUMMARY_REG_SIZE}, + {NULL} + }; + + memory_region_init(&opp->mem, "openpic", 0x40000); switch (opp->model) { case OPENPIC_MODEL_FSL_MPIC_20: default: + opp->fsl = &fsl_mpic_20; + opp->brr1 = 0x00400200; opp->flags |= OPENPIC_FLAG_IDR_CRIT; opp->nb_irqs = 80; - opp->vid = VID_REVISION_1_2; - opp->vir = VIR_GENERIC; - opp->vector_mask = 0xFFFF; - opp->tfrr_reset = 0; - opp->ivpr_reset = IVPR_MASK_MASK; - opp->idr_reset = 1 << 0; - opp->max_irq = FSL_MPIC_20_MAX_IRQ; - opp->irq_ipi0 = FSL_MPIC_20_IPI_IRQ; - opp->irq_tim0 = FSL_MPIC_20_TMR_IRQ; - opp->irq_msi = FSL_MPIC_20_MSI_IRQ; - opp->brr1 = FSL_BRR1_IPID | FSL_BRR1_IPMJ | FSL_BRR1_IPMN; - /* XXX really only available as of MPIC 4.0 */ + opp->mpic_mode_mask = GCR_MODE_MIXED; + + fsl_common_init(opp); + map_list(opp, list_be, &list_count); + map_list(opp, list_fsl, &list_count); + + break; + + case OPENPIC_MODEL_FSL_MPIC_42: + opp->fsl = &fsl_mpic_42; + opp->brr1 = 0x00400402; + opp->flags |= OPENPIC_FLAG_ILR; + opp->nb_irqs = 196; opp->mpic_mode_mask = GCR_MODE_PROXY; - msi_supported = true; - list = list_be; - - for (i = 0; i < FSL_MPIC_20_MAX_EXT; i++) { - opp->src[i].level = false; - } - - /* Internal interrupts, including message and MSI */ - for (i = 16; i < MAX_SRC; i++) { - opp->src[i].type = IRQ_TYPE_FSLINT; - opp->src[i].level = true; - } - - /* timers and IPIs */ - for (i = MAX_SRC; i < MAX_IRQ; i++) { - opp->src[i].type = IRQ_TYPE_FSLSPECIAL; - opp->src[i].level = false; - } + fsl_common_init(opp); + map_list(opp, list_be, &list_count); + map_list(opp, list_fsl, &list_count); break; @@ -1475,31 +1604,16 @@ static int openpic_init(SysBusDevice *dev) opp->irq_tim0 = RAVEN_TMR_IRQ; opp->brr1 = -1; opp->mpic_mode_mask = GCR_MODE_MIXED; - list = list_le; - /* Don't map MSI region */ - list[2].map = false; /* Only UP supported today */ if (opp->nb_cpus != 1) { return -EINVAL; } + + map_list(opp, list_le, &list_count); break; } - memory_region_init(&opp->mem, "openpic", 0x40000); - - for (i = 0; i < ARRAY_SIZE(list_le); i++) { - if (!list[i].map) { - continue; - } - - memory_region_init_io(&opp->sub_io_mem[i], list[i].ops, opp, - list[i].name, list[i].size); - - memory_region_add_subregion(&opp->mem, list[i].start_addr, - &opp->sub_io_mem[i]); - } - for (i = 0; i < opp->nb_cpus; i++) { opp->dst[i].irqs = g_new(qemu_irq, OPENPIC_OUTPUT_NB); for (j = 0; j < OPENPIC_OUTPUT_NB; j++) { diff --git a/hw/openpic.h b/hw/openpic.h index e226d7b56..9dcaf0e7c 100644 --- a/hw/openpic.h +++ b/hw/openpic.h @@ -13,5 +13,6 @@ enum { #define OPENPIC_MODEL_RAVEN 0 #define OPENPIC_MODEL_FSL_MPIC_20 1 +#define OPENPIC_MODEL_FSL_MPIC_42 2 #endif /* __OPENPIC_H__ */ From bd25922e737a2c90668a7bdd1e1319413a7a51f3 Mon Sep 17 00:00:00 2001 From: Scott Wood Date: Mon, 21 Jan 2013 15:53:54 +0000 Subject: [PATCH 19/20] PPC: e500: fix mpic_iack address MPIC+0xa0 is IACK for the current CPU. MPIC+0x200a0 is IACK for CPU 0. This fix allows EPR to work with an SMP target. Signed-off-by: Scott Wood Signed-off-by: Alexander Graf --- hw/ppc/e500.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c index 9ccf4d184..530f9290f 100644 --- a/hw/ppc/e500.c +++ b/hw/ppc/e500.c @@ -505,7 +505,7 @@ void ppce500_init(PPCE500Params *params) irqs[i][OPENPIC_OUTPUT_CINT] = input[PPCE500_INPUT_CINT]; env->spr[SPR_BOOKE_PIR] = cs->cpu_index = i; env->mpic_iack = MPC8544_CCSRBAR_BASE + - MPC8544_MPIC_REGS_OFFSET + 0x200A0; + MPC8544_MPIC_REGS_OFFSET + 0xa0; ppc_booke_timers_init(cpu, 400000000, PPC_TIMER_E500); From f5fba9d27f14603dc7f85779e7b7362fb1cfcbd8 Mon Sep 17 00:00:00 2001 From: Scott Wood Date: Mon, 21 Jan 2013 15:53:55 +0000 Subject: [PATCH 20/20] PPC: e500: Select MPIC v4.2 on ppce500 platform The compatible string is changed to fsl,mpic on all e500 platforms, to advertise the existence of BRR1. This matches what the device tree will have on real hardware. With MPIC v4.2 max_cpu can be increased from 15 to 32. Signed-off-by: Scott Wood Signed-off-by: Alexander Graf --- hw/ppc/e500.c | 4 ++-- hw/ppc/e500.h | 2 ++ hw/ppc/e500plat.c | 4 +++- hw/ppc/mpc8544ds.c | 2 ++ 4 files changed, 9 insertions(+), 3 deletions(-) diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c index 530f9290f..b7474c05f 100644 --- a/hw/ppc/e500.c +++ b/hw/ppc/e500.c @@ -297,7 +297,7 @@ static int ppce500_load_device_tree(CPUPPCState *env, snprintf(mpic, sizeof(mpic), "%s/pic@%llx", soc, MPC8544_MPIC_REGS_OFFSET); qemu_devtree_add_subnode(fdt, mpic); qemu_devtree_setprop_string(fdt, mpic, "device_type", "open-pic"); - qemu_devtree_setprop_string(fdt, mpic, "compatible", "chrp,open-pic"); + qemu_devtree_setprop_string(fdt, mpic, "compatible", "fsl,mpic"); qemu_devtree_setprop_cells(fdt, mpic, "reg", MPC8544_MPIC_REGS_OFFSET, 0x40000); qemu_devtree_setprop_cell(fdt, mpic, "#address-cells", 0); @@ -545,7 +545,7 @@ void ppce500_init(PPCE500Params *params) mpic = g_new(qemu_irq, 256); dev = qdev_create(NULL, "openpic"); qdev_prop_set_uint32(dev, "nb_cpus", smp_cpus); - qdev_prop_set_uint32(dev, "model", OPENPIC_MODEL_FSL_MPIC_20); + qdev_prop_set_uint32(dev, "model", params->mpic_version); qdev_init_nofail(dev); s = SYS_BUS_DEVICE(dev); diff --git a/hw/ppc/e500.h b/hw/ppc/e500.h index f5ff27385..226c93d24 100644 --- a/hw/ppc/e500.h +++ b/hw/ppc/e500.h @@ -16,6 +16,8 @@ typedef struct PPCE500Params { /* required -- must at least add toplevel board compatible */ void (*fixup_devtree)(struct PPCE500Params *params, void *fdt); + + int mpic_version; } PPCE500Params; void ppce500_init(PPCE500Params *params); diff --git a/hw/ppc/e500plat.c b/hw/ppc/e500plat.c index 2dcc4a985..25ac4b1da 100644 --- a/hw/ppc/e500plat.c +++ b/hw/ppc/e500plat.c @@ -15,6 +15,7 @@ #include "../boards.h" #include "sysemu/device_tree.h" #include "hw/pci/pci.h" +#include "hw/openpic.h" static void e500plat_fixup_devtree(PPCE500Params *params, void *fdt) { @@ -44,6 +45,7 @@ static void e500plat_init(QEMUMachineInitArgs *args) .pci_first_slot = 0x1, .pci_nr_slots = PCI_SLOT_MAX - 1, .fixup_devtree = e500plat_fixup_devtree, + .mpic_version = OPENPIC_MODEL_FSL_MPIC_42, }; ppce500_init(¶ms); @@ -53,7 +55,7 @@ static QEMUMachine e500plat_machine = { .name = "ppce500", .desc = "generic paravirt e500 platform", .init = e500plat_init, - .max_cpus = 15, + .max_cpus = 32, DEFAULT_MACHINE_OPTIONS, }; diff --git a/hw/ppc/mpc8544ds.c b/hw/ppc/mpc8544ds.c index 8e05e55c8..e25c70b1f 100644 --- a/hw/ppc/mpc8544ds.c +++ b/hw/ppc/mpc8544ds.c @@ -14,6 +14,7 @@ #include "e500.h" #include "../boards.h" #include "sysemu/device_tree.h" +#include "hw/openpic.h" static void mpc8544ds_fixup_devtree(PPCE500Params *params, void *fdt) { @@ -43,6 +44,7 @@ static void mpc8544ds_init(QEMUMachineInitArgs *args) .pci_first_slot = 0x11, .pci_nr_slots = 2, .fixup_devtree = mpc8544ds_fixup_devtree, + .mpic_version = OPENPIC_MODEL_FSL_MPIC_20, }; ppce500_init(¶ms);