Search
lxdream.org :: lxdream/src/mmio.h
lxdream 0.9.1
released Jun 29
Download Now
filename src/mmio.h
changeset 1067:d3c00ffccfcd
prev975:007bf7eb944f
prev946:d41ee7994db7
author nkeynes
date Fri Mar 02 23:49:10 2012 +1000 (12 years ago)
permissions -rw-r--r--
last change Android WIP:
* Rename gui_jni.c to gui_android.c - now quite android specific.
* Implement generic EGL driver with very minimal Java wrapper
* Run emulation in separate thread, and implement simple queue for
inter-thread communication.
* Add menu/action-bar items for start + reset
file annotate diff log raw
nkeynes@31
     1
/**
nkeynes@561
     2
 * $Id$
nkeynes@31
     3
 *
nkeynes@31
     4
 * mmio.h defines a complicated batch of macros used to build up the 
nkeynes@31
     5
 * memory-mapped I/O regions in a reasonably readable fashion.
nkeynes@31
     6
 *
nkeynes@31
     7
 * Copyright (c) 2005 Nathan Keynes.
nkeynes@31
     8
 *
nkeynes@31
     9
 * This program is free software; you can redistribute it and/or modify
nkeynes@31
    10
 * it under the terms of the GNU General Public License as published by
nkeynes@31
    11
 * the Free Software Foundation; either version 2 of the License, or
nkeynes@31
    12
 * (at your option) any later version.
nkeynes@31
    13
 *
nkeynes@31
    14
 * This program is distributed in the hope that it will be useful,
nkeynes@31
    15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
nkeynes@31
    16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
nkeynes@31
    17
 * GNU General Public License for more details.
nkeynes@31
    18
 */
nkeynes@929
    19
#ifndef lxdream_mmio_H
nkeynes@929
    20
#define lxdream_mmio_H 1
nkeynes@10
    21
nkeynes@10
    22
#ifdef __cplusplus
nkeynes@10
    23
extern "C" {
nkeynes@10
    24
#if 0
nkeynes@10
    25
}
nkeynes@10
    26
#endif
nkeynes@10
    27
#endif
nkeynes@10
    28
nkeynes@10
    29
#include <stdint.h>
nkeynes@10
    30
#include <stdlib.h>
nkeynes@929
    31
#include "mem.h"
nkeynes@10
    32
nkeynes@796
    33
#define LXDREAM_PAGE_TABLE_ENTRIES 128*1024
nkeynes@796
    34
#define LXDREAM_PAGE_SIZE 4096
nkeynes@796
    35
#define LXDREAM_PAGE_BITS 12
nkeynes@10
    36
nkeynes@10
    37
#define PORT_R 1
nkeynes@10
    38
#define PORT_W 2
nkeynes@10
    39
#define PORT_MEM 4 /* store written value */
nkeynes@10
    40
#define PORT_RW 3
nkeynes@10
    41
#define PORT_MR 5
nkeynes@10
    42
#define PORT_MRW 7
nkeynes@172
    43
#define PORT_NOTRACE 16
nkeynes@10
    44
#define UNDEFINED 0xDEADBEEF /* This has to be a value that nothing inits to */
nkeynes@10
    45
nkeynes@10
    46
struct mmio_region {
nkeynes@10
    47
    char *id, *desc;
nkeynes@10
    48
    uint32_t base;
nkeynes@929
    49
    struct mem_region_fn fn;
nkeynes@10
    50
    char *mem;
nkeynes@10
    51
    char *save_mem; /* Used to compare for gui updates */
nkeynes@10
    52
    struct mmio_port {
nkeynes@10
    53
        char *id, *desc;
nkeynes@10
    54
        int width;
nkeynes@10
    55
        uint32_t offset;
nkeynes@10
    56
        uint32_t def_val;
nkeynes@10
    57
        int flags;
nkeynes@10
    58
        uint32_t *val;
nkeynes@10
    59
    } ports[80];
nkeynes@10
    60
    struct mmio_port **index; /* reverse lookup by address */
nkeynes@10
    61
    int trace_flag; /* set to 1 to enable transfer traces */
nkeynes@10
    62
};
nkeynes@10
    63
nkeynes@10
    64
void register_io_region( struct mmio_region *mmio );
nkeynes@10
    65
void register_io_regions( struct mmio_region **mmiolist );
nkeynes@10
    66
nkeynes@10
    67
extern struct mmio_region *io_rgn[];
nkeynes@674
    68
extern uint32_t num_io_rgns;
nkeynes@10
    69
nkeynes@10
    70
#define MMIO_READ( id, r ) *((int32_t *)(mmio_region_##id.mem + (r)))
nkeynes@136
    71
#define MMIO_READF( id, r ) *((float *)(mmio_region_##id.mem + (r)))
nkeynes@10
    72
#define MMIO_WRITE( id, r, v ) *((int32_t *)(mmio_region_##id.mem + (r))) = (v)
nkeynes@474
    73
#define MMIO_ADDR( id, r) ((int32_t *)(mmio_region_##id.mem + (r)))
nkeynes@10
    74
