Line 24... |
Line 24... |
* Of course, if anyone feels like perfecting it, feel free...
|
* Of course, if anyone feels like perfecting it, feel free...
|
*/
|
*/
|
|
|
#include <string.h>
|
#include <string.h>
|
|
|
|
#include "config.h"
|
|
|
|
#ifdef HAVE_INTTYPES_H
|
|
#include <inttypes.h>
|
|
#endif
|
|
|
|
#include "port.h"
|
|
#include "arch.h"
|
#include "dma.h"
|
#include "dma.h"
|
#include "sim-config.h"
|
#include "sim-config.h"
|
#include "pic.h"
|
#include "pic.h"
|
#include "abstract.h"
|
#include "abstract.h"
|
#include "fields.h"
|
#include "fields.h"
|
#include "debug.h"
|
#include "debug.h"
|
|
|
/* The representation of the DMA controllers */
|
/* The representation of the DMA controllers */
|
static struct dma_controller dmas[MAX_DMAS];
|
static struct dma_controller dmas[MAX_DMAS];
|
|
|
static unsigned long dma_read32( unsigned long addr );
|
static uint32_t dma_read32( oraddr_t addr );
|
static void dma_write32( unsigned long addr, unsigned long value );
|
static void dma_write32( oraddr_t addr, uint32_t value );
|
|
|
static unsigned long dma_read_ch_csr( struct dma_channel *channel );
|
static unsigned long dma_read_ch_csr( struct dma_channel *channel );
|
static void dma_write_ch_csr( struct dma_channel *channel, unsigned long value );
|
static void dma_write_ch_csr( struct dma_channel *channel, unsigned long value );
|
static void dma_controller_clock( struct dma_controller *dma );
|
static void dma_controller_clock( struct dma_controller *dma );
|
static void dma_load_descriptor( struct dma_channel *channel );
|
static void dma_load_descriptor( struct dma_channel *channel );
|
Line 84... |
Line 92... |
struct dma_controller *dma = &(dmas[i]);
|
struct dma_controller *dma = &(dmas[i]);
|
|
|
if ( dma->baseaddr == 0 )
|
if ( dma->baseaddr == 0 )
|
continue;
|
continue;
|
|
|
PRINTF( "\nDMA controller %u at 0x%08lX:\n", i, dma->baseaddr );
|
PRINTF( "\nDMA controller %u at 0x%"PRIxADDR":\n", i, dma->baseaddr );
|
PRINTF( "CSR : 0x%08lX\n", dma->regs.csr );
|
PRINTF( "CSR : 0x%08lX\n", dma->regs.csr );
|
PRINTF( "INT_MSK_A : 0x%08lX\n", dma->regs.int_msk_a );
|
PRINTF( "INT_MSK_A : 0x%08lX\n", dma->regs.int_msk_a );
|
PRINTF( "INT_MSK_B : 0x%08lX\n", dma->regs.int_msk_b );
|
PRINTF( "INT_MSK_B : 0x%08lX\n", dma->regs.int_msk_b );
|
PRINTF( "INT_SRC_A : 0x%08lX\n", dma->regs.int_src_a );
|
PRINTF( "INT_SRC_A : 0x%08lX\n", dma->regs.int_src_a );
|
PRINTF( "INT_SRC_B : 0x%08lX\n", dma->regs.int_src_b );
|
PRINTF( "INT_SRC_B : 0x%08lX\n", dma->regs.int_src_b );
|
Line 109... |
Line 117... |
}
|
}
|
}
|
}
|
|
|
|
|
/* Read a register */
|
/* Read a register */
|
unsigned long dma_read32( unsigned long addr )
|
uint32_t dma_read32( oraddr_t addr )
|
{
|
{
|
unsigned i;
|
unsigned i;
|
struct dma_controller *dma = NULL;
|
struct dma_controller *dma = NULL;
|
|
|
for ( i = 0; i < MAX_DMAS && dma == NULL; ++ i ) {
|
for ( i = 0; i < MAX_DMAS && dma == NULL; ++ i ) {
|
Line 121... |
Line 129... |
dma = &(dmas[i]);
|
dma = &(dmas[i]);
|
}
|
}
|
|
|
/* verify we found a controller */
|
/* verify we found a controller */
|
if ( dma == NULL ) {
|
if ( dma == NULL ) {
|
fprintf( stderr, "dma_read32( 0x%08lX ): Out of range\n", addr );
|
fprintf( stderr, "dma_read32( 0x%"PRIxADDR" ): Out of range\n", addr );
|
runtime.sim.cont_run = 0;
|
runtime.sim.cont_run = 0;
|
return 0;
|
return 0;
|
}
|
}
|
|
|
addr -= dma->baseaddr;
|
addr -= dma->baseaddr;
|
|
|
if ( addr % 4 != 0 ) {
|
if ( addr % 4 != 0 ) {
|
fprintf( stderr, "dma_read32( 0x%08lX ): Not register-aligned\n", addr + dma->baseaddr );
|
fprintf( stderr, "dma_read32( 0x%"PRIxADDR" ): Not register-aligned\n",
|
|
addr + dma->baseaddr );
|
runtime.sim.cont_run = 0;
|
runtime.sim.cont_run = 0;
|
return 0;
|
return 0;
|
}
|
}
|
|
|
if ( addr < DMA_CH_BASE ) {
|
if ( addr < DMA_CH_BASE ) {
|
Line 143... |
Line 152... |
case DMA_INT_MSK_A: return dma->regs.int_msk_a;
|
case DMA_INT_MSK_A: return dma->regs.int_msk_a;
|
case DMA_INT_MSK_B: return dma->regs.int_msk_b;
|
case DMA_INT_MSK_B: return dma->regs.int_msk_b;
|
case DMA_INT_SRC_A: return dma->regs.int_src_a;
|
case DMA_INT_SRC_A: return dma->regs.int_src_a;
|
case DMA_INT_SRC_B: return dma->regs.int_src_b;
|
case DMA_INT_SRC_B: return dma->regs.int_src_b;
|
default:
|
default:
|
fprintf( stderr, "dma_read32( 0x%08lX ): Illegal register\n", addr + dma->baseaddr );
|
fprintf( stderr, "dma_read32( 0x%"PRIxADDR" ): Illegal register\n",
|
|
addr + dma->baseaddr );
|
runtime.sim.cont_run = 0;
|
runtime.sim.cont_run = 0;
|
return 0;
|
return 0;
|
}
|
}
|
} else {
|
} else {
|
/* case of per-channel registers */
|
/* case of per-channel registers */
|
Line 182... |
Line 192... |
}
|
}
|
|
|
|
|
|
|
/* Write a register */
|
/* Write a register */
|
void dma_write32( unsigned long addr, unsigned long value )
|
void dma_write32( oraddr_t addr, uint32_t value )
|
{
|
{
|
unsigned i;
|
unsigned i;
|
struct dma_controller *dma = NULL;
|
struct dma_controller *dma = NULL;
|
|
|
/* Find which controller this is */
|
/* Find which controller this is */
|
Line 195... |
Line 205... |
dma = &(dmas[i]);
|
dma = &(dmas[i]);
|
}
|
}
|
|
|
/* verify we found a controller */
|
/* verify we found a controller */
|
if ( dma == NULL ) {
|
if ( dma == NULL ) {
|
fprintf( stderr, "dma_write32( 0x%08lX ): Out of range\n", addr );
|
fprintf( stderr, "dma_write32( 0x%"PRIxADDR" ): Out of range\n", addr );
|
runtime.sim.cont_run = 0;
|
runtime.sim.cont_run = 0;
|
return;
|
return;
|
}
|
}
|
|
|
addr -= dma->baseaddr;
|
addr -= dma->baseaddr;
|
|
|
if ( addr % 4 != 0 ) {
|
if ( addr % 4 != 0 ) {
|
fprintf( stderr, "dma_write32( 0x%08lX, 0x%08lX ): Not register-aligned\n", addr + dma->baseaddr, value );
|
fprintf( stderr, "dma_write32( 0x%"PRIxADDR", 0x%08"PRIx32" ): Not register-aligned\n", addr + dma->baseaddr, value );
|
runtime.sim.cont_run = 0;
|
runtime.sim.cont_run = 0;
|
return;
|
return;
|
}
|
}
|
|
|
/* case of global (not per-channel) registers */
|
/* case of global (not per-channel) registers */
|
Line 221... |
Line 231... |
case DMA_INT_MSK_A: dma->regs.int_msk_a = value; break;
|
case DMA_INT_MSK_A: dma->regs.int_msk_a = value; break;
|
case DMA_INT_MSK_B: dma->regs.int_msk_b = value; break;
|
case DMA_INT_MSK_B: dma->regs.int_msk_b = value; break;
|
case DMA_INT_SRC_A: dma->regs.int_src_a = value; break;
|
case DMA_INT_SRC_A: dma->regs.int_src_a = value; break;
|
case DMA_INT_SRC_B: dma->regs.int_src_b = value; break;
|
case DMA_INT_SRC_B: dma->regs.int_src_b = value; break;
|
default:
|
default:
|
fprintf( stderr, "dma_write32( 0x%08lX ): Illegal register\n", addr + dma->baseaddr );
|
fprintf( stderr, "dma_write32( 0x%"PRIxADDR" ): Illegal register\n",
|
|
addr + dma->baseaddr );
|
runtime.sim.cont_run = 0;
|
runtime.sim.cont_run = 0;
|
return;
|
return;
|
}
|
}
|
} else {
|
} else {
|
/* case of per-channel registers */
|
/* case of per-channel registers */
|