From bb756eebdac6fd24e8919e2c43f7d2c8c4091f59 Mon Sep 17 00:00:00 2001 From: RajithaY Date: Tue, 25 Apr 2017 03:31:15 -0700 Subject: Adding qemu as a submodule of KVMFORNFV This Patch includes the changes to add qemu as a submodule to kvmfornfv repo and make use of the updated latest qemu for the execution of all testcase Change-Id: I1280af507a857675c7f81d30c95255635667bdd7 Signed-off-by:RajithaY --- qemu/hw/pci-host/Makefile.objs | 18 - qemu/hw/pci-host/apb.c | 871 ---------------------------------------- qemu/hw/pci-host/bonito.c | 858 --------------------------------------- qemu/hw/pci-host/gpex.c | 155 ------- qemu/hw/pci-host/grackle.c | 169 -------- qemu/hw/pci-host/pam.c | 70 ---- qemu/hw/pci-host/piix.c | 888 ----------------------------------------- qemu/hw/pci-host/ppce500.c | 551 ------------------------- qemu/hw/pci-host/prep.c | 406 ------------------- qemu/hw/pci-host/q35.c | 560 -------------------------- qemu/hw/pci-host/uninorth.c | 533 ------------------------- qemu/hw/pci-host/versatile.c | 549 ------------------------- 12 files changed, 5628 deletions(-) delete mode 100644 qemu/hw/pci-host/Makefile.objs delete mode 100644 qemu/hw/pci-host/apb.c delete mode 100644 qemu/hw/pci-host/bonito.c delete mode 100644 qemu/hw/pci-host/gpex.c delete mode 100644 qemu/hw/pci-host/grackle.c delete mode 100644 qemu/hw/pci-host/pam.c delete mode 100644 qemu/hw/pci-host/piix.c delete mode 100644 qemu/hw/pci-host/ppce500.c delete mode 100644 qemu/hw/pci-host/prep.c delete mode 100644 qemu/hw/pci-host/q35.c delete mode 100644 qemu/hw/pci-host/uninorth.c delete mode 100644 qemu/hw/pci-host/versatile.c (limited to 'qemu/hw/pci-host') diff --git a/qemu/hw/pci-host/Makefile.objs b/qemu/hw/pci-host/Makefile.objs deleted file mode 100644 index 45f1f0eba..000000000 --- a/qemu/hw/pci-host/Makefile.objs +++ /dev/null @@ -1,18 +0,0 @@ -common-obj-y += pam.o - -# PPC devices -common-obj-$(CONFIG_PREP_PCI) += prep.o -common-obj-$(CONFIG_GRACKLE_PCI) += grackle.o -# NewWorld PowerMac -common-obj-$(CONFIG_UNIN_PCI) += uninorth.o -# PowerPC E500 boards -common-obj-$(CONFIG_PPCE500_PCI) += ppce500.o - -# ARM devices -common-obj-$(CONFIG_VERSATILE_PCI) += versatile.o - -common-obj-$(CONFIG_PCI_APB) += apb.o -common-obj-$(CONFIG_FULONG) += bonito.o -common-obj-$(CONFIG_PCI_PIIX) += piix.o -common-obj-$(CONFIG_PCI_Q35) += q35.o -common-obj-$(CONFIG_PCI_GENERIC) += gpex.o diff --git a/qemu/hw/pci-host/apb.c b/qemu/hw/pci-host/apb.c deleted file mode 100644 index aaef7bb3a..000000000 --- a/qemu/hw/pci-host/apb.c +++ /dev/null @@ -1,871 +0,0 @@ -/* - * QEMU Ultrasparc APB PCI host - * - * Copyright (c) 2006 Fabrice Bellard - * Copyright (c) 2012,2013 Artyom Tarasenko - * - * 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. - */ - -/* XXX This file and most of its contents are somewhat misnamed. The - Ultrasparc PCI host is called the PCI Bus Module (PBM). The APB is - the secondary PCI bridge. */ - -#include "qemu/osdep.h" -#include "hw/sysbus.h" -#include "hw/pci/pci.h" -#include "hw/pci/pci_host.h" -#include "hw/pci/pci_bridge.h" -#include "hw/pci/pci_bus.h" -#include "hw/pci-host/apb.h" -#include "sysemu/sysemu.h" -#include "exec/address-spaces.h" - -/* debug APB */ -//#define DEBUG_APB - -#ifdef DEBUG_APB -#define APB_DPRINTF(fmt, ...) \ -do { printf("APB: " fmt , ## __VA_ARGS__); } while (0) -#else -#define APB_DPRINTF(fmt, ...) -#endif - -/* debug IOMMU */ -//#define DEBUG_IOMMU - -#ifdef DEBUG_IOMMU -#define IOMMU_DPRINTF(fmt, ...) \ -do { printf("IOMMU: " fmt , ## __VA_ARGS__); } while (0) -#else -#define IOMMU_DPRINTF(fmt, ...) -#endif - -/* - * Chipset docs: - * PBM: "UltraSPARC IIi User's Manual", - * http://www.sun.com/processors/manuals/805-0087.pdf - * - * APB: "Advanced PCI Bridge (APB) User's Manual", - * http://www.sun.com/processors/manuals/805-1251.pdf - */ - -#define PBM_PCI_IMR_MASK 0x7fffffff -#define PBM_PCI_IMR_ENABLED 0x80000000 - -#define POR (1U << 31) -#define SOFT_POR (1U << 30) -#define SOFT_XIR (1U << 29) -#define BTN_POR (1U << 28) -#define BTN_XIR (1U << 27) -#define RESET_MASK 0xf8000000 -#define RESET_WCMASK 0x98000000 -#define RESET_WMASK 0x60000000 - -#define MAX_IVEC 0x40 -#define NO_IRQ_REQUEST (MAX_IVEC + 1) - -#define IOMMU_PAGE_SIZE_8K (1ULL << 13) -#define IOMMU_PAGE_MASK_8K (~(IOMMU_PAGE_SIZE_8K - 1)) -#define IOMMU_PAGE_SIZE_64K (1ULL << 16) -#define IOMMU_PAGE_MASK_64K (~(IOMMU_PAGE_SIZE_64K - 1)) - -#define IOMMU_NREGS 3 - -#define IOMMU_CTRL 0x0 -#define IOMMU_CTRL_TBW_SIZE (1ULL << 2) -#define IOMMU_CTRL_MMU_EN (1ULL) - -#define IOMMU_CTRL_TSB_SHIFT 16 - -#define IOMMU_BASE 0x8 -#define IOMMU_FLUSH 0x10 - -#define IOMMU_TTE_DATA_V (1ULL << 63) -#define IOMMU_TTE_DATA_SIZE (1ULL << 61) -#define IOMMU_TTE_DATA_W (1ULL << 1) - -#define IOMMU_TTE_PHYS_MASK_8K 0x1ffffffe000ULL -#define IOMMU_TTE_PHYS_MASK_64K 0x1ffffff8000ULL - -#define IOMMU_TSB_8K_OFFSET_MASK_8M 0x00000000007fe000ULL -#define IOMMU_TSB_8K_OFFSET_MASK_16M 0x0000000000ffe000ULL -#define IOMMU_TSB_8K_OFFSET_MASK_32M 0x0000000001ffe000ULL -#define IOMMU_TSB_8K_OFFSET_MASK_64M 0x0000000003ffe000ULL -#define IOMMU_TSB_8K_OFFSET_MASK_128M 0x0000000007ffe000ULL -#define IOMMU_TSB_8K_OFFSET_MASK_256M 0x000000000fffe000ULL -#define IOMMU_TSB_8K_OFFSET_MASK_512M 0x000000001fffe000ULL -#define IOMMU_TSB_8K_OFFSET_MASK_1G 0x000000003fffe000ULL - -#define IOMMU_TSB_64K_OFFSET_MASK_64M 0x0000000003ff0000ULL -#define IOMMU_TSB_64K_OFFSET_MASK_128M 0x0000000007ff0000ULL -#define IOMMU_TSB_64K_OFFSET_MASK_256M 0x000000000fff0000ULL -#define IOMMU_TSB_64K_OFFSET_MASK_512M 0x000000001fff0000ULL -#define IOMMU_TSB_64K_OFFSET_MASK_1G 0x000000003fff0000ULL -#define IOMMU_TSB_64K_OFFSET_MASK_2G 0x000000007fff0000ULL - -typedef struct IOMMUState { - AddressSpace iommu_as; - MemoryRegion iommu; - - uint64_t regs[IOMMU_NREGS]; -} IOMMUState; - -#define TYPE_APB "pbm" - -#define APB_DEVICE(obj) \ - OBJECT_CHECK(APBState, (obj), TYPE_APB) - -typedef struct APBState { - PCIHostState parent_obj; - - MemoryRegion apb_config; - MemoryRegion pci_config; - MemoryRegion pci_mmio; - MemoryRegion pci_ioport; - uint64_t pci_irq_in; - IOMMUState iommu; - uint32_t pci_control[16]; - uint32_t pci_irq_map[8]; - uint32_t pci_err_irq_map[4]; - uint32_t obio_irq_map[32]; - qemu_irq *pbm_irqs; - qemu_irq *ivec_irqs; - unsigned int irq_request; - uint32_t reset_control; - unsigned int nr_resets; -} APBState; - -static inline void pbm_set_request(APBState *s, unsigned int irq_num) -{ - APB_DPRINTF("%s: request irq %d\n", __func__, irq_num); - - s->irq_request = irq_num; - qemu_set_irq(s->ivec_irqs[irq_num], 1); -} - -static inline void pbm_check_irqs(APBState *s) -{ - - unsigned int i; - - /* Previous request is not acknowledged, resubmit */ - if (s->irq_request != NO_IRQ_REQUEST) { - pbm_set_request(s, s->irq_request); - return; - } - /* no request pending */ - if (s->pci_irq_in == 0ULL) { - return; - } - for (i = 0; i < 32; i++) { - if (s->pci_irq_in & (1ULL << i)) { - if (s->pci_irq_map[i >> 2] & PBM_PCI_IMR_ENABLED) { - pbm_set_request(s, i); - return; - } - } - } - for (i = 32; i < 64; i++) { - if (s->pci_irq_in & (1ULL << i)) { - if (s->obio_irq_map[i - 32] & PBM_PCI_IMR_ENABLED) { - pbm_set_request(s, i); - break; - } - } - } -} - -static inline void pbm_clear_request(APBState *s, unsigned int irq_num) -{ - APB_DPRINTF("%s: clear request irq %d\n", __func__, irq_num); - qemu_set_irq(s->ivec_irqs[irq_num], 0); - s->irq_request = NO_IRQ_REQUEST; -} - -static AddressSpace *pbm_pci_dma_iommu(PCIBus *bus, void *opaque, int devfn) -{ - IOMMUState *is = opaque; - - return &is->iommu_as; -} - -/* Called from RCU critical section */ -static IOMMUTLBEntry pbm_translate_iommu(MemoryRegion *iommu, hwaddr addr, - bool is_write) -{ - IOMMUState *is = container_of(iommu, IOMMUState, iommu); - hwaddr baseaddr, offset; - uint64_t tte; - uint32_t tsbsize; - IOMMUTLBEntry ret = { - .target_as = &address_space_memory, - .iova = 0, - .translated_addr = 0, - .addr_mask = ~(hwaddr)0, - .perm = IOMMU_NONE, - }; - - if (!(is->regs[IOMMU_CTRL >> 3] & IOMMU_CTRL_MMU_EN)) { - /* IOMMU disabled, passthrough using standard 8K page */ - ret.iova = addr & IOMMU_PAGE_MASK_8K; - ret.translated_addr = addr; - ret.addr_mask = IOMMU_PAGE_MASK_8K; - ret.perm = IOMMU_RW; - - return ret; - } - - baseaddr = is->regs[IOMMU_BASE >> 3]; - tsbsize = (is->regs[IOMMU_CTRL >> 3] >> IOMMU_CTRL_TSB_SHIFT) & 0x7; - - if (is->regs[IOMMU_CTRL >> 3] & IOMMU_CTRL_TBW_SIZE) { - /* 64K */ - switch (tsbsize) { - case 0: - offset = (addr & IOMMU_TSB_64K_OFFSET_MASK_64M) >> 13; - break; - case 1: - offset = (addr & IOMMU_TSB_64K_OFFSET_MASK_128M) >> 13; - break; - case 2: - offset = (addr & IOMMU_TSB_64K_OFFSET_MASK_256M) >> 13; - break; - case 3: - offset = (addr & IOMMU_TSB_64K_OFFSET_MASK_512M) >> 13; - break; - case 4: - offset = (addr & IOMMU_TSB_64K_OFFSET_MASK_1G) >> 13; - break; - case 5: - offset = (addr & IOMMU_TSB_64K_OFFSET_MASK_2G) >> 13; - break; - default: - /* Not implemented, error */ - return ret; - } - } else { - /* 8K */ - switch (tsbsize) { - case 0: - offset = (addr & IOMMU_TSB_8K_OFFSET_MASK_8M) >> 10; - break; - case 1: - offset = (addr & IOMMU_TSB_8K_OFFSET_MASK_16M) >> 10; - break; - case 2: - offset = (addr & IOMMU_TSB_8K_OFFSET_MASK_32M) >> 10; - break; - case 3: - offset = (addr & IOMMU_TSB_8K_OFFSET_MASK_64M) >> 10; - break; - case 4: - offset = (addr & IOMMU_TSB_8K_OFFSET_MASK_128M) >> 10; - break; - case 5: - offset = (addr & IOMMU_TSB_8K_OFFSET_MASK_256M) >> 10; - break; - case 6: - offset = (addr & IOMMU_TSB_8K_OFFSET_MASK_512M) >> 10; - break; - case 7: - offset = (addr & IOMMU_TSB_8K_OFFSET_MASK_1G) >> 10; - break; - } - } - - tte = address_space_ldq_be(&address_space_memory, baseaddr + offset, - MEMTXATTRS_UNSPECIFIED, NULL); - - if (!(tte & IOMMU_TTE_DATA_V)) { - /* Invalid mapping */ - return ret; - } - - if (tte & IOMMU_TTE_DATA_W) { - /* Writeable */ - ret.perm = IOMMU_RW; - } else { - ret.perm = IOMMU_RO; - } - - /* Extract phys */ - if (tte & IOMMU_TTE_DATA_SIZE) { - /* 64K */ - ret.iova = addr & IOMMU_PAGE_MASK_64K; - ret.translated_addr = tte & IOMMU_TTE_PHYS_MASK_64K; - ret.addr_mask = (IOMMU_PAGE_SIZE_64K - 1); - } else { - /* 8K */ - ret.iova = addr & IOMMU_PAGE_MASK_8K; - ret.translated_addr = tte & IOMMU_TTE_PHYS_MASK_8K; - ret.addr_mask = (IOMMU_PAGE_SIZE_8K - 1); - } - - return ret; -} - -static MemoryRegionIOMMUOps pbm_iommu_ops = { - .translate = pbm_translate_iommu, -}; - -static void iommu_config_write(void *opaque, hwaddr addr, - uint64_t val, unsigned size) -{ - IOMMUState *is = opaque; - - IOMMU_DPRINTF("IOMMU config write: 0x%" HWADDR_PRIx " val: %" PRIx64 - " size: %d\n", addr, val, size); - - switch (addr) { - case IOMMU_CTRL: - if (size == 4) { - is->regs[IOMMU_CTRL >> 3] &= 0xffffffffULL; - is->regs[IOMMU_CTRL >> 3] |= val << 32; - } else { - is->regs[IOMMU_CTRL >> 3] = val; - } - break; - case IOMMU_CTRL + 0x4: - is->regs[IOMMU_CTRL >> 3] &= 0xffffffff00000000ULL; - is->regs[IOMMU_CTRL >> 3] |= val & 0xffffffffULL; - break; - case IOMMU_BASE: - if (size == 4) { - is->regs[IOMMU_BASE >> 3] &= 0xffffffffULL; - is->regs[IOMMU_BASE >> 3] |= val << 32; - } else { - is->regs[IOMMU_BASE >> 3] = val; - } - break; - case IOMMU_BASE + 0x4: - is->regs[IOMMU_BASE >> 3] &= 0xffffffff00000000ULL; - is->regs[IOMMU_BASE >> 3] |= val & 0xffffffffULL; - break; - case IOMMU_FLUSH: - case IOMMU_FLUSH + 0x4: - break; - default: - qemu_log_mask(LOG_UNIMP, - "apb iommu: Unimplemented register write " - "reg 0x%" HWADDR_PRIx " size 0x%x value 0x%" PRIx64 "\n", - addr, size, val); - break; - } -} - -static uint64_t iommu_config_read(void *opaque, hwaddr addr, unsigned size) -{ - IOMMUState *is = opaque; - uint64_t val; - - switch (addr) { - case IOMMU_CTRL: - if (size == 4) { - val = is->regs[IOMMU_CTRL >> 3] >> 32; - } else { - val = is->regs[IOMMU_CTRL >> 3]; - } - break; - case IOMMU_CTRL + 0x4: - val = is->regs[IOMMU_CTRL >> 3] & 0xffffffffULL; - break; - case IOMMU_BASE: - if (size == 4) { - val = is->regs[IOMMU_BASE >> 3] >> 32; - } else { - val = is->regs[IOMMU_BASE >> 3]; - } - break; - case IOMMU_BASE + 0x4: - val = is->regs[IOMMU_BASE >> 3] & 0xffffffffULL; - break; - case IOMMU_FLUSH: - case IOMMU_FLUSH + 0x4: - val = 0; - break; - default: - qemu_log_mask(LOG_UNIMP, - "apb iommu: Unimplemented register read " - "reg 0x%" HWADDR_PRIx " size 0x%x\n", - addr, size); - val = 0; - break; - } - - IOMMU_DPRINTF("IOMMU config read: 0x%" HWADDR_PRIx " val: %" PRIx64 - " size: %d\n", addr, val, size); - - return val; -} - -static void apb_config_writel (void *opaque, hwaddr addr, - uint64_t val, unsigned size) -{ - APBState *s = opaque; - IOMMUState *is = &s->iommu; - - APB_DPRINTF("%s: addr " TARGET_FMT_plx " val %" PRIx64 "\n", __func__, addr, val); - - switch (addr & 0xffff) { - case 0x30 ... 0x4f: /* DMA error registers */ - /* XXX: not implemented yet */ - break; - case 0x200 ... 0x217: /* IOMMU */ - iommu_config_write(is, (addr & 0x1f), val, size); - break; - case 0xc00 ... 0xc3f: /* PCI interrupt control */ - if (addr & 4) { - unsigned int ino = (addr & 0x3f) >> 3; - s->pci_irq_map[ino] &= PBM_PCI_IMR_MASK; - s->pci_irq_map[ino] |= val & ~PBM_PCI_IMR_MASK; - if ((s->irq_request == ino) && !(val & ~PBM_PCI_IMR_MASK)) { - pbm_clear_request(s, ino); - } - pbm_check_irqs(s); - } - break; - case 0x1000 ... 0x107f: /* OBIO interrupt control */ - if (addr & 4) { - unsigned int ino = ((addr & 0xff) >> 3); - s->obio_irq_map[ino] &= PBM_PCI_IMR_MASK; - s->obio_irq_map[ino] |= val & ~PBM_PCI_IMR_MASK; - if ((s->irq_request == (ino | 0x20)) - && !(val & ~PBM_PCI_IMR_MASK)) { - pbm_clear_request(s, ino | 0x20); - } - pbm_check_irqs(s); - } - break; - case 0x1400 ... 0x14ff: /* PCI interrupt clear */ - if (addr & 4) { - unsigned int ino = (addr & 0xff) >> 5; - if ((s->irq_request / 4) == ino) { - pbm_clear_request(s, s->irq_request); - pbm_check_irqs(s); - } - } - break; - case 0x1800 ... 0x1860: /* OBIO interrupt clear */ - if (addr & 4) { - unsigned int ino = ((addr & 0xff) >> 3) | 0x20; - if (s->irq_request == ino) { - pbm_clear_request(s, ino); - pbm_check_irqs(s); - } - } - break; - case 0x2000 ... 0x202f: /* PCI control */ - s->pci_control[(addr & 0x3f) >> 2] = val; - break; - case 0xf020 ... 0xf027: /* Reset control */ - if (addr & 4) { - val &= RESET_MASK; - s->reset_control &= ~(val & RESET_WCMASK); - s->reset_control |= val & RESET_WMASK; - if (val & SOFT_POR) { - s->nr_resets = 0; - qemu_system_reset_request(); - } else if (val & SOFT_XIR) { - qemu_system_reset_request(); - } - } - break; - case 0x5000 ... 0x51cf: /* PIO/DMA diagnostics */ - case 0xa400 ... 0xa67f: /* IOMMU diagnostics */ - case 0xa800 ... 0xa80f: /* Interrupt diagnostics */ - case 0xf000 ... 0xf01f: /* FFB config, memory control */ - /* we don't care */ - default: - break; - } -} - -static uint64_t apb_config_readl (void *opaque, - hwaddr addr, unsigned size) -{ - APBState *s = opaque; - IOMMUState *is = &s->iommu; - uint32_t val; - - switch (addr & 0xffff) { - case 0x30 ... 0x4f: /* DMA error registers */ - val = 0; - /* XXX: not implemented yet */ - break; - case 0x200 ... 0x217: /* IOMMU */ - val = iommu_config_read(is, (addr & 0x1f), size); - break; - case 0xc00 ... 0xc3f: /* PCI interrupt control */ - if (addr & 4) { - val = s->pci_irq_map[(addr & 0x3f) >> 3]; - } else { - val = 0; - } - break; - case 0x1000 ... 0x107f: /* OBIO interrupt control */ - if (addr & 4) { - val = s->obio_irq_map[(addr & 0xff) >> 3]; - } else { - val = 0; - } - break; - case 0x1080 ... 0x108f: /* PCI bus error */ - if (addr & 4) { - val = s->pci_err_irq_map[(addr & 0xf) >> 3]; - } else { - val = 0; - } - break; - case 0x2000 ... 0x202f: /* PCI control */ - val = s->pci_control[(addr & 0x3f) >> 2]; - break; - case 0xf020 ... 0xf027: /* Reset control */ - if (addr & 4) { - val = s->reset_control; - } else { - val = 0; - } - break; - case 0x5000 ... 0x51cf: /* PIO/DMA diagnostics */ - case 0xa400 ... 0xa67f: /* IOMMU diagnostics */ - case 0xa800 ... 0xa80f: /* Interrupt diagnostics */ - case 0xf000 ... 0xf01f: /* FFB config, memory control */ - /* we don't care */ - default: - val = 0; - break; - } - APB_DPRINTF("%s: addr " TARGET_FMT_plx " -> %x\n", __func__, addr, val); - - return val; -} - -static const MemoryRegionOps apb_config_ops = { - .read = apb_config_readl, - .write = apb_config_writel, - .endianness = DEVICE_NATIVE_ENDIAN, -}; - -static void apb_pci_config_write(void *opaque, hwaddr addr, - uint64_t val, unsigned size) -{ - APBState *s = opaque; - PCIHostState *phb = PCI_HOST_BRIDGE(s); - - val = qemu_bswap_len(val, size); - APB_DPRINTF("%s: addr " TARGET_FMT_plx " val %" PRIx64 "\n", __func__, addr, val); - pci_data_write(phb->bus, addr, val, size); -} - -static uint64_t apb_pci_config_read(void *opaque, hwaddr addr, - unsigned size) -{ - uint32_t ret; - APBState *s = opaque; - PCIHostState *phb = PCI_HOST_BRIDGE(s); - - ret = pci_data_read(phb->bus, addr, size); - ret = qemu_bswap_len(ret, size); - APB_DPRINTF("%s: addr " TARGET_FMT_plx " -> %x\n", __func__, addr, ret); - return ret; -} - -/* The APB host has an IRQ line for each IRQ line of each slot. */ -static int pci_apb_map_irq(PCIDevice *pci_dev, int irq_num) -{ - return ((pci_dev->devfn & 0x18) >> 1) + irq_num; -} - -static int pci_pbm_map_irq(PCIDevice *pci_dev, int irq_num) -{ - int bus_offset; - if (pci_dev->devfn & 1) - bus_offset = 16; - else - bus_offset = 0; - return (bus_offset + (PCI_SLOT(pci_dev->devfn) << 2) + irq_num) & 0x1f; -} - -static void pci_apb_set_irq(void *opaque, int irq_num, int level) -{ - APBState *s = opaque; - - APB_DPRINTF("%s: set irq_in %d level %d\n", __func__, irq_num, level); - /* PCI IRQ map onto the first 32 INO. */ - if (irq_num < 32) { - if (level) { - s->pci_irq_in |= 1ULL << irq_num; - if (s->pci_irq_map[irq_num >> 2] & PBM_PCI_IMR_ENABLED) { - pbm_set_request(s, irq_num); - } - } else { - s->pci_irq_in &= ~(1ULL << irq_num); - } - } else { - /* OBIO IRQ map onto the next 32 INO. */ - if (level) { - APB_DPRINTF("%s: set irq %d level %d\n", __func__, irq_num, level); - s->pci_irq_in |= 1ULL << irq_num; - if ((s->irq_request == NO_IRQ_REQUEST) - && (s->obio_irq_map[irq_num - 32] & PBM_PCI_IMR_ENABLED)) { - pbm_set_request(s, irq_num); - } - } else { - s->pci_irq_in &= ~(1ULL << irq_num); - } - } -} - -static int apb_pci_bridge_initfn(PCIDevice *dev) -{ - pci_bridge_initfn(dev, TYPE_PCI_BUS); - - /* - * command register: - * According to PCI bridge spec, after reset - * bus master bit is off - * memory space enable bit is off - * According to manual (805-1251.pdf). - * the reset value should be zero unless the boot pin is tied high - * (which is true) and thus it should be PCI_COMMAND_MEMORY. - */ - pci_set_word(dev->config + PCI_COMMAND, - PCI_COMMAND_MEMORY); - pci_set_word(dev->config + PCI_STATUS, - PCI_STATUS_FAST_BACK | PCI_STATUS_66MHZ | - PCI_STATUS_DEVSEL_MEDIUM); - return 0; -} - -PCIBus *pci_apb_init(hwaddr special_base, - hwaddr mem_base, - qemu_irq *ivec_irqs, PCIBus **bus2, PCIBus **bus3, - qemu_irq **pbm_irqs) -{ - DeviceState *dev; - SysBusDevice *s; - PCIHostState *phb; - APBState *d; - IOMMUState *is; - PCIDevice *pci_dev; - PCIBridge *br; - - /* Ultrasparc PBM main bus */ - dev = qdev_create(NULL, TYPE_APB); - qdev_init_nofail(dev); - s = SYS_BUS_DEVICE(dev); - /* apb_config */ - sysbus_mmio_map(s, 0, special_base); - /* PCI configuration space */ - sysbus_mmio_map(s, 1, special_base + 0x1000000ULL); - /* pci_ioport */ - sysbus_mmio_map(s, 2, special_base + 0x2000000ULL); - d = APB_DEVICE(dev); - - memory_region_init(&d->pci_mmio, OBJECT(s), "pci-mmio", 0x100000000ULL); - memory_region_add_subregion(get_system_memory(), mem_base, &d->pci_mmio); - - phb = PCI_HOST_BRIDGE(dev); - phb->bus = pci_register_bus(DEVICE(phb), "pci", - pci_apb_set_irq, pci_pbm_map_irq, d, - &d->pci_mmio, - get_system_io(), - 0, 32, TYPE_PCI_BUS); - - *pbm_irqs = d->pbm_irqs; - d->ivec_irqs = ivec_irqs; - - pci_create_simple(phb->bus, 0, "pbm-pci"); - - /* APB IOMMU */ - is = &d->iommu; - memset(is, 0, sizeof(IOMMUState)); - - memory_region_init_iommu(&is->iommu, OBJECT(dev), &pbm_iommu_ops, - "iommu-apb", UINT64_MAX); - address_space_init(&is->iommu_as, &is->iommu, "pbm-as"); - pci_setup_iommu(phb->bus, pbm_pci_dma_iommu, is); - - /* APB secondary busses */ - pci_dev = pci_create_multifunction(phb->bus, PCI_DEVFN(1, 0), true, - "pbm-bridge"); - br = PCI_BRIDGE(pci_dev); - pci_bridge_map_irq(br, "Advanced PCI Bus secondary bridge 1", - pci_apb_map_irq); - qdev_init_nofail(&pci_dev->qdev); - *bus2 = pci_bridge_get_sec_bus(br); - - pci_dev = pci_create_multifunction(phb->bus, PCI_DEVFN(1, 1), true, - "pbm-bridge"); - br = PCI_BRIDGE(pci_dev); - pci_bridge_map_irq(br, "Advanced PCI Bus secondary bridge 2", - pci_apb_map_irq); - qdev_init_nofail(&pci_dev->qdev); - *bus3 = pci_bridge_get_sec_bus(br); - - return phb->bus; -} - -static void pci_pbm_reset(DeviceState *d) -{ - unsigned int i; - APBState *s = APB_DEVICE(d); - - for (i = 0; i < 8; i++) { - s->pci_irq_map[i] &= PBM_PCI_IMR_MASK; - } - for (i = 0; i < 32; i++) { - s->obio_irq_map[i] &= PBM_PCI_IMR_MASK; - } - - s->irq_request = NO_IRQ_REQUEST; - s->pci_irq_in = 0ULL; - - if (s->nr_resets++ == 0) { - /* Power on reset */ - s->reset_control = POR; - } -} - -static const MemoryRegionOps pci_config_ops = { - .read = apb_pci_config_read, - .write = apb_pci_config_write, - .endianness = DEVICE_NATIVE_ENDIAN, -}; - -static int pci_pbm_init_device(SysBusDevice *dev) -{ - APBState *s; - unsigned int i; - - s = APB_DEVICE(dev); - for (i = 0; i < 8; i++) { - s->pci_irq_map[i] = (0x1f << 6) | (i << 2); - } - for (i = 0; i < 2; i++) { - s->pci_err_irq_map[i] = (0x1f << 6) | 0x30; - } - for (i = 0; i < 32; i++) { - s->obio_irq_map[i] = ((0x1f << 6) | 0x20) + i; - } - s->pbm_irqs = qemu_allocate_irqs(pci_apb_set_irq, s, MAX_IVEC); - s->irq_request = NO_IRQ_REQUEST; - s->pci_irq_in = 0ULL; - - /* apb_config */ - memory_region_init_io(&s->apb_config, OBJECT(s), &apb_config_ops, s, - "apb-config", 0x10000); - /* at region 0 */ - sysbus_init_mmio(dev, &s->apb_config); - - memory_region_init_io(&s->pci_config, OBJECT(s), &pci_config_ops, s, - "apb-pci-config", 0x1000000); - /* at region 1 */ - sysbus_init_mmio(dev, &s->pci_config); - - /* pci_ioport */ - memory_region_init_alias(&s->pci_ioport, OBJECT(s), "apb-pci-ioport", - get_system_io(), 0, 0x10000); - /* at region 2 */ - sysbus_init_mmio(dev, &s->pci_ioport); - - return 0; -} - -static void pbm_pci_host_realize(PCIDevice *d, Error **errp) -{ - pci_set_word(d->config + PCI_COMMAND, - PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); - pci_set_word(d->config + PCI_STATUS, - PCI_STATUS_FAST_BACK | PCI_STATUS_66MHZ | - PCI_STATUS_DEVSEL_MEDIUM); -} - -static void pbm_pci_host_class_init(ObjectClass *klass, void *data) -{ - PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - DeviceClass *dc = DEVICE_CLASS(klass); - - k->realize = pbm_pci_host_realize; - k->vendor_id = PCI_VENDOR_ID_SUN; - k->device_id = PCI_DEVICE_ID_SUN_SABRE; - k->class_id = PCI_CLASS_BRIDGE_HOST; - /* - * PCI-facing part of the host bridge, not usable without the - * host-facing part, which can't be device_add'ed, yet. - */ - dc->cannot_instantiate_with_device_add_yet = true; -} - -static const TypeInfo pbm_pci_host_info = { - .name = "pbm-pci", - .parent = TYPE_PCI_DEVICE, - .instance_size = sizeof(PCIDevice), - .class_init = pbm_pci_host_class_init, -}; - -static void pbm_host_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); - - k->init = pci_pbm_init_device; - set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); - dc->reset = pci_pbm_reset; -} - -static const TypeInfo pbm_host_info = { - .name = TYPE_APB, - .parent = TYPE_PCI_HOST_BRIDGE, - .instance_size = sizeof(APBState), - .class_init = pbm_host_class_init, -}; - -static void pbm_pci_bridge_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - - k->init = apb_pci_bridge_initfn; - k->exit = pci_bridge_exitfn; - k->vendor_id = PCI_VENDOR_ID_SUN; - k->device_id = PCI_DEVICE_ID_SUN_SIMBA; - k->revision = 0x11; - k->config_write = pci_bridge_write_config; - k->is_bridge = 1; - set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); - dc->reset = pci_bridge_reset; - dc->vmsd = &vmstate_pci_device; -} - -static const TypeInfo pbm_pci_bridge_info = { - .name = "pbm-bridge", - .parent = TYPE_PCI_BRIDGE, - .class_init = pbm_pci_bridge_class_init, -}; - -static void pbm_register_types(void) -{ - type_register_static(&pbm_host_info); - type_register_static(&pbm_pci_host_info); - type_register_static(&pbm_pci_bridge_info); -} - -type_init(pbm_register_types) diff --git a/qemu/hw/pci-host/bonito.c b/qemu/hw/pci-host/bonito.c deleted file mode 100644 index 1999ece59..000000000 --- a/qemu/hw/pci-host/bonito.c +++ /dev/null @@ -1,858 +0,0 @@ -/* - * bonito north bridge support - * - * Copyright (c) 2008 yajin (yajin@vm-kernel.org) - * Copyright (c) 2010 Huacai Chen (zltjiangshi@gmail.com) - * - * This code is licensed under the GNU GPL v2. - * - * Contributions after 2012-01-13 are licensed under the terms of the - * GNU GPL, version 2 or (at your option) any later version. - */ - -/* - * fulong 2e mini pc has a bonito north bridge. - */ - -/* what is the meaning of devfn in qemu and IDSEL in bonito northbridge? - * - * devfn pci_slot<<3 + funno - * one pci bus can have 32 devices and each device can have 8 functions. - * - * In bonito north bridge, pci slot = IDSEL bit - 12. - * For example, PCI_IDSEL_VIA686B = 17, - * pci slot = 17-12=5 - * - * so - * VT686B_FUN0's devfn = (5<<3)+0 - * VT686B_FUN1's devfn = (5<<3)+1 - * - * qemu also uses pci address for north bridge to access pci config register. - * bus_no [23:16] - * dev_no [15:11] - * fun_no [10:8] - * reg_no [7:2] - * - * so function bonito_sbridge_pciaddr for the translation from - * north bridge address to pci address. - */ - -#include "qemu/osdep.h" - -#include "hw/hw.h" -#include "hw/pci/pci.h" -#include "hw/i386/pc.h" -#include "hw/mips/mips.h" -#include "hw/pci/pci_host.h" -#include "sysemu/sysemu.h" -#include "exec/address-spaces.h" - -//#define DEBUG_BONITO - -#ifdef DEBUG_BONITO -#define DPRINTF(fmt, ...) fprintf(stderr, "%s: " fmt, __FUNCTION__, ##__VA_ARGS__) -#else -#define DPRINTF(fmt, ...) -#endif - -/* from linux soure code. include/asm-mips/mips-boards/bonito64.h*/ -#define BONITO_BOOT_BASE 0x1fc00000 -#define BONITO_BOOT_SIZE 0x00100000 -#define BONITO_BOOT_TOP (BONITO_BOOT_BASE+BONITO_BOOT_SIZE-1) -#define BONITO_FLASH_BASE 0x1c000000 -#define BONITO_FLASH_SIZE 0x03000000 -#define BONITO_FLASH_TOP (BONITO_FLASH_BASE+BONITO_FLASH_SIZE-1) -#define BONITO_SOCKET_BASE 0x1f800000 -#define BONITO_SOCKET_SIZE 0x00400000 -#define BONITO_SOCKET_TOP (BONITO_SOCKET_BASE+BONITO_SOCKET_SIZE-1) -#define BONITO_REG_BASE 0x1fe00000 -#define BONITO_REG_SIZE 0x00040000 -#define BONITO_REG_TOP (BONITO_REG_BASE+BONITO_REG_SIZE-1) -#define BONITO_DEV_BASE 0x1ff00000 -#define BONITO_DEV_SIZE 0x00100000 -#define BONITO_DEV_TOP (BONITO_DEV_BASE+BONITO_DEV_SIZE-1) -#define BONITO_PCILO_BASE 0x10000000 -#define BONITO_PCILO_BASE_VA 0xb0000000 -#define BONITO_PCILO_SIZE 0x0c000000 -#define BONITO_PCILO_TOP (BONITO_PCILO_BASE+BONITO_PCILO_SIZE-1) -#define BONITO_PCILO0_BASE 0x10000000 -#define BONITO_PCILO1_BASE 0x14000000 -#define BONITO_PCILO2_BASE 0x18000000 -#define BONITO_PCIHI_BASE 0x20000000 -#define BONITO_PCIHI_SIZE 0x20000000 -#define BONITO_PCIHI_TOP (BONITO_PCIHI_BASE+BONITO_PCIHI_SIZE-1) -#define BONITO_PCIIO_BASE 0x1fd00000 -#define BONITO_PCIIO_BASE_VA 0xbfd00000 -#define BONITO_PCIIO_SIZE 0x00010000 -#define BONITO_PCIIO_TOP (BONITO_PCIIO_BASE+BONITO_PCIIO_SIZE-1) -#define BONITO_PCICFG_BASE 0x1fe80000 -#define BONITO_PCICFG_SIZE 0x00080000 -#define BONITO_PCICFG_TOP (BONITO_PCICFG_BASE+BONITO_PCICFG_SIZE-1) - - -#define BONITO_PCICONFIGBASE 0x00 -#define BONITO_REGBASE 0x100 - -#define BONITO_PCICONFIG_BASE (BONITO_PCICONFIGBASE+BONITO_REG_BASE) -#define BONITO_PCICONFIG_SIZE (0x100) - -#define BONITO_INTERNAL_REG_BASE (BONITO_REGBASE+BONITO_REG_BASE) -#define BONITO_INTERNAL_REG_SIZE (0x70) - -#define BONITO_SPCICONFIG_BASE (BONITO_PCICFG_BASE) -#define BONITO_SPCICONFIG_SIZE (BONITO_PCICFG_SIZE) - - - -/* 1. Bonito h/w Configuration */ -/* Power on register */ - -#define BONITO_BONPONCFG (0x00 >> 2) /* 0x100 */ -#define BONITO_BONGENCFG_OFFSET 0x4 -#define BONITO_BONGENCFG (BONITO_BONGENCFG_OFFSET>>2) /*0x104 */ - -/* 2. IO & IDE configuration */ -#define BONITO_IODEVCFG (0x08 >> 2) /* 0x108 */ - -/* 3. IO & IDE configuration */ -#define BONITO_SDCFG (0x0c >> 2) /* 0x10c */ - -/* 4. PCI address map control */ -#define BONITO_PCIMAP (0x10 >> 2) /* 0x110 */ -#define BONITO_PCIMEMBASECFG (0x14 >> 2) /* 0x114 */ -#define BONITO_PCIMAP_CFG (0x18 >> 2) /* 0x118 */ - -/* 5. ICU & GPIO regs */ -/* GPIO Regs - r/w */ -#define BONITO_GPIODATA_OFFSET 0x1c -#define BONITO_GPIODATA (BONITO_GPIODATA_OFFSET >> 2) /* 0x11c */ -#define BONITO_GPIOIE (0x20 >> 2) /* 0x120 */ - -/* ICU Configuration Regs - r/w */ -#define BONITO_INTEDGE (0x24 >> 2) /* 0x124 */ -#define BONITO_INTSTEER (0x28 >> 2) /* 0x128 */ -#define BONITO_INTPOL (0x2c >> 2) /* 0x12c */ - -/* ICU Enable Regs - IntEn & IntISR are r/o. */ -#define BONITO_INTENSET (0x30 >> 2) /* 0x130 */ -#define BONITO_INTENCLR (0x34 >> 2) /* 0x134 */ -#define BONITO_INTEN (0x38 >> 2) /* 0x138 */ -#define BONITO_INTISR (0x3c >> 2) /* 0x13c */ - -/* PCI mail boxes */ -#define BONITO_PCIMAIL0_OFFSET 0x40 -#define BONITO_PCIMAIL1_OFFSET 0x44 -#define BONITO_PCIMAIL2_OFFSET 0x48 -#define BONITO_PCIMAIL3_OFFSET 0x4c -#define BONITO_PCIMAIL0 (0x40 >> 2) /* 0x140 */ -#define BONITO_PCIMAIL1 (0x44 >> 2) /* 0x144 */ -#define BONITO_PCIMAIL2 (0x48 >> 2) /* 0x148 */ -#define BONITO_PCIMAIL3 (0x4c >> 2) /* 0x14c */ - -/* 6. PCI cache */ -#define BONITO_PCICACHECTRL (0x50 >> 2) /* 0x150 */ -#define BONITO_PCICACHETAG (0x54 >> 2) /* 0x154 */ -#define BONITO_PCIBADADDR (0x58 >> 2) /* 0x158 */ -#define BONITO_PCIMSTAT (0x5c >> 2) /* 0x15c */ - -/* 7. other*/ -#define BONITO_TIMECFG (0x60 >> 2) /* 0x160 */ -#define BONITO_CPUCFG (0x64 >> 2) /* 0x164 */ -#define BONITO_DQCFG (0x68 >> 2) /* 0x168 */ -#define BONITO_MEMSIZE (0x6C >> 2) /* 0x16c */ - -#define BONITO_REGS (0x70 >> 2) - -/* PCI config for south bridge. type 0 */ -#define BONITO_PCICONF_IDSEL_MASK 0xfffff800 /* [31:11] */ -#define BONITO_PCICONF_IDSEL_OFFSET 11 -#define BONITO_PCICONF_FUN_MASK 0x700 /* [10:8] */ -#define BONITO_PCICONF_FUN_OFFSET 8 -#define BONITO_PCICONF_REG_MASK 0xFC -#define BONITO_PCICONF_REG_OFFSET 0 - - -/* idsel BIT = pci slot number +12 */ -#define PCI_SLOT_BASE 12 -#define PCI_IDSEL_VIA686B_BIT (17) -#define PCI_IDSEL_VIA686B (1<> 2; - - DPRINTF("bonito_writel "TARGET_FMT_plx" val %x saddr %x\n", addr, val, saddr); - switch (saddr) { - case BONITO_BONPONCFG: - case BONITO_IODEVCFG: - case BONITO_SDCFG: - case BONITO_PCIMAP: - case BONITO_PCIMEMBASECFG: - case BONITO_PCIMAP_CFG: - case BONITO_GPIODATA: - case BONITO_GPIOIE: - case BONITO_INTEDGE: - case BONITO_INTSTEER: - case BONITO_INTPOL: - case BONITO_PCIMAIL0: - case BONITO_PCIMAIL1: - case BONITO_PCIMAIL2: - case BONITO_PCIMAIL3: - case BONITO_PCICACHECTRL: - case BONITO_PCICACHETAG: - case BONITO_PCIBADADDR: - case BONITO_PCIMSTAT: - case BONITO_TIMECFG: - case BONITO_CPUCFG: - case BONITO_DQCFG: - case BONITO_MEMSIZE: - s->regs[saddr] = val; - break; - case BONITO_BONGENCFG: - if (!(s->regs[saddr] & 0x04) && (val & 0x04)) { - reset = 1; /* bit 2 jump from 0 to 1 cause reset */ - } - s->regs[saddr] = val; - if (reset) { - qemu_system_reset_request(); - } - break; - case BONITO_INTENSET: - s->regs[BONITO_INTENSET] = val; - s->regs[BONITO_INTEN] |= val; - break; - case BONITO_INTENCLR: - s->regs[BONITO_INTENCLR] = val; - s->regs[BONITO_INTEN] &= ~val; - break; - case BONITO_INTEN: - case BONITO_INTISR: - DPRINTF("write to readonly bonito register %x\n", saddr); - break; - default: - DPRINTF("write to unknown bonito register %x\n", saddr); - break; - } -} - -static uint64_t bonito_readl(void *opaque, hwaddr addr, - unsigned size) -{ - PCIBonitoState *s = opaque; - uint32_t saddr; - - saddr = addr >> 2; - - DPRINTF("bonito_readl "TARGET_FMT_plx"\n", addr); - switch (saddr) { - case BONITO_INTISR: - return s->regs[saddr]; - default: - return s->regs[saddr]; - } -} - -static const MemoryRegionOps bonito_ops = { - .read = bonito_readl, - .write = bonito_writel, - .endianness = DEVICE_NATIVE_ENDIAN, - .valid = { - .min_access_size = 4, - .max_access_size = 4, - }, -}; - -static void bonito_pciconf_writel(void *opaque, hwaddr addr, - uint64_t val, unsigned size) -{ - PCIBonitoState *s = opaque; - PCIDevice *d = PCI_DEVICE(s); - - DPRINTF("bonito_pciconf_writel "TARGET_FMT_plx" val %x\n", addr, val); - d->config_write(d, addr, val, 4); -} - -static uint64_t bonito_pciconf_readl(void *opaque, hwaddr addr, - unsigned size) -{ - - PCIBonitoState *s = opaque; - PCIDevice *d = PCI_DEVICE(s); - - DPRINTF("bonito_pciconf_readl "TARGET_FMT_plx"\n", addr); - return d->config_read(d, addr, 4); -} - -/* north bridge PCI configure space. 0x1fe0 0000 - 0x1fe0 00ff */ - -static const MemoryRegionOps bonito_pciconf_ops = { - .read = bonito_pciconf_readl, - .write = bonito_pciconf_writel, - .endianness = DEVICE_NATIVE_ENDIAN, - .valid = { - .min_access_size = 4, - .max_access_size = 4, - }, -}; - -static uint64_t bonito_ldma_readl(void *opaque, hwaddr addr, - unsigned size) -{ - uint32_t val; - PCIBonitoState *s = opaque; - - if (addr >= sizeof(s->bonldma)) { - return 0; - } - - val = ((uint32_t *)(&s->bonldma))[addr/sizeof(uint32_t)]; - - return val; -} - -static void bonito_ldma_writel(void *opaque, hwaddr addr, - uint64_t val, unsigned size) -{ - PCIBonitoState *s = opaque; - - if (addr >= sizeof(s->bonldma)) { - return; - } - - ((uint32_t *)(&s->bonldma))[addr/sizeof(uint32_t)] = val & 0xffffffff; -} - -static const MemoryRegionOps bonito_ldma_ops = { - .read = bonito_ldma_readl, - .write = bonito_ldma_writel, - .endianness = DEVICE_NATIVE_ENDIAN, - .valid = { - .min_access_size = 4, - .max_access_size = 4, - }, -}; - -static uint64_t bonito_cop_readl(void *opaque, hwaddr addr, - unsigned size) -{ - uint32_t val; - PCIBonitoState *s = opaque; - - if (addr >= sizeof(s->boncop)) { - return 0; - } - - val = ((uint32_t *)(&s->boncop))[addr/sizeof(uint32_t)]; - - return val; -} - -static void bonito_cop_writel(void *opaque, hwaddr addr, - uint64_t val, unsigned size) -{ - PCIBonitoState *s = opaque; - - if (addr >= sizeof(s->boncop)) { - return; - } - - ((uint32_t *)(&s->boncop))[addr/sizeof(uint32_t)] = val & 0xffffffff; -} - -static const MemoryRegionOps bonito_cop_ops = { - .read = bonito_cop_readl, - .write = bonito_cop_writel, - .endianness = DEVICE_NATIVE_ENDIAN, - .valid = { - .min_access_size = 4, - .max_access_size = 4, - }, -}; - -static uint32_t bonito_sbridge_pciaddr(void *opaque, hwaddr addr) -{ - PCIBonitoState *s = opaque; - PCIHostState *phb = PCI_HOST_BRIDGE(s->pcihost); - uint32_t cfgaddr; - uint32_t idsel; - uint32_t devno; - uint32_t funno; - uint32_t regno; - uint32_t pciaddr; - - /* support type0 pci config */ - if ((s->regs[BONITO_PCIMAP_CFG] & 0x10000) != 0x0) { - return 0xffffffff; - } - - cfgaddr = addr & 0xffff; - cfgaddr |= (s->regs[BONITO_PCIMAP_CFG] & 0xffff) << 16; - - idsel = (cfgaddr & BONITO_PCICONF_IDSEL_MASK) >> BONITO_PCICONF_IDSEL_OFFSET; - devno = ctz32(idsel); - funno = (cfgaddr & BONITO_PCICONF_FUN_MASK) >> BONITO_PCICONF_FUN_OFFSET; - regno = (cfgaddr & BONITO_PCICONF_REG_MASK) >> BONITO_PCICONF_REG_OFFSET; - - if (idsel == 0) { - fprintf(stderr, "error in bonito pci config address " TARGET_FMT_plx - ",pcimap_cfg=%x\n", addr, s->regs[BONITO_PCIMAP_CFG]); - exit(1); - } - pciaddr = PCI_ADDR(pci_bus_num(phb->bus), devno, funno, regno); - DPRINTF("cfgaddr %x pciaddr %x busno %x devno %d funno %d regno %d\n", - cfgaddr, pciaddr, pci_bus_num(phb->bus), devno, funno, regno); - - return pciaddr; -} - -static void bonito_spciconf_writeb(void *opaque, hwaddr addr, - uint32_t val) -{ - PCIBonitoState *s = opaque; - PCIDevice *d = PCI_DEVICE(s); - PCIHostState *phb = PCI_HOST_BRIDGE(s->pcihost); - uint32_t pciaddr; - uint16_t status; - - DPRINTF("bonito_spciconf_writeb "TARGET_FMT_plx" val %x\n", addr, val); - pciaddr = bonito_sbridge_pciaddr(s, addr); - - if (pciaddr == 0xffffffff) { - return; - } - - /* set the pci address in s->config_reg */ - phb->config_reg = (pciaddr) | (1u << 31); - pci_data_write(phb->bus, phb->config_reg, val & 0xff, 1); - - /* clear PCI_STATUS_REC_MASTER_ABORT and PCI_STATUS_REC_TARGET_ABORT */ - status = pci_get_word(d->config + PCI_STATUS); - status &= ~(PCI_STATUS_REC_MASTER_ABORT | PCI_STATUS_REC_TARGET_ABORT); - pci_set_word(d->config + PCI_STATUS, status); -} - -static void bonito_spciconf_writew(void *opaque, hwaddr addr, - uint32_t val) -{ - PCIBonitoState *s = opaque; - PCIDevice *d = PCI_DEVICE(s); - PCIHostState *phb = PCI_HOST_BRIDGE(s->pcihost); - uint32_t pciaddr; - uint16_t status; - - DPRINTF("bonito_spciconf_writew "TARGET_FMT_plx" val %x\n", addr, val); - assert((addr & 0x1) == 0); - - pciaddr = bonito_sbridge_pciaddr(s, addr); - - if (pciaddr == 0xffffffff) { - return; - } - - /* set the pci address in s->config_reg */ - phb->config_reg = (pciaddr) | (1u << 31); - pci_data_write(phb->bus, phb->config_reg, val, 2); - - /* clear PCI_STATUS_REC_MASTER_ABORT and PCI_STATUS_REC_TARGET_ABORT */ - status = pci_get_word(d->config + PCI_STATUS); - status &= ~(PCI_STATUS_REC_MASTER_ABORT | PCI_STATUS_REC_TARGET_ABORT); - pci_set_word(d->config + PCI_STATUS, status); -} - -static void bonito_spciconf_writel(void *opaque, hwaddr addr, - uint32_t val) -{ - PCIBonitoState *s = opaque; - PCIDevice *d = PCI_DEVICE(s); - PCIHostState *phb = PCI_HOST_BRIDGE(s->pcihost); - uint32_t pciaddr; - uint16_t status; - - DPRINTF("bonito_spciconf_writel "TARGET_FMT_plx" val %x\n", addr, val); - assert((addr & 0x3) == 0); - - pciaddr = bonito_sbridge_pciaddr(s, addr); - - if (pciaddr == 0xffffffff) { - return; - } - - /* set the pci address in s->config_reg */ - phb->config_reg = (pciaddr) | (1u << 31); - pci_data_write(phb->bus, phb->config_reg, val, 4); - - /* clear PCI_STATUS_REC_MASTER_ABORT and PCI_STATUS_REC_TARGET_ABORT */ - status = pci_get_word(d->config + PCI_STATUS); - status &= ~(PCI_STATUS_REC_MASTER_ABORT | PCI_STATUS_REC_TARGET_ABORT); - pci_set_word(d->config + PCI_STATUS, status); -} - -static uint32_t bonito_spciconf_readb(void *opaque, hwaddr addr) -{ - PCIBonitoState *s = opaque; - PCIDevice *d = PCI_DEVICE(s); - PCIHostState *phb = PCI_HOST_BRIDGE(s->pcihost); - uint32_t pciaddr; - uint16_t status; - - DPRINTF("bonito_spciconf_readb "TARGET_FMT_plx"\n", addr); - pciaddr = bonito_sbridge_pciaddr(s, addr); - - if (pciaddr == 0xffffffff) { - return 0xff; - } - - /* set the pci address in s->config_reg */ - phb->config_reg = (pciaddr) | (1u << 31); - - /* clear PCI_STATUS_REC_MASTER_ABORT and PCI_STATUS_REC_TARGET_ABORT */ - status = pci_get_word(d->config + PCI_STATUS); - status &= ~(PCI_STATUS_REC_MASTER_ABORT | PCI_STATUS_REC_TARGET_ABORT); - pci_set_word(d->config + PCI_STATUS, status); - - return pci_data_read(phb->bus, phb->config_reg, 1); -} - -static uint32_t bonito_spciconf_readw(void *opaque, hwaddr addr) -{ - PCIBonitoState *s = opaque; - PCIDevice *d = PCI_DEVICE(s); - PCIHostState *phb = PCI_HOST_BRIDGE(s->pcihost); - uint32_t pciaddr; - uint16_t status; - - DPRINTF("bonito_spciconf_readw "TARGET_FMT_plx"\n", addr); - assert((addr & 0x1) == 0); - - pciaddr = bonito_sbridge_pciaddr(s, addr); - - if (pciaddr == 0xffffffff) { - return 0xffff; - } - - /* set the pci address in s->config_reg */ - phb->config_reg = (pciaddr) | (1u << 31); - - /* clear PCI_STATUS_REC_MASTER_ABORT and PCI_STATUS_REC_TARGET_ABORT */ - status = pci_get_word(d->config + PCI_STATUS); - status &= ~(PCI_STATUS_REC_MASTER_ABORT | PCI_STATUS_REC_TARGET_ABORT); - pci_set_word(d->config + PCI_STATUS, status); - - return pci_data_read(phb->bus, phb->config_reg, 2); -} - -static uint32_t bonito_spciconf_readl(void *opaque, hwaddr addr) -{ - PCIBonitoState *s = opaque; - PCIDevice *d = PCI_DEVICE(s); - PCIHostState *phb = PCI_HOST_BRIDGE(s->pcihost); - uint32_t pciaddr; - uint16_t status; - - DPRINTF("bonito_spciconf_readl "TARGET_FMT_plx"\n", addr); - assert((addr & 0x3) == 0); - - pciaddr = bonito_sbridge_pciaddr(s, addr); - - if (pciaddr == 0xffffffff) { - return 0xffffffff; - } - - /* set the pci address in s->config_reg */ - phb->config_reg = (pciaddr) | (1u << 31); - - /* clear PCI_STATUS_REC_MASTER_ABORT and PCI_STATUS_REC_TARGET_ABORT */ - status = pci_get_word(d->config + PCI_STATUS); - status &= ~(PCI_STATUS_REC_MASTER_ABORT | PCI_STATUS_REC_TARGET_ABORT); - pci_set_word(d->config + PCI_STATUS, status); - - return pci_data_read(phb->bus, phb->config_reg, 4); -} - -/* south bridge PCI configure space. 0x1fe8 0000 - 0x1fef ffff */ -static const MemoryRegionOps bonito_spciconf_ops = { - .old_mmio = { - .read = { - bonito_spciconf_readb, - bonito_spciconf_readw, - bonito_spciconf_readl, - }, - .write = { - bonito_spciconf_writeb, - bonito_spciconf_writew, - bonito_spciconf_writel, - }, - }, - .endianness = DEVICE_NATIVE_ENDIAN, -}; - -#define BONITO_IRQ_BASE 32 - -static void pci_bonito_set_irq(void *opaque, int irq_num, int level) -{ - BonitoState *s = opaque; - qemu_irq *pic = s->pic; - PCIBonitoState *bonito_state = s->pci_dev; - int internal_irq = irq_num - BONITO_IRQ_BASE; - - if (bonito_state->regs[BONITO_INTEDGE] & (1 << internal_irq)) { - qemu_irq_pulse(*pic); - } else { /* level triggered */ - if (bonito_state->regs[BONITO_INTPOL] & (1 << internal_irq)) { - qemu_irq_raise(*pic); - } else { - qemu_irq_lower(*pic); - } - } -} - -/* map the original irq (0~3) to bonito irq (16~47, but 16~31 are unused) */ -static int pci_bonito_map_irq(PCIDevice * pci_dev, int irq_num) -{ - int slot; - - slot = (pci_dev->devfn >> 3); - - switch (slot) { - case 5: /* FULONG2E_VIA_SLOT, SouthBridge, IDE, USB, ACPI, AC97, MC97 */ - return irq_num % 4 + BONITO_IRQ_BASE; - case 6: /* FULONG2E_ATI_SLOT, VGA */ - return 4 + BONITO_IRQ_BASE; - case 7: /* FULONG2E_RTL_SLOT, RTL8139 */ - return 5 + BONITO_IRQ_BASE; - case 8 ... 12: /* PCI slot 1 to 4 */ - return (slot - 8 + irq_num) + 6 + BONITO_IRQ_BASE; - default: /* Unknown device, don't do any translation */ - return irq_num; - } -} - -static void bonito_reset(void *opaque) -{ - PCIBonitoState *s = opaque; - - /* set the default value of north bridge registers */ - - s->regs[BONITO_BONPONCFG] = 0xc40; - s->regs[BONITO_BONGENCFG] = 0x1384; - s->regs[BONITO_IODEVCFG] = 0x2bff8010; - s->regs[BONITO_SDCFG] = 0x255e0091; - - s->regs[BONITO_GPIODATA] = 0x1ff; - s->regs[BONITO_GPIOIE] = 0x1ff; - s->regs[BONITO_DQCFG] = 0x8; - s->regs[BONITO_MEMSIZE] = 0x10000000; - s->regs[BONITO_PCIMAP] = 0x6140; -} - -static const VMStateDescription vmstate_bonito = { - .name = "Bonito", - .version_id = 1, - .minimum_version_id = 1, - .fields = (VMStateField[]) { - VMSTATE_PCI_DEVICE(dev, PCIBonitoState), - VMSTATE_END_OF_LIST() - } -}; - -static int bonito_pcihost_initfn(SysBusDevice *dev) -{ - PCIHostState *phb = PCI_HOST_BRIDGE(dev); - - phb->bus = pci_register_bus(DEVICE(dev), "pci", - pci_bonito_set_irq, pci_bonito_map_irq, dev, - get_system_memory(), get_system_io(), - 0x28, 32, TYPE_PCI_BUS); - - return 0; -} - -static void bonito_realize(PCIDevice *dev, Error **errp) -{ - PCIBonitoState *s = PCI_BONITO(dev); - SysBusDevice *sysbus = SYS_BUS_DEVICE(s->pcihost); - PCIHostState *phb = PCI_HOST_BRIDGE(s->pcihost); - - /* Bonito North Bridge, built on FPGA, VENDOR_ID/DEVICE_ID are "undefined" */ - pci_config_set_prog_interface(dev->config, 0x00); - - /* set the north bridge register mapping */ - memory_region_init_io(&s->iomem, OBJECT(s), &bonito_ops, s, - "north-bridge-register", BONITO_INTERNAL_REG_SIZE); - sysbus_init_mmio(sysbus, &s->iomem); - sysbus_mmio_map(sysbus, 0, BONITO_INTERNAL_REG_BASE); - - /* set the north bridge pci configure mapping */ - memory_region_init_io(&phb->conf_mem, OBJECT(s), &bonito_pciconf_ops, s, - "north-bridge-pci-config", BONITO_PCICONFIG_SIZE); - sysbus_init_mmio(sysbus, &phb->conf_mem); - sysbus_mmio_map(sysbus, 1, BONITO_PCICONFIG_BASE); - - /* set the south bridge pci configure mapping */ - memory_region_init_io(&phb->data_mem, OBJECT(s), &bonito_spciconf_ops, s, - "south-bridge-pci-config", BONITO_SPCICONFIG_SIZE); - sysbus_init_mmio(sysbus, &phb->data_mem); - sysbus_mmio_map(sysbus, 2, BONITO_SPCICONFIG_BASE); - - memory_region_init_io(&s->iomem_ldma, OBJECT(s), &bonito_ldma_ops, s, - "ldma", 0x100); - sysbus_init_mmio(sysbus, &s->iomem_ldma); - sysbus_mmio_map(sysbus, 3, 0xbfe00200); - - memory_region_init_io(&s->iomem_cop, OBJECT(s), &bonito_cop_ops, s, - "cop", 0x100); - sysbus_init_mmio(sysbus, &s->iomem_cop); - sysbus_mmio_map(sysbus, 4, 0xbfe00300); - - /* Map PCI IO Space 0x1fd0 0000 - 0x1fd1 0000 */ - memory_region_init_alias(&s->bonito_pciio, OBJECT(s), "isa_mmio", - get_system_io(), 0, BONITO_PCIIO_SIZE); - sysbus_init_mmio(sysbus, &s->bonito_pciio); - sysbus_mmio_map(sysbus, 5, BONITO_PCIIO_BASE); - - /* add pci local io mapping */ - memory_region_init_alias(&s->bonito_localio, OBJECT(s), "isa_mmio", - get_system_io(), 0, BONITO_DEV_SIZE); - sysbus_init_mmio(sysbus, &s->bonito_localio); - sysbus_mmio_map(sysbus, 6, BONITO_DEV_BASE); - - /* set the default value of north bridge pci config */ - pci_set_word(dev->config + PCI_COMMAND, 0x0000); - pci_set_word(dev->config + PCI_STATUS, 0x0000); - pci_set_word(dev->config + PCI_SUBSYSTEM_VENDOR_ID, 0x0000); - pci_set_word(dev->config + PCI_SUBSYSTEM_ID, 0x0000); - - pci_set_byte(dev->config + PCI_INTERRUPT_LINE, 0x00); - pci_set_byte(dev->config + PCI_INTERRUPT_PIN, 0x01); - pci_set_byte(dev->config + PCI_MIN_GNT, 0x3c); - pci_set_byte(dev->config + PCI_MAX_LAT, 0x00); - - qemu_register_reset(bonito_reset, s); -} - -PCIBus *bonito_init(qemu_irq *pic) -{ - DeviceState *dev; - BonitoState *pcihost; - PCIHostState *phb; - PCIBonitoState *s; - PCIDevice *d; - - dev = qdev_create(NULL, TYPE_BONITO_PCI_HOST_BRIDGE); - phb = PCI_HOST_BRIDGE(dev); - pcihost = BONITO_PCI_HOST_BRIDGE(dev); - pcihost->pic = pic; - qdev_init_nofail(dev); - - /* set the pcihost pointer before bonito_initfn is called */ - d = pci_create(phb->bus, PCI_DEVFN(0, 0), TYPE_PCI_BONITO); - s = PCI_BONITO(d); - s->pcihost = pcihost; - pcihost->pci_dev = s; - qdev_init_nofail(DEVICE(d)); - - return phb->bus; -} - -static void bonito_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - - k->realize = bonito_realize; - k->vendor_id = 0xdf53; - k->device_id = 0x00d5; - k->revision = 0x01; - k->class_id = PCI_CLASS_BRIDGE_HOST; - dc->desc = "Host bridge"; - dc->vmsd = &vmstate_bonito; - /* - * PCI-facing part of the host bridge, not usable without the - * host-facing part, which can't be device_add'ed, yet. - */ - dc->cannot_instantiate_with_device_add_yet = true; -} - -static const TypeInfo bonito_info = { - .name = TYPE_PCI_BONITO, - .parent = TYPE_PCI_DEVICE, - .instance_size = sizeof(PCIBonitoState), - .class_init = bonito_class_init, -}; - -static void bonito_pcihost_class_init(ObjectClass *klass, void *data) -{ - SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); - - k->init = bonito_pcihost_initfn; -} - -static const TypeInfo bonito_pcihost_info = { - .name = TYPE_BONITO_PCI_HOST_BRIDGE, - .parent = TYPE_PCI_HOST_BRIDGE, - .instance_size = sizeof(BonitoState), - .class_init = bonito_pcihost_class_init, -}; - -static void bonito_register_types(void) -{ - type_register_static(&bonito_pcihost_info); - type_register_static(&bonito_info); -} - -type_init(bonito_register_types) diff --git a/qemu/hw/pci-host/gpex.c b/qemu/hw/pci-host/gpex.c deleted file mode 100644 index 66055ee5c..000000000 --- a/qemu/hw/pci-host/gpex.c +++ /dev/null @@ -1,155 +0,0 @@ -/* - * QEMU Generic PCI Express Bridge Emulation - * - * Copyright (C) 2015 Alexander Graf - * - * Code loosely based on q35.c. - * - * 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. - * - * Check out these documents for more information on the device: - * - * http://www.kernel.org/doc/Documentation/devicetree/bindings/pci/host-generic-pci.txt - * http://www.firmware.org/1275/practice/imap/imap0_9d.pdf - */ -#include "qemu/osdep.h" -#include "hw/hw.h" -#include "hw/pci-host/gpex.h" - -/**************************************************************************** - * GPEX host - */ - -static void gpex_set_irq(void *opaque, int irq_num, int level) -{ - GPEXHost *s = opaque; - - qemu_set_irq(s->irq[irq_num], level); -} - -static void gpex_host_realize(DeviceState *dev, Error **errp) -{ - PCIHostState *pci = PCI_HOST_BRIDGE(dev); - GPEXHost *s = GPEX_HOST(dev); - SysBusDevice *sbd = SYS_BUS_DEVICE(dev); - PCIExpressHost *pex = PCIE_HOST_BRIDGE(dev); - int i; - - pcie_host_mmcfg_init(pex, PCIE_MMCFG_SIZE_MAX); - memory_region_init(&s->io_mmio, OBJECT(s), "gpex_mmio", UINT64_MAX); - memory_region_init(&s->io_ioport, OBJECT(s), "gpex_ioport", 64 * 1024); - - sysbus_init_mmio(sbd, &pex->mmio); - sysbus_init_mmio(sbd, &s->io_mmio); - sysbus_init_mmio(sbd, &s->io_ioport); - for (i = 0; i < GPEX_NUM_IRQS; i++) { - sysbus_init_irq(sbd, &s->irq[i]); - } - - pci->bus = pci_register_bus(dev, "pcie.0", gpex_set_irq, - pci_swizzle_map_irq_fn, s, &s->io_mmio, - &s->io_ioport, 0, 4, TYPE_PCIE_BUS); - - qdev_set_parent_bus(DEVICE(&s->gpex_root), BUS(pci->bus)); - qdev_init_nofail(DEVICE(&s->gpex_root)); -} - -static const char *gpex_host_root_bus_path(PCIHostState *host_bridge, - PCIBus *rootbus) -{ - return "0000:00"; -} - -static void gpex_host_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - PCIHostBridgeClass *hc = PCI_HOST_BRIDGE_CLASS(klass); - - hc->root_bus_path = gpex_host_root_bus_path; - dc->realize = gpex_host_realize; - set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); - dc->fw_name = "pci"; -} - -static void gpex_host_initfn(Object *obj) -{ - GPEXHost *s = GPEX_HOST(obj); - GPEXRootState *root = &s->gpex_root; - - object_initialize(root, sizeof(*root), TYPE_GPEX_ROOT_DEVICE); - object_property_add_child(obj, "gpex_root", OBJECT(root), NULL); - qdev_prop_set_uint32(DEVICE(root), "addr", PCI_DEVFN(0, 0)); - qdev_prop_set_bit(DEVICE(root), "multifunction", false); -} - -static const TypeInfo gpex_host_info = { - .name = TYPE_GPEX_HOST, - .parent = TYPE_PCIE_HOST_BRIDGE, - .instance_size = sizeof(GPEXHost), - .instance_init = gpex_host_initfn, - .class_init = gpex_host_class_init, -}; - -/**************************************************************************** - * GPEX Root D0:F0 - */ - -static const VMStateDescription vmstate_gpex_root = { - .name = "gpex_root", - .version_id = 1, - .minimum_version_id = 1, - .fields = (VMStateField[]) { - VMSTATE_PCI_DEVICE(parent_obj, GPEXRootState), - VMSTATE_END_OF_LIST() - } -}; - -static void gpex_root_class_init(ObjectClass *klass, void *data) -{ - PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - DeviceClass *dc = DEVICE_CLASS(klass); - - set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); - dc->desc = "QEMU generic PCIe host bridge"; - dc->vmsd = &vmstate_gpex_root; - k->vendor_id = PCI_VENDOR_ID_REDHAT; - k->device_id = PCI_DEVICE_ID_REDHAT_PCIE_HOST; - k->revision = 0; - k->class_id = PCI_CLASS_BRIDGE_HOST; - /* - * PCI-facing part of the host bridge, not usable without the - * host-facing part, which can't be device_add'ed, yet. - */ - dc->cannot_instantiate_with_device_add_yet = true; -} - -static const TypeInfo gpex_root_info = { - .name = TYPE_GPEX_ROOT_DEVICE, - .parent = TYPE_PCI_DEVICE, - .instance_size = sizeof(GPEXRootState), - .class_init = gpex_root_class_init, -}; - -static void gpex_register(void) -{ - type_register_static(&gpex_root_info); - type_register_static(&gpex_host_info); -} - -type_init(gpex_register) diff --git a/qemu/hw/pci-host/grackle.c b/qemu/hw/pci-host/grackle.c deleted file mode 100644 index 8f9121615..000000000 --- a/qemu/hw/pci-host/grackle.c +++ /dev/null @@ -1,169 +0,0 @@ -/* - * QEMU Grackle PCI host (heathrow OldWorld PowerMac) - * - * Copyright (c) 2006-2007 Fabrice Bellard - * Copyright (c) 2007 Jocelyn Mayer - * - * 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 "qemu/osdep.h" -#include "hw/pci/pci_host.h" -#include "hw/ppc/mac.h" -#include "hw/pci/pci.h" - -/* debug Grackle */ -//#define DEBUG_GRACKLE - -#ifdef DEBUG_GRACKLE -#define GRACKLE_DPRINTF(fmt, ...) \ - do { printf("GRACKLE: " fmt , ## __VA_ARGS__); } while (0) -#else -#define GRACKLE_DPRINTF(fmt, ...) -#endif - -#define GRACKLE_PCI_HOST_BRIDGE(obj) \ - OBJECT_CHECK(GrackleState, (obj), TYPE_GRACKLE_PCI_HOST_BRIDGE) - -typedef struct GrackleState { - PCIHostState parent_obj; - - MemoryRegion pci_mmio; - MemoryRegion pci_hole; -} GrackleState; - -/* Don't know if this matches real hardware, but it agrees with OHW. */ -static int pci_grackle_map_irq(PCIDevice *pci_dev, int irq_num) -{ - return (irq_num + (pci_dev->devfn >> 3)) & 3; -} - -static void pci_grackle_set_irq(void *opaque, int irq_num, int level) -{ - qemu_irq *pic = opaque; - - GRACKLE_DPRINTF("set_irq num %d level %d\n", irq_num, level); - qemu_set_irq(pic[irq_num + 0x15], level); -} - -PCIBus *pci_grackle_init(uint32_t base, qemu_irq *pic, - MemoryRegion *address_space_mem, - MemoryRegion *address_space_io) -{ - DeviceState *dev; - SysBusDevice *s; - PCIHostState *phb; - GrackleState *d; - - dev = qdev_create(NULL, TYPE_GRACKLE_PCI_HOST_BRIDGE); - qdev_init_nofail(dev); - s = SYS_BUS_DEVICE(dev); - phb = PCI_HOST_BRIDGE(dev); - d = GRACKLE_PCI_HOST_BRIDGE(dev); - - memory_region_init(&d->pci_mmio, OBJECT(s), "pci-mmio", 0x100000000ULL); - memory_region_init_alias(&d->pci_hole, OBJECT(s), "pci-hole", &d->pci_mmio, - 0x80000000ULL, 0x7e000000ULL); - memory_region_add_subregion(address_space_mem, 0x80000000ULL, - &d->pci_hole); - - phb->bus = pci_register_bus(dev, NULL, - pci_grackle_set_irq, - pci_grackle_map_irq, - pic, - &d->pci_mmio, - address_space_io, - 0, 4, TYPE_PCI_BUS); - - pci_create_simple(phb->bus, 0, "grackle"); - - sysbus_mmio_map(s, 0, base); - sysbus_mmio_map(s, 1, base + 0x00200000); - - return phb->bus; -} - -static int pci_grackle_init_device(SysBusDevice *dev) -{ - PCIHostState *phb; - - phb = PCI_HOST_BRIDGE(dev); - - memory_region_init_io(&phb->conf_mem, OBJECT(dev), &pci_host_conf_le_ops, - dev, "pci-conf-idx", 0x1000); - memory_region_init_io(&phb->data_mem, OBJECT(dev), &pci_host_data_le_ops, - dev, "pci-data-idx", 0x1000); - sysbus_init_mmio(dev, &phb->conf_mem); - sysbus_init_mmio(dev, &phb->data_mem); - - return 0; -} - -static void grackle_pci_host_realize(PCIDevice *d, Error **errp) -{ - d->config[0x09] = 0x01; -} - -static void grackle_pci_class_init(ObjectClass *klass, void *data) -{ - PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - DeviceClass *dc = DEVICE_CLASS(klass); - - k->realize = grackle_pci_host_realize; - k->vendor_id = PCI_VENDOR_ID_MOTOROLA; - k->device_id = PCI_DEVICE_ID_MOTOROLA_MPC106; - k->revision = 0x00; - k->class_id = PCI_CLASS_BRIDGE_HOST; - /* - * PCI-facing part of the host bridge, not usable without the - * host-facing part, which can't be device_add'ed, yet. - */ - dc->cannot_instantiate_with_device_add_yet = true; -} - -static const TypeInfo grackle_pci_info = { - .name = "grackle", - .parent = TYPE_PCI_DEVICE, - .instance_size = sizeof(PCIDevice), - .class_init = grackle_pci_class_init, -}; - -static void pci_grackle_class_init(ObjectClass *klass, void *data) -{ - SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); - DeviceClass *dc = DEVICE_CLASS(klass); - - k->init = pci_grackle_init_device; - set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); -} - -static const TypeInfo grackle_pci_host_info = { - .name = TYPE_GRACKLE_PCI_HOST_BRIDGE, - .parent = TYPE_PCI_HOST_BRIDGE, - .instance_size = sizeof(GrackleState), - .class_init = pci_grackle_class_init, -}; - -static void grackle_register_types(void) -{ - type_register_static(&grackle_pci_info); - type_register_static(&grackle_pci_host_info); -} - -type_init(grackle_register_types) diff --git a/qemu/hw/pci-host/pam.c b/qemu/hw/pci-host/pam.c deleted file mode 100644 index e361ecb7e..000000000 --- a/qemu/hw/pci-host/pam.c +++ /dev/null @@ -1,70 +0,0 @@ -/* - * QEMU Smram/pam logic implementation - * - * Copyright (c) 2006 Fabrice Bellard - * Copyright (c) 2011 Isaku Yamahata - * VA Linux Systems Japan K.K. - * Copyright (c) 2012 Jason Baron - * - * Split out from piix.c - * - * 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 "qemu/osdep.h" -#include "qom/object.h" -#include "sysemu/sysemu.h" -#include "hw/pci-host/pam.h" - -void init_pam(DeviceState *dev, MemoryRegion *ram_memory, - MemoryRegion *system_memory, MemoryRegion *pci_address_space, - PAMMemoryRegion *mem, uint32_t start, uint32_t size) -{ - int i; - - /* RAM */ - memory_region_init_alias(&mem->alias[3], OBJECT(dev), "pam-ram", ram_memory, - start, size); - /* ROM (XXX: not quite correct) */ - memory_region_init_alias(&mem->alias[1], OBJECT(dev), "pam-rom", ram_memory, - start, size); - memory_region_set_readonly(&mem->alias[1], true); - - /* XXX: should distinguish read/write cases */ - memory_region_init_alias(&mem->alias[0], OBJECT(dev), "pam-pci", pci_address_space, - start, size); - memory_region_init_alias(&mem->alias[2], OBJECT(dev), "pam-pci", ram_memory, - start, size); - - for (i = 0; i < 4; ++i) { - memory_region_set_enabled(&mem->alias[i], false); - memory_region_add_subregion_overlap(system_memory, start, - &mem->alias[i], 1); - } - mem->current = 0; -} - -void pam_update(PAMMemoryRegion *pam, int idx, uint8_t val) -{ - assert(0 <= idx && idx <= 12); - - memory_region_set_enabled(&pam->alias[pam->current], false); - pam->current = (val >> ((!(idx & 1)) * 4)) & PAM_ATTR_MASK; - memory_region_set_enabled(&pam->alias[pam->current], true); -} diff --git a/qemu/hw/pci-host/piix.c b/qemu/hw/pci-host/piix.c deleted file mode 100644 index df2b0e26f..000000000 --- a/qemu/hw/pci-host/piix.c +++ /dev/null @@ -1,888 +0,0 @@ -/* - * QEMU i440FX/PIIX3 PCI Bridge Emulation - * - * Copyright (c) 2006 Fabrice Bellard - * - * 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 "qemu/osdep.h" -#include "hw/hw.h" -#include "hw/i386/pc.h" -#include "hw/pci/pci.h" -#include "hw/pci/pci_host.h" -#include "hw/isa/isa.h" -#include "hw/sysbus.h" -#include "qapi/error.h" -#include "qemu/range.h" -#include "hw/xen/xen.h" -#include "hw/pci-host/pam.h" -#include "sysemu/sysemu.h" -#include "hw/i386/ioapic.h" -#include "qapi/visitor.h" -#include "qemu/error-report.h" - -/* - * I440FX chipset data sheet. - * http://download.intel.com/design/chipsets/datashts/29054901.pdf - */ - -#define I440FX_PCI_HOST_BRIDGE(obj) \ - OBJECT_CHECK(I440FXState, (obj), TYPE_I440FX_PCI_HOST_BRIDGE) - -typedef struct I440FXState { - PCIHostState parent_obj; - PcPciInfo pci_info; - uint64_t pci_hole64_size; - uint32_t short_root_bus; -} I440FXState; - -#define PIIX_NUM_PIC_IRQS 16 /* i8259 * 2 */ -#define PIIX_NUM_PIRQS 4ULL /* PIRQ[A-D] */ -#define XEN_PIIX_NUM_PIRQS 128ULL -#define PIIX_PIRQC 0x60 - -/* - * Reset Control Register: PCI-accessible ISA-Compatible Register at address - * 0xcf9, provided by the PCI/ISA bridge (PIIX3 PCI function 0, 8086:7000). - */ -#define RCR_IOPORT 0xcf9 - -typedef struct PIIX3State { - PCIDevice dev; - - /* - * bitmap to track pic levels. - * The pic level is the logical OR of all the PCI irqs mapped to it - * So one PIC level is tracked by PIIX_NUM_PIRQS bits. - * - * PIRQ is mapped to PIC pins, we track it by - * PIIX_NUM_PIRQS * PIIX_NUM_PIC_IRQS = 64 bits with - * pic_irq * PIIX_NUM_PIRQS + pirq - */ -#if PIIX_NUM_PIC_IRQS * PIIX_NUM_PIRQS > 64 -#error "unable to encode pic state in 64bit in pic_levels." -#endif - uint64_t pic_levels; - - qemu_irq *pic; - - /* This member isn't used. Just for save/load compatibility */ - int32_t pci_irq_levels_vmstate[PIIX_NUM_PIRQS]; - - /* Reset Control Register contents */ - uint8_t rcr; - - /* IO memory region for Reset Control Register (RCR_IOPORT) */ - MemoryRegion rcr_mem; -} PIIX3State; - -#define TYPE_PIIX3_PCI_DEVICE "pci-piix3" -#define PIIX3_PCI_DEVICE(obj) \ - OBJECT_CHECK(PIIX3State, (obj), TYPE_PIIX3_PCI_DEVICE) - -#define I440FX_PCI_DEVICE(obj) \ - OBJECT_CHECK(PCII440FXState, (obj), TYPE_I440FX_PCI_DEVICE) - -struct PCII440FXState { - /*< private >*/ - PCIDevice parent_obj; - /*< public >*/ - - MemoryRegion *system_memory; - MemoryRegion *pci_address_space; - MemoryRegion *ram_memory; - PAMMemoryRegion pam_regions[13]; - MemoryRegion smram_region; - MemoryRegion smram, low_smram; -}; - - -#define I440FX_PAM 0x59 -#define I440FX_PAM_SIZE 7 -#define I440FX_SMRAM 0x72 - -/* Older coreboot versions (4.0 and older) read a config register that doesn't - * exist in real hardware, to get the RAM size from QEMU. - */ -#define I440FX_COREBOOT_RAM_SIZE 0x57 - -static void piix3_set_irq(void *opaque, int pirq, int level); -static PCIINTxRoute piix3_route_intx_pin_to_irq(void *opaque, int pci_intx); -static void piix3_write_config_xen(PCIDevice *dev, - uint32_t address, uint32_t val, int len); - -/* return the global irq number corresponding to a given device irq - pin. We could also use the bus number to have a more precise - mapping. */ -static int pci_slot_get_pirq(PCIDevice *pci_dev, int pci_intx) -{ - int slot_addend; - slot_addend = (pci_dev->devfn >> 3) - 1; - return (pci_intx + slot_addend) & 3; -} - -static void i440fx_update_memory_mappings(PCII440FXState *d) -{ - int i; - PCIDevice *pd = PCI_DEVICE(d); - - memory_region_transaction_begin(); - for (i = 0; i < 13; i++) { - pam_update(&d->pam_regions[i], i, - pd->config[I440FX_PAM + ((i + 1) / 2)]); - } - memory_region_set_enabled(&d->smram_region, - !(pd->config[I440FX_SMRAM] & SMRAM_D_OPEN)); - memory_region_set_enabled(&d->smram, - pd->config[I440FX_SMRAM] & SMRAM_G_SMRAME); - memory_region_transaction_commit(); -} - - -static void i440fx_write_config(PCIDevice *dev, - uint32_t address, uint32_t val, int len) -{ - PCII440FXState *d = I440FX_PCI_DEVICE(dev); - - /* XXX: implement SMRAM.D_LOCK */ - pci_default_write_config(dev, address, val, len); - if (ranges_overlap(address, len, I440FX_PAM, I440FX_PAM_SIZE) || - range_covers_byte(address, len, I440FX_SMRAM)) { - i440fx_update_memory_mappings(d); - } -} - -static int i440fx_load_old(QEMUFile* f, void *opaque, int version_id) -{ - PCII440FXState *d = opaque; - PCIDevice *pd = PCI_DEVICE(d); - int ret, i; - uint8_t smm_enabled; - - ret = pci_device_load(pd, f); - if (ret < 0) - return ret; - i440fx_update_memory_mappings(d); - qemu_get_8s(f, &smm_enabled); - - if (version_id == 2) { - for (i = 0; i < PIIX_NUM_PIRQS; i++) { - qemu_get_be32(f); /* dummy load for compatibility */ - } - } - - return 0; -} - -static int i440fx_post_load(void *opaque, int version_id) -{ - PCII440FXState *d = opaque; - - i440fx_update_memory_mappings(d); - return 0; -} - -static const VMStateDescription vmstate_i440fx = { - .name = "I440FX", - .version_id = 3, - .minimum_version_id = 3, - .minimum_version_id_old = 1, - .load_state_old = i440fx_load_old, - .post_load = i440fx_post_load, - .fields = (VMStateField[]) { - VMSTATE_PCI_DEVICE(parent_obj, PCII440FXState), - /* Used to be smm_enabled, which was basically always zero because - * SeaBIOS hardly uses SMM. SMRAM is now handled by CPU code. - */ - VMSTATE_UNUSED(1), - VMSTATE_END_OF_LIST() - } -}; - -static void i440fx_pcihost_get_pci_hole_start(Object *obj, Visitor *v, - const char *name, void *opaque, - Error **errp) -{ - I440FXState *s = I440FX_PCI_HOST_BRIDGE(obj); - uint32_t value = s->pci_info.w32.begin; - - visit_type_uint32(v, name, &value, errp); -} - -static void i440fx_pcihost_get_pci_hole_end(Object *obj, Visitor *v, - const char *name, void *opaque, - Error **errp) -{ - I440FXState *s = I440FX_PCI_HOST_BRIDGE(obj); - uint32_t value = s->pci_info.w32.end; - - visit_type_uint32(v, name, &value, errp); -} - -static void i440fx_pcihost_get_pci_hole64_start(Object *obj, Visitor *v, - const char *name, - void *opaque, Error **errp) -{ - PCIHostState *h = PCI_HOST_BRIDGE(obj); - Range w64; - - pci_bus_get_w64_range(h->bus, &w64); - - visit_type_uint64(v, name, &w64.begin, errp); -} - -static void i440fx_pcihost_get_pci_hole64_end(Object *obj, Visitor *v, - const char *name, void *opaque, - Error **errp) -{ - PCIHostState *h = PCI_HOST_BRIDGE(obj); - Range w64; - - pci_bus_get_w64_range(h->bus, &w64); - - visit_type_uint64(v, name, &w64.end, errp); -} - -static void i440fx_pcihost_initfn(Object *obj) -{ - PCIHostState *s = PCI_HOST_BRIDGE(obj); - I440FXState *d = I440FX_PCI_HOST_BRIDGE(obj); - - memory_region_init_io(&s->conf_mem, obj, &pci_host_conf_le_ops, s, - "pci-conf-idx", 4); - memory_region_init_io(&s->data_mem, obj, &pci_host_data_le_ops, s, - "pci-conf-data", 4); - - object_property_add(obj, PCI_HOST_PROP_PCI_HOLE_START, "int", - i440fx_pcihost_get_pci_hole_start, - NULL, NULL, NULL, NULL); - - object_property_add(obj, PCI_HOST_PROP_PCI_HOLE_END, "int", - i440fx_pcihost_get_pci_hole_end, - NULL, NULL, NULL, NULL); - - object_property_add(obj, PCI_HOST_PROP_PCI_HOLE64_START, "int", - i440fx_pcihost_get_pci_hole64_start, - NULL, NULL, NULL, NULL); - - object_property_add(obj, PCI_HOST_PROP_PCI_HOLE64_END, "int", - i440fx_pcihost_get_pci_hole64_end, - NULL, NULL, NULL, NULL); - - d->pci_info.w32.end = IO_APIC_DEFAULT_ADDRESS; -} - -static void i440fx_pcihost_realize(DeviceState *dev, Error **errp) -{ - PCIHostState *s = PCI_HOST_BRIDGE(dev); - SysBusDevice *sbd = SYS_BUS_DEVICE(dev); - - sysbus_add_io(sbd, 0xcf8, &s->conf_mem); - sysbus_init_ioports(sbd, 0xcf8, 4); - - sysbus_add_io(sbd, 0xcfc, &s->data_mem); - sysbus_init_ioports(sbd, 0xcfc, 4); -} - -static void i440fx_realize(PCIDevice *dev, Error **errp) -{ - dev->config[I440FX_SMRAM] = 0x02; - - if (object_property_get_bool(qdev_get_machine(), "iommu", NULL)) { - error_report("warning: i440fx doesn't support emulated iommu"); - } -} - -PCIBus *i440fx_init(const char *host_type, const char *pci_type, - PCII440FXState **pi440fx_state, - int *piix3_devfn, - ISABus **isa_bus, qemu_irq *pic, - MemoryRegion *address_space_mem, - MemoryRegion *address_space_io, - ram_addr_t ram_size, - ram_addr_t below_4g_mem_size, - ram_addr_t above_4g_mem_size, - MemoryRegion *pci_address_space, - MemoryRegion *ram_memory) -{ - DeviceState *dev; - PCIBus *b; - PCIDevice *d; - PCIHostState *s; - PIIX3State *piix3; - PCII440FXState *f; - unsigned i; - I440FXState *i440fx; - - dev = qdev_create(NULL, host_type); - s = PCI_HOST_BRIDGE(dev); - b = pci_bus_new(dev, NULL, pci_address_space, - address_space_io, 0, TYPE_PCI_BUS); - s->bus = b; - object_property_add_child(qdev_get_machine(), "i440fx", OBJECT(dev), NULL); - qdev_init_nofail(dev); - - d = pci_create_simple(b, 0, pci_type); - *pi440fx_state = I440FX_PCI_DEVICE(d); - f = *pi440fx_state; - f->system_memory = address_space_mem; - f->pci_address_space = pci_address_space; - f->ram_memory = ram_memory; - - i440fx = I440FX_PCI_HOST_BRIDGE(dev); - i440fx->pci_info.w32.begin = below_4g_mem_size; - - /* setup pci memory mapping */ - pc_pci_as_mapping_init(OBJECT(f), f->system_memory, - f->pci_address_space); - - /* if *disabled* show SMRAM to all CPUs */ - memory_region_init_alias(&f->smram_region, OBJECT(d), "smram-region", - f->pci_address_space, 0xa0000, 0x20000); - memory_region_add_subregion_overlap(f->system_memory, 0xa0000, - &f->smram_region, 1); - memory_region_set_enabled(&f->smram_region, true); - - /* smram, as seen by SMM CPUs */ - memory_region_init(&f->smram, OBJECT(d), "smram", 1ull << 32); - memory_region_set_enabled(&f->smram, true); - memory_region_init_alias(&f->low_smram, OBJECT(d), "smram-low", - f->ram_memory, 0xa0000, 0x20000); - memory_region_set_enabled(&f->low_smram, true); - memory_region_add_subregion(&f->smram, 0xa0000, &f->low_smram); - object_property_add_const_link(qdev_get_machine(), "smram", - OBJECT(&f->smram), &error_abort); - - init_pam(dev, f->ram_memory, f->system_memory, f->pci_address_space, - &f->pam_regions[0], PAM_BIOS_BASE, PAM_BIOS_SIZE); - for (i = 0; i < 12; ++i) { - init_pam(dev, f->ram_memory, f->system_memory, f->pci_address_space, - &f->pam_regions[i+1], PAM_EXPAN_BASE + i * PAM_EXPAN_SIZE, - PAM_EXPAN_SIZE); - } - - /* Xen supports additional interrupt routes from the PCI devices to - * the IOAPIC: the four pins of each PCI device on the bus are also - * connected to the IOAPIC directly. - * These additional routes can be discovered through ACPI. */ - if (xen_enabled()) { - PCIDevice *pci_dev = pci_create_simple_multifunction(b, - -1, true, "PIIX3-xen"); - piix3 = PIIX3_PCI_DEVICE(pci_dev); - pci_bus_irqs(b, xen_piix3_set_irq, xen_pci_slot_get_pirq, - piix3, XEN_PIIX_NUM_PIRQS); - } else { - PCIDevice *pci_dev = pci_create_simple_multifunction(b, - -1, true, "PIIX3"); - piix3 = PIIX3_PCI_DEVICE(pci_dev); - pci_bus_irqs(b, piix3_set_irq, pci_slot_get_pirq, piix3, - PIIX_NUM_PIRQS); - pci_bus_set_route_irq_fn(b, piix3_route_intx_pin_to_irq); - } - piix3->pic = pic; - *isa_bus = ISA_BUS(qdev_get_child_bus(DEVICE(piix3), "isa.0")); - - *piix3_devfn = piix3->dev.devfn; - - ram_size = ram_size / 8 / 1024 / 1024; - if (ram_size > 255) { - ram_size = 255; - } - d->config[I440FX_COREBOOT_RAM_SIZE] = ram_size; - - i440fx_update_memory_mappings(f); - - return b; -} - -PCIBus *find_i440fx(void) -{ - PCIHostState *s = OBJECT_CHECK(PCIHostState, - object_resolve_path("/machine/i440fx", NULL), - TYPE_PCI_HOST_BRIDGE); - return s ? s->bus : NULL; -} - -/* PIIX3 PCI to ISA bridge */ -static void piix3_set_irq_pic(PIIX3State *piix3, int pic_irq) -{ - qemu_set_irq(piix3->pic[pic_irq], - !!(piix3->pic_levels & - (((1ULL << PIIX_NUM_PIRQS) - 1) << - (pic_irq * PIIX_NUM_PIRQS)))); -} - -static void piix3_set_irq_level_internal(PIIX3State *piix3, int pirq, int level) -{ - int pic_irq; - uint64_t mask; - - pic_irq = piix3->dev.config[PIIX_PIRQC + pirq]; - if (pic_irq >= PIIX_NUM_PIC_IRQS) { - return; - } - - mask = 1ULL << ((pic_irq * PIIX_NUM_PIRQS) + pirq); - piix3->pic_levels &= ~mask; - piix3->pic_levels |= mask * !!level; -} - -static void piix3_set_irq_level(PIIX3State *piix3, int pirq, int level) -{ - int pic_irq; - - pic_irq = piix3->dev.config[PIIX_PIRQC + pirq]; - if (pic_irq >= PIIX_NUM_PIC_IRQS) { - return; - } - - piix3_set_irq_level_internal(piix3, pirq, level); - - piix3_set_irq_pic(piix3, pic_irq); -} - -static void piix3_set_irq(void *opaque, int pirq, int level) -{ - PIIX3State *piix3 = opaque; - piix3_set_irq_level(piix3, pirq, level); -} - -static PCIINTxRoute piix3_route_intx_pin_to_irq(void *opaque, int pin) -{ - PIIX3State *piix3 = opaque; - int irq = piix3->dev.config[PIIX_PIRQC + pin]; - PCIINTxRoute route; - - if (irq < PIIX_NUM_PIC_IRQS) { - route.mode = PCI_INTX_ENABLED; - route.irq = irq; - } else { - route.mode = PCI_INTX_DISABLED; - route.irq = -1; - } - return route; -} - -/* irq routing is changed. so rebuild bitmap */ -static void piix3_update_irq_levels(PIIX3State *piix3) -{ - int pirq; - - piix3->pic_levels = 0; - for (pirq = 0; pirq < PIIX_NUM_PIRQS; pirq++) { - piix3_set_irq_level(piix3, pirq, - pci_bus_get_irq_level(piix3->dev.bus, pirq)); - } -} - -static void piix3_write_config(PCIDevice *dev, - uint32_t address, uint32_t val, int len) -{ - pci_default_write_config(dev, address, val, len); - if (ranges_overlap(address, len, PIIX_PIRQC, 4)) { - PIIX3State *piix3 = PIIX3_PCI_DEVICE(dev); - int pic_irq; - - pci_bus_fire_intx_routing_notifier(piix3->dev.bus); - piix3_update_irq_levels(piix3); - for (pic_irq = 0; pic_irq < PIIX_NUM_PIC_IRQS; pic_irq++) { - piix3_set_irq_pic(piix3, pic_irq); - } - } -} - -static void piix3_write_config_xen(PCIDevice *dev, - uint32_t address, uint32_t val, int len) -{ - xen_piix_pci_write_config_client(address, val, len); - piix3_write_config(dev, address, val, len); -} - -static void piix3_reset(void *opaque) -{ - PIIX3State *d = opaque; - uint8_t *pci_conf = d->dev.config; - - pci_conf[0x04] = 0x07; /* master, memory and I/O */ - pci_conf[0x05] = 0x00; - pci_conf[0x06] = 0x00; - pci_conf[0x07] = 0x02; /* PCI_status_devsel_medium */ - pci_conf[0x4c] = 0x4d; - pci_conf[0x4e] = 0x03; - pci_conf[0x4f] = 0x00; - pci_conf[0x60] = 0x80; - pci_conf[0x61] = 0x80; - pci_conf[0x62] = 0x80; - pci_conf[0x63] = 0x80; - pci_conf[0x69] = 0x02; - pci_conf[0x70] = 0x80; - pci_conf[0x76] = 0x0c; - pci_conf[0x77] = 0x0c; - pci_conf[0x78] = 0x02; - pci_conf[0x79] = 0x00; - pci_conf[0x80] = 0x00; - pci_conf[0x82] = 0x00; - pci_conf[0xa0] = 0x08; - pci_conf[0xa2] = 0x00; - pci_conf[0xa3] = 0x00; - pci_conf[0xa4] = 0x00; - pci_conf[0xa5] = 0x00; - pci_conf[0xa6] = 0x00; - pci_conf[0xa7] = 0x00; - pci_conf[0xa8] = 0x0f; - pci_conf[0xaa] = 0x00; - pci_conf[0xab] = 0x00; - pci_conf[0xac] = 0x00; - pci_conf[0xae] = 0x00; - - d->pic_levels = 0; - d->rcr = 0; -} - -static int piix3_post_load(void *opaque, int version_id) -{ - PIIX3State *piix3 = opaque; - int pirq; - - /* Because the i8259 has not been deserialized yet, qemu_irq_raise - * might bring the system to a different state than the saved one; - * for example, the interrupt could be masked but the i8259 would - * not know that yet and would trigger an interrupt in the CPU. - * - * Here, we update irq levels without raising the interrupt. - * Interrupt state will be deserialized separately through the i8259. - */ - piix3->pic_levels = 0; - for (pirq = 0; pirq < PIIX_NUM_PIRQS; pirq++) { - piix3_set_irq_level_internal(piix3, pirq, - pci_bus_get_irq_level(piix3->dev.bus, pirq)); - } - return 0; -} - -static void piix3_pre_save(void *opaque) -{ - int i; - PIIX3State *piix3 = opaque; - - for (i = 0; i < ARRAY_SIZE(piix3->pci_irq_levels_vmstate); i++) { - piix3->pci_irq_levels_vmstate[i] = - pci_bus_get_irq_level(piix3->dev.bus, i); - } -} - -static bool piix3_rcr_needed(void *opaque) -{ - PIIX3State *piix3 = opaque; - - return (piix3->rcr != 0); -} - -static const VMStateDescription vmstate_piix3_rcr = { - .name = "PIIX3/rcr", - .version_id = 1, - .minimum_version_id = 1, - .needed = piix3_rcr_needed, - .fields = (VMStateField[]) { - VMSTATE_UINT8(rcr, PIIX3State), - VMSTATE_END_OF_LIST() - } -}; - -static const VMStateDescription vmstate_piix3 = { - .name = "PIIX3", - .version_id = 3, - .minimum_version_id = 2, - .post_load = piix3_post_load, - .pre_save = piix3_pre_save, - .fields = (VMStateField[]) { - VMSTATE_PCI_DEVICE(dev, PIIX3State), - VMSTATE_INT32_ARRAY_V(pci_irq_levels_vmstate, PIIX3State, - PIIX_NUM_PIRQS, 3), - VMSTATE_END_OF_LIST() - }, - .subsections = (const VMStateDescription*[]) { - &vmstate_piix3_rcr, - NULL - } -}; - - -static void rcr_write(void *opaque, hwaddr addr, uint64_t val, unsigned len) -{ - PIIX3State *d = opaque; - - if (val & 4) { - qemu_system_reset_request(); - return; - } - d->rcr = val & 2; /* keep System Reset type only */ -} - -static uint64_t rcr_read(void *opaque, hwaddr addr, unsigned len) -{ - PIIX3State *d = opaque; - - return d->rcr; -} - -static const MemoryRegionOps rcr_ops = { - .read = rcr_read, - .write = rcr_write, - .endianness = DEVICE_LITTLE_ENDIAN -}; - -static void piix3_realize(PCIDevice *dev, Error **errp) -{ - PIIX3State *d = PIIX3_PCI_DEVICE(dev); - - if (!isa_bus_new(DEVICE(d), get_system_memory(), - pci_address_space_io(dev), errp)) { - return; - } - - memory_region_init_io(&d->rcr_mem, OBJECT(dev), &rcr_ops, d, - "piix3-reset-control", 1); - memory_region_add_subregion_overlap(pci_address_space_io(dev), RCR_IOPORT, - &d->rcr_mem, 1); - - qemu_register_reset(piix3_reset, d); -} - -static void pci_piix3_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - - dc->desc = "ISA bridge"; - dc->vmsd = &vmstate_piix3; - dc->hotpluggable = false; - k->realize = piix3_realize; - k->vendor_id = PCI_VENDOR_ID_INTEL; - /* 82371SB PIIX3 PCI-to-ISA bridge (Step A1) */ - k->device_id = PCI_DEVICE_ID_INTEL_82371SB_0; - k->class_id = PCI_CLASS_BRIDGE_ISA; - /* - * Reason: part of PIIX3 southbridge, needs to be wired up by - * pc_piix.c's pc_init1() - */ - dc->cannot_instantiate_with_device_add_yet = true; -} - -static const TypeInfo piix3_pci_type_info = { - .name = TYPE_PIIX3_PCI_DEVICE, - .parent = TYPE_PCI_DEVICE, - .instance_size = sizeof(PIIX3State), - .abstract = true, - .class_init = pci_piix3_class_init, -}; - -static void piix3_class_init(ObjectClass *klass, void *data) -{ - PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - - k->config_write = piix3_write_config; -} - -static const TypeInfo piix3_info = { - .name = "PIIX3", - .parent = TYPE_PIIX3_PCI_DEVICE, - .class_init = piix3_class_init, -}; - -static void piix3_xen_class_init(ObjectClass *klass, void *data) -{ - PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - - k->config_write = piix3_write_config_xen; -}; - -static const TypeInfo piix3_xen_info = { - .name = "PIIX3-xen", - .parent = TYPE_PIIX3_PCI_DEVICE, - .class_init = piix3_xen_class_init, -}; - -static void i440fx_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - - k->realize = i440fx_realize; - k->config_write = i440fx_write_config; - k->vendor_id = PCI_VENDOR_ID_INTEL; - k->device_id = PCI_DEVICE_ID_INTEL_82441; - k->revision = 0x02; - k->class_id = PCI_CLASS_BRIDGE_HOST; - dc->desc = "Host bridge"; - dc->vmsd = &vmstate_i440fx; - /* - * PCI-facing part of the host bridge, not usable without the - * host-facing part, which can't be device_add'ed, yet. - */ - dc->cannot_instantiate_with_device_add_yet = true; - dc->hotpluggable = false; -} - -static const TypeInfo i440fx_info = { - .name = TYPE_I440FX_PCI_DEVICE, - .parent = TYPE_PCI_DEVICE, - .instance_size = sizeof(PCII440FXState), - .class_init = i440fx_class_init, -}; - -/* IGD Passthrough Host Bridge. */ -typedef struct { - uint8_t offset; - uint8_t len; -} IGDHostInfo; - -/* Here we just expose minimal host bridge offset subset. */ -static const IGDHostInfo igd_host_bridge_infos[] = { - {0x08, 2}, /* revision id */ - {0x2c, 2}, /* sybsystem vendor id */ - {0x2e, 2}, /* sybsystem id */ - {0x50, 2}, /* SNB: processor graphics control register */ - {0x52, 2}, /* processor graphics control register */ - {0xa4, 4}, /* SNB: graphics base of stolen memory */ - {0xa8, 4}, /* SNB: base of GTT stolen memory */ -}; - -static int host_pci_config_read(int pos, int len, uint32_t *val) -{ - char path[PATH_MAX]; - int config_fd; - ssize_t size = sizeof(path); - /* Access real host bridge. */ - int rc = snprintf(path, size, "/sys/bus/pci/devices/%04x:%02x:%02x.%d/%s", - 0, 0, 0, 0, "config"); - int ret = 0; - - if (rc >= size || rc < 0) { - return -ENODEV; - } - - config_fd = open(path, O_RDWR); - if (config_fd < 0) { - return -ENODEV; - } - - if (lseek(config_fd, pos, SEEK_SET) != pos) { - ret = -errno; - goto out; - } - - do { - rc = read(config_fd, (uint8_t *)val, len); - } while (rc < 0 && (errno == EINTR || errno == EAGAIN)); - if (rc != len) { - ret = -errno; - } - -out: - close(config_fd); - return ret; -} - -static int igd_pt_i440fx_initfn(struct PCIDevice *pci_dev) -{ - uint32_t val = 0; - int rc, i, num; - int pos, len; - - num = ARRAY_SIZE(igd_host_bridge_infos); - for (i = 0; i < num; i++) { - pos = igd_host_bridge_infos[i].offset; - len = igd_host_bridge_infos[i].len; - rc = host_pci_config_read(pos, len, &val); - if (rc) { - return -ENODEV; - } - pci_default_write_config(pci_dev, pos, val, len); - } - - return 0; -} - -static void igd_passthrough_i440fx_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - - k->init = igd_pt_i440fx_initfn; - dc->desc = "IGD Passthrough Host bridge"; -} - -static const TypeInfo igd_passthrough_i440fx_info = { - .name = TYPE_IGD_PASSTHROUGH_I440FX_PCI_DEVICE, - .parent = TYPE_I440FX_PCI_DEVICE, - .instance_size = sizeof(PCII440FXState), - .class_init = igd_passthrough_i440fx_class_init, -}; - -static const char *i440fx_pcihost_root_bus_path(PCIHostState *host_bridge, - PCIBus *rootbus) -{ - I440FXState *s = I440FX_PCI_HOST_BRIDGE(host_bridge); - - /* For backwards compat with old device paths */ - if (s->short_root_bus) { - return "0000"; - } - return "0000:00"; -} - -static Property i440fx_props[] = { - DEFINE_PROP_SIZE(PCI_HOST_PROP_PCI_HOLE64_SIZE, I440FXState, - pci_hole64_size, DEFAULT_PCI_HOLE64_SIZE), - DEFINE_PROP_UINT32("short_root_bus", I440FXState, short_root_bus, 0), - DEFINE_PROP_END_OF_LIST(), -}; - -static void i440fx_pcihost_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - PCIHostBridgeClass *hc = PCI_HOST_BRIDGE_CLASS(klass); - - hc->root_bus_path = i440fx_pcihost_root_bus_path; - dc->realize = i440fx_pcihost_realize; - dc->fw_name = "pci"; - dc->props = i440fx_props; -} - -static const TypeInfo i440fx_pcihost_info = { - .name = TYPE_I440FX_PCI_HOST_BRIDGE, - .parent = TYPE_PCI_HOST_BRIDGE, - .instance_size = sizeof(I440FXState), - .instance_init = i440fx_pcihost_initfn, - .class_init = i440fx_pcihost_class_init, -}; - -static void i440fx_register_types(void) -{ - type_register_static(&i440fx_info); - type_register_static(&igd_passthrough_i440fx_info); - type_register_static(&piix3_pci_type_info); - type_register_static(&piix3_info); - type_register_static(&piix3_xen_info); - type_register_static(&i440fx_pcihost_info); -} - -type_init(i440fx_register_types) diff --git a/qemu/hw/pci-host/ppce500.c b/qemu/hw/pci-host/ppce500.c deleted file mode 100644 index e502bc050..000000000 --- a/qemu/hw/pci-host/ppce500.c +++ /dev/null @@ -1,551 +0,0 @@ -/* - * QEMU PowerPC E500 embedded processors pci controller emulation - * - * Copyright (C) 2009 Freescale Semiconductor, Inc. All rights reserved. - * - * Author: Yu Liu, - * - * This file is derived from hw/ppc4xx_pci.c, - * the copyright for that material belongs to the original owners. - * - * This 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) any later version. - */ - -#include "qemu/osdep.h" -#include "hw/hw.h" -#include "hw/ppc/e500-ccsr.h" -#include "hw/pci/pci.h" -#include "hw/pci/pci_host.h" -#include "qemu/bswap.h" -#include "hw/pci-host/ppce500.h" - -#ifdef DEBUG_PCI -#define pci_debug(fmt, ...) fprintf(stderr, fmt, ## __VA_ARGS__) -#else -#define pci_debug(fmt, ...) -#endif - -#define PCIE500_CFGADDR 0x0 -#define PCIE500_CFGDATA 0x4 -#define PCIE500_REG_BASE 0xC00 -#define PCIE500_ALL_SIZE 0x1000 -#define PCIE500_REG_SIZE (PCIE500_ALL_SIZE - PCIE500_REG_BASE) - -#define PCIE500_PCI_IOLEN 0x10000ULL - -#define PPCE500_PCI_CONFIG_ADDR 0x0 -#define PPCE500_PCI_CONFIG_DATA 0x4 -#define PPCE500_PCI_INTACK 0x8 - -#define PPCE500_PCI_OW1 (0xC20 - PCIE500_REG_BASE) -#define PPCE500_PCI_OW2 (0xC40 - PCIE500_REG_BASE) -#define PPCE500_PCI_OW3 (0xC60 - PCIE500_REG_BASE) -#define PPCE500_PCI_OW4 (0xC80 - PCIE500_REG_BASE) -#define PPCE500_PCI_IW3 (0xDA0 - PCIE500_REG_BASE) -#define PPCE500_PCI_IW2 (0xDC0 - PCIE500_REG_BASE) -#define PPCE500_PCI_IW1 (0xDE0 - PCIE500_REG_BASE) - -#define PPCE500_PCI_GASKET_TIMR (0xE20 - PCIE500_REG_BASE) - -#define PCI_POTAR 0x0 -#define PCI_POTEAR 0x4 -#define PCI_POWBAR 0x8 -#define PCI_POWAR 0x10 - -#define PCI_PITAR 0x0 -#define PCI_PIWBAR 0x8 -#define PCI_PIWBEAR 0xC -#define PCI_PIWAR 0x10 - -#define PPCE500_PCI_NR_POBS 5 -#define PPCE500_PCI_NR_PIBS 3 - -#define PIWAR_EN 0x80000000 /* Enable */ -#define PIWAR_PF 0x20000000 /* prefetch */ -#define PIWAR_TGI_LOCAL 0x00f00000 /* target - local memory */ -#define PIWAR_READ_SNOOP 0x00050000 -#define PIWAR_WRITE_SNOOP 0x00005000 -#define PIWAR_SZ_MASK 0x0000003f - -struct pci_outbound { - uint32_t potar; - uint32_t potear; - uint32_t powbar; - uint32_t powar; - MemoryRegion mem; -}; - -struct pci_inbound { - uint32_t pitar; - uint32_t piwbar; - uint32_t piwbear; - uint32_t piwar; - MemoryRegion mem; -}; - -#define TYPE_PPC_E500_PCI_HOST_BRIDGE "e500-pcihost" - -#define PPC_E500_PCI_HOST_BRIDGE(obj) \ - OBJECT_CHECK(PPCE500PCIState, (obj), TYPE_PPC_E500_PCI_HOST_BRIDGE) - -struct PPCE500PCIState { - PCIHostState parent_obj; - - struct pci_outbound pob[PPCE500_PCI_NR_POBS]; - struct pci_inbound pib[PPCE500_PCI_NR_PIBS]; - uint32_t gasket_time; - qemu_irq irq[PCI_NUM_PINS]; - uint32_t irq_num[PCI_NUM_PINS]; - uint32_t first_slot; - uint32_t first_pin_irq; - AddressSpace bm_as; - MemoryRegion bm; - /* mmio maps */ - MemoryRegion container; - MemoryRegion iomem; - MemoryRegion pio; - MemoryRegion busmem; -}; - -#define TYPE_PPC_E500_PCI_BRIDGE "e500-host-bridge" -#define PPC_E500_PCI_BRIDGE(obj) \ - OBJECT_CHECK(PPCE500PCIBridgeState, (obj), TYPE_PPC_E500_PCI_BRIDGE) - -struct PPCE500PCIBridgeState { - /*< private >*/ - PCIDevice parent; - /*< public >*/ - - MemoryRegion bar0; -}; - -typedef struct PPCE500PCIBridgeState PPCE500PCIBridgeState; -typedef struct PPCE500PCIState PPCE500PCIState; - -static uint64_t pci_reg_read4(void *opaque, hwaddr addr, - unsigned size) -{ - PPCE500PCIState *pci = opaque; - unsigned long win; - uint32_t value = 0; - int idx; - - win = addr & 0xfe0; - - switch (win) { - case PPCE500_PCI_OW1: - case PPCE500_PCI_OW2: - case PPCE500_PCI_OW3: - case PPCE500_PCI_OW4: - idx = (addr >> 5) & 0x7; - switch (addr & 0x1F) { - case PCI_POTAR: - value = pci->pob[idx].potar; - break; - case PCI_POTEAR: - value = pci->pob[idx].potear; - break; - case PCI_POWBAR: - value = pci->pob[idx].powbar; - break; - case PCI_POWAR: - value = pci->pob[idx].powar; - break; - default: - break; - } - break; - - case PPCE500_PCI_IW3: - case PPCE500_PCI_IW2: - case PPCE500_PCI_IW1: - idx = ((addr >> 5) & 0x3) - 1; - switch (addr & 0x1F) { - case PCI_PITAR: - value = pci->pib[idx].pitar; - break; - case PCI_PIWBAR: - value = pci->pib[idx].piwbar; - break; - case PCI_PIWBEAR: - value = pci->pib[idx].piwbear; - break; - case PCI_PIWAR: - value = pci->pib[idx].piwar; - break; - default: - break; - }; - break; - - case PPCE500_PCI_GASKET_TIMR: - value = pci->gasket_time; - break; - - default: - break; - } - - pci_debug("%s: win:%lx(addr:" TARGET_FMT_plx ") -> value:%x\n", __func__, - win, addr, value); - return value; -} - -/* DMA mapping */ -static void e500_update_piw(PPCE500PCIState *pci, int idx) -{ - uint64_t tar = ((uint64_t)pci->pib[idx].pitar) << 12; - uint64_t wbar = ((uint64_t)pci->pib[idx].piwbar) << 12; - uint64_t war = pci->pib[idx].piwar; - uint64_t size = 2ULL << (war & PIWAR_SZ_MASK); - MemoryRegion *address_space_mem = get_system_memory(); - MemoryRegion *mem = &pci->pib[idx].mem; - MemoryRegion *bm = &pci->bm; - char *name; - - if (memory_region_is_mapped(mem)) { - /* Before we modify anything, unmap and destroy the region */ - memory_region_del_subregion(bm, mem); - object_unparent(OBJECT(mem)); - } - - if (!(war & PIWAR_EN)) { - /* Not enabled, nothing to do */ - return; - } - - name = g_strdup_printf("PCI Inbound Window %d", idx); - memory_region_init_alias(mem, OBJECT(pci), name, address_space_mem, tar, - size); - memory_region_add_subregion_overlap(bm, wbar, mem, -1); - g_free(name); - - pci_debug("%s: Added window of size=%#lx from PCI=%#lx to CPU=%#lx\n", - __func__, size, wbar, tar); -} - -/* BAR mapping */ -static void e500_update_pow(PPCE500PCIState *pci, int idx) -{ - uint64_t tar = ((uint64_t)pci->pob[idx].potar) << 12; - uint64_t wbar = ((uint64_t)pci->pob[idx].powbar) << 12; - uint64_t war = pci->pob[idx].powar; - uint64_t size = 2ULL << (war & PIWAR_SZ_MASK); - MemoryRegion *mem = &pci->pob[idx].mem; - MemoryRegion *address_space_mem = get_system_memory(); - char *name; - - if (memory_region_is_mapped(mem)) { - /* Before we modify anything, unmap and destroy the region */ - memory_region_del_subregion(address_space_mem, mem); - object_unparent(OBJECT(mem)); - } - - if (!(war & PIWAR_EN)) { - /* Not enabled, nothing to do */ - return; - } - - name = g_strdup_printf("PCI Outbound Window %d", idx); - memory_region_init_alias(mem, OBJECT(pci), name, &pci->busmem, tar, - size); - memory_region_add_subregion(address_space_mem, wbar, mem); - g_free(name); - - pci_debug("%s: Added window of size=%#lx from CPU=%#lx to PCI=%#lx\n", - __func__, size, wbar, tar); -} - -static void pci_reg_write4(void *opaque, hwaddr addr, - uint64_t value, unsigned size) -{ - PPCE500PCIState *pci = opaque; - unsigned long win; - int idx; - - win = addr & 0xfe0; - - pci_debug("%s: value:%x -> win:%lx(addr:" TARGET_FMT_plx ")\n", - __func__, (unsigned)value, win, addr); - - switch (win) { - case PPCE500_PCI_OW1: - case PPCE500_PCI_OW2: - case PPCE500_PCI_OW3: - case PPCE500_PCI_OW4: - idx = (addr >> 5) & 0x7; - switch (addr & 0x1F) { - case PCI_POTAR: - pci->pob[idx].potar = value; - e500_update_pow(pci, idx); - break; - case PCI_POTEAR: - pci->pob[idx].potear = value; - e500_update_pow(pci, idx); - break; - case PCI_POWBAR: - pci->pob[idx].powbar = value; - e500_update_pow(pci, idx); - break; - case PCI_POWAR: - pci->pob[idx].powar = value; - e500_update_pow(pci, idx); - break; - default: - break; - }; - break; - - case PPCE500_PCI_IW3: - case PPCE500_PCI_IW2: - case PPCE500_PCI_IW1: - idx = ((addr >> 5) & 0x3) - 1; - switch (addr & 0x1F) { - case PCI_PITAR: - pci->pib[idx].pitar = value; - e500_update_piw(pci, idx); - break; - case PCI_PIWBAR: - pci->pib[idx].piwbar = value; - e500_update_piw(pci, idx); - break; - case PCI_PIWBEAR: - pci->pib[idx].piwbear = value; - e500_update_piw(pci, idx); - break; - case PCI_PIWAR: - pci->pib[idx].piwar = value; - e500_update_piw(pci, idx); - break; - default: - break; - }; - break; - - case PPCE500_PCI_GASKET_TIMR: - pci->gasket_time = value; - break; - - default: - break; - }; -} - -static const MemoryRegionOps e500_pci_reg_ops = { - .read = pci_reg_read4, - .write = pci_reg_write4, - .endianness = DEVICE_BIG_ENDIAN, -}; - -static int mpc85xx_pci_map_irq(PCIDevice *pci_dev, int pin) -{ - int devno = pci_dev->devfn >> 3; - int ret; - - ret = ppce500_pci_map_irq_slot(devno, pin); - - pci_debug("%s: devfn %x irq %d -> %d devno:%x\n", __func__, - pci_dev->devfn, pin, ret, devno); - - return ret; -} - -static void mpc85xx_pci_set_irq(void *opaque, int pin, int level) -{ - PPCE500PCIState *s = opaque; - qemu_irq *pic = s->irq; - - pci_debug("%s: PCI irq %d, level:%d\n", __func__, pin , level); - - qemu_set_irq(pic[pin], level); -} - -static PCIINTxRoute e500_route_intx_pin_to_irq(void *opaque, int pin) -{ - PCIINTxRoute route; - PPCE500PCIState *s = opaque; - - route.mode = PCI_INTX_ENABLED; - route.irq = s->irq_num[pin]; - - pci_debug("%s: PCI irq-pin = %d, irq_num= %d\n", __func__, pin, route.irq); - return route; -} - -static const VMStateDescription vmstate_pci_outbound = { - .name = "pci_outbound", - .version_id = 0, - .minimum_version_id = 0, - .fields = (VMStateField[]) { - VMSTATE_UINT32(potar, struct pci_outbound), - VMSTATE_UINT32(potear, struct pci_outbound), - VMSTATE_UINT32(powbar, struct pci_outbound), - VMSTATE_UINT32(powar, struct pci_outbound), - VMSTATE_END_OF_LIST() - } -}; - -static const VMStateDescription vmstate_pci_inbound = { - .name = "pci_inbound", - .version_id = 0, - .minimum_version_id = 0, - .fields = (VMStateField[]) { - VMSTATE_UINT32(pitar, struct pci_inbound), - VMSTATE_UINT32(piwbar, struct pci_inbound), - VMSTATE_UINT32(piwbear, struct pci_inbound), - VMSTATE_UINT32(piwar, struct pci_inbound), - VMSTATE_END_OF_LIST() - } -}; - -static const VMStateDescription vmstate_ppce500_pci = { - .name = "ppce500_pci", - .version_id = 1, - .minimum_version_id = 1, - .fields = (VMStateField[]) { - VMSTATE_STRUCT_ARRAY(pob, PPCE500PCIState, PPCE500_PCI_NR_POBS, 1, - vmstate_pci_outbound, struct pci_outbound), - VMSTATE_STRUCT_ARRAY(pib, PPCE500PCIState, PPCE500_PCI_NR_PIBS, 1, - vmstate_pci_inbound, struct pci_inbound), - VMSTATE_UINT32(gasket_time, PPCE500PCIState), - VMSTATE_END_OF_LIST() - } -}; - -#include "exec/address-spaces.h" - -static void e500_pcihost_bridge_realize(PCIDevice *d, Error **errp) -{ - PPCE500PCIBridgeState *b = PPC_E500_PCI_BRIDGE(d); - PPCE500CCSRState *ccsr = CCSR(container_get(qdev_get_machine(), - "/e500-ccsr")); - - pci_config_set_class(d->config, PCI_CLASS_BRIDGE_PCI); - d->config[PCI_HEADER_TYPE] = - (d->config[PCI_HEADER_TYPE] & PCI_HEADER_TYPE_MULTI_FUNCTION) | - PCI_HEADER_TYPE_BRIDGE; - - memory_region_init_alias(&b->bar0, OBJECT(ccsr), "e500-pci-bar0", &ccsr->ccsr_space, - 0, int128_get64(ccsr->ccsr_space.size)); - pci_register_bar(d, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &b->bar0); -} - -static AddressSpace *e500_pcihost_set_iommu(PCIBus *bus, void *opaque, - int devfn) -{ - PPCE500PCIState *s = opaque; - - return &s->bm_as; -} - -static int e500_pcihost_initfn(SysBusDevice *dev) -{ - PCIHostState *h; - PPCE500PCIState *s; - PCIBus *b; - int i; - - h = PCI_HOST_BRIDGE(dev); - s = PPC_E500_PCI_HOST_BRIDGE(dev); - - for (i = 0; i < ARRAY_SIZE(s->irq); i++) { - sysbus_init_irq(dev, &s->irq[i]); - } - - for (i = 0; i < PCI_NUM_PINS; i++) { - s->irq_num[i] = s->first_pin_irq + i; - } - - memory_region_init(&s->pio, OBJECT(s), "pci-pio", PCIE500_PCI_IOLEN); - memory_region_init(&s->busmem, OBJECT(s), "pci bus memory", UINT64_MAX); - - /* PIO lives at the bottom of our bus space */ - memory_region_add_subregion_overlap(&s->busmem, 0, &s->pio, -2); - - b = pci_register_bus(DEVICE(dev), NULL, mpc85xx_pci_set_irq, - mpc85xx_pci_map_irq, s, &s->busmem, &s->pio, - PCI_DEVFN(s->first_slot, 0), 4, TYPE_PCI_BUS); - h->bus = b; - - /* Set up PCI view of memory */ - memory_region_init(&s->bm, OBJECT(s), "bm-e500", UINT64_MAX); - memory_region_add_subregion(&s->bm, 0x0, &s->busmem); - address_space_init(&s->bm_as, &s->bm, "pci-bm"); - pci_setup_iommu(b, e500_pcihost_set_iommu, s); - - pci_create_simple(b, 0, "e500-host-bridge"); - - memory_region_init(&s->container, OBJECT(h), "pci-container", PCIE500_ALL_SIZE); - memory_region_init_io(&h->conf_mem, OBJECT(h), &pci_host_conf_be_ops, h, - "pci-conf-idx", 4); - memory_region_init_io(&h->data_mem, OBJECT(h), &pci_host_data_le_ops, h, - "pci-conf-data", 4); - memory_region_init_io(&s->iomem, OBJECT(s), &e500_pci_reg_ops, s, - "pci.reg", PCIE500_REG_SIZE); - memory_region_add_subregion(&s->container, PCIE500_CFGADDR, &h->conf_mem); - memory_region_add_subregion(&s->container, PCIE500_CFGDATA, &h->data_mem); - memory_region_add_subregion(&s->container, PCIE500_REG_BASE, &s->iomem); - sysbus_init_mmio(dev, &s->container); - pci_bus_set_route_irq_fn(b, e500_route_intx_pin_to_irq); - - return 0; -} - -static void e500_host_bridge_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - - k->realize = e500_pcihost_bridge_realize; - k->vendor_id = PCI_VENDOR_ID_FREESCALE; - k->device_id = PCI_DEVICE_ID_MPC8533E; - k->class_id = PCI_CLASS_PROCESSOR_POWERPC; - dc->desc = "Host bridge"; - /* - * PCI-facing part of the host bridge, not usable without the - * host-facing part, which can't be device_add'ed, yet. - */ - dc->cannot_instantiate_with_device_add_yet = true; -} - -static const TypeInfo e500_host_bridge_info = { - .name = "e500-host-bridge", - .parent = TYPE_PCI_DEVICE, - .instance_size = sizeof(PPCE500PCIBridgeState), - .class_init = e500_host_bridge_class_init, -}; - -static Property pcihost_properties[] = { - DEFINE_PROP_UINT32("first_slot", PPCE500PCIState, first_slot, 0x11), - DEFINE_PROP_UINT32("first_pin_irq", PPCE500PCIState, first_pin_irq, 0x1), - DEFINE_PROP_END_OF_LIST(), -}; - -static void e500_pcihost_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); - - k->init = e500_pcihost_initfn; - set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); - dc->props = pcihost_properties; - dc->vmsd = &vmstate_ppce500_pci; -} - -static const TypeInfo e500_pcihost_info = { - .name = TYPE_PPC_E500_PCI_HOST_BRIDGE, - .parent = TYPE_PCI_HOST_BRIDGE, - .instance_size = sizeof(PPCE500PCIState), - .class_init = e500_pcihost_class_init, -}; - -static void e500_pci_register_types(void) -{ - type_register_static(&e500_pcihost_info); - type_register_static(&e500_host_bridge_info); -} - -type_init(e500_pci_register_types) diff --git a/qemu/hw/pci-host/prep.c b/qemu/hw/pci-host/prep.c deleted file mode 100644 index 487e32ecb..000000000 --- a/qemu/hw/pci-host/prep.c +++ /dev/null @@ -1,406 +0,0 @@ -/* - * QEMU PREP PCI host - * - * Copyright (c) 2006 Fabrice Bellard - * Copyright (c) 2011-2013 Andreas Färber - * - * 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 "qemu/osdep.h" -#include "qapi/error.h" -#include "hw/hw.h" -#include "hw/pci/pci.h" -#include "hw/pci/pci_bus.h" -#include "hw/pci/pci_host.h" -#include "hw/i386/pc.h" -#include "hw/loader.h" -#include "exec/address-spaces.h" -#include "elf.h" - -#define TYPE_RAVEN_PCI_DEVICE "raven" -#define TYPE_RAVEN_PCI_HOST_BRIDGE "raven-pcihost" - -#define RAVEN_PCI_DEVICE(obj) \ - OBJECT_CHECK(RavenPCIState, (obj), TYPE_RAVEN_PCI_DEVICE) - -typedef struct RavenPCIState { - PCIDevice dev; - - uint32_t elf_machine; - char *bios_name; - MemoryRegion bios; -} RavenPCIState; - -#define RAVEN_PCI_HOST_BRIDGE(obj) \ - OBJECT_CHECK(PREPPCIState, (obj), TYPE_RAVEN_PCI_HOST_BRIDGE) - -typedef struct PRePPCIState { - PCIHostState parent_obj; - - qemu_irq irq[PCI_NUM_PINS]; - PCIBus pci_bus; - AddressSpace pci_io_as; - MemoryRegion pci_io; - MemoryRegion pci_io_non_contiguous; - MemoryRegion pci_memory; - MemoryRegion pci_intack; - MemoryRegion bm; - MemoryRegion bm_ram_alias; - MemoryRegion bm_pci_memory_alias; - AddressSpace bm_as; - RavenPCIState pci_dev; - - int contiguous_map; -} PREPPCIState; - -#define BIOS_SIZE (1024 * 1024) - -static inline uint32_t raven_pci_io_config(hwaddr addr) -{ - int i; - - for (i = 0; i < 11; i++) { - if ((addr & (1 << (11 + i))) != 0) { - break; - } - } - return (addr & 0x7ff) | (i << 11); -} - -static void raven_pci_io_write(void *opaque, hwaddr addr, - uint64_t val, unsigned int size) -{ - PREPPCIState *s = opaque; - PCIHostState *phb = PCI_HOST_BRIDGE(s); - pci_data_write(phb->bus, raven_pci_io_config(addr), val, size); -} - -static uint64_t raven_pci_io_read(void *opaque, hwaddr addr, - unsigned int size) -{ - PREPPCIState *s = opaque; - PCIHostState *phb = PCI_HOST_BRIDGE(s); - return pci_data_read(phb->bus, raven_pci_io_config(addr), size); -} - -static const MemoryRegionOps raven_pci_io_ops = { - .read = raven_pci_io_read, - .write = raven_pci_io_write, - .endianness = DEVICE_LITTLE_ENDIAN, -}; - -static uint64_t raven_intack_read(void *opaque, hwaddr addr, - unsigned int size) -{ - return pic_read_irq(isa_pic); -} - -static const MemoryRegionOps raven_intack_ops = { - .read = raven_intack_read, - .valid = { - .max_access_size = 1, - }, -}; - -static inline hwaddr raven_io_address(PREPPCIState *s, - hwaddr addr) -{ - if (s->contiguous_map == 0) { - /* 64 KB contiguous space for IOs */ - addr &= 0xFFFF; - } else { - /* 8 MB non-contiguous space for IOs */ - addr = (addr & 0x1F) | ((addr & 0x007FFF000) >> 7); - } - - /* FIXME: handle endianness switch */ - - return addr; -} - -static uint64_t raven_io_read(void *opaque, hwaddr addr, - unsigned int size) -{ - PREPPCIState *s = opaque; - uint8_t buf[4]; - - addr = raven_io_address(s, addr); - address_space_read(&s->pci_io_as, addr + 0x80000000, - MEMTXATTRS_UNSPECIFIED, buf, size); - - if (size == 1) { - return buf[0]; - } else if (size == 2) { - return lduw_le_p(buf); - } else if (size == 4) { - return ldl_le_p(buf); - } else { - g_assert_not_reached(); - } -} - -static void raven_io_write(void *opaque, hwaddr addr, - uint64_t val, unsigned int size) -{ - PREPPCIState *s = opaque; - uint8_t buf[4]; - - addr = raven_io_address(s, addr); - - if (size == 1) { - buf[0] = val; - } else if (size == 2) { - stw_le_p(buf, val); - } else if (size == 4) { - stl_le_p(buf, val); - } else { - g_assert_not_reached(); - } - - address_space_write(&s->pci_io_as, addr + 0x80000000, - MEMTXATTRS_UNSPECIFIED, buf, size); -} - -static const MemoryRegionOps raven_io_ops = { - .read = raven_io_read, - .write = raven_io_write, - .endianness = DEVICE_LITTLE_ENDIAN, - .impl.max_access_size = 4, - .valid.unaligned = true, -}; - -static int raven_map_irq(PCIDevice *pci_dev, int irq_num) -{ - return (irq_num + (pci_dev->devfn >> 3)) & 1; -} - -static void raven_set_irq(void *opaque, int irq_num, int level) -{ - qemu_irq *pic = opaque; - - qemu_set_irq(pic[irq_num] , level); -} - -static AddressSpace *raven_pcihost_set_iommu(PCIBus *bus, void *opaque, - int devfn) -{ - PREPPCIState *s = opaque; - - return &s->bm_as; -} - -static void raven_change_gpio(void *opaque, int n, int level) -{ - PREPPCIState *s = opaque; - - s->contiguous_map = level; -} - -static void raven_pcihost_realizefn(DeviceState *d, Error **errp) -{ - SysBusDevice *dev = SYS_BUS_DEVICE(d); - PCIHostState *h = PCI_HOST_BRIDGE(dev); - PREPPCIState *s = RAVEN_PCI_HOST_BRIDGE(dev); - MemoryRegion *address_space_mem = get_system_memory(); - int i; - - for (i = 0; i < PCI_NUM_PINS; i++) { - sysbus_init_irq(dev, &s->irq[i]); - } - - qdev_init_gpio_in(d, raven_change_gpio, 1); - - pci_bus_irqs(&s->pci_bus, raven_set_irq, raven_map_irq, s->irq, - PCI_NUM_PINS); - - memory_region_init_io(&h->conf_mem, OBJECT(h), &pci_host_conf_le_ops, s, - "pci-conf-idx", 4); - memory_region_add_subregion(&s->pci_io, 0xcf8, &h->conf_mem); - - memory_region_init_io(&h->data_mem, OBJECT(h), &pci_host_data_le_ops, s, - "pci-conf-data", 4); - memory_region_add_subregion(&s->pci_io, 0xcfc, &h->data_mem); - - memory_region_init_io(&h->mmcfg, OBJECT(s), &raven_pci_io_ops, s, - "pciio", 0x00400000); - memory_region_add_subregion(address_space_mem, 0x80800000, &h->mmcfg); - - memory_region_init_io(&s->pci_intack, OBJECT(s), &raven_intack_ops, s, - "pci-intack", 1); - memory_region_add_subregion(address_space_mem, 0xbffffff0, &s->pci_intack); - - /* TODO Remove once realize propagates to child devices. */ - object_property_set_bool(OBJECT(&s->pci_dev), true, "realized", errp); -} - -static void raven_pcihost_initfn(Object *obj) -{ - PCIHostState *h = PCI_HOST_BRIDGE(obj); - PREPPCIState *s = RAVEN_PCI_HOST_BRIDGE(obj); - MemoryRegion *address_space_mem = get_system_memory(); - DeviceState *pci_dev; - - memory_region_init(&s->pci_io, obj, "pci-io", 0x3f800000); - memory_region_init_io(&s->pci_io_non_contiguous, obj, &raven_io_ops, s, - "pci-io-non-contiguous", 0x00800000); - memory_region_init(&s->pci_memory, obj, "pci-memory", 0x3f000000); - address_space_init(&s->pci_io_as, &s->pci_io, "raven-io"); - - /* CPU address space */ - memory_region_add_subregion(address_space_mem, 0x80000000, &s->pci_io); - memory_region_add_subregion_overlap(address_space_mem, 0x80000000, - &s->pci_io_non_contiguous, 1); - memory_region_add_subregion(address_space_mem, 0xc0000000, &s->pci_memory); - pci_bus_new_inplace(&s->pci_bus, sizeof(s->pci_bus), DEVICE(obj), NULL, - &s->pci_memory, &s->pci_io, 0, TYPE_PCI_BUS); - - /* Bus master address space */ - memory_region_init(&s->bm, obj, "bm-raven", UINT32_MAX); - memory_region_init_alias(&s->bm_pci_memory_alias, obj, "bm-pci-memory", - &s->pci_memory, 0, - memory_region_size(&s->pci_memory)); - memory_region_init_alias(&s->bm_ram_alias, obj, "bm-system", - get_system_memory(), 0, 0x80000000); - memory_region_add_subregion(&s->bm, 0 , &s->bm_pci_memory_alias); - memory_region_add_subregion(&s->bm, 0x80000000, &s->bm_ram_alias); - address_space_init(&s->bm_as, &s->bm, "raven-bm"); - pci_setup_iommu(&s->pci_bus, raven_pcihost_set_iommu, s); - - h->bus = &s->pci_bus; - - object_initialize(&s->pci_dev, sizeof(s->pci_dev), TYPE_RAVEN_PCI_DEVICE); - 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 void raven_realize(PCIDevice *d, Error **errp) -{ - RavenPCIState *s = RAVEN_PCI_DEVICE(d); - char *filename; - int bios_size = -1; - - d->config[0x0C] = 0x08; // cache_line_size - d->config[0x0D] = 0x10; // latency_timer - d->config[0x34] = 0x00; // capabilities_pointer - - memory_region_init_ram(&s->bios, OBJECT(s), "bios", BIOS_SIZE, - &error_fatal); - 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) { - if (s->elf_machine != EM_NONE) { - bios_size = load_elf(filename, NULL, NULL, NULL, - NULL, NULL, 1, s->elf_machine, 0, 0); - } - if (bios_size < 0) { - 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); - } - } - } - if (bios_size < 0 || bios_size > BIOS_SIZE) { - /* FIXME should error_setg() */ - hw_error("qemu: could not load bios image '%s'\n", s->bios_name); - } - g_free(filename); - } -} - -static const VMStateDescription vmstate_raven = { - .name = "raven", - .version_id = 0, - .minimum_version_id = 0, - .fields = (VMStateField[]) { - VMSTATE_PCI_DEVICE(dev, RavenPCIState), - VMSTATE_END_OF_LIST() - }, -}; - -static void raven_class_init(ObjectClass *klass, void *data) -{ - PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - DeviceClass *dc = DEVICE_CLASS(klass); - - k->realize = raven_realize; - k->vendor_id = PCI_VENDOR_ID_MOTOROLA; - k->device_id = PCI_DEVICE_ID_MOTOROLA_RAVEN; - k->revision = 0x00; - k->class_id = PCI_CLASS_BRIDGE_HOST; - dc->desc = "PReP Host Bridge - Motorola Raven"; - dc->vmsd = &vmstate_raven; - /* - * Reason: PCI-facing part of the host bridge, not usable without - * the host-facing part, which can't be device_add'ed, yet. - * Reason: realize() method uses hw_error(). - */ - dc->cannot_instantiate_with_device_add_yet = true; -} - -static const TypeInfo raven_info = { - .name = TYPE_RAVEN_PCI_DEVICE, - .parent = TYPE_PCI_DEVICE, - .instance_size = sizeof(RavenPCIState), - .class_init = raven_class_init, -}; - -static Property raven_pcihost_properties[] = { - DEFINE_PROP_UINT32("elf-machine", PREPPCIState, pci_dev.elf_machine, - EM_NONE), - DEFINE_PROP_STRING("bios-name", PREPPCIState, pci_dev.bios_name), - DEFINE_PROP_END_OF_LIST() -}; - -static void raven_pcihost_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - - set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); - dc->realize = raven_pcihost_realizefn; - dc->props = raven_pcihost_properties; - dc->fw_name = "pci"; -} - -static const TypeInfo raven_pcihost_info = { - .name = TYPE_RAVEN_PCI_HOST_BRIDGE, - .parent = TYPE_PCI_HOST_BRIDGE, - .instance_size = sizeof(PREPPCIState), - .instance_init = raven_pcihost_initfn, - .class_init = raven_pcihost_class_init, -}; - -static void raven_register_types(void) -{ - type_register_static(&raven_pcihost_info); - type_register_static(&raven_info); -} - -type_init(raven_register_types) diff --git a/qemu/hw/pci-host/q35.c b/qemu/hw/pci-host/q35.c deleted file mode 100644 index 70f897e3a..000000000 --- a/qemu/hw/pci-host/q35.c +++ /dev/null @@ -1,560 +0,0 @@ -/* - * QEMU MCH/ICH9 PCI Bridge Emulation - * - * Copyright (c) 2006 Fabrice Bellard - * Copyright (c) 2009, 2010, 2011 - * Isaku Yamahata - * VA Linux Systems Japan K.K. - * Copyright (C) 2012 Jason Baron - * - * This is based on piix.c, but heavily modified. - * - * 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 "qemu/osdep.h" -#include "hw/hw.h" -#include "hw/pci-host/q35.h" -#include "qapi/error.h" -#include "qapi/visitor.h" - -/**************************************************************************** - * Q35 host - */ - -static void q35_host_realize(DeviceState *dev, Error **errp) -{ - PCIHostState *pci = PCI_HOST_BRIDGE(dev); - Q35PCIHost *s = Q35_HOST_DEVICE(dev); - SysBusDevice *sbd = SYS_BUS_DEVICE(dev); - - sysbus_add_io(sbd, MCH_HOST_BRIDGE_CONFIG_ADDR, &pci->conf_mem); - sysbus_init_ioports(sbd, MCH_HOST_BRIDGE_CONFIG_ADDR, 4); - - sysbus_add_io(sbd, MCH_HOST_BRIDGE_CONFIG_DATA, &pci->data_mem); - sysbus_init_ioports(sbd, MCH_HOST_BRIDGE_CONFIG_DATA, 4); - - pci->bus = pci_bus_new(DEVICE(s), "pcie.0", - s->mch.pci_address_space, s->mch.address_space_io, - 0, TYPE_PCIE_BUS); - qdev_set_parent_bus(DEVICE(&s->mch), BUS(pci->bus)); - qdev_init_nofail(DEVICE(&s->mch)); -} - -static const char *q35_host_root_bus_path(PCIHostState *host_bridge, - PCIBus *rootbus) -{ - Q35PCIHost *s = Q35_HOST_DEVICE(host_bridge); - - /* For backwards compat with old device paths */ - if (s->mch.short_root_bus) { - return "0000"; - } - return "0000:00"; -} - -static void q35_host_get_pci_hole_start(Object *obj, Visitor *v, - const char *name, void *opaque, - Error **errp) -{ - Q35PCIHost *s = Q35_HOST_DEVICE(obj); - uint32_t value = s->mch.pci_info.w32.begin; - - visit_type_uint32(v, name, &value, errp); -} - -static void q35_host_get_pci_hole_end(Object *obj, Visitor *v, - const char *name, void *opaque, - Error **errp) -{ - Q35PCIHost *s = Q35_HOST_DEVICE(obj); - uint32_t value = s->mch.pci_info.w32.end; - - visit_type_uint32(v, name, &value, errp); -} - -static void q35_host_get_pci_hole64_start(Object *obj, Visitor *v, - const char *name, void *opaque, - Error **errp) -{ - PCIHostState *h = PCI_HOST_BRIDGE(obj); - Range w64; - - pci_bus_get_w64_range(h->bus, &w64); - - visit_type_uint64(v, name, &w64.begin, errp); -} - -static void q35_host_get_pci_hole64_end(Object *obj, Visitor *v, - const char *name, void *opaque, - Error **errp) -{ - PCIHostState *h = PCI_HOST_BRIDGE(obj); - Range w64; - - pci_bus_get_w64_range(h->bus, &w64); - - visit_type_uint64(v, name, &w64.end, errp); -} - -static void q35_host_get_mmcfg_size(Object *obj, Visitor *v, const char *name, - void *opaque, Error **errp) -{ - PCIExpressHost *e = PCIE_HOST_BRIDGE(obj); - uint32_t value = e->size; - - visit_type_uint32(v, name, &value, errp); -} - -static Property mch_props[] = { - DEFINE_PROP_UINT64(PCIE_HOST_MCFG_BASE, Q35PCIHost, parent_obj.base_addr, - MCH_HOST_BRIDGE_PCIEXBAR_DEFAULT), - DEFINE_PROP_SIZE(PCI_HOST_PROP_PCI_HOLE64_SIZE, Q35PCIHost, - mch.pci_hole64_size, DEFAULT_PCI_HOLE64_SIZE), - DEFINE_PROP_UINT32("short_root_bus", Q35PCIHost, mch.short_root_bus, 0), - DEFINE_PROP_END_OF_LIST(), -}; - -static void q35_host_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - PCIHostBridgeClass *hc = PCI_HOST_BRIDGE_CLASS(klass); - - hc->root_bus_path = q35_host_root_bus_path; - dc->realize = q35_host_realize; - dc->props = mch_props; - set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); - dc->fw_name = "pci"; -} - -static void q35_host_initfn(Object *obj) -{ - Q35PCIHost *s = Q35_HOST_DEVICE(obj); - PCIHostState *phb = PCI_HOST_BRIDGE(obj); - - memory_region_init_io(&phb->conf_mem, obj, &pci_host_conf_le_ops, phb, - "pci-conf-idx", 4); - memory_region_init_io(&phb->data_mem, obj, &pci_host_data_le_ops, phb, - "pci-conf-data", 4); - - object_initialize(&s->mch, sizeof(s->mch), TYPE_MCH_PCI_DEVICE); - object_property_add_child(OBJECT(s), "mch", OBJECT(&s->mch), NULL); - qdev_prop_set_uint32(DEVICE(&s->mch), "addr", PCI_DEVFN(0, 0)); - qdev_prop_set_bit(DEVICE(&s->mch), "multifunction", false); - - object_property_add(obj, PCI_HOST_PROP_PCI_HOLE_START, "int", - q35_host_get_pci_hole_start, - NULL, NULL, NULL, NULL); - - object_property_add(obj, PCI_HOST_PROP_PCI_HOLE_END, "int", - q35_host_get_pci_hole_end, - NULL, NULL, NULL, NULL); - - object_property_add(obj, PCI_HOST_PROP_PCI_HOLE64_START, "int", - q35_host_get_pci_hole64_start, - NULL, NULL, NULL, NULL); - - object_property_add(obj, PCI_HOST_PROP_PCI_HOLE64_END, "int", - q35_host_get_pci_hole64_end, - NULL, NULL, NULL, NULL); - - object_property_add(obj, PCIE_HOST_MCFG_SIZE, "int", - q35_host_get_mmcfg_size, - NULL, NULL, NULL, NULL); - - /* Leave enough space for the biggest MCFG BAR */ - /* TODO: this matches current bios behaviour, but - * it's not a power of two, which means an MTRR - * can't cover it exactly. - */ - s->mch.pci_info.w32.begin = MCH_HOST_BRIDGE_PCIEXBAR_DEFAULT + - MCH_HOST_BRIDGE_PCIEXBAR_MAX; - s->mch.pci_info.w32.end = IO_APIC_DEFAULT_ADDRESS; -} - -static const TypeInfo q35_host_info = { - .name = TYPE_Q35_HOST_DEVICE, - .parent = TYPE_PCIE_HOST_BRIDGE, - .instance_size = sizeof(Q35PCIHost), - .instance_init = q35_host_initfn, - .class_init = q35_host_class_init, -}; - -/**************************************************************************** - * MCH D0:F0 - */ - -static uint64_t tseg_blackhole_read(void *ptr, hwaddr reg, unsigned size) -{ - return 0xffffffff; -} - -static void tseg_blackhole_write(void *opaque, hwaddr addr, uint64_t val, - unsigned width) -{ - /* nothing */ -} - -static const MemoryRegionOps tseg_blackhole_ops = { - .read = tseg_blackhole_read, - .write = tseg_blackhole_write, - .endianness = DEVICE_NATIVE_ENDIAN, - .valid.min_access_size = 1, - .valid.max_access_size = 4, - .impl.min_access_size = 4, - .impl.max_access_size = 4, - .endianness = DEVICE_LITTLE_ENDIAN, -}; - -/* PCIe MMCFG */ -static void mch_update_pciexbar(MCHPCIState *mch) -{ - PCIDevice *pci_dev = PCI_DEVICE(mch); - BusState *bus = qdev_get_parent_bus(DEVICE(mch)); - PCIExpressHost *pehb = PCIE_HOST_BRIDGE(bus->parent); - - uint64_t pciexbar; - int enable; - uint64_t addr; - uint64_t addr_mask; - uint32_t length; - - pciexbar = pci_get_quad(pci_dev->config + MCH_HOST_BRIDGE_PCIEXBAR); - enable = pciexbar & MCH_HOST_BRIDGE_PCIEXBAREN; - addr_mask = MCH_HOST_BRIDGE_PCIEXBAR_ADMSK; - switch (pciexbar & MCH_HOST_BRIDGE_PCIEXBAR_LENGTH_MASK) { - case MCH_HOST_BRIDGE_PCIEXBAR_LENGTH_256M: - length = 256 * 1024 * 1024; - break; - case MCH_HOST_BRIDGE_PCIEXBAR_LENGTH_128M: - length = 128 * 1024 * 1024; - addr_mask |= MCH_HOST_BRIDGE_PCIEXBAR_128ADMSK | - MCH_HOST_BRIDGE_PCIEXBAR_64ADMSK; - break; - case MCH_HOST_BRIDGE_PCIEXBAR_LENGTH_64M: - length = 64 * 1024 * 1024; - addr_mask |= MCH_HOST_BRIDGE_PCIEXBAR_64ADMSK; - break; - case MCH_HOST_BRIDGE_PCIEXBAR_LENGTH_RVD: - default: - enable = 0; - length = 0; - abort(); - break; - } - addr = pciexbar & addr_mask; - pcie_host_mmcfg_update(pehb, enable, addr, length); - /* Leave enough space for the MCFG BAR */ - /* - * TODO: this matches current bios behaviour, but it's not a power of two, - * which means an MTRR can't cover it exactly. - */ - if (enable) { - mch->pci_info.w32.begin = addr + length; - } else { - mch->pci_info.w32.begin = MCH_HOST_BRIDGE_PCIEXBAR_DEFAULT; - } -} - -/* PAM */ -static void mch_update_pam(MCHPCIState *mch) -{ - PCIDevice *pd = PCI_DEVICE(mch); - int i; - - memory_region_transaction_begin(); - for (i = 0; i < 13; i++) { - pam_update(&mch->pam_regions[i], i, - pd->config[MCH_HOST_BRIDGE_PAM0 + ((i + 1) / 2)]); - } - memory_region_transaction_commit(); -} - -/* SMRAM */ -static void mch_update_smram(MCHPCIState *mch) -{ - PCIDevice *pd = PCI_DEVICE(mch); - bool h_smrame = (pd->config[MCH_HOST_BRIDGE_ESMRAMC] & MCH_HOST_BRIDGE_ESMRAMC_H_SMRAME); - uint32_t tseg_size; - - /* implement SMRAM.D_LCK */ - if (pd->config[MCH_HOST_BRIDGE_SMRAM] & MCH_HOST_BRIDGE_SMRAM_D_LCK) { - pd->config[MCH_HOST_BRIDGE_SMRAM] &= ~MCH_HOST_BRIDGE_SMRAM_D_OPEN; - pd->wmask[MCH_HOST_BRIDGE_SMRAM] = MCH_HOST_BRIDGE_SMRAM_WMASK_LCK; - pd->wmask[MCH_HOST_BRIDGE_ESMRAMC] = MCH_HOST_BRIDGE_ESMRAMC_WMASK_LCK; - } - - memory_region_transaction_begin(); - - if (pd->config[MCH_HOST_BRIDGE_SMRAM] & SMRAM_D_OPEN) { - /* Hide (!) low SMRAM if H_SMRAME = 1 */ - memory_region_set_enabled(&mch->smram_region, h_smrame); - /* Show high SMRAM if H_SMRAME = 1 */ - memory_region_set_enabled(&mch->open_high_smram, h_smrame); - } else { - /* Hide high SMRAM and low SMRAM */ - memory_region_set_enabled(&mch->smram_region, true); - memory_region_set_enabled(&mch->open_high_smram, false); - } - - if (pd->config[MCH_HOST_BRIDGE_SMRAM] & SMRAM_G_SMRAME) { - memory_region_set_enabled(&mch->low_smram, !h_smrame); - memory_region_set_enabled(&mch->high_smram, h_smrame); - } else { - memory_region_set_enabled(&mch->low_smram, false); - memory_region_set_enabled(&mch->high_smram, false); - } - - if (pd->config[MCH_HOST_BRIDGE_ESMRAMC] & MCH_HOST_BRIDGE_ESMRAMC_T_EN) { - switch (pd->config[MCH_HOST_BRIDGE_ESMRAMC] & - MCH_HOST_BRIDGE_ESMRAMC_TSEG_SZ_MASK) { - case MCH_HOST_BRIDGE_ESMRAMC_TSEG_SZ_1MB: - tseg_size = 1024 * 1024; - break; - case MCH_HOST_BRIDGE_ESMRAMC_TSEG_SZ_2MB: - tseg_size = 1024 * 1024 * 2; - break; - case MCH_HOST_BRIDGE_ESMRAMC_TSEG_SZ_8MB: - tseg_size = 1024 * 1024 * 8; - break; - default: - tseg_size = 0; - break; - } - } else { - tseg_size = 0; - } - memory_region_del_subregion(mch->system_memory, &mch->tseg_blackhole); - memory_region_set_enabled(&mch->tseg_blackhole, tseg_size); - memory_region_set_size(&mch->tseg_blackhole, tseg_size); - memory_region_add_subregion_overlap(mch->system_memory, - mch->below_4g_mem_size - tseg_size, - &mch->tseg_blackhole, 1); - - memory_region_set_enabled(&mch->tseg_window, tseg_size); - memory_region_set_size(&mch->tseg_window, tseg_size); - memory_region_set_address(&mch->tseg_window, - mch->below_4g_mem_size - tseg_size); - memory_region_set_alias_offset(&mch->tseg_window, - mch->below_4g_mem_size - tseg_size); - - memory_region_transaction_commit(); -} - -static void mch_write_config(PCIDevice *d, - uint32_t address, uint32_t val, int len) -{ - MCHPCIState *mch = MCH_PCI_DEVICE(d); - - pci_default_write_config(d, address, val, len); - - if (ranges_overlap(address, len, MCH_HOST_BRIDGE_PAM0, - MCH_HOST_BRIDGE_PAM_SIZE)) { - mch_update_pam(mch); - } - - if (ranges_overlap(address, len, MCH_HOST_BRIDGE_PCIEXBAR, - MCH_HOST_BRIDGE_PCIEXBAR_SIZE)) { - mch_update_pciexbar(mch); - } - - if (ranges_overlap(address, len, MCH_HOST_BRIDGE_SMRAM, - MCH_HOST_BRIDGE_SMRAM_SIZE)) { - mch_update_smram(mch); - } -} - -static void mch_update(MCHPCIState *mch) -{ - mch_update_pciexbar(mch); - mch_update_pam(mch); - mch_update_smram(mch); -} - -static int mch_post_load(void *opaque, int version_id) -{ - MCHPCIState *mch = opaque; - mch_update(mch); - return 0; -} - -static const VMStateDescription vmstate_mch = { - .name = "mch", - .version_id = 1, - .minimum_version_id = 1, - .post_load = mch_post_load, - .fields = (VMStateField[]) { - VMSTATE_PCI_DEVICE(parent_obj, MCHPCIState), - /* Used to be smm_enabled, which was basically always zero because - * SeaBIOS hardly uses SMM. SMRAM is now handled by CPU code. - */ - VMSTATE_UNUSED(1), - VMSTATE_END_OF_LIST() - } -}; - -static void mch_reset(DeviceState *qdev) -{ - PCIDevice *d = PCI_DEVICE(qdev); - MCHPCIState *mch = MCH_PCI_DEVICE(d); - - pci_set_quad(d->config + MCH_HOST_BRIDGE_PCIEXBAR, - MCH_HOST_BRIDGE_PCIEXBAR_DEFAULT); - - d->config[MCH_HOST_BRIDGE_SMRAM] = MCH_HOST_BRIDGE_SMRAM_DEFAULT; - d->config[MCH_HOST_BRIDGE_ESMRAMC] = MCH_HOST_BRIDGE_ESMRAMC_DEFAULT; - d->wmask[MCH_HOST_BRIDGE_SMRAM] = MCH_HOST_BRIDGE_SMRAM_WMASK; - d->wmask[MCH_HOST_BRIDGE_ESMRAMC] = MCH_HOST_BRIDGE_ESMRAMC_WMASK; - - mch_update(mch); -} - -static AddressSpace *q35_host_dma_iommu(PCIBus *bus, void *opaque, int devfn) -{ - IntelIOMMUState *s = opaque; - VTDAddressSpace *vtd_as; - - assert(0 <= devfn && devfn <= VTD_PCI_DEVFN_MAX); - - vtd_as = vtd_find_add_as(s, bus, devfn); - return &vtd_as->as; -} - -static void mch_init_dmar(MCHPCIState *mch) -{ - PCIBus *pci_bus = PCI_BUS(qdev_get_parent_bus(DEVICE(mch))); - - mch->iommu = INTEL_IOMMU_DEVICE(qdev_create(NULL, TYPE_INTEL_IOMMU_DEVICE)); - object_property_add_child(OBJECT(mch), "intel-iommu", - OBJECT(mch->iommu), NULL); - qdev_init_nofail(DEVICE(mch->iommu)); - sysbus_mmio_map(SYS_BUS_DEVICE(mch->iommu), 0, Q35_HOST_BRIDGE_IOMMU_ADDR); - - pci_setup_iommu(pci_bus, q35_host_dma_iommu, mch->iommu); -} - -static void mch_realize(PCIDevice *d, Error **errp) -{ - int i; - MCHPCIState *mch = MCH_PCI_DEVICE(d); - - /* setup pci memory mapping */ - pc_pci_as_mapping_init(OBJECT(mch), mch->system_memory, - mch->pci_address_space); - - /* if *disabled* show SMRAM to all CPUs */ - memory_region_init_alias(&mch->smram_region, OBJECT(mch), "smram-region", - mch->pci_address_space, 0xa0000, 0x20000); - memory_region_add_subregion_overlap(mch->system_memory, 0xa0000, - &mch->smram_region, 1); - memory_region_set_enabled(&mch->smram_region, true); - - memory_region_init_alias(&mch->open_high_smram, OBJECT(mch), "smram-open-high", - mch->ram_memory, 0xa0000, 0x20000); - memory_region_add_subregion_overlap(mch->system_memory, 0xfeda0000, - &mch->open_high_smram, 1); - memory_region_set_enabled(&mch->open_high_smram, false); - - /* smram, as seen by SMM CPUs */ - memory_region_init(&mch->smram, OBJECT(mch), "smram", 1ull << 32); - memory_region_set_enabled(&mch->smram, true); - memory_region_init_alias(&mch->low_smram, OBJECT(mch), "smram-low", - mch->ram_memory, 0xa0000, 0x20000); - memory_region_set_enabled(&mch->low_smram, true); - memory_region_add_subregion(&mch->smram, 0xa0000, &mch->low_smram); - memory_region_init_alias(&mch->high_smram, OBJECT(mch), "smram-high", - mch->ram_memory, 0xa0000, 0x20000); - memory_region_set_enabled(&mch->high_smram, true); - memory_region_add_subregion(&mch->smram, 0xfeda0000, &mch->high_smram); - - memory_region_init_io(&mch->tseg_blackhole, OBJECT(mch), - &tseg_blackhole_ops, NULL, - "tseg-blackhole", 0); - memory_region_set_enabled(&mch->tseg_blackhole, false); - memory_region_add_subregion_overlap(mch->system_memory, - mch->below_4g_mem_size, - &mch->tseg_blackhole, 1); - - memory_region_init_alias(&mch->tseg_window, OBJECT(mch), "tseg-window", - mch->ram_memory, mch->below_4g_mem_size, 0); - memory_region_set_enabled(&mch->tseg_window, false); - memory_region_add_subregion(&mch->smram, mch->below_4g_mem_size, - &mch->tseg_window); - object_property_add_const_link(qdev_get_machine(), "smram", - OBJECT(&mch->smram), &error_abort); - - init_pam(DEVICE(mch), mch->ram_memory, mch->system_memory, - mch->pci_address_space, &mch->pam_regions[0], - PAM_BIOS_BASE, PAM_BIOS_SIZE); - for (i = 0; i < 12; ++i) { - init_pam(DEVICE(mch), mch->ram_memory, mch->system_memory, - mch->pci_address_space, &mch->pam_regions[i+1], - PAM_EXPAN_BASE + i * PAM_EXPAN_SIZE, PAM_EXPAN_SIZE); - } - /* Intel IOMMU (VT-d) */ - if (object_property_get_bool(qdev_get_machine(), "iommu", NULL)) { - mch_init_dmar(mch); - } -} - -uint64_t mch_mcfg_base(void) -{ - bool ambiguous; - Object *o = object_resolve_path_type("", TYPE_MCH_PCI_DEVICE, &ambiguous); - if (!o) { - return 0; - } - return MCH_HOST_BRIDGE_PCIEXBAR_DEFAULT; -} - -static void mch_class_init(ObjectClass *klass, void *data) -{ - PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - DeviceClass *dc = DEVICE_CLASS(klass); - - k->realize = mch_realize; - k->config_write = mch_write_config; - dc->reset = mch_reset; - set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); - dc->desc = "Host bridge"; - dc->vmsd = &vmstate_mch; - k->vendor_id = PCI_VENDOR_ID_INTEL; - k->device_id = PCI_DEVICE_ID_INTEL_Q35_MCH; - k->revision = MCH_HOST_BRIDGE_REVISION_DEFAULT; - k->class_id = PCI_CLASS_BRIDGE_HOST; - /* - * PCI-facing part of the host bridge, not usable without the - * host-facing part, which can't be device_add'ed, yet. - */ - dc->cannot_instantiate_with_device_add_yet = true; -} - -static const TypeInfo mch_info = { - .name = TYPE_MCH_PCI_DEVICE, - .parent = TYPE_PCI_DEVICE, - .instance_size = sizeof(MCHPCIState), - .class_init = mch_class_init, -}; - -static void q35_register(void) -{ - type_register_static(&mch_info); - type_register_static(&q35_host_info); -} - -type_init(q35_register); diff --git a/qemu/hw/pci-host/uninorth.c b/qemu/hw/pci-host/uninorth.c deleted file mode 100644 index 15b105423..000000000 --- a/qemu/hw/pci-host/uninorth.c +++ /dev/null @@ -1,533 +0,0 @@ -/* - * QEMU Uninorth PCI host (for all Mac99 and newer machines) - * - * Copyright (c) 2006 Fabrice Bellard - * - * 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 "qemu/osdep.h" -#include "hw/hw.h" -#include "hw/ppc/mac.h" -#include "hw/pci/pci.h" -#include "hw/pci/pci_host.h" - -/* debug UniNorth */ -//#define DEBUG_UNIN - -#ifdef DEBUG_UNIN -#define UNIN_DPRINTF(fmt, ...) \ - do { printf("UNIN: " fmt , ## __VA_ARGS__); } while (0) -#else -#define UNIN_DPRINTF(fmt, ...) -#endif - -static const int unin_irq_line[] = { 0x1b, 0x1c, 0x1d, 0x1e }; - -#define TYPE_UNI_NORTH_PCI_HOST_BRIDGE "uni-north-pci-pcihost" -#define TYPE_UNI_NORTH_AGP_HOST_BRIDGE "uni-north-agp-pcihost" -#define TYPE_UNI_NORTH_INTERNAL_PCI_HOST_BRIDGE "uni-north-internal-pci-pcihost" -#define TYPE_U3_AGP_HOST_BRIDGE "u3-agp-pcihost" - -#define UNI_NORTH_PCI_HOST_BRIDGE(obj) \ - OBJECT_CHECK(UNINState, (obj), TYPE_UNI_NORTH_PCI_HOST_BRIDGE) -#define UNI_NORTH_AGP_HOST_BRIDGE(obj) \ - OBJECT_CHECK(UNINState, (obj), TYPE_UNI_NORTH_AGP_HOST_BRIDGE) -#define UNI_NORTH_INTERNAL_PCI_HOST_BRIDGE(obj) \ - OBJECT_CHECK(UNINState, (obj), TYPE_UNI_NORTH_INTERNAL_PCI_HOST_BRIDGE) -#define U3_AGP_HOST_BRIDGE(obj) \ - OBJECT_CHECK(UNINState, (obj), TYPE_U3_AGP_HOST_BRIDGE) - -typedef struct UNINState { - PCIHostState parent_obj; - - MemoryRegion pci_mmio; - MemoryRegion pci_hole; -} UNINState; - -static int pci_unin_map_irq(PCIDevice *pci_dev, int irq_num) -{ - int retval; - int devfn = pci_dev->devfn & 0x00FFFFFF; - - retval = (((devfn >> 11) & 0x1F) + irq_num) & 3; - - return retval; -} - -static void pci_unin_set_irq(void *opaque, int irq_num, int level) -{ - qemu_irq *pic = opaque; - - UNIN_DPRINTF("%s: setting INT %d = %d\n", __func__, - unin_irq_line[irq_num], level); - qemu_set_irq(pic[unin_irq_line[irq_num]], level); -} - -static uint32_t unin_get_config_reg(uint32_t reg, uint32_t addr) -{ - uint32_t retval; - - if (reg & (1u << 31)) { - /* XXX OpenBIOS compatibility hack */ - retval = reg | (addr & 3); - } else if (reg & 1) { - /* CFA1 style */ - retval = (reg & ~7u) | (addr & 7); - } else { - uint32_t slot, func; - - /* Grab CFA0 style values */ - slot = ctz32(reg & 0xfffff800); - if (slot == 32) { - slot = -1; /* XXX: should this be 0? */ - } - func = (reg >> 8) & 7; - - /* ... and then convert them to x86 format */ - /* config pointer */ - retval = (reg & (0xff - 7)) | (addr & 7); - /* slot */ - retval |= slot << 11; - /* fn */ - retval |= func << 8; - } - - - UNIN_DPRINTF("Converted config space accessor %08x/%08x -> %08x\n", - reg, addr, retval); - - return retval; -} - -static void unin_data_write(void *opaque, hwaddr addr, - uint64_t val, unsigned len) -{ - UNINState *s = opaque; - PCIHostState *phb = PCI_HOST_BRIDGE(s); - UNIN_DPRINTF("write addr " TARGET_FMT_plx " len %d val %"PRIx64"\n", - addr, len, val); - pci_data_write(phb->bus, - unin_get_config_reg(phb->config_reg, addr), - val, len); -} - -static uint64_t unin_data_read(void *opaque, hwaddr addr, - unsigned len) -{ - UNINState *s = opaque; - PCIHostState *phb = PCI_HOST_BRIDGE(s); - uint32_t val; - - val = pci_data_read(phb->bus, - unin_get_config_reg(phb->config_reg, addr), - len); - UNIN_DPRINTF("read addr " TARGET_FMT_plx " len %d val %x\n", - addr, len, val); - return val; -} - -static const MemoryRegionOps unin_data_ops = { - .read = unin_data_read, - .write = unin_data_write, - .endianness = DEVICE_LITTLE_ENDIAN, -}; - -static int pci_unin_main_init_device(SysBusDevice *dev) -{ - PCIHostState *h; - - /* Use values found on a real PowerMac */ - /* Uninorth main bus */ - h = PCI_HOST_BRIDGE(dev); - - memory_region_init_io(&h->conf_mem, OBJECT(h), &pci_host_conf_le_ops, - dev, "pci-conf-idx", 0x1000); - memory_region_init_io(&h->data_mem, OBJECT(h), &unin_data_ops, dev, - "pci-conf-data", 0x1000); - sysbus_init_mmio(dev, &h->conf_mem); - sysbus_init_mmio(dev, &h->data_mem); - - return 0; -} - - -static int pci_u3_agp_init_device(SysBusDevice *dev) -{ - PCIHostState *h; - - /* Uninorth U3 AGP bus */ - h = PCI_HOST_BRIDGE(dev); - - memory_region_init_io(&h->conf_mem, OBJECT(h), &pci_host_conf_le_ops, - dev, "pci-conf-idx", 0x1000); - memory_region_init_io(&h->data_mem, OBJECT(h), &unin_data_ops, dev, - "pci-conf-data", 0x1000); - sysbus_init_mmio(dev, &h->conf_mem); - sysbus_init_mmio(dev, &h->data_mem); - - return 0; -} - -static int pci_unin_agp_init_device(SysBusDevice *dev) -{ - PCIHostState *h; - - /* Uninorth AGP bus */ - h = PCI_HOST_BRIDGE(dev); - - memory_region_init_io(&h->conf_mem, OBJECT(h), &pci_host_conf_le_ops, - dev, "pci-conf-idx", 0x1000); - memory_region_init_io(&h->data_mem, OBJECT(h), &pci_host_data_le_ops, - dev, "pci-conf-data", 0x1000); - sysbus_init_mmio(dev, &h->conf_mem); - sysbus_init_mmio(dev, &h->data_mem); - return 0; -} - -static int pci_unin_internal_init_device(SysBusDevice *dev) -{ - PCIHostState *h; - - /* Uninorth internal bus */ - h = PCI_HOST_BRIDGE(dev); - - memory_region_init_io(&h->conf_mem, OBJECT(h), &pci_host_conf_le_ops, - dev, "pci-conf-idx", 0x1000); - memory_region_init_io(&h->data_mem, OBJECT(h), &pci_host_data_le_ops, - dev, "pci-conf-data", 0x1000); - sysbus_init_mmio(dev, &h->conf_mem); - sysbus_init_mmio(dev, &h->data_mem); - return 0; -} - -PCIBus *pci_pmac_init(qemu_irq *pic, - MemoryRegion *address_space_mem, - MemoryRegion *address_space_io) -{ - DeviceState *dev; - SysBusDevice *s; - PCIHostState *h; - UNINState *d; - - /* Use values found on a real PowerMac */ - /* Uninorth main bus */ - dev = qdev_create(NULL, TYPE_UNI_NORTH_PCI_HOST_BRIDGE); - qdev_init_nofail(dev); - s = SYS_BUS_DEVICE(dev); - h = PCI_HOST_BRIDGE(s); - d = UNI_NORTH_PCI_HOST_BRIDGE(dev); - memory_region_init(&d->pci_mmio, OBJECT(d), "pci-mmio", 0x100000000ULL); - memory_region_init_alias(&d->pci_hole, OBJECT(d), "pci-hole", &d->pci_mmio, - 0x80000000ULL, 0x10000000ULL); - memory_region_add_subregion(address_space_mem, 0x80000000ULL, - &d->pci_hole); - - h->bus = pci_register_bus(dev, NULL, - pci_unin_set_irq, pci_unin_map_irq, - pic, - &d->pci_mmio, - address_space_io, - PCI_DEVFN(11, 0), 4, TYPE_PCI_BUS); - -#if 0 - pci_create_simple(h->bus, PCI_DEVFN(11, 0), "uni-north"); -#endif - - sysbus_mmio_map(s, 0, 0xf2800000); - sysbus_mmio_map(s, 1, 0xf2c00000); - - /* DEC 21154 bridge */ -#if 0 - /* XXX: not activated as PPC BIOS doesn't handle multiple buses properly */ - pci_create_simple(h->bus, PCI_DEVFN(12, 0), "dec-21154"); -#endif - - /* Uninorth AGP bus */ - pci_create_simple(h->bus, PCI_DEVFN(11, 0), "uni-north-agp"); - dev = qdev_create(NULL, TYPE_UNI_NORTH_AGP_HOST_BRIDGE); - qdev_init_nofail(dev); - s = SYS_BUS_DEVICE(dev); - sysbus_mmio_map(s, 0, 0xf0800000); - sysbus_mmio_map(s, 1, 0xf0c00000); - - /* Uninorth internal bus */ -#if 0 - /* XXX: not needed for now */ - pci_create_simple(h->bus, PCI_DEVFN(14, 0), - "uni-north-internal-pci"); - dev = qdev_create(NULL, TYPE_UNI_NORTH_INTERNAL_PCI_HOST_BRIDGE); - qdev_init_nofail(dev); - s = SYS_BUS_DEVICE(dev); - sysbus_mmio_map(s, 0, 0xf4800000); - sysbus_mmio_map(s, 1, 0xf4c00000); -#endif - - return h->bus; -} - -PCIBus *pci_pmac_u3_init(qemu_irq *pic, - MemoryRegion *address_space_mem, - MemoryRegion *address_space_io) -{ - DeviceState *dev; - SysBusDevice *s; - PCIHostState *h; - UNINState *d; - - /* Uninorth AGP bus */ - - dev = qdev_create(NULL, TYPE_U3_AGP_HOST_BRIDGE); - qdev_init_nofail(dev); - s = SYS_BUS_DEVICE(dev); - h = PCI_HOST_BRIDGE(dev); - d = U3_AGP_HOST_BRIDGE(dev); - - memory_region_init(&d->pci_mmio, OBJECT(d), "pci-mmio", 0x100000000ULL); - memory_region_init_alias(&d->pci_hole, OBJECT(d), "pci-hole", &d->pci_mmio, - 0x80000000ULL, 0x70000000ULL); - memory_region_add_subregion(address_space_mem, 0x80000000ULL, - &d->pci_hole); - - h->bus = pci_register_bus(dev, NULL, - pci_unin_set_irq, pci_unin_map_irq, - pic, - &d->pci_mmio, - address_space_io, - PCI_DEVFN(11, 0), 4, TYPE_PCI_BUS); - - sysbus_mmio_map(s, 0, 0xf0800000); - sysbus_mmio_map(s, 1, 0xf0c00000); - - pci_create_simple(h->bus, 11 << 3, "u3-agp"); - - return h->bus; -} - -static void unin_main_pci_host_realize(PCIDevice *d, Error **errp) -{ - d->config[0x0C] = 0x08; // cache_line_size - d->config[0x0D] = 0x10; // latency_timer - d->config[0x34] = 0x00; // capabilities_pointer -} - -static void unin_agp_pci_host_realize(PCIDevice *d, Error **errp) -{ - d->config[0x0C] = 0x08; // cache_line_size - d->config[0x0D] = 0x10; // latency_timer - // d->config[0x34] = 0x80; // capabilities_pointer - /* - * Set kMacRISCPCIAddressSelect (0x48) register to indicate PCI - * memory space with base 0x80000000, size 0x10000000 for Apple's - * AppleMacRiscPCI driver - */ - d->config[0x48] = 0x0; - d->config[0x49] = 0x0; - d->config[0x4a] = 0x0; - d->config[0x4b] = 0x1; -} - -static void u3_agp_pci_host_realize(PCIDevice *d, Error **errp) -{ - /* cache line size */ - d->config[0x0C] = 0x08; - /* latency timer */ - d->config[0x0D] = 0x10; -} - -static void unin_internal_pci_host_realize(PCIDevice *d, Error **errp) -{ - d->config[0x0C] = 0x08; // cache_line_size - d->config[0x0D] = 0x10; // latency_timer - d->config[0x34] = 0x00; // capabilities_pointer -} - -static void unin_main_pci_host_class_init(ObjectClass *klass, void *data) -{ - PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - DeviceClass *dc = DEVICE_CLASS(klass); - - k->realize = unin_main_pci_host_realize; - k->vendor_id = PCI_VENDOR_ID_APPLE; - k->device_id = PCI_DEVICE_ID_APPLE_UNI_N_PCI; - k->revision = 0x00; - k->class_id = PCI_CLASS_BRIDGE_HOST; - /* - * PCI-facing part of the host bridge, not usable without the - * host-facing part, which can't be device_add'ed, yet. - */ - dc->cannot_instantiate_with_device_add_yet = true; -} - -static const TypeInfo unin_main_pci_host_info = { - .name = "uni-north-pci", - .parent = TYPE_PCI_DEVICE, - .instance_size = sizeof(PCIDevice), - .class_init = unin_main_pci_host_class_init, -}; - -static void u3_agp_pci_host_class_init(ObjectClass *klass, void *data) -{ - PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - DeviceClass *dc = DEVICE_CLASS(klass); - - k->realize = u3_agp_pci_host_realize; - k->vendor_id = PCI_VENDOR_ID_APPLE; - k->device_id = PCI_DEVICE_ID_APPLE_U3_AGP; - k->revision = 0x00; - k->class_id = PCI_CLASS_BRIDGE_HOST; - /* - * PCI-facing part of the host bridge, not usable without the - * host-facing part, which can't be device_add'ed, yet. - */ - dc->cannot_instantiate_with_device_add_yet = true; -} - -static const TypeInfo u3_agp_pci_host_info = { - .name = "u3-agp", - .parent = TYPE_PCI_DEVICE, - .instance_size = sizeof(PCIDevice), - .class_init = u3_agp_pci_host_class_init, -}; - -static void unin_agp_pci_host_class_init(ObjectClass *klass, void *data) -{ - PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - DeviceClass *dc = DEVICE_CLASS(klass); - - k->realize = unin_agp_pci_host_realize; - k->vendor_id = PCI_VENDOR_ID_APPLE; - k->device_id = PCI_DEVICE_ID_APPLE_UNI_N_AGP; - k->revision = 0x00; - k->class_id = PCI_CLASS_BRIDGE_HOST; - /* - * PCI-facing part of the host bridge, not usable without the - * host-facing part, which can't be device_add'ed, yet. - */ - dc->cannot_instantiate_with_device_add_yet = true; -} - -static const TypeInfo unin_agp_pci_host_info = { - .name = "uni-north-agp", - .parent = TYPE_PCI_DEVICE, - .instance_size = sizeof(PCIDevice), - .class_init = unin_agp_pci_host_class_init, -}; - -static void unin_internal_pci_host_class_init(ObjectClass *klass, void *data) -{ - PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - DeviceClass *dc = DEVICE_CLASS(klass); - - k->realize = unin_internal_pci_host_realize; - k->vendor_id = PCI_VENDOR_ID_APPLE; - k->device_id = PCI_DEVICE_ID_APPLE_UNI_N_I_PCI; - k->revision = 0x00; - k->class_id = PCI_CLASS_BRIDGE_HOST; - /* - * PCI-facing part of the host bridge, not usable without the - * host-facing part, which can't be device_add'ed, yet. - */ - dc->cannot_instantiate_with_device_add_yet = true; -} - -static const TypeInfo unin_internal_pci_host_info = { - .name = "uni-north-internal-pci", - .parent = TYPE_PCI_DEVICE, - .instance_size = sizeof(PCIDevice), - .class_init = unin_internal_pci_host_class_init, -}; - -static void pci_unin_main_class_init(ObjectClass *klass, void *data) -{ - SysBusDeviceClass *sbc = SYS_BUS_DEVICE_CLASS(klass); - DeviceClass *dc = DEVICE_CLASS(klass); - - sbc->init = pci_unin_main_init_device; - set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); -} - -static const TypeInfo pci_unin_main_info = { - .name = TYPE_UNI_NORTH_PCI_HOST_BRIDGE, - .parent = TYPE_PCI_HOST_BRIDGE, - .instance_size = sizeof(UNINState), - .class_init = pci_unin_main_class_init, -}; - -static void pci_u3_agp_class_init(ObjectClass *klass, void *data) -{ - SysBusDeviceClass *sbc = SYS_BUS_DEVICE_CLASS(klass); - DeviceClass *dc = DEVICE_CLASS(klass); - - sbc->init = pci_u3_agp_init_device; - set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); -} - -static const TypeInfo pci_u3_agp_info = { - .name = TYPE_U3_AGP_HOST_BRIDGE, - .parent = TYPE_PCI_HOST_BRIDGE, - .instance_size = sizeof(UNINState), - .class_init = pci_u3_agp_class_init, -}; - -static void pci_unin_agp_class_init(ObjectClass *klass, void *data) -{ - SysBusDeviceClass *sbc = SYS_BUS_DEVICE_CLASS(klass); - DeviceClass *dc = DEVICE_CLASS(klass); - - sbc->init = pci_unin_agp_init_device; - set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); -} - -static const TypeInfo pci_unin_agp_info = { - .name = TYPE_UNI_NORTH_AGP_HOST_BRIDGE, - .parent = TYPE_PCI_HOST_BRIDGE, - .instance_size = sizeof(UNINState), - .class_init = pci_unin_agp_class_init, -}; - -static void pci_unin_internal_class_init(ObjectClass *klass, void *data) -{ - SysBusDeviceClass *sbc = SYS_BUS_DEVICE_CLASS(klass); - DeviceClass *dc = DEVICE_CLASS(klass); - - sbc->init = pci_unin_internal_init_device; - set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); -} - -static const TypeInfo pci_unin_internal_info = { - .name = TYPE_UNI_NORTH_INTERNAL_PCI_HOST_BRIDGE, - .parent = TYPE_PCI_HOST_BRIDGE, - .instance_size = sizeof(UNINState), - .class_init = pci_unin_internal_class_init, -}; - -static void unin_register_types(void) -{ - type_register_static(&unin_main_pci_host_info); - type_register_static(&u3_agp_pci_host_info); - type_register_static(&unin_agp_pci_host_info); - type_register_static(&unin_internal_pci_host_info); - - type_register_static(&pci_unin_main_info); - type_register_static(&pci_u3_agp_info); - type_register_static(&pci_unin_agp_info); - type_register_static(&pci_unin_internal_info); -} - -type_init(unin_register_types) diff --git a/qemu/hw/pci-host/versatile.c b/qemu/hw/pci-host/versatile.c deleted file mode 100644 index 339ec2c50..000000000 --- a/qemu/hw/pci-host/versatile.c +++ /dev/null @@ -1,549 +0,0 @@ -/* - * ARM Versatile/PB PCI host controller - * - * Copyright (c) 2006-2009 CodeSourcery. - * Written by Paul Brook - * - * This code is licensed under the LGPL. - */ - -#include "qemu/osdep.h" -#include "hw/sysbus.h" -#include "hw/pci/pci.h" -#include "hw/pci/pci_bus.h" -#include "hw/pci/pci_host.h" -#include "exec/address-spaces.h" - -/* Old and buggy versions of QEMU used the wrong mapping from - * PCI IRQs to system interrupt lines. Unfortunately the Linux - * kernel also had the corresponding bug in setting up interrupts - * (so older kernels work on QEMU and not on real hardware). - * We automatically detect these broken kernels and flip back - * to the broken irq mapping by spotting guest writes to the - * PCI_INTERRUPT_LINE register to see where the guest thinks - * interrupts are going to be routed. So we start in state - * ASSUME_OK on reset, and transition to either BROKEN or - * FORCE_OK at the first write to an INTERRUPT_LINE register for - * a slot where broken and correct interrupt mapping would differ. - * Once in either BROKEN or FORCE_OK we never transition again; - * this allows a newer kernel to use the INTERRUPT_LINE - * registers arbitrarily once it has indicated that it isn't - * broken in its init code somewhere. - * - * Unfortunately we have to cope with multiple different - * variants on the broken kernel behaviour: - * phase I (before kernel commit 1bc39ac5d) kernels assume old - * QEMU behaviour, so they use IRQ 27 for all slots - * phase II (1bc39ac5d and later, but before e3e92a7be6) kernels - * swizzle IRQs between slots, but do it wrongly, so they - * work only for every fourth PCI card, and only if (like old - * QEMU) the PCI host device is at slot 0 rather than where - * the h/w actually puts it - * phase III (e3e92a7be6 and later) kernels still swizzle IRQs between - * slots wrongly, but add a fixed offset of 64 to everything - * they write to PCI_INTERRUPT_LINE. - * - * We live in hope of a mythical phase IV kernel which might - * actually behave in ways that work on the hardware. Such a - * kernel should probably start off by writing some value neither - * 27 nor 91 to slot zero's PCI_INTERRUPT_LINE register to - * disable the autodetection. After that it can do what it likes. - * - * Slot % 4 | hw | I | II | III - * ------------------------------- - * 0 | 29 | 27 | 27 | 91 - * 1 | 30 | 27 | 28 | 92 - * 2 | 27 | 27 | 29 | 93 - * 3 | 28 | 27 | 30 | 94 - * - * Since our autodetection is not perfect we also provide a - * property so the user can make us start in BROKEN or FORCE_OK - * on reset if they know they have a bad or good kernel. - */ -enum { - PCI_VPB_IRQMAP_ASSUME_OK, - PCI_VPB_IRQMAP_BROKEN, - PCI_VPB_IRQMAP_FORCE_OK, -}; - -typedef struct { - PCIHostState parent_obj; - - qemu_irq irq[4]; - MemoryRegion controlregs; - MemoryRegion mem_config; - MemoryRegion mem_config2; - /* Containers representing the PCI address spaces */ - MemoryRegion pci_io_space; - MemoryRegion pci_mem_space; - /* Alias regions into PCI address spaces which we expose as sysbus regions. - * The offsets into pci_mem_space are controlled by the imap registers. - */ - MemoryRegion pci_io_window; - MemoryRegion pci_mem_window[3]; - PCIBus pci_bus; - PCIDevice pci_dev; - - /* Constant for life of device: */ - int realview; - uint32_t mem_win_size[3]; - uint8_t irq_mapping_prop; - - /* Variable state: */ - uint32_t imap[3]; - uint32_t smap[3]; - uint32_t selfid; - uint32_t flags; - uint8_t irq_mapping; -} PCIVPBState; - -static void pci_vpb_update_window(PCIVPBState *s, int i) -{ - /* Adjust the offset of the alias region we use for - * the memory window i to account for a change in the - * value of the corresponding IMAP register. - * Note that the semantics of the IMAP register differ - * for realview and versatile variants of the controller. - */ - hwaddr offset; - if (s->realview) { - /* Top bits of register (masked according to window size) provide - * top bits of PCI address. - */ - offset = s->imap[i] & ~(s->mem_win_size[i] - 1); - } else { - /* Bottom 4 bits of register provide top 4 bits of PCI address */ - offset = s->imap[i] << 28; - } - memory_region_set_alias_offset(&s->pci_mem_window[i], offset); -} - -static void pci_vpb_update_all_windows(PCIVPBState *s) -{ - /* Update all alias windows based on the current register state */ - int i; - - for (i = 0; i < 3; i++) { - pci_vpb_update_window(s, i); - } -} - -static int pci_vpb_post_load(void *opaque, int version_id) -{ - PCIVPBState *s = opaque; - pci_vpb_update_all_windows(s); - return 0; -} - -static const VMStateDescription pci_vpb_vmstate = { - .name = "versatile-pci", - .version_id = 1, - .minimum_version_id = 1, - .post_load = pci_vpb_post_load, - .fields = (VMStateField[]) { - VMSTATE_UINT32_ARRAY(imap, PCIVPBState, 3), - VMSTATE_UINT32_ARRAY(smap, PCIVPBState, 3), - VMSTATE_UINT32(selfid, PCIVPBState), - VMSTATE_UINT32(flags, PCIVPBState), - VMSTATE_UINT8(irq_mapping, PCIVPBState), - VMSTATE_END_OF_LIST() - } -}; - -#define TYPE_VERSATILE_PCI "versatile_pci" -#define PCI_VPB(obj) \ - OBJECT_CHECK(PCIVPBState, (obj), TYPE_VERSATILE_PCI) - -#define TYPE_VERSATILE_PCI_HOST "versatile_pci_host" -#define PCI_VPB_HOST(obj) \ - OBJECT_CHECK(PCIDevice, (obj), TYPE_VERSATILE_PCIHOST) - -typedef enum { - PCI_IMAP0 = 0x0, - PCI_IMAP1 = 0x4, - PCI_IMAP2 = 0x8, - PCI_SELFID = 0xc, - PCI_FLAGS = 0x10, - PCI_SMAP0 = 0x14, - PCI_SMAP1 = 0x18, - PCI_SMAP2 = 0x1c, -} PCIVPBControlRegs; - -static void pci_vpb_reg_write(void *opaque, hwaddr addr, - uint64_t val, unsigned size) -{ - PCIVPBState *s = opaque; - - switch (addr) { - case PCI_IMAP0: - case PCI_IMAP1: - case PCI_IMAP2: - { - int win = (addr - PCI_IMAP0) >> 2; - s->imap[win] = val; - pci_vpb_update_window(s, win); - break; - } - case PCI_SELFID: - s->selfid = val; - break; - case PCI_FLAGS: - s->flags = val; - break; - case PCI_SMAP0: - case PCI_SMAP1: - case PCI_SMAP2: - { - int win = (addr - PCI_SMAP0) >> 2; - s->smap[win] = val; - break; - } - default: - qemu_log_mask(LOG_GUEST_ERROR, - "pci_vpb_reg_write: Bad offset %x\n", (int)addr); - break; - } -} - -static uint64_t pci_vpb_reg_read(void *opaque, hwaddr addr, - unsigned size) -{ - PCIVPBState *s = opaque; - - switch (addr) { - case PCI_IMAP0: - case PCI_IMAP1: - case PCI_IMAP2: - { - int win = (addr - PCI_IMAP0) >> 2; - return s->imap[win]; - } - case PCI_SELFID: - return s->selfid; - case PCI_FLAGS: - return s->flags; - case PCI_SMAP0: - case PCI_SMAP1: - case PCI_SMAP2: - { - int win = (addr - PCI_SMAP0) >> 2; - return s->smap[win]; - } - default: - qemu_log_mask(LOG_GUEST_ERROR, - "pci_vpb_reg_read: Bad offset %x\n", (int)addr); - return 0; - } -} - -static const MemoryRegionOps pci_vpb_reg_ops = { - .read = pci_vpb_reg_read, - .write = pci_vpb_reg_write, - .endianness = DEVICE_NATIVE_ENDIAN, - .valid = { - .min_access_size = 4, - .max_access_size = 4, - }, -}; - -static int pci_vpb_broken_irq(int slot, int irq) -{ - /* Determine whether this IRQ value for this slot represents a - * known broken Linux kernel behaviour for this slot. - * Return one of the PCI_VPB_IRQMAP_ constants: - * BROKEN : if this definitely looks like a broken kernel - * FORCE_OK : if this definitely looks good - * ASSUME_OK : if we can't tell - */ - slot %= PCI_NUM_PINS; - - if (irq == 27) { - if (slot == 2) { - /* Might be a Phase I kernel, or might be a fixed kernel, - * since slot 2 is where we expect this IRQ. - */ - return PCI_VPB_IRQMAP_ASSUME_OK; - } - /* Phase I kernel */ - return PCI_VPB_IRQMAP_BROKEN; - } - if (irq == slot + 27) { - /* Phase II kernel */ - return PCI_VPB_IRQMAP_BROKEN; - } - if (irq == slot + 27 + 64) { - /* Phase III kernel */ - return PCI_VPB_IRQMAP_BROKEN; - } - /* Anything else must be a fixed kernel, possibly using an - * arbitrary irq map. - */ - return PCI_VPB_IRQMAP_FORCE_OK; -} - -static void pci_vpb_config_write(void *opaque, hwaddr addr, - uint64_t val, unsigned size) -{ - PCIVPBState *s = opaque; - if (!s->realview && (addr & 0xff) == PCI_INTERRUPT_LINE - && s->irq_mapping == PCI_VPB_IRQMAP_ASSUME_OK) { - uint8_t devfn = addr >> 8; - s->irq_mapping = pci_vpb_broken_irq(PCI_SLOT(devfn), val); - } - pci_data_write(&s->pci_bus, addr, val, size); -} - -static uint64_t pci_vpb_config_read(void *opaque, hwaddr addr, - unsigned size) -{ - PCIVPBState *s = opaque; - uint32_t val; - val = pci_data_read(&s->pci_bus, addr, size); - return val; -} - -static const MemoryRegionOps pci_vpb_config_ops = { - .read = pci_vpb_config_read, - .write = pci_vpb_config_write, - .endianness = DEVICE_NATIVE_ENDIAN, -}; - -static int pci_vpb_map_irq(PCIDevice *d, int irq_num) -{ - PCIVPBState *s = container_of(d->bus, PCIVPBState, pci_bus); - - if (s->irq_mapping == PCI_VPB_IRQMAP_BROKEN) { - /* Legacy broken IRQ mapping for compatibility with old and - * buggy Linux guests - */ - return irq_num; - } - - /* Slot to IRQ mapping for RealView Platform Baseboard 926 backplane - * name slot IntA IntB IntC IntD - * A 31 IRQ28 IRQ29 IRQ30 IRQ27 - * B 30 IRQ27 IRQ28 IRQ29 IRQ30 - * C 29 IRQ30 IRQ27 IRQ28 IRQ29 - * Slot C is for the host bridge; A and B the peripherals. - * Our output irqs 0..3 correspond to the baseboard's 27..30. - * - * This mapping function takes account of an oddity in the PB926 - * board wiring, where the FPGA's P_nINTA input is connected to - * the INTB connection on the board PCI edge connector, P_nINTB - * is connected to INTC, and so on, so everything is one number - * further round from where you might expect. - */ - return pci_swizzle_map_irq_fn(d, irq_num + 2); -} - -static int pci_vpb_rv_map_irq(PCIDevice *d, int irq_num) -{ - /* Slot to IRQ mapping for RealView EB and PB1176 backplane - * name slot IntA IntB IntC IntD - * A 31 IRQ50 IRQ51 IRQ48 IRQ49 - * B 30 IRQ49 IRQ50 IRQ51 IRQ48 - * C 29 IRQ48 IRQ49 IRQ50 IRQ51 - * Slot C is for the host bridge; A and B the peripherals. - * Our output irqs 0..3 correspond to the baseboard's 48..51. - * - * The PB1176 and EB boards don't have the PB926 wiring oddity - * described above; P_nINTA connects to INTA, P_nINTB to INTB - * and so on, which is why this mapping function is different. - */ - return pci_swizzle_map_irq_fn(d, irq_num + 3); -} - -static void pci_vpb_set_irq(void *opaque, int irq_num, int level) -{ - qemu_irq *pic = opaque; - - qemu_set_irq(pic[irq_num], level); -} - -static void pci_vpb_reset(DeviceState *d) -{ - PCIVPBState *s = PCI_VPB(d); - - s->imap[0] = 0; - s->imap[1] = 0; - s->imap[2] = 0; - s->smap[0] = 0; - s->smap[1] = 0; - s->smap[2] = 0; - s->selfid = 0; - s->flags = 0; - s->irq_mapping = s->irq_mapping_prop; - - pci_vpb_update_all_windows(s); -} - -static void pci_vpb_init(Object *obj) -{ - PCIHostState *h = PCI_HOST_BRIDGE(obj); - PCIVPBState *s = PCI_VPB(obj); - - memory_region_init(&s->pci_io_space, OBJECT(s), "pci_io", 1ULL << 32); - memory_region_init(&s->pci_mem_space, OBJECT(s), "pci_mem", 1ULL << 32); - - pci_bus_new_inplace(&s->pci_bus, sizeof(s->pci_bus), DEVICE(obj), "pci", - &s->pci_mem_space, &s->pci_io_space, - PCI_DEVFN(11, 0), TYPE_PCI_BUS); - h->bus = &s->pci_bus; - - object_initialize(&s->pci_dev, sizeof(s->pci_dev), TYPE_VERSATILE_PCI_HOST); - qdev_set_parent_bus(DEVICE(&s->pci_dev), BUS(&s->pci_bus)); - - /* Window sizes for VersatilePB; realview_pci's init will override */ - s->mem_win_size[0] = 0x0c000000; - s->mem_win_size[1] = 0x10000000; - s->mem_win_size[2] = 0x10000000; -} - -static void pci_vpb_realize(DeviceState *dev, Error **errp) -{ - PCIVPBState *s = PCI_VPB(dev); - SysBusDevice *sbd = SYS_BUS_DEVICE(dev); - pci_map_irq_fn mapfn; - int i; - - for (i = 0; i < 4; i++) { - sysbus_init_irq(sbd, &s->irq[i]); - } - - if (s->realview) { - mapfn = pci_vpb_rv_map_irq; - } else { - mapfn = pci_vpb_map_irq; - } - - pci_bus_irqs(&s->pci_bus, pci_vpb_set_irq, mapfn, s->irq, 4); - - /* Our memory regions are: - * 0 : our control registers - * 1 : PCI self config window - * 2 : PCI config window - * 3 : PCI IO window - * 4..6 : PCI memory windows - */ - memory_region_init_io(&s->controlregs, OBJECT(s), &pci_vpb_reg_ops, s, - "pci-vpb-regs", 0x1000); - sysbus_init_mmio(sbd, &s->controlregs); - memory_region_init_io(&s->mem_config, OBJECT(s), &pci_vpb_config_ops, s, - "pci-vpb-selfconfig", 0x1000000); - sysbus_init_mmio(sbd, &s->mem_config); - memory_region_init_io(&s->mem_config2, OBJECT(s), &pci_vpb_config_ops, s, - "pci-vpb-config", 0x1000000); - sysbus_init_mmio(sbd, &s->mem_config2); - - /* The window into I/O space is always into a fixed base address; - * its size is the same for both realview and versatile. - */ - memory_region_init_alias(&s->pci_io_window, OBJECT(s), "pci-vbp-io-window", - &s->pci_io_space, 0, 0x100000); - - sysbus_init_mmio(sbd, &s->pci_io_space); - - /* Create the alias regions corresponding to our three windows onto - * PCI memory space. The sizes vary from board to board; the base - * offsets are guest controllable via the IMAP registers. - */ - for (i = 0; i < 3; i++) { - memory_region_init_alias(&s->pci_mem_window[i], OBJECT(s), "pci-vbp-window", - &s->pci_mem_space, 0, s->mem_win_size[i]); - sysbus_init_mmio(sbd, &s->pci_mem_window[i]); - } - - /* TODO Remove once realize propagates to child devices. */ - object_property_set_bool(OBJECT(&s->pci_dev), true, "realized", errp); -} - -static void versatile_pci_host_realize(PCIDevice *d, Error **errp) -{ - pci_set_word(d->config + PCI_STATUS, - PCI_STATUS_66MHZ | PCI_STATUS_DEVSEL_MEDIUM); - pci_set_byte(d->config + PCI_LATENCY_TIMER, 0x10); -} - -static void versatile_pci_host_class_init(ObjectClass *klass, void *data) -{ - PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - DeviceClass *dc = DEVICE_CLASS(klass); - - k->realize = versatile_pci_host_realize; - k->vendor_id = PCI_VENDOR_ID_XILINX; - k->device_id = PCI_DEVICE_ID_XILINX_XC2VP30; - k->class_id = PCI_CLASS_PROCESSOR_CO; - /* - * PCI-facing part of the host bridge, not usable without the - * host-facing part, which can't be device_add'ed, yet. - */ - dc->cannot_instantiate_with_device_add_yet = true; -} - -static const TypeInfo versatile_pci_host_info = { - .name = TYPE_VERSATILE_PCI_HOST, - .parent = TYPE_PCI_DEVICE, - .instance_size = sizeof(PCIDevice), - .class_init = versatile_pci_host_class_init, -}; - -static Property pci_vpb_properties[] = { - DEFINE_PROP_UINT8("broken-irq-mapping", PCIVPBState, irq_mapping_prop, - PCI_VPB_IRQMAP_ASSUME_OK), - DEFINE_PROP_END_OF_LIST() -}; - -static void pci_vpb_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - - dc->realize = pci_vpb_realize; - dc->reset = pci_vpb_reset; - dc->vmsd = &pci_vpb_vmstate; - dc->props = pci_vpb_properties; - /* Reason: object_unref() hangs */ - dc->cannot_destroy_with_object_finalize_yet = true; -} - -static const TypeInfo pci_vpb_info = { - .name = TYPE_VERSATILE_PCI, - .parent = TYPE_PCI_HOST_BRIDGE, - .instance_size = sizeof(PCIVPBState), - .instance_init = pci_vpb_init, - .class_init = pci_vpb_class_init, -}; - -static void pci_realview_init(Object *obj) -{ - PCIVPBState *s = PCI_VPB(obj); - - s->realview = 1; - /* The PCI window sizes are different on Realview boards */ - s->mem_win_size[0] = 0x01000000; - s->mem_win_size[1] = 0x04000000; - s->mem_win_size[2] = 0x08000000; -} - -static void pci_realview_class_init(ObjectClass *class, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(class); - - /* Reason: object_unref() hangs */ - dc->cannot_destroy_with_object_finalize_yet = true; -} - -static const TypeInfo pci_realview_info = { - .name = "realview_pci", - .parent = TYPE_VERSATILE_PCI, - .instance_init = pci_realview_init, - .class_init = pci_realview_class_init, -}; - -static void versatile_pci_register_types(void) -{ - type_register_static(&pci_vpb_info); - type_register_static(&pci_realview_info); - type_register_static(&versatile_pci_host_info); -} - -type_init(versatile_pci_register_types) -- cgit 1.2.3-korg