#define MMIO_REG( id, r ) ((int32_t *)(mmio_region_##id.mem + (r)))
nkeynes@10
    75
#define MMIO_REGID( mid, r ) (mmio_region_##mid.index[(r)>>2] != NULL ? \
nkeynes@10
    76
            mmio_region_##mid.index[(r)>>2]->id : "<UNDEF>" )
nkeynes@10
    77
#define MMIO_REGDESC( mid, r) (mmio_region_##mid.index[(r)>>2] != NULL ? \
nkeynes@10
    78
            mmio_region_##mid.index[(r)>>2]->desc : "Undefined register" )
nkeynes@10
    79
#define MMIO_TRACE( mid ) mmio_region_##mid.trace_flag = 1
nkeynes@10
    80
#define MMIO_NOTRACE( mid ) mmio_region_##mid.trace_flag = 0
nkeynes@10
    81
nkeynes@10
    82
#define MMIO_REGID_BYNUM( mid, r ) (io_rgn[mid]->index[(r)>>2] != NULL ? \
nkeynes@10
    83
            io_rgn[mid]->index[(r)>>2]->id : "<UNDEF>" )
nkeynes@10
    84
#define MMIO_REGDESC_BYNUM( mid, r ) (io_rgn[mid]->index[(r)>>2] != NULL ? \
nkeynes@10
    85
            io_rgn[mid]->index[(r)>>2]->desc : "Undefined register" )
nkeynes@172
    86
#define MMIO_NOTRACE_BYNUM( mid, r ) (io_rgn[mid]->index[(r)>>2] != NULL ? \
nkeynes@172
    87
				      (io_rgn[mid]->index[(r)>>2]->flags & PORT_NOTRACE) : 0 )
nkeynes@10
    88
#define MMIO_NAME_BYNUM( mid ) (io_rgn[mid]->id)
nkeynes@10
    89
nkeynes@156
    90
#define MMIO_REGID_IOBYNUM( io, r ) (io->index[(r)>>2] != NULL ? \
nkeynes@156
    91
            io->index[(r)>>2]->id : "<UNDEF>" )
nkeynes@156
    92
#define MMIO_REGDESC_IOBYNUM( io, r ) (io->index[(r)>>2] != NULL ? \
nkeynes@156
    93
            io->index[(r)>>2]->desc : "Undefined register" )
nkeynes@172
    94
#define MMIO_NOTRACE_IOBYNUM( io, r ) (io->index[(r)>>2] != NULL ? \
nkeynes@172
    95
				      (io->index[(r)>>2]->flags & PORT_NOTRACE) : 0 )
nkeynes@156
    96
nkeynes@10
    97
#ifdef __cplusplus
nkeynes@10
    98
}
nkeynes@10
    99
#endif
nkeynes@10
   100
nkeynes@10
   101
#endif
nkeynes@10
   102
nkeynes@10
   103
#ifdef MMIO_IMPL
nkeynes@10
   104
nkeynes@10
   105
#ifndef MMIO_IMPL_INCLUDED
nkeynes@10
   106
#define MMIO_IMPL_INCLUDED
nkeynes@10
   107
#undef MMIO_REGION_BEGIN
nkeynes@10
   108
#undef LONG_PORT
nkeynes@10
   109
#undef WORD_PORT
nkeynes@10
   110
#undef BYTE_PORT
nkeynes@10
   111
#undef MMIO_REGION_END
nkeynes@10
   112
#undef MMIO_REGION_LIST_BEGIN
nkeynes@10
   113
#undef MMIO_REGION
nkeynes@10
   114
#undef MMIO_REGION_LIST_END
nkeynes@975
   115
#define MMIO_REGION_BEGIN(b,id,d) struct mmio_region mmio_region_##id = { #id, d, b, {mmio_region_##id##_read, mmio_region_##id##_write,mmio_region_##id##_read_word, mmio_region_##id##_write,mmio_region_##id##_read_byte, mmio_region_##id##_write,NULL, NULL, unmapped_prefetch, mmio_region_##id##_read_byte}, 0, 0, {
nkeynes@10
   116
#define LONG_PORT( o,id,f,def,d ) { #id, d, 32, o, def, f },
nkeynes@10
   117
#define WORD_PORT( o,id,f,def,d ) { #id, d, 16, o, def, f },
nkeynes@10
   118
#define BYTE_PORT( o,id,f,def,d ) { #id, d, 8, o, def, f },
nkeynes@10
   119
#define MMIO_REGION_END {NULL, NULL, 0, 0, 0, 0} } };
nkeynes@10
   120
#define MMIO_REGION_LIST_BEGIN(id) struct mmio_region *mmio_list_##id[] = {
nkeynes@10
   121
#define MMIO_REGION( id ) &mmio_region_##id,
nkeynes@10
   122
#define MMIO_REGION_LIST_END NULL};
nkeynes@10
   123
nkeynes@10
   124
/* Stub defines for modules we haven't got to yet, or ones which don't
nkeynes@10
   125
 * actually need any direct code on read and/or write
nkeynes@10
   126
 */
nkeynes@10
   127
#define MMIO_REGION_READ_STUBFN( id ) \
nkeynes@929
   128
