Search
lxdream.org :: lxdream/src/sh4/sh4mmio.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/sh4/sh4mmio.c
changeset 10:c898b37506e0
prev1:eea311cfd33e
next19:9da7a8e38f9d
author nkeynes
date Sun Dec 11 12:00:09 2005 +0000 (18 years ago)
permissions -rw-r--r--
last change Moved arm material under aica/
Hooked arm disasm up
file annotate diff log raw
nkeynes@1
     1
#include "dream.h"
nkeynes@1
     2
#include "mem.h"
nkeynes@1
     3
#include "sh4core.h"
nkeynes@1
     4
#include "sh4mmio.h"
nkeynes@1
     5
#define MMIO_IMPL
nkeynes@1
     6
#include "sh4mmio.h"
nkeynes@1
     7
nkeynes@1
     8
/********************************* MMU *************************************/
nkeynes@1
     9
nkeynes@1
    10
MMIO_REGION_READ_STUBFN( MMU )
nkeynes@1
    11
nkeynes@10
    12
#define OCRAM_START (0x1C000000>>PAGE_BITS)
nkeynes@10
    13
#define OCRAM_END   (0x20000000>>PAGE_BITS)
nkeynes@10
    14
nkeynes@10
    15
static char *cache = NULL;
nkeynes@10
    16
nkeynes@1
    17
void mmio_region_MMU_write( uint32_t reg, uint32_t val )
nkeynes@1
    18
{
nkeynes@1
    19
    switch(reg) {
nkeynes@1
    20
        case CCR:
nkeynes@10
    21
            mmu_set_cache_mode( val & (CCR_OIX|CCR_ORA) );
nkeynes@1
    22
            INFO( "Cache mode set to %08X", val );
nkeynes@1
    23
            break;
nkeynes@1
    24
        default:
nkeynes@1
    25
            break;
nkeynes@1
    26
    }
nkeynes@1
    27
    MMIO_WRITE( MMU, reg, val );
nkeynes@1
    28
}
nkeynes@1
    29
nkeynes@1
    30
nkeynes@10
    31
void mmu_init() 
nkeynes@10
    32
{
nkeynes@10
    33
  cache = mem_alloc_pages(2);
nkeynes@10
    34
}
nkeynes@10
    35
nkeynes@10
    36
void mmu_set_cache_mode( int mode )
nkeynes@10
    37
{
nkeynes@10
    38
    uint32_t i;
nkeynes@10
    39
    switch( mode ) {
nkeynes@10
    40
        case MEM_OC_INDEX0: /* OIX=0 */
nkeynes@10
    41
            for( i=OCRAM_START; i<OCRAM_END; i++ )
nkeynes@10
    42
                page_map[i] = cache + ((i&0x02)<<(PAGE_BITS-1));
nkeynes@10
    43
            break;
nkeynes@10
    44
        case MEM_OC_INDEX1: /* OIX=1 */
nkeynes@10
    45
            for( i=OCRAM_START; i<OCRAM_END; i++ )
nkeynes@10
    46
                page_map[i] = cache + ((i&0x02000000)>>(25-PAGE_BITS));
nkeynes@10
    47
            break;
nkeynes@10
    48
        default: /* disabled */
nkeynes@10
    49
            for( i=OCRAM_START; i<OCRAM_END; i++ )
nkeynes@10
    50
                page_map[i] = NULL;
nkeynes@10
    51
            break;
nkeynes@10
    52
    }
nkeynes@10
    53
}
nkeynes@10
    54
nkeynes@10
    55
nkeynes@1
    56
/********************************* BSC *************************************/
nkeynes@1
    57
nkeynes@1
    58
uint16_t bsc_output_mask_lo = 0, bsc_output_mask_hi = 0;
nkeynes@1
    59
uint16_t bsc_input_mask_lo = 0, bsc_input_mask_hi = 0;
nkeynes@1
    60
uint32_t bsc_output = 0, bsc_input = 0x0300;
nkeynes@1
    61
nkeynes@1
    62
void bsc_out( int output, int mask )
nkeynes@1
    63
{
nkeynes@1
    64
    /* Go figure... The BIOS won't start without this mess though */
nkeynes@1
    65
    if( ((output | (~mask)) & 0x03) == 3 ) {
nkeynes@1
    66
        bsc_output |= 0x03;
nkeynes@1
    67
    } else {
nkeynes@1
    68
        bsc_output &= ~0x03;
nkeynes@1
    69
    }
nkeynes@1
    70
}
nkeynes@1
    71
