]> xenbits.xensource.com Git - qemu-xen-4.0-testing.git/commitdiff
More PCI mapping/remapping for Gallileo.
authorths <ths@c046a42c-6fe2-441c-8c8c-71466251a162>
Sun, 10 Jun 2007 15:08:43 +0000 (15:08 +0000)
committerths <ths@c046a42c-6fe2-441c-8c8c-71466251a162>
Sun, 10 Jun 2007 15:08:43 +0000 (15:08 +0000)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2972 c046a42c-6fe2-441c-8c8c-71466251a162

hw/gt64xxx.c
hw/mips_malta.c

index f75f8af210fdc34cf0035f234af94c9855daa662..818e913513c963dbefeffeec3da99c4ac58cecc5 100644 (file)
@@ -222,34 +222,217 @@ typedef target_phys_addr_t pci_addr_t;
 #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)          \
+    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];
-    target_phys_addr_t PCI0IO_start;
-    target_phys_addr_t PCI0IO_length;
+    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;
 
-static void gt64120_pci_mapping(GT64120State *s)
+/* 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)
 {
-    /* 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);
-    }
+    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;
+}
+
+/* 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)
+{
+    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;
+    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)
+{
+    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;
+}
+
+static CPUWriteMemoryFunc *gt64120_mmio_write[] = {
+    &gt64120_mmio_writeb,
+    &gt64120_mmio_writew,
+    &gt64120_mmio_writel,
+};
+
+static CPUReadMemoryFunc *gt64120_mmio_read[] = {
+    &gt64120_mmio_readb,
+    &gt64120_mmio_readw,
+    &gt64120_mmio_readl,
+};
+
 static void gt64120_writel (void *opaque, target_phys_addr_t addr,
                             uint32_t val)
 {
@@ -272,53 +455,142 @@ static void gt64120_writel (void *opaque, target_phys_addr_t addr,
         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_pci_mapping(s);
+        gt64120_PCI0IO_mapping(s);
         break;
     case GT_PCI0M0LD:
         s->regs[GT_PCI0M0LD]    = val & 0x00007fff;
         s->regs[GT_PCI0M0REMAP] = val & 0x000007ff;
-        gt64120_pci_mapping(s);
+        gt64120_PCI0M0_mapping(s);
         break;
     case GT_PCI0M1LD:
         s->regs[GT_PCI0M1LD]    = val & 0x00007fff;
         s->regs[GT_PCI0M1REMAP] = val & 0x000007ff;
-        gt64120_pci_mapping(s);
+        gt64120_PCI0M1_mapping(s);
         break;
     case GT_PCI1IOLD:
         s->regs[GT_PCI1IOLD]    = val & 0x00007fff;
         s->regs[GT_PCI1IOREMAP] = val & 0x000007ff;
-        gt64120_pci_mapping(s);
+        gt64120_PCI1IO_mapping(s);
         break;
     case GT_PCI1M0LD:
         s->regs[GT_PCI1M0LD]    = val & 0x00007fff;
         s->regs[GT_PCI1M0REMAP] = val & 0x000007ff;
-        gt64120_pci_mapping(s);
+        gt64120_PCI1M1_mapping(s);
         break;
     case GT_PCI1M1LD:
         s->regs[GT_PCI1M1LD]    = val & 0x00007fff;
         s->regs[GT_PCI1M1REMAP] = val & 0x000007ff;
-        gt64120_pci_mapping(s);
+        gt64120_PCI1M1_mapping(s);
         break;
     case GT_PCI0IOHD:
+        s->regs[saddr] = val & 0x0000007f;
+        gt64120_PCI0IO_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_pci_mapping(s);
+        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_pci_mapping(s);
+        gt64120_PCI1M1REMAP_mapping(s);
         break;
 
     /* CPU Error Report */
@@ -1026,7 +1298,17 @@ void gt64120_reset(void *opaque)
 
     /* Interrupt registers are all zeroed at reset */
 
-    gt64120_pci_mapping(s);
+    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);
 }
 
 static uint32_t gt64120_read_config(PCIDevice *d, uint32_t address, int len)
@@ -1070,18 +1352,16 @@ PCIBus *pci_gt64120_init(qemu_irq *pic)
 {
     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);
+    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);
index 36b5f43e6ddc82de10d0da80957b37f23c90dac0..aa00d382b8af49544e12f330357695784d550fd3 100644 (file)
@@ -543,6 +543,15 @@ static void write_bootloader (CPUState *env, unsigned long bios_offset, int64_t
     stl_raw(p++, 0x34e70000 | (env->ram_size & 0xffff));           /* ori a3, a3, low(env->ram_size) */
 
     /* Load BAR registers as done by YAMON */
+    stl_raw(p++, 0x3c09b400);                                      /* lui t1, 0xb400 */
+
+#ifdef TARGET_WORDS_BIGENDIAN
+    stl_raw(p++, 0x3c08df00);                                      /* lui t0, 0xdf00 */
+#else
+    stl_raw(p++, 0x340800df);                                      /* ori t0, r0, 0x00df */
+#endif
+    stl_raw(p++, 0xad280068);                                      /* sw t0, 0x0068(t1) */
+
     stl_raw(p++, 0x3c09bbe0);                                      /* lui t1, 0xbbe0 */
 
 #ifdef TARGET_WORDS_BIGENDIAN