int32_t FASTCALL mmio_region_##id##_read( uint32_t reg ) { \
nkeynes@929
   129
    reg = reg & 0xFFF; \
nkeynes@10
   130
    int32_t val = MMIO_READ( id, reg ); \
nkeynes@10
   131
    WARN( "Read from unimplemented module %s (%03X => %08X) [%s: %s]",\
nkeynes@10
   132
          #id, reg, val, MMIO_REGID(id,reg), MMIO_REGDESC(id,reg) ); \
nkeynes@10
   133
    return val; \
nkeynes@10
   134
}
nkeynes@10
   135
#define MMIO_REGION_WRITE_STUBFN( id ) \
nkeynes@929
   136
void FASTCALL mmio_region_##id##_write( uint32_t reg, uint32_t val ) { \
nkeynes@929
   137
    reg = reg & 0xFFF; \
nkeynes@10
   138
    WARN( "Write to unimplemented module %s (%03X <= %08X) [%s: %s]", \
nkeynes@10
   139
          #id, reg, val, MMIO_REGID(id,reg), MMIO_REGDESC(id,reg) ); \
nkeynes@10
   140
    MMIO_WRITE( id, reg, val ); \
nkeynes@10
   141
}
nkeynes@10
   142
#define MMIO_REGION_STUBFNS( id ) \
nkeynes@10
   143
    MMIO_REGION_READ_STUBFN( id ) \
nkeynes@10
   144
    MMIO_REGION_WRITE_STUBFN( id )
nkeynes@10
   145
#define MMIO_REGION_READ_DEFFN( id ) \
nkeynes@929
   146
int32_t FASTCALL mmio_region_##id##_read( uint32_t reg ) { \
nkeynes@929
   147
    return MMIO_READ( id, reg&0xFFF ); \
nkeynes@10
   148
}
nkeynes@10
   149
#define MMIO_REGION_WRITE_DEFFN( id ) \
nkeynes@929
   150
void FASTCALL mmio_region_##id##_write( uint32_t reg, uint32_t val ) { \
nkeynes@929
   151
    MMIO_WRITE( id, reg&0xFFF, val ); \
nkeynes@10
   152
}
nkeynes@10
   153
#define MMIO_REGION_DEFFNS( id ) \
nkeynes@10
   154
    MMIO_REGION_READ_DEFFN( id ) \
nkeynes@10
   155
    MMIO_REGION_WRITE_DEFFN( id )
nkeynes@975
   156
nkeynes@10
   157
#endif
nkeynes@10
   158
nkeynes@10
   159
#else
nkeynes@10
   160
nkeynes@10
   161
#ifndef MMIO_IFACE_INCLUDED
nkeynes@10
   162
#define MMIO_IFACE_INCLUDED
nkeynes@10
   163
#define MMIO_REGION_BEGIN(b,id,d) \
nkeynes@10
   164
extern struct mmio_region mmio_region_##id; \
nkeynes@929
   165
int32_t FASTCALL mmio_region_##id##_read(uint32_t); \
nkeynes@975
   166
int32_t FASTCALL mmio_region_##id##_read_word(uint32_t); \
nkeynes@975
   167
int32_t FASTCALL mmio_region_##id##_read_byte(uint32_t); \
nkeynes@929
   168
void FASTCALL mmio_region_##id##_write(uint32_t, uint32_t); \
nkeynes@10
   169
enum mmio_region_##id##_port_t {
nkeynes@10
   170
#define LONG_PORT( o,id,f,def,d ) id = o,
nkeynes@10
   171
#define WORD_PORT( o,id,f,def,d ) id = o,
nkeynes@10
   172
#define BYTE_PORT( o,id,f,def,d ) id = o,
nkeynes@10
   173
#define MMIO_REGION_END };
nkeynes@10
   174
#define MMIO_REGION_LIST_BEGIN(id) extern struct mmio_region *mmio_list_##id[];
nkeynes@10
   175
#define MMIO_REGION( id )
nkeynes@10
   176
#define MMIO_REGION_LIST_END
nkeynes@10
   177
#endif
nkeynes@10
   178
nkeynes@929
   179
#define MMIO_REGION_WRITE_FN( id, reg, val ) \
nkeynes@929
   180
void FASTCALL mmio_region_##id##_write( uint32_t reg, uint32_t val )
nkeynes@929
   181
nkeynes@929
   182
#define MMIO_REGION_READ_FN( id, reg ) \
nkeynes@929
   183
int32_t FASTCALL mmio_region_##id##_read( uint32_t reg )
nkeynes@929
   184
nkeynes@975
   185
#define MMIO_REGION_READ_DEFSUBFNS( id ) \
nkeynes@975
   186
int32_t FASTCALL mmio_region_##id##_read_word( uint32_t reg ) { return SIGNEXT16(mmio_region_##id##_read(reg)); } \
nkeynes@975
   187
int32_t FASTCALL mmio_region_##id##_read_byte( uint32_t reg ) { return SIGNEXT8(mmio_region_##id##_read(reg)); }
nkeynes@975
   188
nkeynes@929
   189
nkeynes@10
   190
#endif
nkeynes@10
   191
.