Add PowerPC power-management state check callback.
[qemu] / hw / gt64xxx.c
index 818e913..fdb70b3 100644 (file)
@@ -2,7 +2,7 @@
  * 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
@@ -222,42 +222,18 @@ 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)          \
+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;
 
@@ -288,160 +264,50 @@ static void check_reserved_space (target_phys_addr_t *start,
     *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)
+static void gt64120_pci_mapping(GT64120State *s)
 {
-#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;
+    /* 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[] = {
-    &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)
 {
     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) {
@@ -455,142 +321,54 @@ 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_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 */
@@ -749,8 +527,7 @@ static void gt64120_writel (void *opaque, target_phys_addr_t addr,
         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 */
@@ -806,9 +583,7 @@ static uint32_t gt64120_readl (void *opaque,
     uint32_t val;
     uint32_t saddr;
 
-    val = 0;
     saddr = (addr & 0xfff) >> 2;
-
     switch (saddr) {
 
     /* CPU Configuration */
@@ -825,7 +600,7 @@ static uint32_t gt64120_readl (void *opaque,
     case GT_CPUERR_DATAHI:
     case GT_CPUERR_PARITY:
         /* Emulated memory has no error, always return the initial
-           values */ 
+           values */
         val = s->regs[saddr];
         break;
 
@@ -835,7 +610,7 @@ static uint32_t gt64120_readl (void *opaque,
         /* 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 */
@@ -845,7 +620,7 @@ static uint32_t gt64120_readl (void *opaque,
     case GT_ECC_CALC:
     case GT_ECC_ERRADDR:
         /* Emulated memory has no error, always return the initial
-           values */ 
+           values */
         val = s->regs[saddr];
         break;
 
@@ -884,7 +659,7 @@ static uint32_t gt64120_readl (void *opaque,
         val = s->regs[saddr];
         break;
     case GT_PCI0_IACK:
-        /* Read the IRQ number */ 
+        /* Read the IRQ number */
         val = pic_read_irq(isa_pic);
         break;
 
@@ -989,10 +764,7 @@ static uint32_t gt64120_readl (void *opaque,
         val = s->pci->config_reg;
         break;
     case GT_PCI0_CFGDATA:
-        if (!(s->pci->config_reg & (1u << 31)))
-            val = 0xffffffff;
-        else
-            val = pci_host_data_readl(s->pci, 0);
+        val = pci_host_data_readl(s->pci, 0);
         break;
 
     case GT_PCI0_CMD:
@@ -1065,9 +837,9 @@ static uint32_t gt64120_readl (void *opaque,
         break;
     }
 
-#ifdef TARGET_WORDS_BIGENDIAN
-    val = bswap32(val);
-#endif
+    if (!(s->regs[GT_PCI0_CMD] & 1))
+        val = bswap32(val);
+
     return val;
 }
 
@@ -1299,33 +1071,17 @@ void gt64120_reset(void *opaque)
     /* 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);
 }
 
@@ -1355,22 +1111,18 @@ PCIBus *pci_gt64120_init(qemu_irq *pic)
 
     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[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;
@@ -1393,6 +1145,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;