From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([140.186.70.92]:57348) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1QWJW9-0006va-Ix for qemu-devel@nongnu.org; Mon, 13 Jun 2011 22:38:18 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1QWJW0-0006h0-I0 for qemu-devel@nongnu.org; Mon, 13 Jun 2011 22:38:12 -0400 Received: from fmmailgate02.web.de ([217.72.192.227]:57761) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1QWJVz-0006gL-3D for qemu-devel@nongnu.org; Mon, 13 Jun 2011 22:38:04 -0400 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Tue, 14 Jun 2011 04:37:40 +0200 Message-Id: <1308019077-61957-7-git-send-email-andreas.faerber@web.de> In-Reply-To: <1308019077-61957-6-git-send-email-andreas.faerber@web.de> References: <1308019077-61957-1-git-send-email-andreas.faerber@web.de> <1308019077-61957-2-git-send-email-andreas.faerber@web.de> <1308019077-61957-3-git-send-email-andreas.faerber@web.de> <1308019077-61957-4-git-send-email-andreas.faerber@web.de> <1308019077-61957-5-git-send-email-andreas.faerber@web.de> <1308019077-61957-6-git-send-email-andreas.faerber@web.de> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Sender: andreas.faerber@web.de Content-Transfer-Encoding: quoted-printable Subject: [Qemu-devel] [RFC 06/23] prep: Add i82378 PCI-to-ISA bridge emulation List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: =?UTF-8?q?Andreas=20F=C3=A4rber?= , =?UTF-8?q?Herv=C3=A9=20Poussineau?= , Markus Armbruster Signed-off-by: Herv=C3=A9 Poussineau Inverse endianness in order to work on x86 and ppc host. Create ISA bus in this device (suggested by Markus). Cc: Markus Armbruster Signed-off-by: Andreas F=C3=A4rber --- 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) +=3D ccid-card-emulate= d.o # PPC devices hw-obj-$(CONFIG_OPENPIC) +=3D openpic.o hw-obj-$(CONFIG_PREP_PCI) +=3D prep_pci.o +hw-obj-$(CONFIG_I82378) +=3D i82378.o # Mac shared devices hw-obj-$(CONFIG_MACIO) +=3D macio.o hw-obj-$(CONFIG_CUDA) +=3D cuda.o diff --git a/default-configs/ppc-softmmu.mak b/default-configs/ppc-softmm= u.mak index 1d1a7c2..df64ee6 100644 --- a/default-configs/ppc-softmmu.mak +++ b/default-configs/ppc-softmmu.mak @@ -14,7 +14,9 @@ CONFIG_DMA=3Dy CONFIG_I82374=3Dy CONFIG_OPENPIC=3Dy CONFIG_PREP_PCI=3Dy +CONFIG_I82378=3Dy CONFIG_MACIO=3Dy +CONFIG_PCSPK=3Dy CONFIG_CUDA=3Dy CONFIG_ADB=3Dy CONFIG_MAC_NVRAM=3Dy 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 . + */ + +#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 ad= dr) +{ + 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 =3D opaque; + DPRINTF("%s: " TARGET_FMT_plx "=3D%02x\n", __func__, addr, value); + addr =3D 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 =3D opaque; + DPRINTF("%s: " TARGET_FMT_plx "=3D%04x\n", __func__, addr, value); + addr =3D 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 =3D opaque; + DPRINTF("%s: " TARGET_FMT_plx "=3D%08x\n", __func__, addr, value); + addr =3D i82378_io_address(s, addr); + cpu_outl(addr, value); +} + +static uint32_t i82378_io_readb(void *opaque, target_phys_addr_t addr) +{ + I82378State *s =3D opaque; + DPRINTF("%s: " TARGET_FMT_plx "\n", __func__, addr); + addr =3D i82378_io_address(s, addr); + return cpu_inb(addr); +} + +static uint32_t i82378_io_readw(void *opaque, target_phys_addr_t addr) +{ + I82378State *s =3D opaque; + DPRINTF("%s: " TARGET_FMT_plx "\n", __func__, addr); + addr =3D i82378_io_address(s, addr); + return cpu_inw(addr); +} + +static uint32_t i82378_io_readl(void *opaque, target_phys_addr_t addr) +{ + I82378State *s =3D opaque; + DPRINTF("%s: " TARGET_FMT_plx "\n", __func__, addr); + addr =3D i82378_io_address(s, addr); + return cpu_inl(addr); +} + +static CPUWriteMemoryFunc * const i82378_io_write[] =3D { + i82378_io_writeb, + i82378_io_writew, + i82378_io_writel, +}; + +static CPUReadMemoryFunc * const i82378_io_read[] =3D { + 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 "=3D%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 "=3D%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 "=3D%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[] =3D { + i82378_mem_writeb, + i82378_mem_writew, + i82378_mem_writel, +}; + +static CPUReadMemoryFunc * const i82378_mem_read[] =3D { + 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 =3D 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 =3D cpu_register_io_memory(i82378_io_read, + i82378_io_write, s, DEVICE_INVERSE_= ENDIAN); + s->s_mem =3D cpu_register_io_memory(i82378_mem_read, + i82378_mem_write, s, DEVICE_INVERS= E_ENDIAN); +} + +static void pci_i82378_ioport_map(PCIDevice *pci_dev, int region_num, + pcibus_t addr, pcibus_t size, int type= ) +{ + I82378State *s =3D &DO_UPCAST(PCIi82378State, pci_dev, pci_dev)->sta= te; + + DPRINTF("%s: %s addr=3D0x%" FMT_PCIBUS " size=3D0x%" 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 =3D &DO_UPCAST(PCIi82378State, pci_dev, pci_dev)->sta= te; + + DPRINTF("%s: %s addr=3D0x%" FMT_PCIBUS " size=3D0x%" 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 =3D DO_UPCAST(PCIi82378State, pci_dev, pci_dev); + I82378State *s =3D &pci->state; + uint8_t *pci_conf; + + pci_conf =3D 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_MASTE= R); + pci_set_word(pci_conf + PCI_STATUS, + PCI_STATUS_DEVSEL_MEDIUM); + pci_conf[PCI_REVISION_ID] =3D 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] =3D 1; /* interrupt pin 0 */ + + pci_register_bar(pci_dev, 0, 0x00010000, + PCI_BASE_ADDRESS_SPACE_MEMORY, pci_i82378_ioport_ma= p); + + 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_bas= e); + + isa_mem_base =3D pci->isa_mem_base; + i82378_init(&pci_dev->qdev, s); + + return 0; +} + +static PCIDeviceInfo pci_i82378_info =3D { + .init =3D pci_i82378_init, + .qdev.name =3D "i82378", + .qdev.size =3D sizeof(PCIi82378State), + .qdev.props =3D (Property[]) { + DEFINE_PROP_HEX32("iobase", PCIi82378State, isa_io_base, 0x80000= 000), + DEFINE_PROP_HEX32("membase", PCIi82378State, isa_mem_base, 0xc00= 00000), + 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 =20 #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 --=20 1.7.5.3