Search
lxdream.org :: lxdream/src/asic.c :: diff
lxdream 0.9.1
released Jun 29
Download Now
filename src/asic.c
changeset 302:96b5cc24309c
prev279:7bb759c23271
next305:1191085c5988
author nkeynes
date Wed Jan 17 21:27:20 2007 +0000 (13 years ago)
permissions -rw-r--r--
last change Rename SPUDMA to G2DMA (following KOS's lead)
Remove sh4r.icount (obsolete)
Rewrite G2 fifo status in terms of slice cycles
file annotate diff log raw
1.1 --- a/src/asic.c Sun Jan 14 02:54:40 2007 +0000
1.2 +++ b/src/asic.c Wed Jan 17 21:27:20 2007 +0000
1.3 @@ -1,5 +1,5 @@
1.4 /**
1.5 - * $Id: asic.c,v 1.23 2007-01-14 02:54:40 nkeynes Exp $
1.6 + * $Id: asic.c,v 1.24 2007-01-17 21:27:20 nkeynes Exp $
1.7 *
1.8 * Support for the miscellaneous ASIC functions (Primarily event multiplexing,
1.9 * and DMA).
1.10 @@ -44,28 +44,63 @@
1.11 static void asic_check_cleared_events( void );
1.12 static void asic_init( void );
1.13 static void asic_reset( void );
1.14 +static uint32_t asic_run_slice( uint32_t nanosecs );
1.15 static void asic_save_state( FILE *f );
1.16 static int asic_load_state( FILE *f );
1.17 +static uint32_t g2_update_fifo_status( uint32_t slice_cycle );
1.18
1.19 -struct dreamcast_module asic_module = { "ASIC", asic_init, asic_reset, NULL, NULL,
1.20 +struct dreamcast_module asic_module = { "ASIC", asic_init, asic_reset, NULL, asic_run_slice,
1.21 NULL, asic_save_state, asic_load_state };
1.22
1.23 -#define G2_BIT5_TICKS 8
1.24 -#define G2_BIT4_TICKS 16
1.25 -#define G2_BIT0_ON_TICKS 24
1.26 -#define G2_BIT0_OFF_TICKS 24
1.27 +#define G2_BIT5_TICKS 60
1.28 +#define G2_BIT4_TICKS 160
1.29 +#define G2_BIT0_ON_TICKS 120
1.30 +#define G2_BIT0_OFF_TICKS 420
1.31
1.32 struct asic_g2_state {
1.33 - unsigned int last_update_time;
1.34 - unsigned int bit5_off_timer;
1.35 - unsigned int bit4_on_timer;
1.36 - unsigned int bit4_off_timer;
1.37 - unsigned int bit0_on_timer;
1.38 - unsigned int bit0_off_timer;
1.39 + int bit5_off_timer;
1.40 + int bit4_on_timer;
1.41 + int bit4_off_timer;
1.42 + int bit0_on_timer;
1.43 + int bit0_off_timer;
1.44 };
1.45
1.46 static struct asic_g2_state g2_state;
1.47
1.48 +static uint32_t asic_run_slice( uint32_t nanosecs )
1.49 +{
1.50 + g2_update_fifo_status(nanosecs);
1.51 + if( g2_state.bit5_off_timer <= (int32_t)nanosecs ) {
1.52 + g2_state.bit5_off_timer = -1;
1.53 + } else {
1.54 + g2_state.bit5_off_timer -= nanosecs;
1.55 + }
1.56 +
1.57 + if( g2_state.bit4_off_timer <= (int32_t)nanosecs ) {
1.58 + g2_state.bit4_off_timer = -1;
1.59 + } else {
1.60 + g2_state.bit4_off_timer -= nanosecs;
1.61 + }
1.62 + if( g2_state.bit4_on_timer <= (int32_t)nanosecs ) {
1.63 + g2_state.bit4_on_timer = -1;
1.64 + } else {
1.65 + g2_state.bit4_on_timer -= nanosecs;
1.66 + }
1.67 +
1.68 + if( g2_state.bit0_off_timer <= (int32_t)nanosecs ) {
1.69 + g2_state.bit0_off_timer = -1;
1.70 + } else {
1.71 + g2_state.bit0_off_timer -= nanosecs;
1.72 + }
1.73 + if( g2_state.bit0_on_timer <= (int32_t)nanosecs ) {
1.74 + g2_state.bit0_on_timer = -1;
1.75 + } else {
1.76 + g2_state.bit0_on_timer -= nanosecs;
1.77 + }
1.78 +
1.79 + return nanosecs;
1.80 +}
1.81 +
1.82 static void asic_init( void )
1.83 {
1.84 register_io_region( &mmio_region_ASIC );
1.85 @@ -75,7 +110,7 @@
1.86
1.87 static void asic_reset( void )
1.88 {
1.89 - memset( &g2_state, 0, sizeof(g2_state) );
1.90 + memset( &g2_state, 0xFF, sizeof(g2_state) );
1.91 }
1.92
1.93 static void asic_save_state( FILE *f )
1.94 @@ -92,53 +127,84 @@
1.95 }
1.96
1.97
1.98 -/* FIXME: Handle rollover */
1.99 +/**
1.100 + * Setup the timers for the 3 FIFO status bits following a write through the G2
1.101 + * bus from the SH4 side. The timing is roughly as follows: (times are
1.102 + * approximate based on software readings - I wouldn't take this as gospel but
1.103 + * it seems to be enough to fool most programs).
1.104 + * 0ns: Bit 5 (Input fifo?) goes high immediately on the write
1.105 + * 40ns: Bit 5 goes low and bit 4 goes high
1.106 + * 120ns: Bit 4 goes low, bit 0 goes high
1.107 + * 240ns: Bit 0 goes low.
1.108 + *
1.109 + * Additional writes while the FIFO is in operation extend the time that the
1.110 + * bits remain high as one might expect, without altering the time at which
1.111 + * they initially go high.
1.112 + */
1.113 void asic_g2_write_word()
1.114 {
1.115 - g2_state.last_update_time = sh4r.icount;
1.116 - g2_state.bit5_off_timer = sh4r.icount + G2_BIT5_TICKS;
1.117 - if( g2_state.bit4_off_timer < sh4r.icount )
1.118 - g2_state.bit4_on_timer = sh4r.icount + G2_BIT5_TICKS;
1.119 - g2_state.bit4_off_timer = max(sh4r.icount,g2_state.bit4_off_timer) + G2_BIT4_TICKS;
1.120 - if( g2_state.bit0_off_timer < sh4r.icount ) {
1.121 - g2_state.bit0_on_timer = sh4r.icount + G2_BIT0_ON_TICKS;
1.122 + if( g2_state.bit5_off_timer < (int32_t)sh4r.slice_cycle ) {
1.123 + g2_state.bit5_off_timer = sh4r.slice_cycle + G2_BIT5_TICKS;
1.124 + } else {
1.125 + g2_state.bit5_off_timer += G2_BIT5_TICKS;
1.126 + }
1.127 +
1.128 + if( g2_state.bit4_on_timer < (int32_t)sh4r.slice_cycle ) {
1.129 + g2_state.bit4_on_timer = sh4r.slice_cycle + G2_BIT5_TICKS;
1.130 + }
1.131 +
1.132 + if( g2_state.bit4_off_timer < (int32_t)sh4r.slice_cycle ) {
1.133 + g2_state.bit4_off_timer = g2_state.bit4_on_timer + G2_BIT4_TICKS;
1.134 + } else {
1.135 + g2_state.bit4_off_timer += G2_BIT4_TICKS;
1.136 + }
1.137 +
1.138 + if( g2_state.bit0_on_timer < (int32_t)sh4r.slice_cycle ) {
1.139 + g2_state.bit0_on_timer = sh4r.slice_cycle + G2_BIT0_ON_TICKS;
1.140 + }
1.141 +
1.142 + if( g2_state.bit0_off_timer < (int32_t)sh4r.slice_cycle ) {
1.143 g2_state.bit0_off_timer = g2_state.bit0_on_timer + G2_BIT0_OFF_TICKS;
1.144 } else {
1.145 g2_state.bit0_off_timer += G2_BIT0_OFF_TICKS;
1.146 }
1.147 +
1.148 MMIO_WRITE( ASIC, G2STATUS, MMIO_READ(ASIC, G2STATUS) | 0x20 );
1.149 }
1.150
1.151 -static uint32_t g2_read_status()
1.152 +static uint32_t g2_update_fifo_status( uint32_t nanos )
1.153 {
1.154 - if( sh4r.icount < g2_state.last_update_time ) {
1.155 - /* Rollover */
1.156 - if( g2_state.last_update_time < g2_state.bit5_off_timer )
1.157 - g2_state.bit5_off_timer = 0;
1.158 - if( g2_state.last_update_time < g2_state.bit4_off_timer )
1.159 - g2_state.bit4_off_timer = 0;
1.160 - if( g2_state.last_update_time < g2_state.bit4_on_timer )
1.161 - g2_state.bit4_on_timer = 0;
1.162 - if( g2_state.last_update_time < g2_state.bit0_off_timer )
1.163 - g2_state.bit0_off_timer = 0;
1.164 - if( g2_state.last_update_time < g2_state.bit0_on_timer )
1.165 - g2_state.bit0_on_timer = 0;
1.166 + uint32_t val = MMIO_READ( ASIC, G2STATUS );
1.167 + if( ((uint32_t)g2_state.bit5_off_timer) <= nanos ) {
1.168 + val = val & (~0x20);
1.169 + g2_state.bit5_off_timer = -1;
1.170 }
1.171 - uint32_t val = MMIO_READ( ASIC, G2STATUS );
1.172 - if( g2_state.bit5_off_timer <= sh4r.icount )
1.173 - val = val & (~0x20);
1.174 - if( g2_state.bit4_off_timer <= sh4r.icount ||
1.175 - (sh4r.icount + G2_BIT5_TICKS) < g2_state.bit4_off_timer )
1.176 + if( ((uint32_t)g2_state.bit4_on_timer) <= nanos ) {
1.177 + val = val | 0x10;
1.178 + g2_state.bit4_on_timer = -1;
1.179 + }
1.180 + if( ((uint32_t)g2_state.bit4_off_timer) <= nanos ) {
1.181 val = val & (~0x10);
1.182 - else if( g2_state.bit4_on_timer <= sh4r.icount )
1.183 - val = val | 0x10;
1.184 - if( g2_state.bit0_off_timer <= sh4r.icount )
1.185 + g2_state.bit4_off_timer = -1;
1.186 + }
1.187 +
1.188 + if( ((uint32_t)g2_state.bit0_on_timer) <= nanos ) {
1.189 + val = val | 0x01;
1.190 + g2_state.bit0_on_timer = -1;
1.191 + }
1.192 + if( ((uint32_t)g2_state.bit0_off_timer) <= nanos ) {
1.193 val = val & (~0x01);
1.194 - else if( g2_state.bit0_on_timer <= sh4r.icount )
1.195 - val = val | 0x01;
1.196 - return val | 0x0E;
1.197 + g2_state.bit0_off_timer = -1;
1.198 + }
1.199 +
1.200 + MMIO_WRITE( ASIC, G2STATUS, val );
1.201 + return val;
1.202 }
1.203
1.204 +static int g2_read_status() {
1.205 + return g2_update_fifo_status( sh4r.slice_cycle );
1.206 +}
1.207 +
1.208
1.209 void asic_event( int event )
1.210 {
1.211 @@ -183,13 +249,13 @@
1.212 {
1.213 uint32_t offset = channel << 5;
1.214
1.215 - if( MMIO_READ( EXTDMA, SPUDMA0CTL1 + offset ) == 1 ) {
1.216 - if( MMIO_READ( EXTDMA, SPUDMA0CTL2 + offset ) == 1 ) {
1.217 - uint32_t extaddr = MMIO_READ( EXTDMA, SPUDMA0EXT + offset );
1.218 - uint32_t sh4addr = MMIO_READ( EXTDMA, SPUDMA0SH4 + offset );
1.219 - uint32_t length = MMIO_READ( EXTDMA, SPUDMA0SIZ + offset ) & 0x1FFFFFFF;
1.220 - uint32_t dir = MMIO_READ( EXTDMA, SPUDMA0DIR + offset );
1.221 - uint32_t mode = MMIO_READ( EXTDMA, SPUDMA0MOD + offset );
1.222 + if( MMIO_READ( EXTDMA, G2DMA0CTL1 + offset ) == 1 ) {
1.223 + if( MMIO_READ( EXTDMA, G2DMA0CTL2 + offset ) == 1 ) {
1.224 + uint32_t extaddr = MMIO_READ( EXTDMA, G2DMA0EXT + offset );
1.225 + uint32_t sh4addr = MMIO_READ( EXTDMA, G2DMA0SH4 + offset );
1.226 + uint32_t length = MMIO_READ( EXTDMA, G2DMA0SIZ + offset ) & 0x1FFFFFFF;
1.227 + uint32_t dir = MMIO_READ( EXTDMA, G2DMA0DIR + offset );
1.228 + uint32_t mode = MMIO_READ( EXTDMA, G2DMA0MOD + offset );
1.229 char buf[length];
1.230 if( dir == 0 ) { /* SH4 to device */
1.231 mem_copy_from_sh4( buf, sh4addr, length );
1.232 @@ -198,10 +264,10 @@
1.233 mem_copy_from_sh4( buf, extaddr, length );
1.234 mem_copy_to_sh4( sh4addr, buf, length );
1.235 }
1.236 - MMIO_WRITE( EXTDMA, SPUDMA0CTL2 + offset, 0 );
1.237 - asic_event( EVENT_SPU_DMA0 + channel );
1.238 + MMIO_WRITE( EXTDMA, G2DMA0CTL2 + offset, 0 );
1.239 + asic_event( EVENT_G2_DMA0 + channel );
1.240 } else {
1.241 - MMIO_WRITE( EXTDMA, SPUDMA0CTL2 + offset, 0 );
1.242 + MMIO_WRITE( EXTDMA, G2DMA0CTL2 + offset, 0 );
1.243 }
1.244 }
1.245 }
1.246 @@ -368,34 +434,34 @@
1.247 idereg.interface_enabled = FALSE;
1.248 }
1.249 break;
1.250 - case SPUDMA0CTL1:
1.251 - case SPUDMA0CTL2:
1.252 + case G2DMA0CTL1:
1.253 + case G2DMA0CTL2:
1.254 MMIO_WRITE( EXTDMA, reg, val );
1.255 g2_dma_transfer( 0 );
1.256 break;
1.257 - case SPUDMA0UN1:
1.258 + case G2DMA0STOP:
1.259 break;
1.260 - case SPUDMA1CTL1:
1.261 - case SPUDMA1CTL2:
1.262 + case G2DMA1CTL1:
1.263 + case G2DMA1CTL2:
1.264 MMIO_WRITE( EXTDMA, reg, val );
1.265 g2_dma_transfer( 1 );
1.266 break;
1.267
1.268 - case SPUDMA1UN1:
1.269 + case G2DMA1STOP:
1.270 break;
1.271 - case SPUDMA2CTL1:
1.272 - case SPUDMA2CTL2:
1.273 + case G2DMA2CTL1:
1.274 + case G2DMA2CTL2:
1.275 MMIO_WRITE( EXTDMA, reg, val );
1.276 g2_dma_transfer( 2 );
1.277 break;
1.278 - case SPUDMA2UN1:
1.279 + case G2DMA2STOP:
1.280 break;
1.281 - case SPUDMA3CTL1:
1.282 - case SPUDMA3CTL2:
1.283 + case G2DMA3CTL1:
1.284 + case G2DMA3CTL2:
1.285 MMIO_WRITE( EXTDMA, reg, val );
1.286 g2_dma_transfer( 3 );
1.287 break;
1.288 - case SPUDMA3UN1:
1.289 + case G2DMA3STOP:
1.290 break;
1.291 case PVRDMA2CTL1:
1.292 case PVRDMA2CTL2:
.