* [Qemu-devel] [RFC 1/6] pci: add MPC105 PCI host bridge emulation
2013-03-14 22:12 [Qemu-devel] [RFC 0/6] ppc/prep: add IBM RS/6000 43p machine Hervé Poussineau
@ 2013-03-14 22:12 ` Hervé Poussineau
2013-03-14 22:12 ` [Qemu-devel] [RFC 2/6] prep: add IBM RS/6000 7248 (43p) machine emulation Hervé Poussineau
` (4 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Hervé Poussineau @ 2013-03-14 22:12 UTC (permalink / raw)
To: qemu-devel; +Cc: Andreas Färber, Hervé Poussineau
Missing parts are:
- set_irq() and map_irq() functions
- missing handling of non-contiguous I/O
- migration
There is also somewhere a bug in the memory controller, which means
that some real firmwares may not detect the correct amount of memory.
This can be bypassed by adding '-m 1G' on the command line.
---
default-configs/ppc-softmmu.mak | 1 +
hw/Makefile.objs | 1 +
hw/mpc105.c | 419 +++++++++++++++++++++++++++++++++++++++
hw/pci/pci_ids.h | 1 +
trace-events | 7 +
5 files changed, 429 insertions(+)
create mode 100644 hw/mpc105.c
diff --git a/default-configs/ppc-softmmu.mak b/default-configs/ppc-softmmu.mak
index c209a8d..45ab549 100644
--- a/default-configs/ppc-softmmu.mak
+++ b/default-configs/ppc-softmmu.mak
@@ -27,6 +27,7 @@ CONFIG_MAC_NVRAM=y
CONFIG_MAC_DBDMA=y
CONFIG_HEATHROW_PIC=y
CONFIG_GRACKLE_PCI=y
+CONFIG_MPC105_PCI=y
CONFIG_UNIN_PCI=y
CONFIG_DEC_PCI=y
CONFIG_PPCE500_PCI=y
diff --git a/hw/Makefile.objs b/hw/Makefile.objs
index eb7eb31..098d5d3 100644
--- a/hw/Makefile.objs
+++ b/hw/Makefile.objs
@@ -50,6 +50,7 @@ common-obj-y += pam.o
common-obj-$(CONFIG_PREP_PCI) += prep_pci.o
common-obj-$(CONFIG_I82378) += i82378.o
common-obj-$(CONFIG_PC87312) += pc87312.o
+common-obj-$(CONFIG_MPC105_PCI) += mpc105.o
# Mac shared devices
common-obj-$(CONFIG_MACIO) += macio.o
common-obj-$(CONFIG_CUDA) += cuda.o
diff --git a/hw/mpc105.c b/hw/mpc105.c
new file mode 100644
index 0000000..63be5b5
--- /dev/null
+++ b/hw/mpc105.c
@@ -0,0 +1,419 @@
+/*
+ * QEMU MPC-105 Eagle PCI host
+ *
+ * Copyright (c) 2013 Hervé Poussineau
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) version 3 or any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "pci/pci.h"
+#include "pci/pci_bus.h"
+#include "pci/pci_host.h"
+#include "exec/address-spaces.h"
+#include "pc.h"
+#include "loader.h"
+#include "trace.h"
+
+#define TYPE_MPC105_PCI_HOST_BRIDGE "mpc105-pcihost"
+#define MPC105_PCI_HOST_BRIDGE(obj) \
+ OBJECT_CHECK(Mpc105HostState, (obj), TYPE_MPC105_PCI_HOST_BRIDGE)
+
+#define TYPE_MPC105 "mpc105"
+#define MPC105(obj) \
+ OBJECT_CHECK(Mpc105State, (obj), TYPE_MPC105)
+
+#define MEM_STA_03 0x0080
+#define MEM_STA_47 0x0084
+#define EXT_MEM_STA_03 0x0088
+#define EXT_MEM_STA_47 0x008c
+#define MEM_END_03 0x0090
+#define MEM_END_47 0x0094
+#define EXT_MEM_END_03 0x0098
+#define EXT_MEM_END_47 0x009c
+#define MEM_BANK_EN 0x00a0
+#define PROC_CFG_A8 0x00a8
+#define PROC_CFG_AC 0x00ac
+#define ALT_OSV_1 0x00ba
+#define ERR_EN_REG1 0x00c0
+#define ERR_DR1 0x00c1
+#define ERR_EN_REG2 0x00c4
+#define MEM_CFG_1 0x00f0
+#define MEM_CFG_2 0x00f4
+#define MEM_CFG_4 0x00fc
+
+#define BIOS_SIZE (1024 * 1024)
+
+typedef struct Mpc105State {
+ PCIDevice dev;
+ uint32_t ram_size;
+ char *bios_name;
+ MemoryRegion bios;
+ MemoryRegion simm[8];
+ bool use_sizer[8];
+ MemoryRegion simm_sizer[8];
+} Mpc105State;
+
+static uint64_t mpc105_unassigned_read(void *opaque, hwaddr addr,
+ unsigned int size)
+{
+ trace_mpc105_unassigned_mem_read(addr);
+ return 0;
+}
+
+static void mpc105_unassigned_write(void *opaque, hwaddr addr, uint64_t data,
+ unsigned int size)
+{
+ trace_mpc105_unassigned_mem_write(addr, data);
+}
+
+static const MemoryRegionOps mpc105_unassigned_ops = {
+ .read = mpc105_unassigned_read,
+ .write = mpc105_unassigned_write,
+};
+
+static void mpc105_write_config(PCIDevice *dev, uint32_t addr, uint32_t val, int l)
+{
+ Mpc105State *s = MPC105(dev);
+ uint8_t *pci_conf;
+ int i;
+
+ pci_conf = s->dev.config;
+
+ pci_default_write_config(dev, addr, val, l);
+ if ((addr >= MEM_STA_03 && addr <= MEM_BANK_EN) || addr == MEM_CFG_1) {
+ uint32_t start_address, end_address;
+ uint32_t start, ext_start, end, ext_end;
+ uint32_t cfg1 = pci_get_long(pci_conf + MEM_CFG_1);
+ uint8_t en;
+ bool enabled;
+
+ memory_region_transaction_begin();
+ if (cfg1 & (1 << 19)) {
+ /* MEMGO enabled */
+ en = pci_get_byte(pci_conf + MEM_BANK_EN);
+ } else {
+ en = 0;
+ }
+
+ for (i = 0; i < 8; i++) {
+ enabled = (en & (1 << i));
+
+ start = pci_get_byte(pci_conf + MEM_STA_03 + i);
+ ext_start = pci_get_byte(pci_conf + EXT_MEM_STA_03 + i) & 0x3;
+ end = pci_get_byte(pci_conf + MEM_END_03 + i);
+ ext_end = pci_get_byte(pci_conf + EXT_MEM_STA_03 + i) & 0x3;
+ start_address = (ext_start << 28) | (start << 20);
+ end_address = (ext_end << 28) | (end << 20) | 0xfffff;
+
+ enabled &= start_address < end_address;
+
+ if (enabled) {
+ trace_mpc105_simm_enable(i, start_address, end_address + 1);
+ } else {
+ trace_mpc105_simm_disable(i);
+ }
+
+ if (memory_region_size(&s->simm[i]) == 0) {
+ continue;
+ }
+
+ /* Clean links between system memory, simm_sizer and simm */
+ if (s->use_sizer[i]) {
+ memory_region_del_subregion(get_system_memory(), &s->simm_sizer[i]);
+ memory_region_del_subregion(&s->simm_sizer[i], &s->simm[i]);
+ s->use_sizer[i] = false;
+ } else {
+ memory_region_del_subregion(get_system_memory(), &s->simm[i]);
+ }
+
+ /* Recreate links compatible with new memory layout */
+ if (enabled && end_address - start_address + 1 < memory_region_size(&s->simm[i])) {
+ memory_region_init_io(&s->simm_sizer[i], &mpc105_unassigned_ops,
+ s, memory_region_name(&s->simm_sizer[i]),
+ end_address - start_address + 1);
+ memory_region_add_subregion(&s->simm_sizer[i], 0, &s->simm[i]);
+ memory_region_add_subregion(get_system_memory(), start_address, &s->simm_sizer[i]);
+ s->use_sizer[i] = true;
+ } else {
+ memory_region_add_subregion(get_system_memory(), start_address, &s->simm[i]);
+ }
+ memory_region_set_enabled(&s->simm[i], enabled);
+ }
+ memory_region_transaction_commit();
+ }
+}
+
+static void mpc105_reset(Mpc105State *s)
+{
+ uint8_t *pci_conf;
+ int id;
+
+ pci_conf = s->dev.config;
+
+ memset(pci_conf + PCI_CONFIG_HEADER_SIZE, 0, PCI_CONFIG_SPACE_SIZE - PCI_CONFIG_HEADER_SIZE);
+ pci_conf[PCI_COMMAND] = PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
+ pci_conf[PCI_STATUS] = PCI_STATUS_FAST_BACK;
+ pci_set_long(pci_conf + PROC_CFG_A8, 0xff000010);
+ pci_set_long(pci_conf + PROC_CFG_AC, 0x000c060c);
+ pci_set_byte(pci_conf + ALT_OSV_1, 0x04);
+ pci_set_byte(pci_conf + ERR_EN_REG1, 0x01);
+ pci_set_long(pci_conf + MEM_CFG_1, 0xff020000);
+ pci_set_long(pci_conf + MEM_CFG_2, 0x00000003);
+ pci_set_long(pci_conf + MEM_CFG_4, 0x00100000);
+
+ memset(s->dev.wmask + PCI_CONFIG_HEADER_SIZE, 0, MEM_CFG_1 - PCI_CONFIG_HEADER_SIZE);
+ memset(s->dev.wmask + 0x70, 0xff, 2);
+ memset(s->dev.wmask + MEM_STA_03, 0xff, MEM_BANK_EN - MEM_STA_03 + 1);
+ memset(s->dev.wmask + PROC_CFG_A8, 0xff, 8);
+ pci_set_word(s->dev.wmask + ALT_OSV_1, 0xffff);
+ pci_set_byte(s->dev.wmask + ERR_EN_REG1, 0xff);
+ pci_set_byte(s->dev.w1cmask + ERR_DR1, 0xff);
+ pci_set_byte(s->dev.w1cmask + 0xc3, 0xff);
+ pci_set_byte(s->dev.wmask + ERR_EN_REG2, 0xff);
+ pci_set_byte(s->dev.w1cmask + 0xc5, 0xff);
+ pci_set_byte(s->dev.w1cmask + 0xc7, 0xff);
+
+ for (id = 0; id < 8; ++id) {
+ memory_region_set_enabled(&s->simm[id], false);
+ }
+}
+
+static void qdev_mpc105_reset(DeviceState *dev)
+{
+ Mpc105State *s = MPC105(dev);
+ mpc105_reset(s);
+}
+
+static const VMStateDescription vmstate_mpc105 = {
+ .name = "mpc105",
+ .version_id = 1,
+ .minimum_version_id = 0,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField []) {
+ // FIXME
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+static uint64_t mpc105_intack_read(void *opaque, hwaddr addr,
+ unsigned int size)
+{
+ return pic_read_irq(isa_pic);
+}
+
+static const MemoryRegionOps mpc105_intack_ops = {
+ .read = mpc105_intack_read,
+ .valid = {
+ .max_access_size = 1,
+ },
+};
+
+static int mpc105_initfn(PCIDevice *dev)
+{
+ Mpc105State *s = MPC105(dev);
+ char *filename;
+ int bios_size;
+ int i = 0;
+ uint32_t simm_size[8] = { 0 };
+
+ unsigned int ram_size = s->ram_size / (1024 * 1024);
+ while (i < 8) {
+ int idx = qemu_fls(ram_size);
+ if (idx < 5) {
+ /* Need at least 16 Mb for a slot */
+ break;
+ } else if (idx >= 8) {
+ /* Limit to 128 Mb by slot (at max) */
+ idx = 8;
+ }
+ simm_size[i] = 1 << (idx - 1);
+ ram_size -= simm_size[i];
+ i++;
+ }
+
+ for (i = 0; i < 8; i++) {
+ char name[] = "simm.?";
+ name[5] = i + '0';
+ if (simm_size[i]) {
+ trace_mpc105_simm_size(i, simm_size[i]);
+ memory_region_init_ram(&s->simm[i], name, simm_size[i] * 1024 * 1024);
+ vmstate_register_ram_global(&s->simm[i]);
+ } else {
+ memory_region_init(&s->simm[i], name, 0);
+ }
+ memory_region_init(&s->simm_sizer[i], "sizer", 0);
+ memory_region_add_subregion_overlap(get_system_memory(), 0, &s->simm[i], i);
+ memory_region_set_enabled(&s->simm[i], false);
+ }
+
+ memory_region_init_ram(&s->bios, "bios", BIOS_SIZE);
+ memory_region_set_readonly(&s->bios, true);
+ memory_region_add_subregion(get_system_memory(), (uint32_t)(-BIOS_SIZE), &s->bios);
+ vmstate_register_ram_global(&s->bios);
+ if (s->bios_name) {
+ filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, s->bios_name);
+ if (filename) {
+ bios_size = get_image_size(filename);
+ if (bios_size > 0 && bios_size <= BIOS_SIZE) {
+ hwaddr bios_addr;
+ bios_size = (bios_size + 0xfff) & ~0xfff;
+ bios_addr = (uint32_t)(-BIOS_SIZE);
+ bios_size = load_image_targphys(filename, bios_addr, bios_size);
+ }
+ } else {
+ bios_size = -1;
+ }
+ if (bios_size < 0 || bios_size > BIOS_SIZE) {
+ hw_error("qemu: could not load IBM 43p bios '%s'\n", s->bios_name);
+ }
+ if (filename) {
+ g_free(filename);
+ }
+ }
+
+ return 0;
+}
+
+static void mpc105_class_init(ObjectClass *klass, void *data)
+{
+ PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ k->init = mpc105_initfn;
+ k->vendor_id = PCI_VENDOR_ID_MOTOROLA;
+ k->device_id = PCI_DEVICE_ID_MOTOROLA_MPC105;
+ k->class_id = PCI_CLASS_BRIDGE_HOST;
+ k->config_write = mpc105_write_config;
+ dc->desc = "MPC105 PCI bridge/Memory controller";
+ dc->reset = qdev_mpc105_reset;
+ dc->vmsd = &vmstate_mpc105;
+ dc->no_user = 1;
+}
+
+static TypeInfo mpc105_info = {
+ .name = TYPE_MPC105,
+ .parent = TYPE_PCI_DEVICE,
+ .instance_size = sizeof(Mpc105State),
+ .class_init = mpc105_class_init,
+};
+
+typedef struct Mpc105HostState {
+ PCIHostState host_state;
+ uint32_t ram_size;
+ qemu_irq irq[PCI_NUM_PINS];
+ PCIBus pci_bus;
+ MemoryRegion pci_io;
+ MemoryRegion isa_io;
+ MemoryRegion pci_intack;
+ MemoryRegion pci_memory;
+ MemoryRegion rom;
+ Mpc105State pci_dev;
+} Mpc105HostState;
+
+static void mpc105_set_irq(void *opaque, int irq_num, int level)
+{
+ // FIXME
+}
+
+static int mpc105_map_irq(PCIDevice *dev, int irq_num)
+{
+ // FIXME
+ return 0;
+}
+
+static void mpc105_pcihost_realizefn(DeviceState *d, Error **errp)
+{
+ SysBusDevice *dev = SYS_BUS_DEVICE(d);
+ PCIHostState *h = PCI_HOST_BRIDGE(dev);
+ Mpc105HostState *s = MPC105_PCI_HOST_BRIDGE(dev);
+ int i;
+
+ for (i = 0; i < PCI_NUM_PINS; i++) {
+ sysbus_init_irq(dev, &s->irq[i]);
+ }
+
+ pci_bus_irqs(&s->pci_bus, mpc105_set_irq, mpc105_map_irq, s->irq, 4);
+
+ memory_region_init_io(&h->conf_mem, &pci_host_conf_le_ops, s,
+ "pci-conf-idx", 1);
+ memory_region_add_subregion(get_system_io(), 0xcf8, &h->conf_mem);
+
+ memory_region_init_io(&h->data_mem, &pci_host_data_le_ops, s,
+ "pci-conf-data", 4);
+ memory_region_add_subregion(get_system_io(), 0xcfc, &h->data_mem);
+
+ object_property_set_bool(OBJECT(&s->pci_dev), true, "realized", errp);
+}
+
+static void mpc105_pcihost_initfn(Object *obj)
+{
+ PCIHostState *h = PCI_HOST_BRIDGE(obj);
+ Mpc105HostState *s = MPC105_PCI_HOST_BRIDGE(obj);
+ DeviceState *pci_dev;
+
+ memory_region_init(&s->pci_io, "pci-io", 0x3f800000);
+ isa_mmio_setup(&s->isa_io, 0x800000); /* FIXME: should handle non-contiguous I/O */
+ memory_region_init(&s->pci_memory, "pci-memory", 0x3f000000);
+ memory_region_init_io(&s->pci_intack, &mpc105_intack_ops, &s->pci_dev,
+ "pci-intack", 0x10);
+
+ memory_region_init_io(get_system_memory(), &mpc105_unassigned_ops,
+ &s->pci_dev, "system", UINT32_MAX);
+ memory_region_add_subregion(get_system_memory(), 0x80000000, &s->pci_io);
+ memory_region_add_subregion(&s->pci_io, 0, &s->isa_io);
+ memory_region_add_subregion(get_system_memory(), 0xc0000000, &s->pci_memory);
+ memory_region_add_subregion(get_system_memory(), 0xbffffff0, &s->pci_intack);
+
+ pci_bus_new_inplace(&s->pci_bus, DEVICE(obj), NULL,
+ &s->pci_memory, get_system_io(), 0);
+ h->bus = &s->pci_bus;
+
+ object_initialize(&s->pci_dev, TYPE_MPC105);
+ pci_dev = DEVICE(&s->pci_dev);
+ qdev_set_parent_bus(pci_dev, BUS(&s->pci_bus));
+ object_property_set_int(OBJECT(&s->pci_dev), PCI_DEVFN(0, 0), "addr",
+ NULL);
+ qdev_prop_set_bit(pci_dev, "multifunction", false);
+}
+
+static Property mpc105_pcihost_properties[] = {
+ DEFINE_PROP_UINT32("ram-size", Mpc105HostState, pci_dev.ram_size, 0),
+ DEFINE_PROP_STRING("bios-name", Mpc105HostState, pci_dev.bios_name),
+ DEFINE_PROP_END_OF_LIST()
+};
+
+static void mpc105_pcihost_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ dc->realize = mpc105_pcihost_realizefn;
+ dc->props = mpc105_pcihost_properties;
+ dc->no_user = 1;
+}
+
+static TypeInfo mpc105_pcihost_info = {
+ .name = TYPE_MPC105_PCI_HOST_BRIDGE,
+ .parent = TYPE_PCI_HOST_BRIDGE,
+ .instance_size = sizeof(Mpc105HostState),
+ .instance_init = mpc105_pcihost_initfn,
+ .class_init = mpc105_pcihost_class_init,
+};
+
+static void mpc105_register_types(void)
+{
+ type_register_static(&mpc105_pcihost_info);
+ type_register_static(&mpc105_info);
+}
+
+type_init(mpc105_register_types)
diff --git a/hw/pci/pci_ids.h b/hw/pci/pci_ids.h
index d8dc2f1..933b987 100644
--- a/hw/pci/pci_ids.h
+++ b/hw/pci/pci_ids.h
@@ -69,6 +69,7 @@
#define PCI_VENDOR_ID_TI 0x104c
#define PCI_VENDOR_ID_MOTOROLA 0x1057
+#define PCI_DEVICE_ID_MOTOROLA_MPC105 0x0001
#define PCI_DEVICE_ID_MOTOROLA_MPC106 0x0002
#define PCI_DEVICE_ID_MOTOROLA_RAVEN 0x4801
diff --git a/trace-events b/trace-events
index d6a847d..49ab9d5 100644
--- a/trace-events
+++ b/trace-events
@@ -757,6 +757,13 @@ pc87312_info_ide(uint32_t base) "base 0x%x"
pc87312_info_parallel(uint32_t base, uint32_t irq) "base 0x%x, irq %u"
pc87312_info_serial(int n, uint32_t base, uint32_t irq) "id=%d, base 0x%x, irq %u"
+# hw/mpc105.c
+mpc105_unassigned_mem_read(uint64_t addr) "Unassigned mem read %" PRIx64
+mpc105_unassigned_mem_write(uint64_t addr, uint64_t val) "Unassigned mem write %" PRIx64 " = 0x%" PRIx64
+mpc105_simm_enable(int id, uint32_t start, uint32_t end) "SIMM #%d 0x%08x-0x%08x"
+mpc105_simm_disable(int id) "SIMM #%d disabled"
+mpc105_simm_size(int id, uint32_t size) "SIMM #%d is %u MB"
+
# xen-all.c
xen_ram_alloc(unsigned long ram_addr, unsigned long size) "requested: %#lx, size %#lx"
xen_client_set_memory(uint64_t start_addr, unsigned long size, bool log_dirty) "%#"PRIx64" size %#lx, log_dirty %i"
--
1.7.10.4
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [Qemu-devel] [RFC 2/6] prep: add IBM RS/6000 7248 (43p) machine emulation
2013-03-14 22:12 [Qemu-devel] [RFC 0/6] ppc/prep: add IBM RS/6000 43p machine Hervé Poussineau
2013-03-14 22:12 ` [Qemu-devel] [RFC 1/6] pci: add MPC105 PCI host bridge emulation Hervé Poussineau
@ 2013-03-14 22:12 ` Hervé Poussineau
2013-03-14 22:12 ` [Qemu-devel] [RFC 3/6] prep: add RS/6000 debug device Hervé Poussineau
` (3 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Hervé Poussineau @ 2013-03-14 22:12 UTC (permalink / raw)
To: qemu-devel; +Cc: Andreas Färber, Hervé Poussineau
Machine is very simple (only one PCI host bridge and an ISA bridge).
Provide a ibm_43p.cfg file to add more devices to this machine.
Syntax is:
qemu-system-ppc -M 43p -readconfig ibm_43p.cfg
---
docs/ibm_43p.cfg | 34 ++++++++++++++++++++
hw/ppc/prep.c | 94 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 128 insertions(+)
create mode 100644 docs/ibm_43p.cfg
diff --git a/docs/ibm_43p.cfg b/docs/ibm_43p.cfg
new file mode 100644
index 0000000..cf80b89
--- /dev/null
+++ b/docs/ibm_43p.cfg
@@ -0,0 +1,34 @@
+############################################################################
+#
+# qemu-system-ppc -M 43p creates a bare machine with just the very essential
+# chipset devices being present:
+#
+# 00.0 - Host bridge
+# 0b.0 - ISA bridge
+#
+# This config file documents the other devices and how they are
+# created. You can simply use "-readconfig $thisfile" to create
+# them all.
+
+[device]
+ driver = "i8042"
+
+[device]
+ driver = "pc87312"
+ config = "12"
+
+[device]
+ driver = "pcnet"
+ addr = "12.0"
+
+[device]
+ driver = "isa-ide"
+ iobase = "0x1f0"
+ iobase2 = "0x3f6"
+ irq = "14"
+
+[device]
+ driver = "isa-ide"
+ iobase = "0x170"
+ iobase2 = "0x376"
+ irq = "15"
diff --git a/hw/ppc/prep.c b/hw/ppc/prep.c
index 2920911..6c5558e 100644
--- a/hw/ppc/prep.c
+++ b/hw/ppc/prep.c
@@ -30,6 +30,7 @@
#include "sysemu/sysemu.h"
#include "hw/isa.h"
#include "hw/pci/pci.h"
+#include "hw/pci/pci_bus.h"
#include "hw/pci/pci_host.h"
#include "hw/ppc.h"
#include "hw/boards.h"
@@ -663,6 +664,91 @@ static void ppc_prep_init(QEMUMachineInitArgs *args)
audio_init(isa_bus, pci_bus);
}
+static int prep_set_cmos_checksum(DeviceState *dev, void *opaque)
+{
+ uint16_t checksum = *(uint16_t*)opaque;
+ ISADevice *rtc;
+
+ rtc = ISA_DEVICE(object_dynamic_cast(OBJECT(dev), "mc146818rtc"));
+ if (rtc) {
+ rtc_set_memory(rtc, 0x2e, checksum & 0xff);
+ rtc_set_memory(rtc, 0x3e, checksum & 0xff);
+ rtc_set_memory(rtc, 0x2f, checksum >> 8);
+ rtc_set_memory(rtc, 0x3f, checksum >> 8);
+ }
+ return 0;
+}
+
+static void ibm_43p_init(QEMUMachineInitArgs *args)
+{
+ CPUPPCState *env = NULL;
+ uint16_t cmos_checksum;
+ PowerPCCPU *cpu;
+ DeviceState *dev;
+ SysBusDevice *pcihost;
+ PCIBus *pci_bus;
+ ISABus *isa_bus;
+ qemu_irq *cpu_exit_irq;
+
+ /* init CPU */
+ if (!args->cpu_model)
+ args->cpu_model = "604";
+ {
+ cpu = cpu_ppc_init(args->cpu_model);
+ if (cpu == NULL) {
+ fprintf(stderr, "Unable to find PowerPC CPU definition\n");
+ exit(1);
+ }
+ env = &cpu->env;
+
+ if (env->flags & POWERPC_FLAG_RTC_CLK) {
+ /* POWER / PowerPC 601 RTC clock frequency is 7.8125 MHz */
+ cpu_ppc_tb_init(env, 7812500UL);
+ } else {
+ /* Set time-base frequency to 100 Mhz */
+ cpu_ppc_tb_init(env, 100UL * 1000UL * 1000UL);
+ }
+ qemu_register_reset(ppc_prep_reset, cpu);
+ }
+ if (PPC_INPUT(env) != PPC_FLAGS_INPUT_6xx) {
+ hw_error("Only 6xx bus is supported on PREP machine\n");
+ }
+
+ /* PCI host */
+ pcihost = SYS_BUS_DEVICE(qdev_create(NULL, "mpc105-pcihost"));
+ qdev_prop_set_uint32(DEVICE(pcihost), "ram-size", (uint32_t)args->ram_size);
+ if (bios_name == NULL)
+ bios_name = "P93H1904.IMG";
+ qdev_prop_set_string(DEVICE(pcihost), "bios-name", bios_name);
+ object_property_add_child(qdev_get_machine(), "eagle", OBJECT(pcihost), NULL);
+ qdev_init_nofail(DEVICE(pcihost));
+ pci_bus = PCI_BUS(qdev_get_child_bus(DEVICE(pcihost), "pci.0"));
+ if (pci_bus == NULL) {
+ fprintf(stderr, "Couldn't create PCI host controller.\n");
+ exit(1);
+ }
+
+ /* PCI -> ISA bridge */
+ dev = DEVICE(pci_create_simple(pci_bus, PCI_DEVFN(11, 0), "i82378"));
+ cpu_exit_irq = qemu_allocate_irqs(cpu_request_exit, NULL, 1);
+ qdev_connect_gpio_out(dev, 0,
+ first_cpu->irq_inputs[PPC6xx_INPUT_INT]);
+ qdev_connect_gpio_out(dev, 1, *cpu_exit_irq);
+ sysbus_connect_irq(pcihost, 0, qdev_get_gpio_in(dev, 9));
+ sysbus_connect_irq(pcihost, 1, qdev_get_gpio_in(dev, 11));
+ sysbus_connect_irq(pcihost, 2, qdev_get_gpio_in(dev, 9));
+ sysbus_connect_irq(pcihost, 3, qdev_get_gpio_in(dev, 11));
+ isa_bus = ISA_BUS(qdev_get_child_bus(dev, "isa.0"));
+
+ /* initialize CMOS checksums */
+ cmos_checksum = 0x6aa9;
+ qbus_walk_children(BUS(isa_bus), prep_set_cmos_checksum, NULL,
+ &cmos_checksum);
+
+ /* Now that we have PCI and ISA, initialize audio subsystem */
+ audio_init(isa_bus, pci_bus);
+}
+
static QEMUMachine prep_machine = {
.name = "prep",
.desc = "PowerPC PREP platform",
@@ -671,9 +757,17 @@ static QEMUMachine prep_machine = {
DEFAULT_MACHINE_OPTIONS,
};
+static QEMUMachine ibm_43p_machine = {
+ .name = "43p",
+ .desc = "IBM RS/6000 7248 (43p)",
+ .init = ibm_43p_init,
+ .max_cpus = 1,
+};
+
static void prep_machine_init(void)
{
qemu_register_machine(&prep_machine);
+ qemu_register_machine(&ibm_43p_machine);
}
machine_init(prep_machine_init);
--
1.7.10.4
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [Qemu-devel] [RFC 3/6] prep: add RS/6000 debug device
2013-03-14 22:12 [Qemu-devel] [RFC 0/6] ppc/prep: add IBM RS/6000 43p machine Hervé Poussineau
2013-03-14 22:12 ` [Qemu-devel] [RFC 1/6] pci: add MPC105 PCI host bridge emulation Hervé Poussineau
2013-03-14 22:12 ` [Qemu-devel] [RFC 2/6] prep: add IBM RS/6000 7248 (43p) machine emulation Hervé Poussineau
@ 2013-03-14 22:12 ` Hervé Poussineau
2013-03-14 22:12 ` [Qemu-devel] [RFC 4/6] m48t59: move ISA ports registration to QOM constructor Hervé Poussineau
` (2 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Hervé Poussineau @ 2013-03-14 22:12 UTC (permalink / raw)
To: qemu-devel; +Cc: Andreas Färber, Hervé Poussineau
Document it for the IBM 43p emulation.
Signed-off-by: Hervé Poussineau <hpoussin@reactos.org>
---
docs/ibm_43p.cfg | 3 +
hw/ppc/Makefile.objs | 1 +
hw/ppc/rs6000_debug.c | 260 +++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 264 insertions(+)
create mode 100644 hw/ppc/rs6000_debug.c
diff --git a/docs/ibm_43p.cfg b/docs/ibm_43p.cfg
index cf80b89..92c9e8f 100644
--- a/docs/ibm_43p.cfg
+++ b/docs/ibm_43p.cfg
@@ -32,3 +32,6 @@
iobase = "0x170"
iobase2 = "0x376"
irq = "15"
+
+[device]
+ driver = "rs6000-debug"
diff --git a/hw/ppc/Makefile.objs b/hw/ppc/Makefile.objs
index 4de0209..8be8264 100644
--- a/hw/ppc/Makefile.objs
+++ b/hw/ppc/Makefile.objs
@@ -23,6 +23,7 @@ obj-$(CONFIG_PSERIES) += spapr_hcall.o spapr_iommu.o spapr_rtas.o
obj-y += ppc405_boards.o ppc4xx_devs.o ppc405_uc.o ppc440_bamboo.o
# PReP
obj-y += prep.o
+obj-y += rs6000_debug.o
# OldWorld PowerMac
obj-y += mac_oldworld.o
# NewWorld PowerMac
diff --git a/hw/ppc/rs6000_debug.c b/hw/ppc/rs6000_debug.c
new file mode 100644
index 0000000..d7b8721
--- /dev/null
+++ b/hw/ppc/rs6000_debug.c
@@ -0,0 +1,260 @@
+/*
+ * QEMU IBM RS/6000 debug port emulation
+ *
+ * Copyright (c) 2011 Hervé Poussineau
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) version 3 or any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "hw/isa.h"
+#include "char/char.h"
+
+#define TYPE_RS6000_DEBUG "rs6000-debug"
+#define RS6000(obj) \
+ OBJECT_CHECK(rs6000DebugState, (obj), TYPE_RS6000_DEBUG)
+
+static struct {
+ uint8_t code;
+ const char* message;
+} checkpoints[] = {
+ { 0x00, "Manufacturing - Reserved for Parallel port download protocol" },
+ { 0x01, "Clear the EPOW register 1. Memory modules 2. system board" },
+ { 0x02, "Determine system bus speed, set ISA advisor" },
+ { 0x04, "Set memory refresh" },
+ { 0x05, "Transfer control to Operating System ( normal boot )" },
+ { 0x06, "Jump to set environment or check flash" },
+ { 0x08, "Run recovery block base memory, test 2k, then set stack" },
+ { 0x09, "Copy CRC verification code to RAM" },
+ { 0x0A, "Turn on cache" },
+ { 0x0B, "Flush cache" },
+ { 0x0C, "Jump to CRC verification code in RAM" },
+ { 0x0D, "Compute composite image CRC" },
+ { 0x0E, "Jump back to ROM" },
+ { 0x0F, "Turn off cache" },
+ { 0x10, "Check if composite image CRC is valid" },
+ { 0x11, "Good CRC - jump to composite image" },
+ { 0x12, "Bad CRC - initialize base memory, stack" },
+ { 0x13, "Bad CRC - copy uncompressed recovery block code to RAM" },
+ { 0x14, "Bad CRC - jump to code in RAM" },
+ { 0x15, "Bad CRC - turn on cache" },
+ { 0x16, "Bad CRC - copy recovery block data section to RAM" },
+ { 0x17, "Bad CRC - invalidate and flush cache, set TOC" },
+ { 0x18, "Bad CRC - branch to high level recovery control routine" },
+ { 0x19, "Initialize base memory, stack" },
+ { 0x1A, "Copy uncompressed recovery block code to RAM" },
+ { 0x1B, "Jump to code in RAM" },
+ { 0x1C, "Turn on cache" },
+ { 0x1D, "Copy recovery block data section to RAM" },
+ { 0x1E, "Invalidate and flush cache, set TOC" },
+ { 0x1F, "Branch to high level control routine" },
+ { 0x20, "Initialize system I/O" },
+ { 0x21, "Run a console diagnostic routine" },
+ { 0x22, "No memory found" },
+ { 0x23, "No DIMM found in socket" },
+ { 0x24, "Remove bad DIMM found from DIMM information" },
+ { 0x25, "Unsupported DIMM detected" },
+ { 0x26, "Check valid image - start" },
+ { 0x27, "Check valid image - successful" },
+ { 0x28, "Wait for interrupt" },
+ { 0x29, "Transfers information to the business audio chip" },
+ { 0x2B, "Wait until sound chip has been initialized" },
+ { 0x2C, "Initialize the current input/pointer device" },
+ { 0x2D, "Initialize the current output" },
+ { 0x2E, "Register a console driver" },
+ { 0x30, "Set up early memory allocation heap, initialize Super I/O" },
+ { 0x31, "Determine system bus speed, set ISA driver" },
+ { 0x32, "Resync to SP (Console image)" },
+ { 0x33, "Set memory refresh" },
+ { 0x35, "Jump to set environment" },
+ { 0x40, "Initialize interrupt subsystem and 8259s" },
+ { 0x41, "SP command setup" },
+ { 0x42, "SP mailbox interface" },
+ { 0x43, "get_vpd entry" },
+ { 0x44, "init_sp entry" },
+ { 0x45, "sp_recovery -> resync SP & CPU" },
+ { 0x46, "IRQ13 stuck high Bad System Board or Service Processor" },
+ { 0x47, "Entry to error checking routine-No system board VPD, bad CRC Bad System Board" },
+ { 0x48, "Power supply or system board problem" },
+ { 0x49, "Voltage problem, system board, power supply or CPU 5V" },
+ { 0x4A, "Voltage problem, system board or power supply 12V" },
+ { 0x4B, "CPU over temperature or bad system board" },
+ { 0x4C, "start bit-map display function" },
+ { 0x4D, "Bit-map file read into memory, start processing" },
+ { 0x4E, "End bit-map display function" },
+ { 0x4F, "IO/MEM over termperature or bad system board" },
+ { 0x50, "Initialize CMOS RTC periodic interrupt" },
+ { 0x51, "System board or system over temperature, CPU card Critical " },
+ { 0x52, "Bad system board (fan fail reported)" },
+ { 0x53, "Bad system board or Fans" },
+ { 0x54, "Fan fail warning" },
+ { 0x55, "Bad system board (unsupported EPOW)" },
+ { 0x56, "Voltage problem, system board, power supply or CPU 3.3V/2.5V" },
+ { 0x57, "Bad or low battery" },
+ { 0x58, "IRQ13 test failure" },
+ { 0x59, "EPOW test failure" },
+ { 0x5A, "Spurious IRQ6 interrupt (i.e. interrupt glitch)" },
+ { 0x5B, "Fan failure warning" },
+ { 0x5B, "Transfer control to Operating System ( service mode bootlist )" },
+ { 0x5C, "Clear EPOW register failure" },
+ { 0x5D, "Clear EPOW register failure" },
+ { 0x60, "Initialize keyboard/mouse controller, and password" },
+ { 0x61, "Extended memory initialization command" },
+ { 0x62, "Diskette initialization command" },
+ { 0x64, "Test of day routine" },
+ { 0x6A, "SCSI initialization command" },
+ { 0x70, "Initialize debugger" },
+ { 0x71, "Start checking whether CMOS contents are valid" },
+ { 0x72, "End checking whether CMOS contents are valid" },
+ { 0x73, "Dumps contents of CMOS data area to a file" },
+ { 0x74, "Establishing Host conmnection" },
+ { 0x75, "BootP request" },
+ { 0x77, "Resync to SP (Recvoery image)" },
+ { 0x79, "Dupms contents of NVRAM data area to a file" },
+ { 0x7A, "NVRAM initialization" },
+ { 0x7B, "Check NVRAM validity CRC" },
+ { 0x7C, "Loads contents of CMOS from file" },
+ { 0x80, "Initialize system call table" },
+ { 0x82, "Register a manager for use by the system" },
+ { 0x88, "Halt. System locked by error condition - power off" },
+ { 0x90, "Initialize VDISK file system" },
+ { 0x91, "Low-level initialize VDISK file systems" },
+ { 0x94, "Start SCSI initialization" },
+ { 0x96, "SCSI bus scan start" },
+ { 0x97, "SCSI polling interrupt" },
+ { 0x98, "SCSI device detected" },
+ { 0x9E, "Real Time clock RTC initialization" },
+ { 0x9F, "Exit SCSI initialization" },
+ { 0xA0, "Start resident monitor, run V:autoexec.6md" },
+ { 0xA1, "Enter resident monitor" },
+ { 0xA2, "Resident monitor process" },
+ { 0xA3, "Resident monitor process" },
+ { 0xA4, "Exit resident monitor" },
+ { 0xA5, "ASCII terminal initialization" },
+ { 0xA6, "ASCII terminal initialization exit" },
+ { 0xA9, "p9 driver initialization" },
+ { 0xAA, "p9 driver exit" },
+ { 0xAB, "Keyboard driver initialization" },
+ { 0xAC, "Keyboard driver exit" },
+ { 0xAD, "Mouse driver initialization" },
+ { 0xAE, "Mouse driver exit" },
+ { 0xB0, "Initialize rest of file system" },
+ { 0xB1, "Diskette initialization" },
+ { 0xB2, "Diskette drive type determination" },
+ { 0xB3, "Diskette initialization complete" },
+ { 0xC0, "Check if flash ROM OK" },
+ { 0xCA, "Build boot table - Networks" },
+ { 0xCB, "Build boot table - DASD" },
+ { 0xCC, "Build boot table - CDROM" },
+ { 0xCD, "Build boot table - diskettes" },
+ { 0xCE, "No operating system boot, exit normal boot sequence" },
+ { 0xD0, "Start of boot sequence" },
+ { 0xD2, "No operating system boot - ensure CMOS RTC periodic clock updates displayed" },
+ { 0xD4, "Initialize console for loading diagnostics" },
+ { 0xD8, "Exit from diagnostic - run resident monitor" },
+ { 0xDA, "IRQ15" },
+ { 0xDB, "Unexpected processor exception" },
+ { 0xDC, "Dynamic console selection" },
+ { 0xDD, "Early processor exception" },
+ { 0xDE, "Alternating pattern of FDE and FDA indicates a processor exception has been detected." },
+ { 0xE1, "Test timeout" },
+ { 0xE2, "Initialize system I/O" },
+ { 0xE4, "Initialize super I/O with default values" },
+ { 0xE6, "Set up early memory allocation heap" },
+ { 0xE8, "Initialize primary diskette drive in polled mode" },
+ { 0xEA, "Try to load in recovery image from diskette" },
+ { 0xEB, "Verify recovery image is valid" },
+ { 0xEC, "Get recovery image entry point" },
+ { 0xED, "Invalidate instruction cache" },
+ { 0xEE, "Jump to composite image" },
+ { 0xF0, "Manufacturing - Check for parallel port hook" },
+ { 0xF4, "Manufacturing - Start flag not received" },
+ { 0xF5, "Manufacturing - Invalid start flag received" },
+ { 0xF6, "Manufacturing - Receive character timeout" },
+ { 0xF7, "Manufacturing - CRC value mismatch" },
+ { 0xFA, "Error during flash update" },
+ { 0xFC, "Operating system boot - no errors reported by IPL ROS" },
+ { 0xFD, "Operating system boot - non-critical errors reported by IPL ROS" },
+ { 0xFE, "No boot - critical error(s) reported by IPL ROS -or- F1 key pressed" },
+ { 0, NULL },
+};
+
+typedef struct rs6000DebugState {
+ ISADevice dev;
+ MemoryRegion io;
+ CharDriverState *chr;
+} rs6000DebugState;
+
+static void rs6000_debug_write(void *opaque, hwaddr addr, uint64_t val,
+ unsigned int size)
+{
+ rs6000DebugState *s = opaque;
+ uint8_t code = val & 0xff;
+ int i = 0;
+
+ while (checkpoints[i].message) {
+ if (checkpoints[i].code == code) {
+ qemu_chr_fe_printf(s->chr, "%s\r\n",
+ checkpoints[i].message);
+ return;
+ }
+ i++;
+ }
+
+ qemu_chr_fe_printf(s->chr, "unknown code 0x%02x\r\n", code);
+}
+
+static const MemoryRegionOps rs6000_debug_ops = {
+ .write = rs6000_debug_write,
+ .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+static int rs6000_debug_init(ISADevice *dev)
+{
+ rs6000DebugState *s = RS6000(dev);
+
+ if (!s->chr) {
+ s->chr = qemu_chr_new("rs6000_debug", "vc", NULL);
+ }
+
+ memory_region_init_io(&s->io, &rs6000_debug_ops, s, "rs6000-debug", 4);
+ isa_register_ioport(dev, &s->io, 0x680);
+ return 0;
+}
+
+static Property rs6000_debug_properties[] = {
+ DEFINE_PROP_CHR("chardev", rs6000DebugState, chr),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void rs6000_debug_class_initfn(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ ISADeviceClass *ic = ISA_DEVICE_CLASS(klass);
+ ic->init = rs6000_debug_init;
+ dc->props = rs6000_debug_properties;
+}
+
+static TypeInfo rs6000_debug_isa_info = {
+ .name = TYPE_RS6000_DEBUG,
+ .parent = TYPE_ISA_DEVICE,
+ .instance_size = sizeof(rs6000DebugState),
+ .class_init = rs6000_debug_class_initfn,
+};
+
+static void rs6000_debug_register_types(void)
+{
+ type_register_static(&rs6000_debug_isa_info);
+}
+
+type_init(rs6000_debug_register_types)
--
1.7.10.4
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [Qemu-devel] [RFC 4/6] m48t59: move ISA ports registration to QOM constructor
2013-03-14 22:12 [Qemu-devel] [RFC 0/6] ppc/prep: add IBM RS/6000 43p machine Hervé Poussineau
` (2 preceding siblings ...)
2013-03-14 22:12 ` [Qemu-devel] [RFC 3/6] prep: add RS/6000 debug device Hervé Poussineau
@ 2013-03-14 22:12 ` Hervé Poussineau
2013-03-14 22:12 ` [Qemu-devel] [RFC 5/6] m48t59: hack(?) to make it work on IBM 43p Hervé Poussineau
2013-03-14 22:12 ` [Qemu-devel] [RFC 6/6] prep: QOM'ify System I/O Hervé Poussineau
5 siblings, 0 replies; 7+ messages in thread
From: Hervé Poussineau @ 2013-03-14 22:12 UTC (permalink / raw)
To: qemu-devel; +Cc: Andreas Färber, Hervé Poussineau
-device m48t59 can now be used to create a fully functional nvram,
and m48t59_init_isa() becomes a much simpler helper.
Signed-off-by: Hervé Poussineau <hpoussin@reactos.org>
---
hw/m48t59.c | 9 ++++-----
1 file changed, 4 insertions(+), 5 deletions(-)
diff --git a/hw/m48t59.c b/hw/m48t59.c
index 39a9d80..1093716 100644
--- a/hw/m48t59.c
+++ b/hw/m48t59.c
@@ -676,11 +676,6 @@ M48t59State *m48t59_init_isa(ISABus *bus, uint32_t io_base, uint16_t size,
d = DO_UPCAST(M48t59ISAState, busdev, dev);
s = &d->state;
- memory_region_init_io(&d->io, &m48t59_io_ops, s, "m48t59", 4);
- if (io_base != 0) {
- isa_register_ioport(dev, &d->io, io_base);
- }
-
return s;
}
@@ -703,6 +698,10 @@ static int m48t59_init_isa1(ISADevice *dev)
isa_init_irq(dev, &s->IRQ, 8);
m48t59_init_common(s);
+ memory_region_init_io(&d->io, &m48t59_io_ops, s, "m48t59", 4);
+ if (s->io_base != 0) {
+ isa_register_ioport(dev, &d->io, s->io_base);
+ }
return 0;
}
--
1.7.10.4
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [Qemu-devel] [RFC 5/6] m48t59: hack(?) to make it work on IBM 43p
2013-03-14 22:12 [Qemu-devel] [RFC 0/6] ppc/prep: add IBM RS/6000 43p machine Hervé Poussineau
` (3 preceding siblings ...)
2013-03-14 22:12 ` [Qemu-devel] [RFC 4/6] m48t59: move ISA ports registration to QOM constructor Hervé Poussineau
@ 2013-03-14 22:12 ` Hervé Poussineau
2013-03-14 22:12 ` [Qemu-devel] [RFC 6/6] prep: QOM'ify System I/O Hervé Poussineau
5 siblings, 0 replies; 7+ messages in thread
From: Hervé Poussineau @ 2013-03-14 22:12 UTC (permalink / raw)
To: qemu-devel; +Cc: Andreas Färber, Hervé Poussineau
Document it for the IBM 43p emulation.
---
docs/ibm_43p.cfg | 6 ++++++
hw/m48t59.c | 2 ++
2 files changed, 8 insertions(+)
diff --git a/docs/ibm_43p.cfg b/docs/ibm_43p.cfg
index 92c9e8f..55329e3 100644
--- a/docs/ibm_43p.cfg
+++ b/docs/ibm_43p.cfg
@@ -11,6 +11,12 @@
# them all.
[device]
+ driver = "m48t59_isa"
+ io_base = "0x74"
+ model = "59"
+ size = "0x1000"
+
+[device]
driver = "i8042"
[device]
diff --git a/hw/m48t59.c b/hw/m48t59.c
index 1093716..c71ba7b 100644
--- a/hw/m48t59.c
+++ b/hw/m48t59.c
@@ -491,6 +491,7 @@ static void NVRAM_writeb(void *opaque, hwaddr addr, uint64_t val,
NVRAM->addr &= ~0xFF00;
NVRAM->addr |= val << 8;
break;
+ case 2:
case 3:
m48t59_write(NVRAM, NVRAM->addr, val);
NVRAM->addr = 0x0000;
@@ -506,6 +507,7 @@ static uint64_t NVRAM_readb(void *opaque, hwaddr addr, unsigned size)
uint32_t retval;
switch (addr) {
+ case 2:
case 3:
retval = m48t59_read(NVRAM, NVRAM->addr);
break;
--
1.7.10.4
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [Qemu-devel] [RFC 6/6] prep: QOM'ify System I/O
2013-03-14 22:12 [Qemu-devel] [RFC 0/6] ppc/prep: add IBM RS/6000 43p machine Hervé Poussineau
` (4 preceding siblings ...)
2013-03-14 22:12 ` [Qemu-devel] [RFC 5/6] m48t59: hack(?) to make it work on IBM 43p Hervé Poussineau
@ 2013-03-14 22:12 ` Hervé Poussineau
5 siblings, 0 replies; 7+ messages in thread
From: Hervé Poussineau @ 2013-03-14 22:12 UTC (permalink / raw)
To: qemu-devel; +Cc: Andreas Färber, Hervé Poussineau
Most of the functionality is extracted from hw/ppc/prep.c.
Also add support for board identification/equipment registers.
Document it for the IBM 43p emulation.
Signed-off-by: Hervé Poussineau <hpoussin@reactos.org>
---
docs/ibm_43p.cfg | 5 +
hw/ppc/Makefile.objs | 1 +
hw/ppc/prep_systemio.c | 290 ++++++++++++++++++++++++++++++++++++++++++++++++
trace-events | 4 +
4 files changed, 300 insertions(+)
create mode 100644 hw/ppc/prep_systemio.c
diff --git a/docs/ibm_43p.cfg b/docs/ibm_43p.cfg
index 55329e3..2a97e3f 100644
--- a/docs/ibm_43p.cfg
+++ b/docs/ibm_43p.cfg
@@ -41,3 +41,8 @@
[device]
driver = "rs6000-debug"
+
+[device]
+ driver = "prep-systemio800"
+ ibm-planar-id = "0xc0"
+ equipment = "0xff"
diff --git a/hw/ppc/Makefile.objs b/hw/ppc/Makefile.objs
index 8be8264..b584902 100644
--- a/hw/ppc/Makefile.objs
+++ b/hw/ppc/Makefile.objs
@@ -23,6 +23,7 @@ obj-$(CONFIG_PSERIES) += spapr_hcall.o spapr_iommu.o spapr_rtas.o
obj-y += ppc405_boards.o ppc4xx_devs.o ppc405_uc.o ppc440_bamboo.o
# PReP
obj-y += prep.o
+obj-y += prep_systemio.o
obj-y += rs6000_debug.o
# OldWorld PowerMac
obj-y += mac_oldworld.o
diff --git a/hw/ppc/prep_systemio.c b/hw/ppc/prep_systemio.c
new file mode 100644
index 0000000..ddd54d1
--- /dev/null
+++ b/hw/ppc/prep_systemio.c
@@ -0,0 +1,290 @@
+/*
+ * QEMU PReP System I/O emulation
+ *
+ * Copyright (c) 2003-2007 Jocelyn Mayer
+ * Copyright (c) 2010-2012 Herve Poussineau
+ * Copyright (c) 2010-2011 Andreas Faerber
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "hw/isa.h"
+#include "exec/address-spaces.h"
+#include "qemu/error-report.h" /* for error_report() */
+#include "sysemu/sysemu.h" /* for vm_stop() */
+#include "trace.h"
+
+/* Bit as defined in PowerPC Reference Plaform v1.1, sect. 6.1.5, p. 132 */
+#define BIT(n) (1 << (7 - (n)))
+
+typedef struct PrepIo800State {
+ ISADevice dev;
+ MemoryRegion ppc_parity_mem;
+
+ qemu_irq non_contiguous_io_map_irq;
+ uint8_t equipment; /* 0x080c */
+ uint8_t system_control; /* 0x081c */
+ uint8_t iomap_type; /* 0x0850 */
+ uint8_t ibm_planar_id; /* 0x0852 */
+ qemu_irq softreset_irq;
+} PrepIo800State;
+
+/* PORT 0092 -- Special Port 92 (Read/Write) */
+
+enum {
+ PORT0092_SOFTRESET = BIT(7),
+ PORT0092_LE_MODE = BIT(6),
+};
+
+static void prep_port0092_write(void *opaque, uint32_t addr, uint32_t val)
+{
+ PrepIo800State *s = opaque;
+
+ trace_prep_systemio_write(addr, val);
+
+ if ((val & PORT0092_SOFTRESET) != 0) {
+ qemu_irq_raise(s->softreset_irq);
+ } else {
+ qemu_irq_lower(s->softreset_irq);
+ }
+
+ if ((val & PORT0092_LE_MODE) != 0) {
+ /* XXX Not supported yet */
+ error_report("little-endian mode not supported");
+ vm_stop(RUN_STATE_PAUSED);
+ } else {
+ /* Nothing to do */
+ }
+}
+
+static uint32_t prep_port0092_read(void *opaque, uint32_t addr)
+{
+ /* XXX LE mode unsupported */
+ trace_prep_systemio_read(addr, 0);
+ return 0;
+}
+
+/* PORT 0808 -- Hardfile Light Register (Write Only) */
+
+enum {
+ PORT0808_HARDFILE_LIGHT_ON = BIT(7),
+};
+
+static void prep_port0808_write(void *opaque, uint32_t addr, uint32_t val)
+{
+ trace_prep_systemio_write(addr, val);
+}
+
+/* PORT 0810 -- Password Protect 1 Register (Write Only) */
+
+/* reset by port 0x4D in the SIO */
+static void prep_port0810_write(void *opaque, uint32_t addr, uint32_t val)
+{
+ trace_prep_systemio_write(addr, val);
+}
+
+/* PORT 0812 -- Password Protect 2 Register (Write Only) */
+
+/* reset by port 0x4D in the SIO */
+static void prep_port0812_write(void *opaque, uint32_t addr, uint32_t val)
+{
+ trace_prep_systemio_write(addr, val);
+}
+
+/* PORT 0814 -- L2 Invalidate Register (Write Only) */
+
+static void prep_port0814_write(void *opaque, uint32_t addr, uint32_t val)
+{
+ trace_prep_systemio_write(addr, val);
+}
+
+/* PORT 0818 -- Reserved for Keylock (Read Only) */
+
+enum {
+ PORT0818_KEYLOCK_SIGNAL_HIGH = BIT(7),
+};
+
+static uint32_t prep_port0818_read(void *opaque, uint32_t addr)
+{
+ uint32_t val = 0;
+ trace_prep_systemio_read(addr, val);
+ return val;
+}
+
+/* PORT 080C -- Equipment */
+
+enum {
+ PORT080C_SCSIFUSE = BIT(1),
+ PORT080C_L2_COPYBACK = BIT(4),
+ PORT080C_L2_256 = BIT(5),
+ PORT080C_UPGRADE_CPU = BIT(6),
+ PORT080C_L2 = BIT(7),
+};
+
+static uint32_t prep_port080c_read(void *opaque, uint32_t addr)
+{
+ PrepIo800State *s = opaque;
+ trace_prep_systemio_read(addr, s->equipment);
+ return s->equipment;
+}
+
+/* PORT 081C -- System Control Register (Read/Write) */
+
+enum {
+ PORT081C_FLOPPY_MOTOR_INHIBIT = BIT(3),
+ PORT081C_MASK_TEA = BIT(2),
+ PORT081C_L2_UPDATE_INHIBIT = BIT(1),
+ PORT081C_L2_CACHEMISS_INHIBIT = BIT(0),
+};
+
+static void prep_port081c_write(void *opaque, uint32_t addr, uint32_t val)
+{
+ PrepIo800State *s = opaque;
+ trace_prep_systemio_write(addr, val);
+ s->system_control = val;
+}
+
+static uint32_t prep_port081c_read(void *opaque, uint32_t addr)
+{
+ PrepIo800State *s = opaque;
+ trace_prep_systemio_read(addr, s->system_control);
+ return s->system_control;
+}
+
+/* System Board Identification */
+
+static uint32_t prep_port0852_read(void *opaque, uint32_t addr)
+{
+ PrepIo800State *s = opaque;
+ trace_prep_systemio_read(addr, s->ibm_planar_id);
+ return s->ibm_planar_id;
+}
+
+/* PORT 0850 -- I/O Map Type Register (Read/Write) */
+
+enum {
+ PORT0850_IOMAP_NONCONTIGUOUS = BIT(7),
+};
+
+static uint32_t prep_port0850_read(void *opaque, uint32_t addr)
+{
+ PrepIo800State *s = opaque;
+ trace_prep_systemio_read(addr, s->iomap_type);
+ return s->iomap_type;
+}
+
+static void prep_port0850_write(void *opaque, uint32_t addr, uint32_t val)
+{
+ PrepIo800State *s = opaque;
+
+ trace_prep_systemio_write(addr, val);
+ qemu_set_irq(s->non_contiguous_io_map_irq,
+ val & PORT0850_IOMAP_NONCONTIGUOUS ? 1 : 0);
+ s->iomap_type = val;
+}
+
+static const MemoryRegionPortio ppc_io800_port_list[] = {
+ { 0x092, 1, 1, .read = prep_port0092_read,
+ .write = prep_port0092_write, },
+ { 0x808, 1, 1, .write = prep_port0808_write, },
+ { 0x80c, 1, 1, .read = prep_port080c_read, },
+ { 0x810, 1, 1, .write = prep_port0810_write, },
+ { 0x812, 1, 1, .write = prep_port0812_write, },
+ { 0x814, 1, 1, .write = prep_port0814_write, },
+ { 0x818, 1, 1, .read = prep_port0818_read, },
+ { 0x81c, 1, 1, .read = prep_port081c_read,
+ .write = prep_port081c_write, },
+ { 0x850, 1, 1, .read = prep_port0850_read,
+ .write = prep_port0850_write, },
+ { 0x852, 1, 1, .read = prep_port0852_read, },
+ PORTIO_END_OF_LIST()
+};
+
+static uint64_t ppc_parity_error_readl(void *opaque, hwaddr addr,
+ unsigned int size)
+{
+ uint32_t val = 0;
+ trace_prep_systemio_read((unsigned int)addr, val);
+ return val;
+}
+
+static const MemoryRegionOps ppc_parity_error_ops = {
+ .read = ppc_parity_error_readl,
+ .valid = {
+ .min_access_size = 4,
+ .max_access_size = 4,
+ },
+};
+
+static int prep_systemio_init(ISADevice *dev)
+{
+ PrepIo800State *s = DO_UPCAST(PrepIo800State, dev, dev);
+ qdev_init_gpio_out(&dev->qdev, &s->non_contiguous_io_map_irq, 1);
+ s->iomap_type = 0; /* contiguous mode XXX 0x1? */
+ s->softreset_irq = first_cpu->irq_inputs[PPC6xx_INPUT_HRESET];
+
+ isa_register_portio_list(dev, 0x0, ppc_io800_port_list, s, "systemio800");
+
+ memory_region_init_io(&s->ppc_parity_mem, &ppc_parity_error_ops, s,
+ "ppc-parity", 0x4);
+ memory_region_add_subregion(get_system_memory(), 0xbfffeff0,
+ &s->ppc_parity_mem);
+ return 0;
+}
+
+static const VMStateDescription vmstate_prep_systemio = {
+ .name = "prep_systemio",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT8(system_control, PrepIo800State),
+ VMSTATE_UINT8(iomap_type, PrepIo800State),
+ VMSTATE_END_OF_LIST()
+ },
+};
+
+static Property prep_systemio_properties[] = {
+ DEFINE_PROP_UINT8("ibm-planar-id", PrepIo800State, ibm_planar_id, 0),
+ DEFINE_PROP_UINT8("equipment", PrepIo800State, equipment, 0),
+ DEFINE_PROP_END_OF_LIST()
+};
+
+static void prep_systemio_class_initfn(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ ISADeviceClass *ic = ISA_DEVICE_CLASS(klass);
+ ic->init = prep_systemio_init;
+ dc->vmsd = &vmstate_prep_systemio;
+ dc->props = prep_systemio_properties;
+ dc->no_user = 1;
+}
+
+static TypeInfo prep_systemio800_info = {
+ .name = "prep-systemio800",
+ .parent = TYPE_ISA_DEVICE,
+ .instance_size = sizeof(PrepIo800State),
+ .class_init = prep_systemio_class_initfn,
+};
+
+static void prep_systemio_register_types(void)
+{
+ type_register_static(&prep_systemio800_info);
+}
+
+type_init(prep_systemio_register_types)
diff --git a/trace-events b/trace-events
index 49ab9d5..8173da4 100644
--- a/trace-events
+++ b/trace-events
@@ -757,6 +757,10 @@ pc87312_info_ide(uint32_t base) "base 0x%x"
pc87312_info_parallel(uint32_t base, uint32_t irq) "base 0x%x, irq %u"
pc87312_info_serial(int n, uint32_t base, uint32_t irq) "id=%d, base 0x%x, irq %u"
+# hw/ppc/prep_systemio.c
+prep_systemio_read(uint32_t addr, uint32_t val) "read addr=%x val=%x"
+prep_systemio_write(uint32_t addr, uint32_t val) "write addr=%x val=%x"
+
# hw/mpc105.c
mpc105_unassigned_mem_read(uint64_t addr) "Unassigned mem read %" PRIx64
mpc105_unassigned_mem_write(uint64_t addr, uint64_t val) "Unassigned mem write %" PRIx64 " = 0x%" PRIx64
--
1.7.10.4
^ permalink raw reply related [flat|nested] 7+ messages in thread