Search
lxdream.org :: lxdream/src/sh4/sh4mmio.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/sh4/sh4mmio.c
changeset 312:2c34bdc36cbd
prev166:8aa70cf503a2
next323:067583c1a704
author nkeynes
date Tue Jan 23 08:17:06 2007 +0000 (13 years ago)
permissions -rw-r--r--
last change Save/restore MMU state (specifically the OC cache ram) correctly
file annotate diff log raw
nkeynes@30
     1
/**
nkeynes@312
     2
 * $Id: sh4mmio.c,v 1.10 2007-01-23 08:17:06 nkeynes Exp $
nkeynes@30
     3
 * 
nkeynes@30
     4
 * Miscellaneous and not-really-implemented SH4 peripheral modules. Also
nkeynes@30
     5
 * responsible for including the IMPL side of the SH4 MMIO pages.
nkeynes@30
     6
 * Most of these will eventually be split off into their own files.
nkeynes@30
     7
 *
nkeynes@30
     8
 * Copyright (c) 2005 Nathan Keynes.
nkeynes@30
     9
 *
nkeynes@30
    10
 * This program is free software; you can redistribute it and/or modify
nkeynes@30
    11
 * it under the terms of the GNU General Public License as published by
nkeynes@30
    12
 * the Free Software Foundation; either version 2 of the License, or
nkeynes@30
    13
 * (at your option) any later version.
nkeynes@30
    14
 *
nkeynes@30
    15
 * This program is distributed in the hope that it will be useful,
nkeynes@30
    16
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
nkeynes@30
    17
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
nkeynes@30
    18
 * GNU General Public License for more details.
nkeynes@30
    19
 */
nkeynes@35
    20
#define MODULE sh4_module
nkeynes@30
    21
nkeynes@1
    22
#include "dream.h"
nkeynes@1
    23
#include "mem.h"
nkeynes@19
    24
#include "clock.h"
nkeynes@1
    25
#include "sh4core.h"
nkeynes@1
    26
#include "sh4mmio.h"
nkeynes@1
    27
#define MMIO_IMPL
nkeynes@1
    28
#include "sh4mmio.h"
nkeynes@1
    29
nkeynes@1
    30
/********************************* MMU *************************************/
nkeynes@1
    31
nkeynes@92
    32
MMIO_REGION_READ_DEFFN( MMU )
nkeynes@1
    33
nkeynes@10
    34
#define OCRAM_START (0x1C000000>>PAGE_BITS)
nkeynes@10
    35
#define OCRAM_END   (0x20000000>>PAGE_BITS)
nkeynes@10
    36
nkeynes@10
    37
static char *cache = NULL;
nkeynes@10
    38
nkeynes@1
    39
void mmio_region_MMU_write( uint32_t reg, uint32_t val )
nkeynes@1
    40
{
nkeynes@1
    41
    switch(reg) {
nkeynes@1
    42
        case CCR:
nkeynes@10
    43
            mmu_set_cache_mode( val & (CCR_OIX|CCR_ORA) );
nkeynes@1
    44
            break;
nkeynes@1
    45
        default:
nkeynes@1
    46
            break;
nkeynes@1
    47
    }
nkeynes@1
    48
    MMIO_WRITE( MMU, reg, val );
nkeynes@1
    49
}
nkeynes@1
    50
nkeynes@1
    51
nkeynes@312
    52
void MMU_init() 
nkeynes@10
    53
{
nkeynes@19
    54
    cache = mem_alloc_pages(2);
nkeynes@10
    55
}
nkeynes@10
    56
nkeynes@312
    57
void MMU_reset()
nkeynes@312
    58
{
nkeynes@312
    59
    mmio_region_MMU_write( CCR, 0 );
nkeynes@312
    60
}
nkeynes@312
    61
nkeynes@312
    62
void MMU_save_state( FILE *f )
nkeynes@312
    63
{
nkeynes@312
    64
    fwrite( cache, 4096, 2, f );
nkeynes@312
    65
}
nkeynes@312
    66
