* QEMU GT64120 PCI host
*
* Copyright (c) 2006,2007 Aurelien Jarno
- *
+ *
* 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
* THE SOFTWARE.
*/
-#include "vl.h"
+#include "hw.h"
+#include "mips.h"
+#include "pci.h"
+#include "pc.h"
typedef target_phys_addr_t pci_addr_t;
#include "pci_host.h"
#define GT_PCI0_HICMASK (0xca4 >> 2)
#define GT_PCI1_SERR1MASK (0xca8 >> 2)
-#define PCI_MAPPING_ENTRY(regname) \
- target_phys_addr_t regname ##_start; \
- target_phys_addr_t regname ##_length; \
- int regname ##_handle
-#define PCI_REMAPPING_ENTRY(regname) \
+typedef PCIHostState GT64120PCIState;
+
+#define PCI_MAPPING_ENTRY(regname) \
target_phys_addr_t regname ##_start; \
target_phys_addr_t regname ##_length; \
- target_phys_addr_t regname ##_offset; \
int regname ##_handle
-typedef PCIHostState GT64120PCIState;
-
typedef struct GT64120State {
GT64120PCIState *pci;
uint32_t regs[GT_REGS];
- PCI_MAPPING_ENTRY(SCS10);
- PCI_REMAPPING_ENTRY(SCS10AR);
- PCI_MAPPING_ENTRY(SCS32);
- PCI_REMAPPING_ENTRY(SCS32AR);
- PCI_MAPPING_ENTRY(CS20);
- PCI_REMAPPING_ENTRY(CS20R);
- PCI_MAPPING_ENTRY(CS3BOOT);
- PCI_REMAPPING_ENTRY(CS3BOOTR);
PCI_MAPPING_ENTRY(PCI0IO);
- PCI_REMAPPING_ENTRY(PCI0IOREMAP);
- PCI_MAPPING_ENTRY(PCI0M0);
- PCI_REMAPPING_ENTRY(PCI0M0REMAP);
- PCI_MAPPING_ENTRY(PCI0M1);
- PCI_REMAPPING_ENTRY(PCI0M1REMAP);
- PCI_MAPPING_ENTRY(PCI1IO);
- PCI_REMAPPING_ENTRY(PCI1IOREMAP);
- PCI_MAPPING_ENTRY(PCI1M0);
- PCI_REMAPPING_ENTRY(PCI1M0REMAP);
- PCI_MAPPING_ENTRY(PCI1M1);
- PCI_REMAPPING_ENTRY(PCI1M1REMAP);
PCI_MAPPING_ENTRY(ISD);
} GT64120State;
*length = end - begin;
}
-/* XXX: cpu_register_physical_memory isn't really suited for dynamic mappings
- since it doesn't layer several mappings over the same address range.
- This should keep track of mappings as set of 2 MB pages / 20 mappings. */
-
-#define BUILD_UPDATE_PCI_MAPPING(reg, remap) \
-static void gt64120_## reg ##_mapping(GT64120State *s) \
-{ \
- target_phys_addr_t start = s->regs[GT_## reg ##LD] << 21; \
- target_phys_addr_t length = ((s->regs[GT_## reg ##HD] + 1) - \
- (s->regs[GT_## reg ##LD] & 0x7f)) << 21; \
- \
- /* Unmap old address */ \
- if (s->remap ##_length) \
- cpu_register_physical_memory(s->remap ##_start, \
- s->remap ##_length, \
- IO_MEM_UNASSIGNED); \
- s->remap ##_length = 0; \
- if (s->reg ##_length) \
- cpu_register_physical_memory(s->reg ##_start, \
- s->reg ##_length, \
- IO_MEM_UNASSIGNED); \
- \
- if ((s->regs[GT_## reg ##LD] & 0x7f) <= s->regs[GT_## reg ##HD]) \
- { \
- check_reserved_space(&start, &length); \
- /* Map new address */ \
-dprintf("PCI " # reg ": %x@%x -> %x@%x, %x\n", s->reg ##_length, s->reg ##_start, length, start, s->reg ##_handle); \
- s->reg ##_start = start; \
- s->reg ##_length = length; \
- cpu_register_physical_memory(s->reg ##_start, \
- s->reg ##_length, \
- s->reg ##_handle); \
- } else \
-dprintf("PCI " # reg ": %x@%x disabled, %x\n", s->reg ##_length, s->reg ##_start, s->reg ##_handle); \
-} \
- \
-static void gt64120_## remap ##_mapping(GT64120State *s) \
-{ \
- /* XXX: range calculation is broken */ \
- target_phys_addr_t start = (s->reg ## _start & ~(0x7ff << 21)) | \
- (s->regs[GT_## remap] << 21); \
- target_phys_addr_t length = s->reg ##_length; \
- \
- if (s->remap ##_length) \
- cpu_register_physical_memory(s->remap ##_start, \
- s->remap ##_length, \
- IO_MEM_UNASSIGNED); \
- check_reserved_space(&start, &length); \
- s->remap ##_start = start; \
- s->remap ##_length = length; \
- s->remap ##_offset = s->reg ##_start - start; \
-dprintf("PCI " # remap ": %x@%x +> %x@%x, %x\n", s->reg ##_length, s->reg ##_start, length, start, s->remap ##_handle); \
- cpu_register_physical_memory(s->remap ##_start, \
- s->remap ##_length, \
- s->remap ##_handle); \
-}
-
-BUILD_UPDATE_PCI_MAPPING(SCS10, SCS10AR)
-BUILD_UPDATE_PCI_MAPPING(SCS32, SCS32AR)
-BUILD_UPDATE_PCI_MAPPING(CS20, CS20R)
-BUILD_UPDATE_PCI_MAPPING(CS3BOOT, CS3BOOTR)
-BUILD_UPDATE_PCI_MAPPING(PCI0IO, PCI0IOREMAP)
-BUILD_UPDATE_PCI_MAPPING(PCI0M0, PCI0M0REMAP)
-BUILD_UPDATE_PCI_MAPPING(PCI0M1, PCI0M1REMAP)
-BUILD_UPDATE_PCI_MAPPING(PCI1IO, PCI1IOREMAP)
-BUILD_UPDATE_PCI_MAPPING(PCI1M0, PCI1M0REMAP)
-BUILD_UPDATE_PCI_MAPPING(PCI1M1, PCI1M1REMAP)
-
static void gt64120_isd_mapping(GT64120State *s)
{
+ target_phys_addr_t start = s->regs[GT_ISD] << 21;
+ target_phys_addr_t length = 0x1000;
+
if (s->ISD_length)
cpu_register_physical_memory(s->ISD_start, s->ISD_length,
IO_MEM_UNASSIGNED);
-dprintf("PCI ISD: %x@%x -> %x@%x, %x\n", s->ISD_length, s->ISD_start, 0x1000, s->regs[GT_ISD] << 21, s->ISD_handle);
- s->ISD_start = s->regs[GT_ISD] << 21;
- s->ISD_length = 0x1000;
+ check_reserved_space(&start, &length);
+ length = 0x1000;
+ /* Map new address */
+ dprintf("ISD: %x@%x -> %x@%x, %x\n", s->ISD_length, s->ISD_start,
+ length, start, s->ISD_handle);
+ s->ISD_start = start;
+ s->ISD_length = length;
cpu_register_physical_memory(s->ISD_start, s->ISD_length, s->ISD_handle);
}
-static void gt64120_mmio_writeb (void *opaque, target_phys_addr_t addr,
- uint32_t val)
-{
- cpu_outb(NULL, addr & 0xffff, val);
-}
-
-static void gt64120_mmio_writew (void *opaque, target_phys_addr_t addr,
- uint32_t val)
-{
-#ifdef TARGET_WORDS_BIGENDIAN
- val = bswap16(val);
-#endif
- cpu_outw(NULL, addr & 0xffff, val);
-}
-
-static void gt64120_mmio_writel (void *opaque, target_phys_addr_t addr,
- uint32_t val)
-{
-#ifdef TARGET_WORDS_BIGENDIAN
- val = bswap32(val);
-#endif
- cpu_outl(NULL, addr & 0xffff, val);
-}
-
-static uint32_t gt64120_mmio_readb (void *opaque, target_phys_addr_t addr)
-{
- uint32_t val;
-
- val = cpu_inb(NULL, addr & 0xffff);
- return val;
-}
-
-static uint32_t gt64120_mmio_readw (void *opaque, target_phys_addr_t addr)
+static void gt64120_pci_mapping(GT64120State *s)
{
- uint32_t val;
-
- val = cpu_inw(NULL, addr & 0xffff);
-#ifdef TARGET_WORDS_BIGENDIAN
- val = bswap16(val);
-#endif
- return val;
-}
-
-static uint32_t gt64120_mmio_readl (void *opaque, target_phys_addr_t addr)
-{
- uint32_t val;
-
- val = cpu_inl(NULL, addr & 0xffff);
-#ifdef TARGET_WORDS_BIGENDIAN
- val = bswap32(val);
-#endif
- return val;
+ /* Update IO mapping */
+ if ((s->regs[GT_PCI0IOLD] & 0x7f) <= s->regs[GT_PCI0IOHD])
+ {
+ /* Unmap old IO address */
+ if (s->PCI0IO_length)
+ {
+ cpu_register_physical_memory(s->PCI0IO_start, s->PCI0IO_length, IO_MEM_UNASSIGNED);
+ }
+ /* Map new IO address */
+ s->PCI0IO_start = s->regs[GT_PCI0IOLD] << 21;
+ s->PCI0IO_length = ((s->regs[GT_PCI0IOHD] + 1) - (s->regs[GT_PCI0IOLD] & 0x7f)) << 21;
+ isa_mem_base = s->PCI0IO_start;
+ isa_mmio_init(s->PCI0IO_start, s->PCI0IO_length);
+ }
}
-static CPUWriteMemoryFunc *gt64120_mmio_write[] = {
- >64120_mmio_writeb,
- >64120_mmio_writew,
- >64120_mmio_writel,
-};
-
-static CPUReadMemoryFunc *gt64120_mmio_read[] = {
- >64120_mmio_readb,
- >64120_mmio_readw,
- >64120_mmio_readl,
-};
-
static void gt64120_writel (void *opaque, target_phys_addr_t addr,
uint32_t val)
{
GT64120State *s = opaque;
uint32_t saddr;
-#ifdef TARGET_WORDS_BIGENDIAN
- val = bswap32(val);
-#endif
+ if (!(s->regs[GT_CPU] & 0x00001000))
+ val = bswap32(val);
saddr = (addr & 0xfff) >> 2;
switch (saddr) {
break;
/* CPU Address Decode */
- case GT_SCS10LD:
- s->regs[GT_SCS10LD] = val & 0x00007fff;
- s->regs[GT_SCS10AR] = val & 0x000007ff;
- gt64120_SCS10_mapping(s);
- break;
- case GT_SCS32LD:
- s->regs[GT_SCS32LD] = val & 0x00007fff;
- s->regs[GT_SCS32AR] = val & 0x000007ff;
-//
-// gt64120_SCS32_mapping(s);
- break;
- case GT_CS20LD:
- s->regs[GT_CS20LD] = val & 0x00007fff;
- s->regs[GT_CS20R] = val & 0x000007ff;
- gt64120_CS20_mapping(s);
- break;
- case GT_CS3BOOTLD:
- s->regs[GT_CS3BOOTLD] = val & 0x00007fff;
- s->regs[GT_CS3BOOTR] = val & 0x000007ff;
- gt64120_CS3BOOT_mapping(s);
- break;
- case GT_SCS10HD:
- s->regs[saddr] = val & 0x0000007f;
- gt64120_SCS10_mapping(s);
- break;
- case GT_SCS32HD:
- s->regs[saddr] = val & 0x0000007f;
-//
-// gt64120_SCS32_mapping(s);
- break;
- case GT_CS20HD:
- s->regs[saddr] = val & 0x0000007f;
- gt64120_CS20_mapping(s);
- break;
- case GT_CS3BOOTHD:
- s->regs[saddr] = val & 0x0000007f;
- gt64120_CS3BOOT_mapping(s);
- break;
case GT_PCI0IOLD:
s->regs[GT_PCI0IOLD] = val & 0x00007fff;
s->regs[GT_PCI0IOREMAP] = val & 0x000007ff;
- gt64120_PCI0IO_mapping(s);
+ gt64120_pci_mapping(s);
break;
case GT_PCI0M0LD:
s->regs[GT_PCI0M0LD] = val & 0x00007fff;
s->regs[GT_PCI0M0REMAP] = val & 0x000007ff;
- gt64120_PCI0M0_mapping(s);
break;
case GT_PCI0M1LD:
s->regs[GT_PCI0M1LD] = val & 0x00007fff;
s->regs[GT_PCI0M1REMAP] = val & 0x000007ff;
- gt64120_PCI0M1_mapping(s);
break;
case GT_PCI1IOLD:
s->regs[GT_PCI1IOLD] = val & 0x00007fff;
s->regs[GT_PCI1IOREMAP] = val & 0x000007ff;
- gt64120_PCI1IO_mapping(s);
break;
case GT_PCI1M0LD:
s->regs[GT_PCI1M0LD] = val & 0x00007fff;
s->regs[GT_PCI1M0REMAP] = val & 0x000007ff;
- gt64120_PCI1M1_mapping(s);
break;
case GT_PCI1M1LD:
s->regs[GT_PCI1M1LD] = val & 0x00007fff;
s->regs[GT_PCI1M1REMAP] = val & 0x000007ff;
- gt64120_PCI1M1_mapping(s);
break;
case GT_PCI0IOHD:
s->regs[saddr] = val & 0x0000007f;
- gt64120_PCI0IO_mapping(s);
+ gt64120_pci_mapping(s);
break;
case GT_PCI0M0HD:
- s->regs[saddr] = val & 0x0000007f;
- gt64120_PCI0M0_mapping(s);
- break;
case GT_PCI0M1HD:
- s->regs[saddr] = val & 0x0000007f;
- gt64120_PCI0M1_mapping(s);
- break;
case GT_PCI1IOHD:
- s->regs[saddr] = val & 0x0000007f;
- gt64120_PCI1IO_mapping(s);
- break;
case GT_PCI1M0HD:
- s->regs[saddr] = val & 0x0000007f;
- gt64120_PCI1M0_mapping(s);
- break;
case GT_PCI1M1HD:
s->regs[saddr] = val & 0x0000007f;
- gt64120_PCI1M1_mapping(s);
break;
case GT_ISD:
s->regs[saddr] = val & 0x00007fff;
gt64120_isd_mapping(s);
break;
- case GT_SCS10AR:
- s->regs[saddr] = val & 0x000007ff;
- gt64120_SCS10AR_mapping(s);
- break;
- case GT_SCS32AR:
- s->regs[saddr] = val & 0x000007ff;
- gt64120_SCS32AR_mapping(s);
- break;
- case GT_CS20R:
- s->regs[saddr] = val & 0x000007ff;
- gt64120_CS20R_mapping(s);
- break;
- case GT_CS3BOOTR:
- s->regs[saddr] = val & 0x000007ff;
- gt64120_CS3BOOTR_mapping(s);
- break;
case GT_PCI0IOREMAP:
- s->regs[saddr] = val & 0x000007ff;
- gt64120_PCI0IOREMAP_mapping(s);
- break;
case GT_PCI0M0REMAP:
- s->regs[saddr] = val & 0x000007ff;
- gt64120_PCI0M0REMAP_mapping(s);
- break;
case GT_PCI0M1REMAP:
- s->regs[saddr] = val & 0x000007ff;
- gt64120_PCI0M1REMAP_mapping(s);
- break;
case GT_PCI1IOREMAP:
- s->regs[saddr] = val & 0x000007ff;
- gt64120_PCI1IOREMAP_mapping(s);
- break;
case GT_PCI1M0REMAP:
- s->regs[saddr] = val & 0x000007ff;
- gt64120_PCI1M0REMAP_mapping(s);
- break;
case GT_PCI1M1REMAP:
s->regs[saddr] = val & 0x000007ff;
- gt64120_PCI1M1REMAP_mapping(s);
break;
/* CPU Error Report */
s->pci->config_reg = val & 0x80fffffc;
break;
case GT_PCI0_CFGDATA:
+ if (!(s->regs[GT_PCI0_CMD] & 1) && (s->pci->config_reg & 0x00fff800))
+ val = bswap32(val);
if (s->pci->config_reg & (1u << 31))
- pci_host_data_writel(s->pci, 0, val);
+ pci_data_write(s->pci->bus, s->pci->config_reg, val, 4);
break;
/* Interrupts */
uint32_t val;
uint32_t saddr;
- val = 0;
saddr = (addr & 0xfff) >> 2;
-
switch (saddr) {
/* CPU Configuration */
case GT_CPUERR_DATAHI:
case GT_CPUERR_PARITY:
/* Emulated memory has no error, always return the initial
- values */
+ values */
val = s->regs[saddr];
break;
/* Reading those register should empty all FIFO on the PCI
bus, which are not emulated. The return value should be
a random value that should be ignored. */
- val = 0xc000ffee;
+ val = 0xc000ffee;
break;
/* ECC */
case GT_ECC_CALC:
case GT_ECC_ERRADDR:
/* Emulated memory has no error, always return the initial
- values */
+ values */
val = s->regs[saddr];
break;
val = s->regs[saddr];
break;
case GT_PCI0_IACK:
- /* Read the IRQ number */
+ /* Read the IRQ number */
val = pic_read_irq(isa_pic);
break;
val = s->pci->config_reg;
break;
case GT_PCI0_CFGDATA:
- if (!(s->pci->config_reg & (1u << 31)))
+ if (!(s->pci->config_reg & (1 << 31)))
val = 0xffffffff;
else
- val = pci_host_data_readl(s->pci, 0);
+ val = pci_data_read(s->pci->bus, s->pci->config_reg, 4);
+ if (!(s->regs[GT_PCI0_CMD] & 1) && (s->pci->config_reg & 0x00fff800))
+ val = bswap32(val);
break;
case GT_PCI0_CMD:
break;
}
-#ifdef TARGET_WORDS_BIGENDIAN
- val = bswap32(val);
-#endif
+ if (!(s->regs[GT_CPU] & 0x00001000))
+ val = bswap32(val);
+
return val;
}
}
}
-extern PCIDevice *piix4_dev;
static int pci_irq_levels[4];
static void pci_gt64120_set_irq(qemu_irq *pic, int irq_num, int level)
}
-void gt64120_reset(void *opaque)
+static void gt64120_reset(void *opaque)
{
GT64120State *s = opaque;
s->regs[GT_PCI1_CFGADDR] = 0x00000000;
s->regs[GT_PCI1_CFGDATA] = 0x00000000;
s->regs[GT_PCI0_CFGADDR] = 0x00000000;
- s->regs[GT_PCI0_CFGDATA] = 0x00000000;
/* Interrupt registers are all zeroed at reset */
gt64120_isd_mapping(s);
- gt64120_SCS10_mapping(s);
-// gt64120_SCS32_mapping(s);
- gt64120_CS20_mapping(s);
- gt64120_CS3BOOT_mapping(s);
- gt64120_PCI0IO_mapping(s);
- gt64120_PCI0M0_mapping(s);
- gt64120_PCI0M1_mapping(s);
- gt64120_PCI1IO_mapping(s);
- gt64120_PCI1M0_mapping(s);
- gt64120_PCI1M1_mapping(s);
+ gt64120_pci_mapping(s);
}
static uint32_t gt64120_read_config(PCIDevice *d, uint32_t address, int len)
{
- uint32_t val = pci_default_read_config(d, address, len);
-#ifdef TARGET_WORDS_BIGENDIAN
- val = bswap32(val);
-#endif
- return val;
+ return pci_default_read_config(d, address, len);
}
static void gt64120_write_config(PCIDevice *d, uint32_t address, uint32_t val,
int len)
{
-#ifdef TARGET_WORDS_BIGENDIAN
- val = bswap32(val);
-#endif
pci_default_write_config(d, address, val, len);
}
GT64120State *s;
PCIDevice *d;
+ (void)&pci_host_data_writeb; /* avoid warning */
+ (void)&pci_host_data_writew; /* avoid warning */
+ (void)&pci_host_data_writel; /* avoid warning */
+ (void)&pci_host_data_readb; /* avoid warning */
+ (void)&pci_host_data_readw; /* avoid warning */
+ (void)&pci_host_data_readl; /* avoid warning */
+
s = qemu_mallocz(sizeof(GT64120State));
s->pci = qemu_mallocz(sizeof(GT64120PCIState));
+
s->pci->bus = pci_register_bus(pci_gt64120_set_irq, pci_gt64120_map_irq,
pic, 144, 4);
-
s->ISD_handle = cpu_register_io_memory(0, gt64120_read, gt64120_write, s);
- s->PCI0IO_handle = cpu_register_io_memory(0, gt64120_mmio_read,
- gt64120_mmio_write, s);
- gt64120_reset(s);
-
d = pci_register_device(s->pci->bus, "GT64120 PCI Bus", sizeof(PCIDevice),
0, gt64120_read_config, gt64120_write_config);
/* FIXME: Malta specific hw assumptions ahead */
- d->config[0x00] = 0xab; // vendor_id
- d->config[0x01] = 0x11;
- d->config[0x02] = 0x20; // device_id
- d->config[0x03] = 0x46;
+ pci_config_set_vendor_id(d->config, PCI_VENDOR_ID_MARVELL);
+ pci_config_set_device_id(d->config, PCI_DEVICE_ID_MARVELL_GT6412X);
d->config[0x04] = 0x00;
d->config[0x05] = 0x00;
d->config[0x08] = 0x10;
d->config[0x09] = 0x00;
- d->config[0x0A] = 0x00;
- d->config[0x0B] = 0x06;
+ pci_config_set_class(d->config, PCI_CLASS_BRIDGE_HOST);
d->config[0x10] = 0x08;
d->config[0x14] = 0x08;
d->config[0x27] = 0x14;
d->config[0x3D] = 0x01;
+ gt64120_reset(s);
+
register_savevm("GT64120 PCI Bus", 0, 1, gt64120_save, gt64120_load, d);
return s->pci->bus;