Search
lxdream.org :: lxdream/src/mmio.h
lxdream 0.9.1
released Jun 29
Download Now
filename src/mmio.h
changeset 172:59cf18b4cfb2
prev156:3b93648a3b07
next474:a0345bf296ed
author nkeynes
date Sat Aug 05 00:18:21 2006 +0000 (17 years ago)
permissions -rw-r--r--
last change Add error lines to tests with incomplete polys
Split clip tests to separate data file
Add tests for cmd bit 23 ("use list size field")
file annotate diff log raw
nkeynes@31
     1
/**
nkeynes@172
     2
 * $Id: mmio.h,v 1.6 2006-06-27 11:02:46 nkeynes Exp $
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@10
    19
#ifndef dream_mmio_H
nkeynes@10
    20
#define dream_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@10
    31
nkeynes@10
    32
#define PAGE_TABLE_ENTRIES 128*1024
nkeynes@10
    33
#define PAGE_SIZE 4096
nkeynes@10
    34
#define PAGE_BITS 12
nkeynes@10
    35
nkeynes@10
    36
#define PORT_R 1
nkeynes@10
    37
#define PORT_W 2
nkeynes@10
    38
#define PORT_MEM 4 /* store written value */
nkeynes@10
    39
#define PORT_RW 3
nkeynes@10
    40
#define PORT_MR 5
nkeynes@10
    41
#define PORT_MRW 7
nkeynes@172
    42
#define PORT_NOTRACE 16
nkeynes@10
    43
#define UNDEFINED 0xDEADBEEF /* This has to be a value that nothing inits to */
nkeynes@10
    44
nkeynes@10
    45
struct mmio_region {
nkeynes@10
    46
    char *id, *desc;
nkeynes@10
    47
    uint32_t base;
nkeynes@10
    48
    int32_t (*io_read)(uint32_t addr);
nkeynes@10
    49
    void (*io_write)(uint32_t addr, uint32_t val);
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@10
    68
extern int 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@10
    73
#define MMIO_REG( id, r ) ((int32_t *)(mmio_region_##id.mem + (r)))
nkeynes@10
    74
#define MMIO_REGID( mid, r ) (mmio_region_##mid.index[(r)>>2] != NULL ? \
nkeynes@10
    75
            mmio_region_##mid.index[(r)>>2]->id : "<UNDEF>" )
nkeynes@10
    76
#define MMIO_REGDESC( mid, r) (mmio_region_##mid.index[(r)>>2] != NULL ? \
nkeynes@10
    77
            mmio_region_##mid.index[(r)>>2]->desc : "Undefined register" )
nkeynes@10
    78
#define MMIO_TRACE( mid ) mmio_region_##mid.trace_flag = 1
nkeynes@10
    79
#define MMIO_NOTRACE( mid ) mmio_region_##mid.trace_flag = 0
nkeynes@10
    80
nkeynes@10
    81
#define MMIO_REGID_BYNUM( mid, r ) (io_rgn[mid]->index[(r)>>2] != NULL ? \
nkeynes@10
    82
            io_rgn[mid]->index[(r)>>2]->id : "<UNDEF>" )
nkeynes@10
    83
#define MMIO_REGDESC_BYNUM( mid, r ) (io_rgn[mid]->index[(r)>>2] != NULL ? \
nkeynes@10
    84
            io_rgn[mid]->index[(r)>>2]->desc : "Undefined register" )
nkeynes@172
    85
#define MMIO_NOTRACE_BYNUM( mid, r ) (io_rgn[mid]->index[(r)>>2] != NULL ? \
nkeynes@172
    86
				      (io_rgn[mid]->index[(r)>>2]->flags & PORT_NOTRACE) : 0 )
nkeynes@10
    87
#define MMIO_NAME_BYNUM( mid ) (io_rgn[mid]->id)
nkeynes@10
    88
nkeynes@156
    89
#define MMIO_REGID_IOBYNUM( io, r ) (io->index[(r)>>2] != NULL ? \
nkeynes@156
    90
            io->index[(r)>>2]->id : "<UNDEF>" )
nkeynes@156
    91
#define MMIO_REGDESC_IOBYNUM( io, r ) (io->index[(r)>>2] != NULL ? \
nkeynes@156
    92
            io->index[(r)>>2]->desc : "Undefined register" )
nkeynes@172
    93
#define MMIO_NOTRACE_IOBYNUM( io, r ) (io->index[(r)>>2] != NULL ? \
nkeynes@172
    94
				      (io->index[(r)>>2]->flags & PORT_NOTRACE) : 0 )
nkeynes@156
    95
nkeynes@10
    96
#ifdef __cplusplus
nkeynes@10
    97
}
nkeynes@10
    98
#endif
nkeynes@10
    99
nkeynes@10
   100
#endif
nkeynes@10
   101
nkeynes@10
   102
#ifdef MMIO_IMPL
nkeynes@10
   103
nkeynes@10
   104
#ifndef MMIO_IMPL_INCLUDED
nkeynes@10
   105
#define MMIO_IMPL_INCLUDED
nkeynes@10
   106
