#include "qemu/osdep.h"
#include "qemu/units.h"
-#include "qemu/error-report.h"
#include "qapi/error.h"
#include "qemu/log.h"
-#include "qemu/module.h"
-#include "cpu.h"
#include "hw/irq.h"
-#include "exec/address-spaces.h"
-#include "exec/memory.h"
-#include "hw/ppc/ppc.h"
+#include "hw/ppc/ppc4xx.h"
#include "hw/qdev-properties.h"
#include "hw/pci/pci.h"
-#include "sysemu/block-backend.h"
#include "sysemu/reset.h"
+#include "cpu.h"
#include "ppc440.h"
-#include "qom/object.h"
/*****************************************************************************/
/* L2 Cache as SRAM */
PESDR1_RSTSTA = 0x365,
};
-#define SDR0_DDR0_DDRM_ENCODE(n) ((((unsigned long)(n)) & 0x03) << 29)
-#define SDR0_DDR0_DDRM_DDR1 0x20000000
-#define SDR0_DDR0_DDRM_DDR2 0x40000000
-
static uint32_t dcr_read_sdr(void *opaque, int dcrn)
{
ppc4xx_sdr_t *sdr = opaque;
sdr, &dcr_read_sdr, &dcr_write_sdr);
}
-/*****************************************************************************/
-/* SDRAM controller */
-typedef struct ppc440_sdram_t {
- uint32_t addr;
- int nbanks;
- MemoryRegion containers[4]; /* used for clipping */
- MemoryRegion *ram_memories;
- hwaddr ram_bases[4];
- hwaddr ram_sizes[4];
- uint32_t bcr[4];
-} ppc440_sdram_t;
-
-enum {
- SDRAM0_CFGADDR = 0x10,
- SDRAM0_CFGDATA,
- SDRAM_R0BAS = 0x40,
- SDRAM_R1BAS,
- SDRAM_R2BAS,
- SDRAM_R3BAS,
- SDRAM_CONF1HB = 0x45,
- SDRAM_PLBADDULL = 0x4a,
- SDRAM_CONF1LL = 0x4b,
- SDRAM_CONFPATHB = 0x4f,
- SDRAM_PLBADDUHB = 0x50,
-};
-
-static uint32_t sdram_bcr(hwaddr ram_base, hwaddr ram_size)
-{
- uint32_t bcr;
-
- switch (ram_size) {
- case (8 * MiB):
- bcr = 0xffc0;
- break;
- case (16 * MiB):
- bcr = 0xff80;
- break;
- case (32 * MiB):
- bcr = 0xff00;
- break;
- case (64 * MiB):
- bcr = 0xfe00;
- break;
- case (128 * MiB):
- bcr = 0xfc00;
- break;
- case (256 * MiB):
- bcr = 0xf800;
- break;
- case (512 * MiB):
- bcr = 0xf000;
- break;
- case (1 * GiB):
- bcr = 0xe000;
- break;
- case (2 * GiB):
- bcr = 0xc000;
- break;
- case (4 * GiB):
- bcr = 0x8000;
- break;
- default:
- error_report("invalid RAM size " TARGET_FMT_plx, ram_size);
- return 0;
- }
- bcr |= ram_base >> 2 & 0xffe00000;
- bcr |= 1;
-
- return bcr;
-}
-
-static inline hwaddr sdram_base(uint32_t bcr)
-{
- return (bcr & 0xffe00000) << 2;
-}
-
-static uint64_t sdram_size(uint32_t bcr)
-{
- uint64_t size;
- int sh;
-
- sh = 1024 - ((bcr >> 6) & 0x3ff);
- size = 8 * MiB * sh;
-
- return size;
-}
-
-static void sdram_set_bcr(ppc440_sdram_t *sdram, int i,
- uint32_t bcr, int enabled)
-{
- if (sdram->bcr[i] & 1) {
- /* First unmap RAM if enabled */
- memory_region_del_subregion(get_system_memory(),
- &sdram->containers[i]);
- memory_region_del_subregion(&sdram->containers[i],
- &sdram->ram_memories[i]);
- object_unparent(OBJECT(&sdram->containers[i]));
- }
- sdram->bcr[i] = bcr & 0xffe0ffc1;
- if (enabled && (bcr & 1)) {
- memory_region_init(&sdram->containers[i], NULL, "sdram-containers",
- sdram_size(bcr));
- memory_region_add_subregion(&sdram->containers[i], 0,
- &sdram->ram_memories[i]);
- memory_region_add_subregion(get_system_memory(),
- sdram_base(bcr),
- &sdram->containers[i]);
- }
-}
-
-static void sdram_map_bcr(ppc440_sdram_t *sdram)
-{
- int i;
-
- for (i = 0; i < sdram->nbanks; i++) {
- if (sdram->ram_sizes[i] != 0) {
- sdram_set_bcr(sdram, i, sdram_bcr(sdram->ram_bases[i],
- sdram->ram_sizes[i]), 1);
- } else {
- sdram_set_bcr(sdram, i, 0, 0);
- }
- }
-}
-
-static uint32_t dcr_read_sdram(void *opaque, int dcrn)
-{
- ppc440_sdram_t *sdram = opaque;
- uint32_t ret = 0;
-
- switch (dcrn) {
- case SDRAM_R0BAS:
- case SDRAM_R1BAS:
- case SDRAM_R2BAS:
- case SDRAM_R3BAS:
- if (sdram->ram_sizes[dcrn - SDRAM_R0BAS]) {
- ret = sdram_bcr(sdram->ram_bases[dcrn - SDRAM_R0BAS],
- sdram->ram_sizes[dcrn - SDRAM_R0BAS]);
- }
- break;
- case SDRAM_CONF1HB:
- case SDRAM_CONF1LL:
- case SDRAM_CONFPATHB:
- case SDRAM_PLBADDULL:
- case SDRAM_PLBADDUHB:
- break;
- case SDRAM0_CFGADDR:
- ret = sdram->addr;
- break;
- case SDRAM0_CFGDATA:
- switch (sdram->addr) {
- case 0x14: /* SDRAM_MCSTAT (405EX) */
- case 0x1F:
- ret = 0x80000000;
- break;
- case 0x21: /* SDRAM_MCOPT2 */
- ret = 0x08000000;
- break;
- case 0x40: /* SDRAM_MB0CF */
- ret = 0x00008001;
- break;
- case 0x7A: /* SDRAM_DLCR */
- ret = 0x02000000;
- break;
- case 0xE1: /* SDR0_DDR0 */
- ret = SDR0_DDR0_DDRM_ENCODE(1) | SDR0_DDR0_DDRM_DDR1;
- break;
- default:
- break;
- }
- break;
- default:
- break;
- }
-
- return ret;
-}
-
-static void dcr_write_sdram(void *opaque, int dcrn, uint32_t val)
-{
- ppc440_sdram_t *sdram = opaque;
-
- switch (dcrn) {
- case SDRAM_R0BAS:
- case SDRAM_R1BAS:
- case SDRAM_R2BAS:
- case SDRAM_R3BAS:
- case SDRAM_CONF1HB:
- case SDRAM_CONF1LL:
- case SDRAM_CONFPATHB:
- case SDRAM_PLBADDULL:
- case SDRAM_PLBADDUHB:
- break;
- case SDRAM0_CFGADDR:
- sdram->addr = val;
- break;
- case SDRAM0_CFGDATA:
- switch (sdram->addr) {
- case 0x00: /* B0CR */
- break;
- default:
- break;
- }
- break;
- default:
- break;
- }
-}
-
-static void sdram_reset(void *opaque)
-{
- ppc440_sdram_t *sdram = opaque;
-
- sdram->addr = 0;
-}
-
-void ppc440_sdram_init(CPUPPCState *env, int nbanks,
- MemoryRegion *ram_memories,
- hwaddr *ram_bases, hwaddr *ram_sizes,
- int do_init)
-{
- ppc440_sdram_t *sdram;
-
- sdram = g_malloc0(sizeof(*sdram));
- sdram->nbanks = nbanks;
- sdram->ram_memories = ram_memories;
- memcpy(sdram->ram_bases, ram_bases, nbanks * sizeof(hwaddr));
- memcpy(sdram->ram_sizes, ram_sizes, nbanks * sizeof(hwaddr));
- qemu_register_reset(&sdram_reset, sdram);
- ppc_dcr_register(env, SDRAM0_CFGADDR,
- sdram, &dcr_read_sdram, &dcr_write_sdram);
- ppc_dcr_register(env, SDRAM0_CFGDATA,
- sdram, &dcr_read_sdram, &dcr_write_sdram);
- if (do_init) {
- sdram_map_bcr(sdram);
- }
-
- ppc_dcr_register(env, SDRAM_R0BAS,
- sdram, &dcr_read_sdram, &dcr_write_sdram);
- ppc_dcr_register(env, SDRAM_R1BAS,
- sdram, &dcr_read_sdram, &dcr_write_sdram);
- ppc_dcr_register(env, SDRAM_R2BAS,
- sdram, &dcr_read_sdram, &dcr_write_sdram);
- ppc_dcr_register(env, SDRAM_R3BAS,
- sdram, &dcr_read_sdram, &dcr_write_sdram);
- ppc_dcr_register(env, SDRAM_CONF1HB,
- sdram, &dcr_read_sdram, &dcr_write_sdram);
- ppc_dcr_register(env, SDRAM_PLBADDULL,
- sdram, &dcr_read_sdram, &dcr_write_sdram);
- ppc_dcr_register(env, SDRAM_CONF1LL,
- sdram, &dcr_read_sdram, &dcr_write_sdram);
- ppc_dcr_register(env, SDRAM_CONFPATHB,
- sdram, &dcr_read_sdram, &dcr_write_sdram);
- ppc_dcr_register(env, SDRAM_PLBADDUHB,
- sdram, &dcr_read_sdram, &dcr_write_sdram);
-}
-
/*****************************************************************************/
/* PLB to AHB bridge */
enum {
int width, i, sidx, didx;
uint8_t *rptr, *wptr;
hwaddr rlen, wlen;
+ hwaddr xferlen;
sidx = didx = 0;
width = 1 << ((val & DMA0_CR_PW) >> 25);
+ xferlen = count * width;
+ wlen = rlen = xferlen;
rptr = cpu_physical_memory_map(dma->ch[chnl].sa, &rlen,
false);
wptr = cpu_physical_memory_map(dma->ch[chnl].da, &wlen,
true);
- if (rptr && wptr) {
+ if (rptr && rlen == xferlen && wptr && wlen == xferlen) {
if (!(val & DMA0_CR_DEC) &&
val & DMA0_CR_SAI && val & DMA0_CR_DAI) {
/* optimise common case */
/*****************************************************************************/
/* PCI Express controller */
-/* FIXME: This is not complete and does not work, only implemented partially
+/*
+ * FIXME: This is not complete and does not work, only implemented partially
* to allow firmware and guests to find an empty bus. Cards should use PCI.
*/
#include "hw/pci/pcie_host.h"
case PEGPL_CFGMSK:
s->cfg_mask = val;
size = ~(val & 0xfffffffe) + 1;
+ /*
+ * Firmware sets this register to E0000001. Why we are not sure,
+ * but the current guess is anything above PCIE_MMCFG_SIZE_MAX is
+ * ignored.
+ */
+ if (size > PCIE_MMCFG_SIZE_MAX) {
+ size = PCIE_MMCFG_SIZE_MAX;
+ }
pcie_host_mmcfg_update(PCIE_HOST_BRIDGE(s), val & 1, s->cfg_base, size);
break;
case PEGPL_MSGBAH:
&dcr_read_pcie, &dcr_write_pcie);
}
-void ppc460ex_pcie_init(CPUPPCState *env)
+void ppc460ex_pcie_init(PowerPCCPU *cpu)
{
DeviceState *dev;
dev = qdev_new(TYPE_PPC460EX_PCIE_HOST);
qdev_prop_set_int32(dev, "dcrn-base", DCRN_PCIE0_BASE);
sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
- ppc460ex_pcie_register_dcrs(PPC460EX_PCIE_HOST(dev), env);
+ ppc460ex_pcie_register_dcrs(PPC460EX_PCIE_HOST(dev), &cpu->env);
dev = qdev_new(TYPE_PPC460EX_PCIE_HOST);
qdev_prop_set_int32(dev, "dcrn-base", DCRN_PCIE1_BASE);
sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
- ppc460ex_pcie_register_dcrs(PPC460EX_PCIE_HOST(dev), env);
+ ppc460ex_pcie_register_dcrs(PPC460EX_PCIE_HOST(dev), &cpu->env);
}