linux-user: fix ppc target_stat64 st_blocks layout
[qemu] / hw / sh7750.c
index 1d18010..cf9cf16 100644 (file)
@@ -23,7 +23,6 @@
  * THE SOFTWARE.
  */
 #include <stdio.h>
-#include <assert.h>
 #include "hw.h"
 #include "sh.h"
 #include "sysemu.h"
@@ -41,7 +40,13 @@ typedef struct SH7750State {
     /* Peripheral frequency in Hz */
     uint32_t periph_freq;
     /* SDRAM controller */
+    uint32_t bcr1;
+    uint16_t bcr2;
+    uint16_t bcr3;
+    uint32_t bcr4;
     uint16_t rfcr;
+    /* PCMCIA controller */
+    uint16_t pcr;
     /* IO ports */
     uint16_t gpioic;
     uint32_t pctra;
@@ -58,14 +63,16 @@ typedef struct SH7750State {
     uint16_t periph_portdirb;  /* Direction seen from the peripherals */
     sh7750_io_device *devices[NB_DEVICES];     /* External peripherals */
 
-    uint16_t icr;
     /* Cache */
     uint32_t ccr;
 
     struct intc_desc intc;
 } SH7750State;
 
-
+static int inline has_bcr3_and_bcr4(SH7750State * s)
+{
+       return (s->cpu->features & SH_FEATURE_BCR3_AND_BCR4);
+}
 /**********************************************************************
  I/O ports
 **********************************************************************/
@@ -208,8 +215,16 @@ static uint32_t sh7750_mem_readw(void *opaque, target_phys_addr_t addr)
     SH7750State *s = opaque;
 
     switch (addr) {
+    case SH7750_BCR2_A7:
+       return s->bcr2;
+    case SH7750_BCR3_A7:
+       if(!has_bcr3_and_bcr4(s))
+           error_access("word read", addr);
+       return s->bcr3;
     case SH7750_FRQCR_A7:
        return 0;
+    case SH7750_PCR_A7:
+       return s->pcr;
     case SH7750_RFCR_A7:
        fprintf(stderr,
                "Read access to refresh count register, incrementing\n");
@@ -218,8 +233,11 @@ static uint32_t sh7750_mem_readw(void *opaque, target_phys_addr_t addr)
        return porta_lines(s);
     case SH7750_PDTRB_A7:
        return portb_lines(s);
-    case 0x1fd00000:
-        return s->icr;
+    case SH7750_RTCOR_A7:
+    case SH7750_RTCNT_A7:
+    case SH7750_RTCSR_A7:
+       ignore_access("word read", addr);
+       return 0;
     default:
        error_access("word read", addr);
        assert(0);
@@ -231,6 +249,18 @@ static uint32_t sh7750_mem_readl(void *opaque, target_phys_addr_t addr)
     SH7750State *s = opaque;
 
     switch (addr) {
+    case SH7750_BCR1_A7:
+       return s->bcr1;
+    case SH7750_BCR4_A7:
+       if(!has_bcr3_and_bcr4(s))
+           error_access("long read", addr);
+       return s->bcr4;
+    case SH7750_WCR1_A7:
+    case SH7750_WCR2_A7:
+    case SH7750_WCR3_A7:
+    case SH7750_MCR_A7:
+        ignore_access("long read", addr);
+        return 0;
     case SH7750_MMUCR_A7:
        return s->cpu->mmucr;
     case SH7750_PTEH_A7:
@@ -261,19 +291,19 @@ static uint32_t sh7750_mem_readl(void *opaque, target_phys_addr_t addr)
     }
 }
 
+#define is_in_sdrmx(a, x) (a >= SH7750_SDMR ## x ## _A7 \
+                       && a <= (SH7750_SDMR ## x ## _A7 + SH7750_SDMR ## x ## _REGNB))
 static void sh7750_mem_writeb(void *opaque, target_phys_addr_t addr,
                              uint32_t mem_value)
 {
-    switch (addr) {
-       /* PRECHARGE ? XXXXX */
-    case SH7750_PRECHARGE0_A7:
-    case SH7750_PRECHARGE1_A7:
+
+    if (is_in_sdrmx(addr, 2) || is_in_sdrmx(addr, 3)) {
        ignore_access("byte write", addr);
        return;
-    default:
-       error_access("byte write", addr);
-       assert(0);
     }
+
+    error_access("byte write", addr);
+    assert(0);
 }
 
 static void sh7750_mem_writew(void *opaque, target_phys_addr_t addr,
@@ -285,9 +315,18 @@ static void sh7750_mem_writew(void *opaque, target_phys_addr_t addr,
     switch (addr) {
        /* SDRAM controller */
     case SH7750_BCR2_A7:
+        s->bcr2 = mem_value;
+        return;
     case SH7750_BCR3_A7:
-    case SH7750_RTCOR_A7:
+       if(!has_bcr3_and_bcr4(s))
+           error_access("word write", addr);
+       s->bcr3 = mem_value;
+       return;
+    case SH7750_PCR_A7:
+       s->pcr = mem_value;
+       return;
     case SH7750_RTCNT_A7:
+    case SH7750_RTCOR_A7:
     case SH7750_RTCSR_A7:
        ignore_access("word write", addr);
        return;
@@ -313,9 +352,6 @@ static void sh7750_mem_writew(void *opaque, target_phys_addr_t addr,
            assert(0);
        }
        return;
-    case 0x1fd00000:
-        s->icr = mem_value;
-       return;
     default:
        error_access("word write", addr);
        assert(0);
@@ -331,7 +367,13 @@ static void sh7750_mem_writel(void *opaque, target_phys_addr_t addr,
     switch (addr) {
        /* SDRAM controller */
     case SH7750_BCR1_A7:
+        s->bcr1 = mem_value;
+        return;
     case SH7750_BCR4_A7:
+       if(!has_bcr3_and_bcr4(s))
+           error_access("long write", addr);
+       s->bcr4 = mem_value;
+       return;
     case SH7750_WCR1_A7:
     case SH7750_WCR2_A7:
     case SH7750_WCR3_A7:
@@ -392,13 +434,13 @@ static void sh7750_mem_writel(void *opaque, target_phys_addr_t addr,
     }
 }
 
-static CPUReadMemoryFunc *sh7750_mem_read[] = {
+static CPUReadMemoryFunc * const sh7750_mem_read[] = {
     sh7750_mem_readb,
     sh7750_mem_readw,
     sh7750_mem_readl
 };
 
-static CPUWriteMemoryFunc *sh7750_mem_write[] = {
+static CPUWriteMemoryFunc * const sh7750_mem_write[] = {
     sh7750_mem_writeb,
     sh7750_mem_writew,
     sh7750_mem_writel
@@ -412,7 +454,9 @@ enum {
        UNUSED = 0,
 
        /* interrupt sources */
-       IRL0, IRL1, IRL2, IRL3, /* only IRLM mode supported */
+       IRL_0, IRL_1, IRL_2, IRL_3, IRL_4, IRL_5, IRL_6, IRL_7,
+       IRL_8, IRL_9, IRL_A, IRL_B, IRL_C, IRL_D, IRL_E,
+       IRL0, IRL1, IRL2, IRL3,
        HUDI, GPIOI,
        DMAC_DMTE0, DMAC_DMTE1, DMAC_DMTE2, DMAC_DMTE3,
        DMAC_DMTE4, DMAC_DMTE5, DMAC_DMTE6, DMAC_DMTE7,
@@ -428,6 +472,8 @@ enum {
 
        /* interrupt groups */
        DMAC, PCIC1, TMU2, RTC, SCI1, SCIF, REF,
+       /* irl bundle */
+       IRL,
 
        NR_SOURCES,
 };
@@ -529,6 +575,29 @@ static struct intc_group groups_pci[] = {
                   PCIC1_PCIDMA0, PCIC1_PCIDMA1, PCIC1_PCIDMA2, PCIC1_PCIDMA3),
 };
 
+static struct intc_vect vectors_irl[] = {
+       INTC_VECT(IRL_0, 0x200),
+       INTC_VECT(IRL_1, 0x220),
+       INTC_VECT(IRL_2, 0x240),
+       INTC_VECT(IRL_3, 0x260),
+       INTC_VECT(IRL_4, 0x280),
+       INTC_VECT(IRL_5, 0x2a0),
+       INTC_VECT(IRL_6, 0x2c0),
+       INTC_VECT(IRL_7, 0x2e0),
+       INTC_VECT(IRL_8, 0x300),
+       INTC_VECT(IRL_9, 0x320),
+       INTC_VECT(IRL_A, 0x340),
+       INTC_VECT(IRL_B, 0x360),
+       INTC_VECT(IRL_C, 0x380),
+       INTC_VECT(IRL_D, 0x3a0),
+       INTC_VECT(IRL_E, 0x3c0),
+};
+
+static struct intc_group groups_irl[] = {
+       INTC_GROUP(IRL, IRL_0, IRL_1, IRL_2, IRL_3, IRL_4, IRL_5, IRL_6,
+               IRL_7, IRL_8, IRL_9, IRL_A, IRL_B, IRL_C, IRL_D, IRL_E),
+};
+
 /**********************************************************************
  Memory mapped cache and TLB
 **********************************************************************/
@@ -619,13 +688,13 @@ static void sh7750_mmct_writel(void *opaque, target_phys_addr_t addr,
     }
 }
 
-static CPUReadMemoryFunc *sh7750_mmct_read[] = {
+static CPUReadMemoryFunc * const sh7750_mmct_read[] = {
     invalid_read,
     invalid_read,
     sh7750_mmct_readl
 };
 
-static CPUWriteMemoryFunc *sh7750_mmct_write[] = {
+static CPUWriteMemoryFunc * const sh7750_mmct_write[] = {
     invalid_write,
     invalid_write,
     sh7750_mmct_writel
@@ -640,14 +709,22 @@ SH7750State *sh7750_init(CPUSH4State * cpu)
     s = qemu_mallocz(sizeof(SH7750State));
     s->cpu = cpu;
     s->periph_freq = 60000000; /* 60MHz */
-    sh7750_io_memory = cpu_register_io_memory(0,
-                                             sh7750_mem_read,
+    sh7750_io_memory = cpu_register_io_memory(sh7750_mem_read,
                                              sh7750_mem_write, s);
-    cpu_register_physical_memory_offset(0x1c000000, 0x04000000,
-                                        sh7750_io_memory, 0x1c000000);
-
-    sh7750_mm_cache_and_tlb = cpu_register_io_memory(0,
-                                                    sh7750_mmct_read,
+    cpu_register_physical_memory_offset(0x1f000000, 0x1000,
+                                        sh7750_io_memory, 0x1f000000);
+    cpu_register_physical_memory_offset(0xff000000, 0x1000,
+                                        sh7750_io_memory, 0x1f000000);
+    cpu_register_physical_memory_offset(0x1f800000, 0x1000,
+                                        sh7750_io_memory, 0x1f800000);
+    cpu_register_physical_memory_offset(0xff800000, 0x1000,
+                                        sh7750_io_memory, 0x1f800000);
+    cpu_register_physical_memory_offset(0x1fc00000, 0x1000,
+                                        sh7750_io_memory, 0x1fc00000);
+    cpu_register_physical_memory_offset(0xffc00000, 0x1000,
+                                        sh7750_io_memory, 0x1fc00000);
+
+    sh7750_mm_cache_and_tlb = cpu_register_io_memory(sh7750_mmct_read,
                                                     sh7750_mmct_write, s);
     cpu_register_physical_memory(0xf0000000, 0x08000000,
                                 sh7750_mm_cache_and_tlb);
@@ -718,5 +795,15 @@ SH7750State *sh7750_init(CPUSH4State * cpu)
                                 NULL, 0);
     }
 
+    sh_intc_register_sources(&s->intc,
+                               _INTC_ARRAY(vectors_irl),
+                               _INTC_ARRAY(groups_irl));
     return s;
 }
+
+qemu_irq sh7750_irl(SH7750State *s)
+{
+    sh_intc_toggle_source(sh_intc_source(&s->intc, IRL), 1, 0); /* enable */
+    return qemu_allocate_irqs(sh_intc_set_irl, sh_intc_source(&s->intc, IRL),
+                               1)[0];
+}