From: "Andreas Färber" <andreas.faerber@web.de>
To: qemu-devel@nongnu.org
Cc: "Andreas Färber" <andreas.faerber@web.de>,
"Hervé Poussineau" <hpoussin@reactos.org>,
"Markus Armbruster" <armbru@redhat.com>
Subject: [Qemu-devel] [RFC 06/23] prep: Add i82378 PCI-to-ISA bridge emulation
Date: Tue, 14 Jun 2011 04:37:40 +0200 [thread overview]
Message-ID: <1308019077-61957-7-git-send-email-andreas.faerber@web.de> (raw)
In-Reply-To: <1308019077-61957-6-git-send-email-andreas.faerber@web.de>
Signed-off-by: Hervé Poussineau <hpoussin@reactos.org>
Inverse endianness in order to work on x86 and ppc host.
Create ISA bus in this device (suggested by Markus).
Cc: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Andreas Färber <andreas.faerber@web.de>
---
Makefile.objs | 1 +
default-configs/ppc-softmmu.mak | 2 +
hw/i82378.c | 298 +++++++++++++++++++++++++++++++++++++++
hw/pci_ids.h | 1 +
4 files changed, 302 insertions(+), 0 deletions(-)
create mode 100644 hw/i82378.c
diff --git a/Makefile.objs b/Makefile.objs
index b0e4c09..fb57bbf 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -210,6 +210,7 @@ hw-obj-$(CONFIG_SMARTCARD_NSS) += ccid-card-emulated.o
# PPC devices
hw-obj-$(CONFIG_OPENPIC) += openpic.o
hw-obj-$(CONFIG_PREP_PCI) += prep_pci.o
+hw-obj-$(CONFIG_I82378) += i82378.o
# Mac shared devices
hw-obj-$(CONFIG_MACIO) += macio.o
hw-obj-$(CONFIG_CUDA) += cuda.o
diff --git a/default-configs/ppc-softmmu.mak b/default-configs/ppc-softmmu.mak
index 1d1a7c2..df64ee6 100644
--- a/default-configs/ppc-softmmu.mak
+++ b/default-configs/ppc-softmmu.mak
@@ -14,7 +14,9 @@ CONFIG_DMA=y
CONFIG_I82374=y
CONFIG_OPENPIC=y
CONFIG_PREP_PCI=y
+CONFIG_I82378=y
CONFIG_MACIO=y
+CONFIG_PCSPK=y
CONFIG_CUDA=y
CONFIG_ADB=y
CONFIG_MAC_NVRAM=y
diff --git a/hw/i82378.c b/hw/i82378.c
new file mode 100644
index 0000000..181e441
--- /dev/null
+++ b/hw/i82378.c
@@ -0,0 +1,298 @@
+/*
+ * QEMU Intel i82378 emulation (PCI to ISA bridge)
+ *
+ * Copyright (c) 2010-2011 Herve Poussineau
+ * Copyright (c) 2003-2007 Jocelyn Mayer
+ * Copyright (c) 2010 Andreas Faerber
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "pci.h"
+#include "pc.h"
+
+//#define DEBUG_I82378
+
+#ifdef DEBUG_I82378
+#define DPRINTF(fmt, ...) \
+do { fprintf(stderr, "i82378: " fmt , ## __VA_ARGS__); } while (0)
+#else
+#define DPRINTF(fmt, ...) \
+do {} while (0)
+#endif
+
+#define BADF(fmt, ...) \
+do { fprintf(stderr, "i82378 ERROR: " fmt , ## __VA_ARGS__); } while (0)
+
+#ifdef HOST_WORDS_BIGENDIAN
+#define DEVICE_INVERSE_ENDIAN DEVICE_LITTLE_ENDIAN
+#else
+#define DEVICE_INVERSE_ENDIAN DEVICE_BIG_ENDIAN
+#endif
+
+typedef struct I82378State {
+ qemu_irq out[2];
+ int s_io;
+ int s_mem;
+} I82378State;
+
+typedef struct PCIi82378State {
+ PCIDevice pci_dev;
+ uint32_t isa_io_base;
+ uint32_t isa_mem_base;
+ I82378State state;
+} PCIi82378State;
+
+static inline target_phys_addr_t i82378_io_address(I82378State *state,
+ target_phys_addr_t addr)
+{
+ if (true) {
+ return addr & 0xFFFF;
+ } else {
+ return (addr & 0x1F) | ((addr & 0x007FFF000) >> 7);
+ }
+}
+
+static void i82378_io_writeb(void *opaque,
+ target_phys_addr_t addr, uint32_t value)
+{
+ I82378State *s = opaque;
+ DPRINTF("%s: " TARGET_FMT_plx "=%02x\n", __func__, addr, value);
+ addr = i82378_io_address(s, addr);
+ cpu_outb(addr, value);
+}
+
+static void i82378_io_writew(void *opaque,
+ target_phys_addr_t addr, uint32_t value)
+{
+ I82378State *s = opaque;
+ DPRINTF("%s: " TARGET_FMT_plx "=%04x\n", __func__, addr, value);
+ addr = i82378_io_address(s, addr);
+ cpu_outw(addr, value);
+}
+
+static void i82378_io_writel(void *opaque,
+ target_phys_addr_t addr, uint32_t value)
+{
+ I82378State *s = opaque;
+ DPRINTF("%s: " TARGET_FMT_plx "=%08x\n", __func__, addr, value);
+ addr = i82378_io_address(s, addr);
+ cpu_outl(addr, value);
+}
+
+static uint32_t i82378_io_readb(void *opaque, target_phys_addr_t addr)
+{
+ I82378State *s = opaque;
+ DPRINTF("%s: " TARGET_FMT_plx "\n", __func__, addr);
+ addr = i82378_io_address(s, addr);
+ return cpu_inb(addr);
+}
+
+static uint32_t i82378_io_readw(void *opaque, target_phys_addr_t addr)
+{
+ I82378State *s = opaque;
+ DPRINTF("%s: " TARGET_FMT_plx "\n", __func__, addr);
+ addr = i82378_io_address(s, addr);
+ return cpu_inw(addr);
+}
+
+static uint32_t i82378_io_readl(void *opaque, target_phys_addr_t addr)
+{
+ I82378State *s = opaque;
+ DPRINTF("%s: " TARGET_FMT_plx "\n", __func__, addr);
+ addr = i82378_io_address(s, addr);
+ return cpu_inl(addr);
+}
+
+static CPUWriteMemoryFunc * const i82378_io_write[] = {
+ i82378_io_writeb,
+ i82378_io_writew,
+ i82378_io_writel,
+};
+
+static CPUReadMemoryFunc * const i82378_io_read[] = {
+ i82378_io_readb,
+ i82378_io_readw,
+ i82378_io_readl,
+};
+
+static void i82378_mem_writeb(void *opaque,
+ target_phys_addr_t addr, uint32_t value)
+{
+ DPRINTF("%s: " TARGET_FMT_plx "=%02x\n", __func__, addr, value);
+ cpu_outb(addr, value);
+}
+
+static void i82378_mem_writew(void *opaque,
+ target_phys_addr_t addr, uint32_t value)
+{
+ DPRINTF("%s: " TARGET_FMT_plx "=%04x\n", __func__, addr, value);
+ cpu_outw(addr, value);
+}
+
+static void i82378_mem_writel(void *opaque,
+ target_phys_addr_t addr, uint32_t value)
+{
+ DPRINTF("%s: " TARGET_FMT_plx "=%08x\n", __func__, addr, value);
+ cpu_outl(addr, value);
+}
+
+static uint32_t i82378_mem_readb(void *opaque, target_phys_addr_t addr)
+{
+ DPRINTF("%s: " TARGET_FMT_plx "\n", __func__, addr);
+ return cpu_inb(addr);
+}
+
+static uint32_t i82378_mem_readw(void *opaque, target_phys_addr_t addr)
+{
+ DPRINTF("%s: " TARGET_FMT_plx "\n", __func__, addr);
+ return cpu_inw(addr);
+}
+
+static uint32_t i82378_mem_readl(void *opaque, target_phys_addr_t addr)
+{
+ DPRINTF("%s: " TARGET_FMT_plx "\n", __func__, addr);
+ return cpu_inl(addr);
+}
+
+static CPUWriteMemoryFunc * const i82378_mem_write[] = {
+ i82378_mem_writeb,
+ i82378_mem_writew,
+ i82378_mem_writel,
+};
+
+static CPUReadMemoryFunc * const i82378_mem_read[] = {
+ i82378_mem_readb,
+ i82378_mem_readw,
+ i82378_mem_readl,
+};
+
+static void i82378_init(DeviceState *dev, I82378State *s)
+{
+ ISADevice *pit;
+
+ isa_bus_new(dev);
+
+ /* This device has:
+ 2 82C59 (irq)
+ 1 82C54 (pit)
+ 2 82C37 (dma)
+ NMI
+ Utility Bus Support Registers
+
+ All devices accept byte access only, except timer
+ */
+
+ /* 2 82C59 (irq) */
+ qdev_init_gpio_out(dev, s->out, 2);
+ isa_bus_irqs(i8259_init(s->out[0]));
+
+ /* 1 82C54 (pit) */
+ pit = pit_init(0x40, 0);
+
+ /* speaker */
+ pcspk_init(pit);
+
+ /* 2 82C37 (dma) */
+ DMA_init(1, &s->out[1]);
+ isa_create_simple("i82374");
+
+ /* timer */
+ isa_create_simple("mc146818rtc");
+
+ s->s_io = cpu_register_io_memory(i82378_io_read,
+ i82378_io_write, s, DEVICE_INVERSE_ENDIAN);
+ s->s_mem = cpu_register_io_memory(i82378_mem_read,
+ i82378_mem_write, s, DEVICE_INVERSE_ENDIAN);
+}
+
+static void pci_i82378_ioport_map(PCIDevice *pci_dev, int region_num,
+ pcibus_t addr, pcibus_t size, int type)
+{
+ I82378State *s = &DO_UPCAST(PCIi82378State, pci_dev, pci_dev)->state;
+
+ DPRINTF("%s: %s addr=0x%" FMT_PCIBUS " size=0x%" FMT_PCIBUS "\n",
+ __func__, pci_dev->name, addr, size);
+
+ cpu_register_physical_memory(addr, size, s->s_io);
+}
+
+static void pci_i82378_mmio_map(PCIDevice *pci_dev, int region_num,
+ pcibus_t addr, pcibus_t size, int type)
+{
+ I82378State *s = &DO_UPCAST(PCIi82378State, pci_dev, pci_dev)->state;
+
+ DPRINTF("%s: %s addr=0x%" FMT_PCIBUS " size=0x%" FMT_PCIBUS "\n",
+ __func__, pci_dev->name, addr, size);
+
+ cpu_register_physical_memory(addr, size, s->s_mem);
+ qemu_register_coalesced_mmio(addr, size);
+}
+
+static int pci_i82378_init(PCIDevice *pci_dev)
+{
+ PCIi82378State *pci = DO_UPCAST(PCIi82378State, pci_dev, pci_dev);
+ I82378State *s = &pci->state;
+ uint8_t *pci_conf;
+
+ pci_conf = pci_dev->config;
+ pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_INTEL);
+ pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_INTEL_82378);
+ pci_set_word(pci_conf + PCI_COMMAND,
+ PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
+ pci_set_word(pci_conf + PCI_STATUS,
+ PCI_STATUS_DEVSEL_MEDIUM);
+ pci_conf[PCI_REVISION_ID] = 0x03;
+ pci_config_set_class(pci_conf, PCI_CLASS_BRIDGE_ISA);
+
+ pci_set_word(pci_conf + PCI_SUBSYSTEM_VENDOR_ID, 0x0);
+ pci_set_word(pci_conf + PCI_SUBSYSTEM_ID, 0x0);
+
+ pci_conf[PCI_INTERRUPT_PIN] = 1; /* interrupt pin 0 */
+
+ pci_register_bar(pci_dev, 0, 0x00010000,
+ PCI_BASE_ADDRESS_SPACE_MEMORY, pci_i82378_ioport_map);
+
+ pci_register_bar(pci_dev, 1, 0x01000000,
+ PCI_BASE_ADDRESS_SPACE_MEMORY, pci_i82378_mmio_map);
+
+ /* Make addresses read only */
+ pci_set_word(pci_dev->wmask + PCI_COMMAND,
+ PCI_COMMAND_SPECIAL);
+ pci_set_long(pci_conf + PCI_BASE_ADDRESS_0 + 0 * 4, pci->isa_io_base);
+ pci_set_long(pci_conf + PCI_BASE_ADDRESS_0 + 1 * 4, pci->isa_mem_base);
+
+ isa_mem_base = pci->isa_mem_base;
+ i82378_init(&pci_dev->qdev, s);
+
+ return 0;
+}
+
+static PCIDeviceInfo pci_i82378_info = {
+ .init = pci_i82378_init,
+ .qdev.name = "i82378",
+ .qdev.size = sizeof(PCIi82378State),
+ .qdev.props = (Property[]) {
+ DEFINE_PROP_HEX32("iobase", PCIi82378State, isa_io_base, 0x80000000),
+ DEFINE_PROP_HEX32("membase", PCIi82378State, isa_mem_base, 0xc0000000),
+ DEFINE_PROP_END_OF_LIST()
+ },
+};
+
+static void i82378_register_devices(void)
+{
+ pci_qdev_register(&pci_i82378_info);
+}
+
+device_init(i82378_register_devices)
diff --git a/hw/pci_ids.h b/hw/pci_ids.h
index d9457ed..d3bef0e 100644
--- a/hw/pci_ids.h
+++ b/hw/pci_ids.h
@@ -98,6 +98,7 @@
#define PCI_DEVICE_ID_MPC8533E 0x0030
#define PCI_VENDOR_ID_INTEL 0x8086
+#define PCI_DEVICE_ID_INTEL_82378 0x0484
#define PCI_DEVICE_ID_INTEL_82441 0x1237
#define PCI_DEVICE_ID_INTEL_82801AA_5 0x2415
#define PCI_DEVICE_ID_INTEL_82801D 0x24CD
--
1.7.5.3
next prev parent reply other threads:[~2011-06-14 2:38 UTC|newest]
Thread overview: 37+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-06-14 2:37 [Qemu-devel] [RFC 00/23] PReP 40P emulation Andreas Färber
2011-06-14 2:37 ` [Qemu-devel] [PATCH RFC 01/23] prep: Refactor CPU initialization Andreas Färber
2011-06-14 2:37 ` [Qemu-devel] [RFC 02/23] prep: qdev'ify PCI Andreas Färber
2011-06-14 2:37 ` [Qemu-devel] [RFC 03/23] prep: Prepare emulation of an IBM RS/6000 6015 / 7020 (40p) Andreas Färber
2011-06-14 2:37 ` [Qemu-devel] [RFC 04/23] 40p: Add PCI host Andreas Färber
2011-06-14 2:37 ` [Qemu-devel] [RFC 05/23] prep: Add i82374 DMA emulation Andreas Färber
2011-06-14 2:37 ` Andreas Färber [this message]
2011-06-14 2:37 ` [Qemu-devel] [RFC 07/23] 40p: Add a PCI to ISA bridge (i82378) Andreas Färber
2011-06-14 2:37 ` [Qemu-devel] [PATCH v5 08/23] qdev: Add support for property type bool Andreas Färber
2011-06-14 2:37 ` [Qemu-devel] [PATCH v5 09/23] qdev: Add helpers for reading properties Andreas Färber
2011-06-14 2:37 ` [Qemu-devel] [RFC v5 10/23] isa: Provide enable and disable callbacks Andreas Färber
2011-06-14 2:37 ` [Qemu-devel] [RFC v5 11/23] isa: Allow to un-assign I/O ports Andreas Färber
2011-06-14 2:37 ` [Qemu-devel] [RFC v5 12/23] isa: Allow to un-associate an IRQ Andreas Färber
2011-06-14 2:37 ` [Qemu-devel] [RFC v5 13/23] parallel: Implement ISA state callbacks Andreas Färber
2011-06-14 2:37 ` [Qemu-devel] [RFC v5 14/23] serial: " Andreas Färber
2011-06-14 2:37 ` [Qemu-devel] [PATCH v5 15/23] fdc: Parametrize ISA base, IRQ and DMA Andreas Färber
2011-06-14 2:37 ` [Qemu-devel] [RFC v5 16/23] fdc: Implement ISA state callbacks Andreas Färber
2011-06-14 2:37 ` [Qemu-devel] [RFC v5 17/23] ide: Allow to discard I/O ports Andreas Färber
2011-06-14 2:37 ` [Qemu-devel] [RFC v5 18/23] ide: Implement ISA state callbacks Andreas Färber
2011-06-14 2:37 ` [Qemu-devel] [RFC v5 19/23] prep: Add pc87312 Super I/O emulation Andreas Färber
2011-06-14 2:37 ` [Qemu-devel] [RFC 20/23] 40p: Add the Super I/O chip (pc87312) Andreas Färber
2011-06-14 2:37 ` [Qemu-devel] [RFC 21/23] 40p: Add an audio card and a keyboard Andreas Färber
2011-06-14 2:37 ` [Qemu-devel] [RFC 22/23] prep: qdev'ify System I/O (WIP) Andreas Färber
2011-06-14 2:37 ` [Qemu-devel] [RFC 23/23] 40p: Add an 8514/A graphics card Andreas Färber
2011-06-15 4:33 ` Roy Tam
2011-06-15 18:11 ` Andreas Färber
2011-06-16 0:02 ` [Qemu-devel] [RFC v2 23/23] 40p: Add an IBM " Andreas Färber
2011-06-18 20:42 ` Blue Swirl
2011-06-19 10:04 ` Andreas Färber
2011-06-19 12:10 ` Hervé Poussineau
2011-06-19 13:27 ` Blue Swirl
2011-06-19 18:40 ` Andreas Färber
2011-06-19 19:03 ` Blue Swirl
2011-06-19 21:38 ` Andreas Färber
2011-06-19 21:43 ` [Qemu-devel] [RFC v3 " Andreas Färber
2011-06-16 0:05 ` [Qemu-devel] [RFC 23/23] 40p: Add an " Andreas Färber
2011-06-16 1:22 ` Roy Tam
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1308019077-61957-7-git-send-email-andreas.faerber@web.de \
--to=andreas.faerber@web.de \
--cc=armbru@redhat.com \
--cc=hpoussin@reactos.org \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).