#undef MMIO_REGION_BEGIN
nkeynes@10
   107
#undef LONG_PORT
nkeynes@10
   108
#undef WORD_PORT
nkeynes@10
   109
#undef BYTE_PORT
nkeynes@10
   110
#undef MMIO_REGION_END
nkeynes@10
   111
#undef MMIO_REGION_LIST_BEGIN
nkeynes@10
   112
#undef MMIO_REGION
nkeynes@10
   113
#undef MMIO_REGION_LIST_END
nkeynes@10
   114
#define MMIO_REGION_BEGIN(b,id,d) struct mmio_region mmio_region_##id = { #id, d, b, mmio_region_##id##_read, mmio_region_##id##_write, 0, 0, {
nkeynes@10
   115
#define LONG_PORT( o,id,f,def,d ) { #id, d, 32, o, def, f },
nkeynes@10
   116
#define WORD_PORT( o,id,f,def,d ) { #id, d, 16, o, def, f },
nkeynes@10
   117
#define BYTE_PORT( o,id,f,def,d ) { #id, d, 8, o, def, f },
nkeynes@10
   118
#define MMIO_REGION_END {NULL, NULL, 0, 0, 0, 0} } };
nkeynes@10
   119
#define MMIO_REGION_LIST_BEGIN(id) struct mmio_region *mmio_list_##id[] = {
nkeynes@10
   120
#define MMIO_REGION( id ) &mmio_region_##id,
nkeynes@10
   121
#define MMIO_REGION_LIST_END NULL};
nkeynes@10
   122
nkeynes@10
   123
/* Stub defines for modules we haven't got to yet, or ones which don't
nkeynes@10
   124
 * actually need any direct code on read and/or write
nkeynes@10
   125
 */
nkeynes@10
   126
#define MMIO_REGION_READ_STUBFN( id ) \
nkeynes@10
   127
int32_t mmio_region_##id##_read( uint32_t reg ) { \
nkeynes@10
   128
    int32_t val = MMIO_READ( id, reg ); \
nkeynes@10
   129
    WARN( "Read from unimplemented module %s (%03X => %08X) [%s: %s]",\
nkeynes@10
   130
          #id, reg, val, MMIO_REGID(id,reg), MMIO_REGDESC(id,reg) ); \
nkeynes@10
   131
    return val; \
nkeynes@10
   132
}
nkeynes@10
   133
#define MMIO_REGION_WRITE_STUBFN( id ) \
nkeynes@10
   134
void mmio_region_##id##_write( uint32_t reg, uint32_t val ) { \
nkeynes@10
   135
    WARN( "Write to unimplemented module %s (%03X <= %08X) [%s: %s]", \
nkeynes@10
   136
          #id, reg, val, MMIO_REGID(id,reg), MMIO_REGDESC(id,reg) ); \
nkeynes@10
   137
    MMIO_WRITE( id, reg, val ); \
nkeynes@10
   138
}
nkeynes@10
   139
#define MMIO_REGION_STUBFNS( id ) \
nkeynes@10
   140
    MMIO_REGION_READ_STUBFN( id ) \
nkeynes@10
   141
    MMIO_REGION_WRITE_STUBFN( id )
nkeynes@10
   142
#define MMIO_REGION_READ_DEFFN( id ) \
nkeynes@10
   143
int32_t mmio_region_##id##_read( uint32_t reg ) { \
nkeynes@10
   144
    return MMIO_READ( id, reg ); \
nkeynes@10
   145
}
nkeynes@10
   146
#define MMIO_REGION_WRITE_DEFFN( id ) \
nkeynes@10
   147
void mmio_region_##id##_write( uint32_t reg, uint32_t val ) { \
nkeynes@10
   148
    MMIO_WRITE( id, reg, val ); \
nkeynes@10
   149
}
nkeynes@10
   150
#define MMIO_REGION_DEFFNS( id ) \
nkeynes@10
   151
    MMIO_REGION_READ_DEFFN( id ) \
nkeynes@10
   152
    MMIO_REGION_WRITE_DEFFN( id )
nkeynes@10
   153
#endif
nkeynes@10
   154
nkeynes@10
   155
#define MMIO_REGION_WRITE_FN( id, reg, val ) \
nkeynes@10
   156
void mmio_region_##id##_write( uint32_t reg, uint32_t val )
nkeynes@10
   157
nkeynes@10
   158
#define MMIO_REGION_READ_FN( id, reg ) \
nkeynes@10
   159
int32_t mmio_region_##id##_read( uint32_t reg )
nkeynes@10
   160
nkeynes@10
   161
#else
nkeynes@10
   162
nkeynes@10
   163
#ifndef MMIO_IFACE_INCLUDED
nkeynes@10
   164
#define MMIO_IFACE_INCLUDED
nkeynes@10
   165
#define MMIO_REGION_BEGIN(b,id,d) \
nkeynes@10
   166
extern struct mmio_region mmio_region_##id; \
nkeynes@10
   167
int32_t mmio_region_##id##_read(uint32_t); \
nkeynes@10
   168
void 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@10
   179
#endif
nkeynes@10
   180
.