LOGIN   :::   RECOVER PASS   :::   GET ACCOUNT    
Browse
  • Projects
  • Code (CVS)
  • Forums
  • News
  • Articles
  • Polls
  •  
    OpenCores
  • FAQ
  • CVS HowTo
  • Mission
  • Media
  • Tools
  • Advertise
  • Mirrors
  • Logos
  • Contact us
  • Find Resources
  • Job Opportunity
  •  
    Tools
  • Search
      
  • Download Cores (CVSGet)
  •  
    More
  • Wishbone
  • Perlilog
  • EDA tools
  • OpenTech CD
  •  
    Navigation: All forums > Openrisc > Message List > Message Post

    Message

    Reply | Reply all
    Date Prev | Date Next | Thread Prev | Thread Next Date Index | Thread Index

    From: György 'nog' Jeney<nog@s...>
    Date: Fri Feb 11 10:48:46 CET 2005
    Subject: [openrisc] [or1ksim #25] Cleanup dma peripheral
    Top
    > This cleans up the dma peripheral. One less *_clock in the main loop! This
    > also fixes compilation of the dmatest test.

    The DMA test fixes have gone into cvs. Here's a patch that will apply cleanly
    against current cvs.

    > ChangeLog:
    > * Cleanup dma peripheral useing the new callbacks.

    nog.
    -------------- next part --------------
    --- sim-config.h 2005-02-04 16:25:08.000000000 +0100
    +++ ../or1ksim-ac/sim-config.h 2005-02-05 10:17:30.000000000 +0100
    @@ -24,7 +24,6 @@

    /* Simulator configuration macros. Eventually this one will be a lot bigger. */

    -#define MAX_DMAS 4 /* Max. number of DMA controllers */
    #define MAX_ETHERNETS 4 /* Max. number of Ethernet MACs */
    #define MAX_GPIOS 4 /* Max. number of GPIO modules */
    #define MAX_MEMORIES 16 /* Max. number of memory devices attached */
    @@ -42,13 +41,6 @@
    int enabled; /* Is tick timer enabled? */
    } tick;

    - int ndmas;
    - struct {
    - unsigned long baseaddr;
    - int irq; /* IRQ of this device */
    - unsigned long vapi_id; /* VAPI id for this instance */
    - } dmas[MAX_DMAS];
    -
    int nethernets;
    struct {
    unsigned long baseaddr;
    --- sim-cmd.c 2005-02-04 15:55:48.000000000 +0100
    +++ ../or1ksim-ac/sim-cmd.c 2005-02-05 10:18:25.000000000 +0100
    @@ -60,7 +60,6 @@
    #include "icache_model.h"
    #include "dcache_model.h"
    #include "branch_predict.h"
    -#include "dma.h"
    #include "ethernet.h"
    #include "gpio.h"
    #include "ps2kbd.h"
    @@ -423,7 +432,6 @@
    if (config.bpb.btic) btic_info();

    if (config.mc.enabled) mc_status();
    - if (config.ndmas) dma_status();
    if (config.nethernets) eth_status();
    if (config.ngpios) gpio_status();
    kbd_info();
    --- sim.cfg 2005-02-04 16:25:08.000000000 +0100
    +++ ../or1ksim-ac/sim.cfg 2005-02-05 11:19:39.000000000 +0100
    @@ -643,11 +643,6 @@

    This section configures the DMAs

    - ndmas = <value>
    - make specified number of instances, configure each
    - instance within device - enddevice construct.
    -
    - instance specific:
    baseaddr = <hex_value>
    address of first DMA register for this device

    @@ -659,14 +654,8 @@
    */

    section dma
    - ndmas = 0
    -
    - /*
    - device 0
    - baseaddr = 0x9a000000
    - irq = 11
    - enddevice
    - */
    + baseaddr = 0x9a000000
    + irq = 11
    end


    --- sim-config.c 2005-02-05 11:26:28.000000000 +0100
    +++ ../or1ksim-ac/sim-config.c 2005-02-05 10:18:09.000000000 +0100
    @@ -124,9 +126,6 @@
    /* Memory Controller */
    config.mc.enabled = 0;

    - /* DMAs */
    - config.ndmas = 0;
    -
    /* CPU */
    config.cpu.superscalar = 0;
    config.sim.history = 0;
    @@ -898,15 +902,6 @@

    fprintf (f, " tick:{enabled:%i},\n", config.tick.enabled);

    - fprintf (f, " ndmas:%i, dmas:{", config.ndmas); - comma = 0; - for (i = 0; i < config.ndmas; i++) { - fprintf (f, "%s\n {baseaddr:0x%08lx, irq:%i, vapi_id:0x%08lx}", - comma ? "," :"", config.dmas[i].baseaddr, config.dmas[i].irq, config.dmas[i].vapi_id); - comma = 1; - } - fprintf (f, "},\n"); - fprintf (f, " nethernets:%i, ethernets:{", config.nethernets); comma = 0; for (i = 0; i < config.nethernets; i++) { --- toplevel.c 2005-02-05 11:26:28.000000000 +0100 +++ ../or1ksim-ac/toplevel.c 2005-02-05 10:17:09.000000000 +0100 @@ -47,7 +47,6 @@ #include "sim-config.h" #include "spr_defs.h" #include "sprs.h" -#include "dma.h" #include "ps2kbd.h" #include "vapi.h" #include "gdbcomm.h" @@ -169,7 +168,6 @@ cur_reset = cur_reset->next; } - dma_reset(); eth_reset(); gpio_reset(); kbd_reset (); @@ -446,7 +444,6 @@ if (config.ic.enabled) ic_clock(); } - if (config.dmas) dma_clock(); if (config.ethernets) eth_clock(); if (config.ngpios) gpio_clock(); if (config.vapi.enabled && runtime.vapi.enabled) vapi_check(); --- peripheral/dma.c 2005-02-05 15:06:48.000000000 +0100 +++ ../or1ksim-ac/peripheral/dma.c 2005-02-05 14:55:29.000000000 +0100 @@ -39,102 +39,88 @@ #include "pic.h" #include "abstract.h" #include "fields.h" +#include "sched.h" #include "debug.h" -/* The representation of the DMA controllers */ -static struct dma_controller dmas[MAX_DMAS]; +/* We keep a copy of all our controllers because we have to export an interface + * to other peripherals eg. ethernet */ +static struct dma_controller *dmas = NULL; static uint32_t dma_read32( oraddr_t addr, void *dat ); static void dma_write32( oraddr_t addr, uint32_t value, void *dat ); 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_controller_clock( struct dma_controller *dma ); +void dma_controller_clock( struct dma_controller *dma ); static void dma_load_descriptor( struct dma_channel *channel ); static void dma_init_transfer( struct dma_channel *channel ); static void dma_channel_terminate_transfer( struct dma_channel *channel, int generate_interrupt ); -static void masked_increase( unsigned long *value, unsigned long mask ); +void dma_channel_clock( void *dat ); + +static void masked_increase( oraddr_t *value, unsigned long mask ); #define CHANNEL_ND_I(ch) (TEST_FLAG(ch->regs.csr,DMA_CH_CSR,MODE) && TEST_FLAG(ch->regs.csr,DMA_CH_CSR,USE_ED) && ch->dma_nd_i) /* Reset. Initializes all registers to default and places devices in memory address space. */ -void dma_reset() +void dma_reset(void *dat) { - unsigned i; + struct dma_controller *dma = dat; + unsigned channel_number; + + memset( dma->ch, 0, sizeof(dma->ch) ); - memset( dmas, 0, sizeof(dmas) ); + dma->regs.csr = 0; + dma->regs.int_msk_a = 0; + dma->regs.int_msk_b = 0; + dma->regs.int_src_a = 0; + dma->regs.int_src_b = 0; - for ( i = 0; i < config.ndmas; ++ i ) { - struct dma_controller *dma = &(dmas[i]); - unsigned channel_number; - - dma->baseaddr = config.dmas[i].baseaddr; - dma->irq = config.dmas[i].irq; - for ( channel_number = 0; channel_number < DMA_NUM_CHANNELS; ++ channel_number ) { - dma->ch[channel_number].controller = &(dmas[i]); - dma->ch[channel_number].channel_number = channel_number; - dma->ch[channel_number].channel_mask = 1LU << channel_number; - dma->ch[channel_number].regs.am0 = dma->ch[channel_number].regs.am1 = 0xFFFFFFFC; - } - if ( dma->baseaddr != 0 ) - register_memoryarea( dma->baseaddr, DMA_ADDR_SPACE, 4, 0, dma_read32, dma_write32, NULL ); + for ( channel_number = 0; channel_number < DMA_NUM_CHANNELS; ++ channel_number ) { + dma->ch[channel_number].controller = dma; + dma->ch[channel_number].channel_number = channel_number; + dma->ch[channel_number].channel_mask = 1LU << channel_number; + dma->ch[channel_number].regs.am0 = dma->ch[channel_number].regs.am1 = 0xFFFFFFFC; } } /* Print register values on stdout */ -void dma_status( void ) +void dma_status( void *dat ) { unsigned i, j; + struct dma_controller *dma = dat; - for ( i = 0; i < config.ndmas; ++ i ) { - struct dma_controller *dma = &(dmas[i]); - - if ( dma->baseaddr == 0 ) - continue; + if ( dma->baseaddr == 0 ) + return; - PRINTF( "\nDMA controller %u at 0x%"PRIxADDR":\n", i, dma->baseaddr ); - PRINTF( "CSR : 0x%08lX\n", dma->regs.csr ); - 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_SRC_A : 0x%08lX\n", dma->regs.int_src_a ); - PRINTF( "INT_SRC_B : 0x%08lX\n", dma->regs.int_src_b ); - - for ( j = 0; j < DMA_NUM_CHANNELS; ++ j ) { - struct dma_channel *channel = &(dma->ch[j]); - if ( !channel->referenced ) - continue; - PRINTF( "CH%u_CSR : 0x%08lX\n", j, channel->regs.csr ); - PRINTF( "CH%u_SZ : 0x%08lX\n", j, channel->regs.sz ); - PRINTF( "CH%u_A0 : 0x%08lX\n", j, channel->regs.a0 ); - PRINTF( "CH%u_AM0 : 0x%08lX\n", j, channel->regs.am0 ); - PRINTF( "CH%u_A1 : 0x%08lX\n", j, channel->regs.a1 ); - PRINTF( "CH%u_AM1 : 0x%08lX\n", j, channel->regs.am1 ); - PRINTF( "CH%u_DESC : 0x%08lX\n", j, channel->regs.desc ); - PRINTF( "CH%u_SWPTR : 0x%08lX\n", j, channel->regs.swptr ); - } + PRINTF( "\nDMA controller %u at 0x%"PRIxADDR":\n", i, dma->baseaddr ); + PRINTF( "CSR : 0x%08lX\n", dma->regs.csr ); + 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_SRC_A : 0x%08lX\n", dma->regs.int_src_a ); + PRINTF( "INT_SRC_B : 0x%08lX\n", dma->regs.int_src_b ); + + for ( j = 0; j < DMA_NUM_CHANNELS; ++ j ) { + struct dma_channel *channel = &(dma->ch[j]); + if ( !channel->referenced ) + continue; + PRINTF( "CH%u_CSR : 0x%08lX\n", j, channel->regs.csr ); + PRINTF( "CH%u_SZ : 0x%08lX\n", j, channel->regs.sz ); + PRINTF( "CH%u_A0 : 0x%08lX\n", j, channel->regs.a0 ); + PRINTF( "CH%u_AM0 : 0x%08lX\n", j, channel->regs.am0 ); + PRINTF( "CH%u_A1 : 0x%08lX\n", j, channel->regs.a1 ); + PRINTF( "CH%u_AM1 : 0x%08lX\n", j, channel->regs.am1 ); + PRINTF( "CH%u_DESC : 0x%08lX\n", j, channel->regs.desc ); + PRINTF( "CH%u_SWPTR : 0x%08lX\n", j, channel->regs.swptr ); } } - + /* Read a register */ uint32_t dma_read32( oraddr_t addr, void *dat ) { - unsigned i; - struct dma_controller *dma = NULL; - - for ( i = 0; i < MAX_DMAS && dma == NULL; ++ i ) { - if ( addr >= dmas[i].baseaddr && addr < dmas[i].baseaddr + DMA_ADDR_SPACE ) - dma = &(dmas[i]); - } - - /* verify we found a controller */ - if ( dma == NULL ) { - fprintf( stderr, "dma_read32( 0x%"PRIxADDR" ): Out of range\n", addr ); - runtime.sim.cont_run = 0; - return 0; - } + struct dma_controller *dma = dat; addr -= dma->baseaddr; @@ -174,6 +160,7 @@ case DMA_CH_SWPTR: return dma->ch[chno].regs.swptr; } } + return 0; } @@ -196,21 +183,7 @@ /* Write a register */ void dma_write32( oraddr_t addr, uint32_t value, void *dat ) { - unsigned i; - struct dma_controller *dma = NULL; - - /* Find which controller this is */ - for ( i = 0; i < MAX_DMAS && dma == NULL; ++ i ) { - if ( (addr >= dmas[i].baseaddr) && (addr < dmas[i].baseaddr + DMA_ADDR_SPACE) ) - dma = &(dmas[i]); - } - - /* verify we found a controller */ - if ( dma == NULL ) { - fprintf( stderr, "dma_write32( 0x%"PRIxADDR" ): Out of range\n", addr ); - runtime.sim.cont_run = 0; - return; - } + struct dma_controller *dma = dat; addr -= dma->baseaddr; @@ -263,141 +236,106 @@ */ void dma_write_ch_csr( struct dma_channel *channel, unsigned long value ) { + /* Check if we should *start* a transfer */ + if ( !TEST_FLAG( channel->regs.csr, DMA_CH_CSR, CH_EN ) && + TEST_FLAG( value, DMA_CH_CSR, CH_EN )) + SCHED_ADD( dma_channel_clock, channel, runtime.sim.cycles + 1 ); + else if ( !TEST_FLAG( value, DMA_CH_CSR, CH_EN ) ) + /* The CH_EN flag is clear, check if we have a transfer in progress and + * clear it */ + SCHED_FIND_REMOVE( dma_channel_clock, channel ); + /* Copy the writable bits to the channel CSR */ channel->regs.csr &= ~DMA_CH_CSR_WRITE_MASK; channel->regs.csr |= value & DMA_CH_CSR_WRITE_MASK; } -/* - * Simulation of control signals - * To be used by simulations for other devices, e.g. ethernet - */ - -void set_dma_req_i( unsigned dma_controller, unsigned channel ) -{ - dmas[dma_controller].ch[channel].dma_req_i = 1; -} -void clear_dma_req_i( unsigned dma_controller, unsigned channel ) -{ - dmas[dma_controller].ch[channel].dma_req_i = 0; -} - -void set_dma_nd_i( unsigned dma_controller, unsigned channel ) -{ - dmas[dma_controller].ch[channel].dma_nd_i = 1; -} - -void clear_dma_nd_i( unsigned dma_controller, unsigned channel ) -{ - dmas[dma_controller].ch[channel].dma_nd_i = 0; -} - -unsigned check_dma_ack_o( unsigned dma_controller, unsigned channel ) -{ - return dmas[dma_controller].ch[channel].dma_ack_o; -} - - - -/* Simulation hook. Must be called every clock cycle to simulate DMA. */ -void dma_clock() -{ - unsigned i; - for ( i = 0; i < MAX_DMAS; ++ i ) { - if ( dmas[i].baseaddr != 0 ) - dma_controller_clock( &(dmas[i]) ); - } -} - - -/* Clock tick for one DMA controller. +/* Clock tick for one channel on one DMA controller. * This does the actual "DMA" operation. * One chunk is transferred per clock. */ -void dma_controller_clock( struct dma_controller *dma ) +void dma_channel_clock( void *dat ) { - unsigned chno; int breakpoint = 0; + struct dma_channel *channel = dat; - for ( chno = 0; chno < DMA_NUM_CHANNELS; ++ chno ) { - struct dma_channel *channel = &(dma->ch[chno]); - - /* check if this channel is enabled */ - if ( !TEST_FLAG( channel->regs.csr, DMA_CH_CSR, CH_EN ) ) - continue; - - /* Do we need to abort? */ - if ( TEST_FLAG( channel->regs.csr, DMA_CH_CSR, STOP ) ) { - debug( 3, "DMA: STOP requested\n" ); - CLEAR_FLAG( channel->regs.csr, DMA_CH_CSR, CH_EN ); - CLEAR_FLAG( channel->regs.csr, DMA_CH_CSR, BUSY ); - SET_FLAG( channel->regs.csr, DMA_CH_CSR, ERR ); - - if ( TEST_FLAG( channel->regs.csr, DMA_CH_CSR, INE_ERR ) && - (channel->controller->regs.int_msk_a & channel->channel_mask) ) { - SET_FLAG( channel->regs.csr, DMA_CH_CSR, INT_ERR ); - channel->controller->regs.int_src_a = channel->channel_mask; - report_interrupt( channel->controller->irq ); - } - - continue; - } - - /* In HW Handshake mode, only work when dma_req_i asserted */ - if ( TEST_FLAG( channel->regs.csr, DMA_CH_CSR, MODE ) && - !channel->dma_req_i ) { - continue; + /* Do we need to abort? */ + if ( TEST_FLAG( channel->regs.csr, DMA_CH_CSR, STOP ) ) { + debug( 3, "DMA: STOP requested\n" ); + CLEAR_FLAG( channel->regs.csr, DMA_CH_CSR, CH_EN ); + CLEAR_FLAG( channel->regs.csr, DMA_CH_CSR, BUSY ); + SET_FLAG( channel->regs.csr, DMA_CH_CSR, ERR ); + + if ( TEST_FLAG( channel->regs.csr, DMA_CH_CSR, INE_ERR ) && + (channel->controller->regs.int_msk_a & channel->channel_mask) ) { + SET_FLAG( channel->regs.csr, DMA_CH_CSR, INT_ERR ); + channel->controller->regs.int_src_a = channel->channel_mask; + report_interrupt( channel->controller->irq ); } - /* If this is the first cycle of the transfer, initialize our state */ - if ( !TEST_FLAG( channel->regs.csr, DMA_CH_CSR, BUSY ) ) { - debug( 4, "DMA: Starting new transfer\n" ); - - CLEAR_FLAG( channel->regs.csr, DMA_CH_CSR, DONE ); - CLEAR_FLAG( channel->regs.csr, DMA_CH_CSR, ERR ); - SET_FLAG( channel->regs.csr, DMA_CH_CSR, BUSY ); - - /* If using linked lists, copy the appropriate fields to our registers */ - if ( TEST_FLAG( channel->regs.csr, DMA_CH_CSR, USE_ED ) ) - dma_load_descriptor( channel ); - else - channel->load_next_descriptor_when_done = 0; - - /* Set our internal status */ - dma_init_transfer( channel ); - - /* Might need to skip descriptor */ - if ( CHANNEL_ND_I( channel ) ) { - debug( 3, "DMA: dma_nd_i asserted before dma_req_i, skipping descriptor\n" ); - dma_channel_terminate_transfer( channel, 0 ); - continue; - } - } + return; + } - /* Transfer one word */ - set_mem32( channel->destination, eval_mem32( channel->source, &breakpoint ), &breakpoint ); + /* In HW Handshake mode, only work when dma_req_i asserted */ + if ( TEST_FLAG(channel->regs.csr, DMA_CH_CSR, MODE) && !channel->dma_req_i ) { + /* Reschedule */ + SCHED_ADD( dma_channel_clock, dat, runtime.sim.cycles + 1 ); + return; + } - /* Advance the source and destionation pointers */ - masked_increase( &(channel->source), channel->source_mask ); - masked_increase( &(channel->destination), channel->destination_mask ); - ++ channel->words_transferred; + /* If this is the first cycle of the transfer, initialize our state */ + if ( !TEST_FLAG( channel->regs.csr, DMA_CH_CSR, BUSY ) ) { + debug( 4, "DMA: Starting new transfer\n" ); + + CLEAR_FLAG( channel->regs.csr, DMA_CH_CSR, DONE ); + CLEAR_FLAG( channel->regs.csr, DMA_CH_CSR, ERR ); + SET_FLAG( channel->regs.csr, DMA_CH_CSR, BUSY ); + + /* If using linked lists, copy the appropriate fields to our registers */ + if ( TEST_FLAG( channel->regs.csr, DMA_CH_CSR, USE_ED ) ) + dma_load_descriptor( channel ); + else + channel->load_next_descriptor_when_done = 0; - /* Have we finished a whole chunk? */ - channel->dma_ack_o = (channel->words_transferred % channel->chunk_size == 0); + /* Set our internal status */ + dma_init_transfer( channel ); - /* When done with a chunk, check for dma_nd_i */ + /* Might need to skip descriptor */ if ( CHANNEL_ND_I( channel ) ) { - debug( 3, "DMA: dma_nd_i asserted\n" ); + debug( 3, "DMA: dma_nd_i asserted before dma_req_i, skipping descriptor\n" ); dma_channel_terminate_transfer( channel, 0 ); - continue; + return; } + } + + /* Transfer one word */ + set_mem32( channel->destination, eval_mem32( channel->source, &breakpoint ), &breakpoint ); - /* Are we done? */ - if ( channel->words_transferred >= channel->total_size ) - dma_channel_terminate_transfer( channel, 1 ); + /* Advance the source and destionation pointers */ + masked_increase( &(channel->source), channel->source_mask ); + masked_increase( &(channel->destination), channel->destination_mask ); + ++ channel->words_transferred; + + /* Have we finished a whole chunk? */ + channel->dma_ack_o = (channel->words_transferred % channel->chunk_size == 0); + + /* When done with a chunk, check for dma_nd_i */ + if ( CHANNEL_ND_I( channel ) ) { + debug( 3, "DMA: dma_nd_i asserted\n" ); + dma_channel_terminate_transfer( channel, 0 ); + return; + } + + /* Are we done? */ + if ( channel->words_transferred >= channel->total_size ) { + dma_channel_terminate_transfer( channel, 1 ); + return; } + + /* Reschedule to transfer the next chunk */ + SCHED_ADD( dma_channel_clock, dat, runtime.sim.cycles + 1 ); } @@ -448,6 +386,8 @@ if ( channel->load_next_descriptor_when_done ) { dma_load_descriptor( channel ); dma_init_transfer( channel ); + /* Reschedule */ + SCHED_ADD( dma_channel_clock, channel, runtime.sim.cycles + 1 ); return; } @@ -460,7 +400,7 @@ /* If needed, write amount of data transferred back to memory */ if ( TEST_FLAG( channel->regs.csr, DMA_CH_CSR, SZ_WB ) && TEST_FLAG( channel->regs.csr, DMA_CH_CSR, USE_ED ) ) { - /* TODO: What should we write back? Doc says "total number of remaining bytes" !? */ + /* TODO: What should we write back? Doc says "total number of remaining bytes" !? */ unsigned long remaining_words = channel->total_size - channel->words_transferred; SET_FIELD( channel->regs.sz, DMA_DESC_CSR, TOT_SZ, remaining_words ); } @@ -484,51 +424,112 @@ } /* Utility function: Add 4 to a value with a mask */ -void masked_increase( unsigned long *value, unsigned long mask ) +static void masked_increase( oraddr_t *value, unsigned long mask ) { *value = (*value & ~mask) | ((*value + 4) & mask); } -/*----------------------------------------------------[ DMA configuration ]---*/ -void dma_ndmas(union param_val val, void *dat) +/*-------------------------------------------[ DMA<->Peripheral interface ]---*/ +/* + * Simulation of control signals + * To be used by simulations for other devices, e.g. ethernet + */ + +void set_dma_req_i( struct dma_channel *channel ) { - if (val.int_val >= 0 && val.int_val < MAX_DMAS) - config.ndmas = val.int_val; - else - CONFIG_ERROR("invalid number of devices."); + channel->dma_req_i = 1; } +void clear_dma_req_i( struct dma_channel *channel ) +{ + channel->dma_req_i = 0; +} + +void set_dma_nd_i( struct dma_channel *channel ) +{ + channel->dma_nd_i = 1; +} + +void clear_dma_nd_i( struct dma_channel *channel ) +{ + channel->dma_nd_i = 0; +} + +unsigned check_dma_ack_o( struct dma_channel *channel ) +{ + return channel->dma_ack_o; +} + +struct dma_channel *find_dma_controller_ch( unsigned controller, + unsigned channel ) +{ + struct dma_controller *cur = dmas; + + while( cur && controller ) { + cur = cur->next; + controller--; + } + + if( !cur ) + return NULL; + + return &(cur->ch[channel]); +} + + +/*----------------------------------------------------[ DMA configuration ]---*/ void dma_baseaddr(union param_val val, void *dat) { - if (current_device >= 0 && current_device < config.ndmas) - config.dmas[current_device].baseaddr = val.addr_val; - else - CONFIG_ERROR("invalid device number."); + struct dma_controller *dma = dat; + dma->baseaddr = val.addr_val; } void dma_irq(union param_val val, void *dat) { - if (current_device >= 0 && current_device < config.ndmas) - config.dmas[current_device].irq = val.int_val; - else - CONFIG_ERROR("invalid device number."); + struct dma_controller *dma = dat; + dma->irq = val.int_val; } void dma_vapi_id(union param_val val, void *dat) { - if (current_device >= 0 && current_device < config.ndmas) - config.dmas[current_device].vapi_id = val.int_val; - else - CONFIG_ERROR("invalid device number."); + struct dma_controller *dma = dat; + dma->vapi_id = val.int_val; +} + +void *dma_sec_start(void) +{ + struct dma_controller *new = malloc(sizeof(struct dma_controller)); + + if(!new) { + fprintf(stderr, "Peripheral DMA: Run out of memory\n"); + exit(-1); + } + + new->next = NULL; + + return new; +} + +void dma_sec_end(void *dat) +{ + struct dma_controller *dma = dat; + struct dma_controller *cur; + + register_memoryarea( dma->baseaddr, DMA_ADDR_SPACE, 4, 0, dma_read32, dma_write32, dat ); + reg_sim_reset( dma_reset, dat ); + reg_sim_stat( dma_status, dat ); + + if(dmas) { + for(cur = dmas; cur->next; cur = cur->next); + cur->next = dma; + } else + dmas = dma; } void reg_dma_sec(void) { - struct config_section *sec = reg_config_sec("dma", NULL, NULL); + struct config_section *sec = reg_config_sec("dma", dma_sec_start, dma_sec_end); - reg_config_param(sec, "ndmas", paramt_int, dma_ndmas); - reg_config_param(sec, "device", paramt_int, change_device); - reg_config_param(sec, "enddevice", paramt_none, end_device); reg_config_param(sec, "irq", paramt_int, dma_irq); reg_config_param(sec, "baseaddr", paramt_addr, dma_baseaddr); reg_config_param(sec, "vapi_id", paramt_addr, dma_vapi_id); --- peripheral/dma.h 2005-02-11 08:49:27.000000000 +0100 +++ ../or1ksim-ac/peripheral/dma.h 2005-02-05 11:15:04.000000000 +0100 @@ -1,4 +1,4 @@ -/* dma.h -- Definition of types and structures for DMA +/* dma.h -- Definition of DMA<->peripheral interface Copyright (C) 2001 by Erez Volk, erez@o... This file is part of OpenRISC 1000 Architectural Simulator. @@ -20,17 +20,6 @@ #include "dma_defs.h" -/* Exported function prototypes */ -void dma_reset( void ); -void dma_clock( void ); -void dma_status( void ); - -void set_dma_req_i( unsigned dma_controller, unsigned channel ); -void clear_dma_req_i( unsigned dma_controller, unsigned channel ); -void set_dma_nd_i( unsigned dma_controller, unsigned channel ); -void clear_dma_nd_i( unsigned dma_controller, unsigned channel ); -unsigned check_dma_ack_o( unsigned dma_controller, unsigned channel ); - /* Implementation of DMA Channel Registers and State */ struct dma_channel { @@ -47,7 +36,7 @@ /* Inner state of transfer etc. */ unsigned load_next_descriptor_when_done; unsigned long current_descriptor; - unsigned long source, destination, source_mask, destination_mask; + oraddr_t source, destination, source_mask, destination_mask; unsigned long chunk_size, total_size, words_transferred; /* The interface registers */ @@ -79,6 +68,9 @@ /* Which interrupt number we generate */ unsigned irq; + /* VAPI id */ + int vapi_id; + /* Controller Registers */ struct { @@ -91,4 +83,14 @@ /* Channels */ struct dma_channel ch[DMA_NUM_CHANNELS]; + + struct dma_controller *next; }; + +void set_dma_req_i( struct dma_channel *channel ); +void clear_dma_req_i( struct dma_channel *channel ); +void set_dma_nd_i( struct dma_channel *channel ); +void clear_dma_nd_i( struct dma_channel *channel ); +unsigned check_dma_ack_o( struct dma_channel *channel ); +struct dma_channel *find_dma_controller_ch( unsigned controller, + unsigned channel );

    ReferenceAuthor
    [openrisc] [or1ksim #25] Cleanup dma peripheralGyörgy 'nog' Jeney

     
    Copyright (c) 1999 OPENCORES.ORG. All rights reserved.