Impement Galilleo ISD register.
authorths <ths@c046a42c-6fe2-441c-8c8c-71466251a162>
Wed, 11 Jul 2007 16:44:32 +0000 (16:44 +0000)
committerths <ths@c046a42c-6fe2-441c-8c8c-71466251a162>
Wed, 11 Jul 2007 16:44:32 +0000 (16:44 +0000)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3061 c046a42c-6fe2-441c-8c8c-71466251a162

hw/gt64xxx.c
hw/mips_malta.c

index f75f8af210fdc34cf0035f234af94c9855daa662..d9f6296478f3766991d488d4ed2e03d7b575a4f9 100644 (file)
@@ -225,13 +225,63 @@ typedef target_phys_addr_t pci_addr_t;
 
 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 */
@@ -311,6 +361,11 @@ static void gt64120_writel (void *opaque, target_phys_addr_t addr,
         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:
@@ -1026,6 +1081,7 @@ void gt64120_reset(void *opaque)
 
     /* Interrupt registers are all zeroed at reset */
 
+    gt64120_isd_mapping(s);
     gt64120_pci_mapping(s);
 }
 
@@ -1070,27 +1126,21 @@ 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);
     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;
@@ -1113,6 +1163,8 @@ PCIBus *pci_gt64120_init(qemu_irq *pic)
     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;
index bc892ed8138329b2a4ad80021d1d0889e54eebfa..ed23052b91cea90f5893aa82e57bc54ca14b5b52 100644 (file)
@@ -538,6 +538,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