nkeynes@1
    72
void mmio_region_BSC_write( uint32_t reg, uint32_t val )
nkeynes@1
    73
{
nkeynes@1
    74
    int i;
nkeynes@1
    75
    switch( reg ) {
nkeynes@1
    76
        case PCTRA:
nkeynes@1
    77
            bsc_input_mask_lo = bsc_output_mask_lo = 0;
nkeynes@1
    78
            for( i=0; i<16; i++ ) {
nkeynes@1
    79
                int bits = (val >> (i<<1)) & 0x03;
nkeynes@1
    80
                if( bits == 2 ) bsc_input_mask_lo |= (1<<i);
nkeynes@1
    81
                else if( bits != 0 ) bsc_output_mask_lo |= (1<<i);
nkeynes@1
    82
            }
nkeynes@1
    83
            bsc_output = (bsc_output&0x000F0000) |
nkeynes@1
    84
                (MMIO_READ( BSC, PDTRA ) & bsc_output_mask_lo);
nkeynes@1
    85
            bsc_out( MMIO_READ( BSC, PDTRA ) | ((MMIO_READ(BSC,PDTRB)<<16)),
nkeynes@1
    86
                     bsc_output_mask_lo | (bsc_output_mask_hi<<16) );
nkeynes@1
    87
            break;
nkeynes@1
    88
        case PCTRB:
nkeynes@1
    89
            bsc_input_mask_hi = bsc_output_mask_hi = 0;
nkeynes@1
    90
            for( i=0; i<4; i++ ) {
nkeynes@1
    91
                int bits = (val >> (i>>1)) & 0x03;
nkeynes@1
    92
                if( bits == 2 ) bsc_input_mask_hi |= (1<<i);
nkeynes@1
    93
                else if( bits != 0 ) bsc_output_mask_hi |= (1<<i);
nkeynes@1
    94
            }
nkeynes@1
    95
            bsc_output = (bsc_output&0xFFFF) |
nkeynes@1
    96
                ((MMIO_READ( BSC, PDTRA ) & bsc_output_mask_hi)<<16);
nkeynes@1
    97
            break;
nkeynes@1
    98
        case PDTRA:
nkeynes@1
    99
            bsc_output = (bsc_output&0x000F0000) |
nkeynes@1
   100
                (val & bsc_output_mask_lo );
nkeynes@1
   101
            bsc_out( val | ((MMIO_READ(BSC,PDTRB)<<16)),
nkeynes@1
   102
                     bsc_output_mask_lo | (bsc_output_mask_hi<<16) );
nkeynes@1
   103
            break;
nkeynes@1
   104
        case PDTRB:
nkeynes@1
   105
            bsc_output = (bsc_output&0xFFFF) |
nkeynes@1
   106
                ( (val & bsc_output_mask_hi)<<16 );
nkeynes@1
   107
            break;
nkeynes@1
   108
    }
nkeynes@1
   109
    WARN( "Write to (mostly) unimplemented BSC (%03X <= %08X) [%s: %s]",
nkeynes@1
   110
          reg, val, MMIO_REGID(BSC,reg), MMIO_REGDESC(BSC,reg) );
nkeynes@1
   111
    MMIO_WRITE( BSC, reg, val );
nkeynes@1
   112
}
nkeynes@1
   113
nkeynes@1
   114
int32_t mmio_region_BSC_read( uint32_t reg )
nkeynes@1
   115
{
nkeynes@1
   116
    int32_t val;
nkeynes@1
   117
    switch( reg ) {
nkeynes@1
   118
        case PDTRA:
nkeynes@1
   119
            val = (bsc_input & bsc_input_mask_lo) | (bsc_output&0xFFFF);
nkeynes@1
   120
            break;
nkeynes@1
   121
        case PDTRB:
nkeynes@1
   122
            val = ((bsc_input>>16) & bsc_input_mask_hi) | (bsc_output>>16);
nkeynes@1
   123
            break;
nkeynes@1
   124
        default:
nkeynes@1
   125
            val = MMIO_READ( BSC, reg );
nkeynes@1
   126
    }
nkeynes@1
   127
    WARN( "Read from (mostly) unimplemented BSC (%03X => %08X) [%s: %s]",
nkeynes@1
   128
          reg, val, MMIO_REGID(BSC,reg), MMIO_REGDESC(BSC,reg) );
nkeynes@1
   129
    return val;
nkeynes@1
   130
}
nkeynes@1
   131
