* 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
typedef PCIHostState GT64120PCIState;
+#define PCI_MAPPING_ENTRY(regname) \
+ target_phys_addr_t regname ##_start; \
+ target_phys_addr_t regname ##_length; \
+ int regname ##_handle
+
typedef struct GT64120State {
GT64120PCIState *pci;
uint32_t regs[GT_REGS];
- target_phys_addr_t PCI0IO_start;
- target_phys_addr_t PCI0IO_length;
+ PCI_MAPPING_ENTRY(PCI0IO);
+ PCI_MAPPING_ENTRY(ISD);
} GT64120State;
+/* Adjust range to avoid touching space which isn't mappable via PCI */
+/* XXX: Hardcoded values for Malta: 0x1e000000 - 0x1f100000
+ 0x1fc00000 - 0x1fd00000 */
+static void check_reserved_space (target_phys_addr_t *start,
+ target_phys_addr_t *length)
+{
+ target_phys_addr_t begin = *start;
+ target_phys_addr_t end = *start + *length;
+
+ if (end >= 0x1e000000LL && end < 0x1f100000LL)
+ end = 0x1e000000LL;
+ if (begin >= 0x1e000000LL && begin < 0x1f100000LL)
+ begin = 0x1f100000LL;
+ if (end >= 0x1fc00000LL && end < 0x1fd00000LL)
+ end = 0x1fc00000LL;
+ if (begin >= 0x1fc00000LL && begin < 0x1fd00000LL)
+ begin = 0x1fd00000LL;
+ /* XXX: This is broken when a reserved range splits the requested range */
+ if (end >= 0x1f100000LL && begin < 0x1e000000LL)
+ end = 0x1e000000LL;
+ if (end >= 0x1fd00000LL && begin < 0x1fc00000LL)
+ end = 0x1fc00000LL;
+
+ *start = begin;
+ *length = end - begin;
+}
+
+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);
+ 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_pci_mapping(GT64120State *s)
{
/* Update IO mapping */
if ((s->regs[GT_PCI0IOLD] & 0x7f) <= s->regs[GT_PCI0IOHD])
{
- /* Unmap old IO address */
+ /* Unmap old IO address */
if (s->PCI0IO_length)
{
- cpu_register_physical_memory(s->PCI0IO_start, s->PCI0IO_length, IO_MEM_UNASSIGNED);
+ 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;
GT64120State *s = opaque;
uint32_t saddr;
-#ifdef TARGET_WORDS_BIGENDIAN
- val = bswap32(val);
-#endif
+ if (!(s->regs[GT_PCI0_CMD] & 1))
+ val = bswap32(val);
saddr = (addr & 0xfff) >> 2;
switch (saddr) {
case GT_PCI0M0LD:
s->regs[GT_PCI0M0LD] = val & 0x00007fff;
s->regs[GT_PCI0M0REMAP] = val & 0x000007ff;
- gt64120_pci_mapping(s);
break;
case GT_PCI0M1LD:
s->regs[GT_PCI0M1LD] = val & 0x00007fff;
s->regs[GT_PCI0M1REMAP] = val & 0x000007ff;
- gt64120_pci_mapping(s);
break;
case GT_PCI1IOLD:
s->regs[GT_PCI1IOLD] = val & 0x00007fff;
s->regs[GT_PCI1IOREMAP] = val & 0x000007ff;
- gt64120_pci_mapping(s);
break;
case GT_PCI1M0LD:
s->regs[GT_PCI1M0LD] = val & 0x00007fff;
s->regs[GT_PCI1M0REMAP] = val & 0x000007ff;
- gt64120_pci_mapping(s);
break;
case GT_PCI1M1LD:
s->regs[GT_PCI1M1LD] = val & 0x00007fff;
s->regs[GT_PCI1M1REMAP] = val & 0x000007ff;
- gt64120_pci_mapping(s);
break;
case GT_PCI0IOHD:
+ s->regs[saddr] = val & 0x0000007f;
+ gt64120_pci_mapping(s);
+ break;
case GT_PCI0M0HD:
case GT_PCI0M1HD:
case GT_PCI1IOHD:
case GT_PCI1M0HD:
case GT_PCI1M1HD:
s->regs[saddr] = val & 0x0000007f;
- gt64120_pci_mapping(s);
break;
+ case GT_ISD:
+ s->regs[saddr] = val & 0x00007fff;
+ gt64120_isd_mapping(s);
+ break;
+
case GT_PCI0IOREMAP:
case GT_PCI0M0REMAP:
case GT_PCI0M1REMAP:
case GT_PCI1M0REMAP:
case GT_PCI1M1REMAP:
s->regs[saddr] = val & 0x000007ff;
- gt64120_pci_mapping(s);
break;
/* CPU Error Report */
s->pci->config_reg = val & 0x80fffffc;
break;
case GT_PCI0_CFGDATA:
- if (s->pci->config_reg & (1u << 31))
- pci_host_data_writel(s->pci, 0, val);
+ pci_host_data_writel(s->pci, 0, val);
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)))
- val = 0xffffffff;
- else
- val = pci_data_read(s->pci->bus, s->pci->config_reg, 4);
+ val = pci_host_data_readl(s->pci, 0);
break;
case GT_PCI0_CMD:
break;
}
-#ifdef TARGET_WORDS_BIGENDIAN
- val = bswap32(val);
-#endif
+ if (!(s->regs[GT_PCI0_CMD] & 1))
+ val = bswap32(val);
+
return val;
}
/* Interrupt registers are all zeroed at reset */
+ gt64120_isd_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;
- int gt64120;
s = qemu_mallocz(sizeof(GT64120State));
s->pci = qemu_mallocz(sizeof(GT64120PCIState));
- gt64120_reset(s);
s->pci->bus = pci_register_bus(pci_gt64120_set_irq, pci_gt64120_map_irq,
pic, 144, 4);
-
- gt64120 = cpu_register_io_memory(0, gt64120_read,
- gt64120_write, s);
- cpu_register_physical_memory(0x1be00000LL, 0x1000, gt64120);
-
+ s->ISD_handle = cpu_register_io_memory(0, gt64120_read, gt64120_write, 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[0x00] = 0xab; /* vendor_id */
d->config[0x01] = 0x11;
- d->config[0x02] = 0x20; // device_id
+ d->config[0x02] = 0x20; /* device_id */
d->config[0x03] = 0x46;
d->config[0x04] = 0x00;
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;