nkeynes@312
    67
int MMU_load_state( FILE *f )
nkeynes@312
    68
{
nkeynes@312
    69
    /* Setup the cache mode according to the saved register value
nkeynes@312
    70
     * (mem_load runs before this point to load all MMIO data)
nkeynes@312
    71
     */
nkeynes@312
    72
    mmio_region_MMU_write( CCR, MMIO_READ(MMU, CCR) );
nkeynes@312
    73
    if( fread( cache, 4096, 2, f ) != 2 ) {
nkeynes@312
    74
	return 1;
nkeynes@312
    75
    }
nkeynes@312
    76
    return 0;
nkeynes@312
    77
}
nkeynes@312
    78
nkeynes@10
    79
void mmu_set_cache_mode( int mode )
nkeynes@10
    80
{
nkeynes@10
    81
    uint32_t i;
nkeynes@10
    82
    switch( mode ) {
nkeynes@10
    83
        case MEM_OC_INDEX0: /* OIX=0 */
nkeynes@10
    84
            for( i=OCRAM_START; i<OCRAM_END; i++ )
nkeynes@10
    85
                page_map[i] = cache + ((i&0x02)<<(PAGE_BITS-1));
nkeynes@10
    86
            break;
nkeynes@10
    87
        case MEM_OC_INDEX1: /* OIX=1 */
nkeynes@10
    88
            for( i=OCRAM_START; i<OCRAM_END; i++ )
nkeynes@10
    89
                page_map[i] = cache + ((i&0x02000000)>>(25-PAGE_BITS));
nkeynes@10
    90
            break;
nkeynes@10
    91
        default: /* disabled */
nkeynes@10
    92
            for( i=OCRAM_START; i<OCRAM_END; i++ )
nkeynes@10
    93
                page_map[i] = NULL;
nkeynes@10
    94
            break;
nkeynes@10
    95
    }
nkeynes@10
    96
}
nkeynes@10
    97
nkeynes@10
    98
nkeynes@1
    99
/********************************* BSC *************************************/
nkeynes@1
   100
nkeynes@1
   101
uint16_t bsc_output_mask_lo = 0, bsc_output_mask_hi = 0;
nkeynes@1
   102
uint16_t bsc_input_mask_lo = 0, bsc_input_mask_hi = 0;
nkeynes@1
   103
uint32_t bsc_output = 0, bsc_input = 0x0300;
nkeynes@1
   104
nkeynes@1
   105
void bsc_out( int output, int mask )
nkeynes@1
   106
{
nkeynes@1
   107
    /* Go figure... The BIOS won't start without this mess though */
nkeynes@1
   108
    if( ((output | (~mask)) & 0x03) == 3 ) {
nkeynes@1
   109
        bsc_output |= 0x03;
nkeynes@1
   110
    } else {
nkeynes@1
   111
        bsc_output &= ~0x03;
nkeynes@1
   112
    }
nkeynes@1
   113
}
nkeynes@1
   114
nkeynes@1
   115