nkeynes@1
   132
/********************************* UBC *************************************/
nkeynes@1
   133
nkeynes@1
   134
MMIO_REGION_STUBFNS( UBC )
nkeynes@1
   135
nkeynes@1
   136
/********************************* CPG *************************************/
nkeynes@1
   137
nkeynes@1
   138
MMIO_REGION_STUBFNS( CPG )
nkeynes@1
   139
nkeynes@1
   140
/********************************* DMAC *************************************/
nkeynes@1
   141
nkeynes@1
   142
MMIO_REGION_STUBFNS( DMAC )
nkeynes@1
   143
nkeynes@1
   144
/********************************** RTC *************************************/
nkeynes@1
   145
nkeynes@1
   146
MMIO_REGION_STUBFNS( RTC )
nkeynes@1
   147
nkeynes@1
   148
/********************************** TMU *************************************/
nkeynes@1
   149
nkeynes@1
   150
int timer_divider[3] = {16,16,16};
nkeynes@1
   151
MMIO_REGION_READ_DEFFN( TMU )
nkeynes@1
   152
nkeynes@1
   153
int get_timer_div( int val )
nkeynes@1
   154
{
nkeynes@1
   155
    switch( val & 0x07 ) {
nkeynes@1
   156
        case 0: return 16; /* assume peripheral clock is IC/4 */
nkeynes@1
   157
        case 1: return 64;
nkeynes@1
   158
        case 2: return 256;
nkeynes@1
   159
        case 3: return 1024;
nkeynes@1
   160
        case 4: return 4096;
nkeynes@1
   161
    }
nkeynes@1
   162
    return 1;
nkeynes@1
   163
}
nkeynes@1
   164
nkeynes@1
   165
void mmio_region_TMU_write( uint32_t reg, uint32_t val )
nkeynes@1
   166
{
nkeynes@1
   167
    switch( reg ) {
nkeynes@1
   168
        case TCR0:
nkeynes@1
   169
            timer_divider[0] = get_timer_div(val);
nkeynes@1
   170
            break;
nkeynes@1
   171
        case TCR1:
nkeynes@1
   172
            timer_divider[1] = get_timer_div(val);
nkeynes@1
   173
            break;
nkeynes@1
   174
        case TCR2:
nkeynes@1
   175
            timer_divider[2] = get_timer_div(val);
nkeynes@1
   176
            break;
nkeynes@1
   177
    }
nkeynes@1
   178
    MMIO_WRITE( TMU, reg, val );
nkeynes@1
   179
}
nkeynes@1
   180
nkeynes@1
   181
void run_timers( int cycles )
nkeynes@1
   182
{
nkeynes@1
   183
    int tcr = MMIO_READ( TMU, TSTR );
nkeynes@1
   184
    cycles *= 16;
nkeynes@1
   185
    if( tcr & 1 ) {
nkeynes@1
   186
        int count = cycles / timer_divider[0];
nkeynes@1
   187
        int *val = MMIO_REG( TMU, TCNT0 );
nkeynes@1
   188
        if( *val < count ) {
nkeynes@1
   189
            MMIO_READ( TMU, TCR0 ) |= 0x100;
nkeynes@1
   190
            /* interrupt goes here */
nkeynes@1
   191
            count -= *val;
nkeynes@1
   192
            *val = MMIO_READ( TMU, TCOR0 ) - count;
nkeynes@1
   193
        } else {
nkeynes@1
   194
            *val -= count;
nkeynes@1
   195
        }
nkeynes@1
   196
    }
nkeynes@1
   197
}
nkeynes@1
   198
nkeynes@1
   199
/********************************** SCI *************************************/
nkeynes@1
   200
nkeynes@1
   201
MMIO_REGION_STUBFNS( SCI )
nkeynes@1
   202
nkeynes@1
   203
/********************************* SCIF *************************************/
nkeynes@1
   204
nkeynes@1
   205
MMIO_REGION_STUBFNS( SCIF )
nkeynes@1
   206
.