qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
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

  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).