void mmio_region_BSC_write( uint32_t reg, uint32_t val )
nkeynes@1
   116
{
nkeynes@1
   117
    int i;
nkeynes@1
   118
    switch( reg ) {
nkeynes@1
   119
        case PCTRA:
nkeynes@1
   120
            bsc_input_mask_lo = bsc_output_mask_lo = 0;
nkeynes@1
   121
            for( i=0; i<16; i++ ) {
nkeynes@1
   122
                int bits = (val >> (i<<1)) & 0x03;
nkeynes@1
   123
                if( bits == 2 ) bsc_input_mask_lo |= (1<<i);
nkeynes@1
   124
                else if( bits != 0 ) bsc_output_mask_lo |= (1<<i);
nkeynes@1
   125
            }
nkeynes@1
   126
            bsc_output = (bsc_output&0x000F0000) |
nkeynes@1
   127
                (MMIO_READ( BSC, PDTRA ) & bsc_output_mask_lo);
nkeynes@1
   128
            bsc_out( MMIO_READ( BSC, PDTRA ) | ((MMIO_READ(BSC,PDTRB)<<16)),
nkeynes@1
   129
                     bsc_output_mask_lo | (bsc_output_mask_hi<<16) );
nkeynes@1
   130
            break;
nkeynes@1
   131
        case PCTRB:
nkeynes@1
   132
            bsc_input_mask_hi = bsc_output_mask_hi = 0;
nkeynes@1
   133
            for( i=0; i<4; i++ ) {
nkeynes@1
   134
                int bits = (val >> (i>>1)) & 0x03;
nkeynes@1
   135
                if( bits == 2 ) bsc_input_mask_hi |= (1<<i);
nkeynes@1
   136
                else if( bits != 0 ) bsc_output_mask_hi |= (1<<i);
nkeynes@1
   137
            }
nkeynes@1
   138
            bsc_output = (bsc_output&0xFFFF) |
nkeynes@1
   139
                ((MMIO_READ( BSC, PDTRA ) & bsc_output_mask_hi)<<16);
nkeynes@1
   140
            break;
nkeynes@1
   141
        case PDTRA:
nkeynes@1
   142
            bsc_output = (bsc_output&0x000F0000) |
nkeynes@1
   143
                (val & bsc_output_mask_lo );
nkeynes@1
   144
            bsc_out( val | ((MMIO_READ(BSC,PDTRB)<<16)),
nkeynes@1
   145
                     bsc_output_mask_lo | (bsc_output_mask_hi<<16) );
nkeynes@1
   146
            break;
nkeynes@1
   147
        case PDTRB:
nkeynes@1
   148
            bsc_output = (bsc_output&0xFFFF) |
nkeynes@1
   149
                ( (val & bsc_output_mask_hi)<<16 );
nkeynes@1
   150
            break;
nkeynes@1
   151
    }
nkeynes@1
   152
    WARN( "Write to (mostly) unimplemented BSC (%03X <= %08X) [%s: %s]",
nkeynes@1
   153
          reg, val, MMIO_REGID(BSC,reg), MMIO_REGDESC(BSC,reg) );
nkeynes@1
   154
    MMIO_WRITE( BSC, reg, val );
nkeynes@1
   155
}
nkeynes@1
   156
nkeynes@1
   157
int32_t mmio_region_BSC_read( uint32_t reg )
nkeynes@1
   158
{
nkeynes@1
   159
    int32_t val;
nkeynes@1
   160
    switch( reg ) {
nkeynes@1
   161
        case PDTRA:
nkeynes@1
   162
            val = (bsc_input & bsc_input_mask_lo) | (bsc_output&0xFFFF);
nkeynes@1
   163
            break;
nkeynes@1
   164
        case PDTRB:
nkeynes@1
   165
            val = ((bsc_input>>16) & bsc_input_mask_hi) | (bsc_output>>16);
nkeynes@1
   166
            break;
nkeynes@1
   167
        default:
nkeynes@1
   168
            val = MMIO_READ( BSC, reg );
nkeynes@1
   169
    }
nkeynes@1
   170
    WARN( "Read from (mostly) unimplemented BSC (%03X => %08X) [%s: %s]",
nkeynes@1
   171
          reg, val, MMIO_REGID(BSC,reg), MMIO_REGDESC(BSC,reg) );
nkeynes@1
   172
    return val;
nkeynes@1
   173
}
nkeynes@1
   174
nkeynes@1
   175
/********************************* UBC *************************************/
nkeynes@1
   176
nkeynes@1
   177
MMIO_REGION_STUBFNS( UBC )
nkeynes@1
   178
nkeynes@1
   179
nkeynes@1
   180
/********************************** SCI *************************************/
nkeynes@1
   181
nkeynes@1
   182
MMIO_REGION_STUBFNS( SCI )
nkeynes@1
   183
.