www.pudn.com > drivers.rar > dma_i.c


/** 
 * @file  dma_i.c 
 * 
 * API for DMA SWE. 
 * 
 * @author   () 
 * @version 0.1 
 */ 
 
/* 
 * History: 
 * 
 *  Date        Author          Modification 
 *  ------------------------------------------------------------------- 
 *  7/2/2003   ()   Create. 
 * 
 * (C) Copyright 2003 by Texas Instruments Incorporated, All Rights Reserved 
 */ 
 
 
 
#include "dma/dma_i.h" 
#include "dma/dma_api.h" 
#include "dma/dma_message.h" 
#include "inth/sys_inth.h" 
 
 
#ifndef _WINDOWS 
#include "dma/sys_dma.h" 
 
#include "nucleus.h" 
#include "inth/iq.h" 
#include "chipset.cfg" 
#endif 
 
 
/** 
 * Pointer on the structure gathering all the global variables 
 * used by DMA instance. 
 */ 
extern T_DMA_ENV_CTRL_BLK* dma_env_ctrl_blk_p; 
extern UINT8 dma_channel_number; 
extern UINT16 dma_it_status; 
 
T_DMA_QUEUE_ARRAY   dma_queue_array   [DMA_MAX_QUEUED_REQUESTS]; 
T_DMA_CHANNEL_ARRAY dma_channel_array [DMA_MAX_NUMBER_OF_CHANNEL]; 
UINT8 dma_function_status [DMA_MAX_NUMBER_OF_CHANNEL]; 
 
UINT8 dma_channel_number_tab[DMA_MAX_NUMBER_OF_CHANNEL]; 
UINT8 dma_it_status_tab[DMA_MAX_NUMBER_OF_CHANNEL]; 
UINT8 total_active_dma_channels; 
#ifndef _WINDOWS 
 
/* Array of pointer on call back function with argument SYS_UWORD16. */ 
/* The size of the array is defined by the number of DMA channels available on the device */ 
T_DMA_CALL_BACK dma_call_back_address[DMA_MAX_NUMBER_OF_CHANNEL]= 
          {dma_call_back_it_chan0, 
          dma_call_back_it_chan1, 
          dma_call_back_it_chan2, 
          dma_call_back_it_chan3, 
          dma_call_back_it_chan4, 
          dma_call_back_it_chan5 
          }; 
#endif 
 
/** 
 * function: dma_send_status_message 
 * 
 * this function will send a status message back to the client 
 */ 
void dma_send_status_message(T_DMA_CHANNEL channel, 
                             T_DMA_RET status,T_RV_RETURN return_path) 
{ 
  T_RVF_MB_STATUS mb_status; 
  T_DMA_STATUS_RSP_MSG* dma_event; 
 
  /* Subscriber must be notified */ 
  mb_status = rvf_get_msg_buf (dma_env_ctrl_blk_p->prim_mb_id, 
                               sizeof(T_DMA_STATUS_RSP_MSG), 
                               DMA_STATUS_RSP_MSG, 
                               (T_RV_HDR **) &dma_event); 
 
  if (mb_status != RVF_RED) /* Memory allocation success */ 
  { 
    /* Fill the message */ 
    dma_event->hdr.msg_id     = DMA_STATUS_RSP_MSG; 
    dma_event->result.channel = channel; 
    dma_event->result.status  = status; 
 
    /* Send message to the client */ 
    if (return_path.callback_func != 0) 
    { 
      return_path.callback_func((void*) dma_event); 
#ifdef DMA_FREE_MESSAGE 
      rvf_free_buf(dma_event); 
#endif 
    } 
    else 
    { 
      rvf_send_msg(return_path.addr_id, dma_event); 
    } 
 
  } 
  else 
  { 
    DMA_SEND_TRACE("DMA Memory allocation error", DMA_TRACE_LEVEL); 
  } 
} 
 
 
T_DMA_RET dma_channel_check (T_DMA_CHANNEL channel) 
{ 
  /* 
    This function does check the channel parameters. 
    Returns DMA_PARAMS_OK is parameters are ok and returns 
    DMA_INVALID_PARAMETER is not correct. 
  */ 
 
  if ((channel >= DMA_MIN_CHANNEL) && (channel <= DMA_MAX_CHANNEL)) 
  { 
    return DMA_PARAMS_OK; 
  } 
  else 
  { 
    DMA_SEND_TRACE_PARAM("DMA parameter Channel has invalid value", channel, 
                        DMA_TRACE_LEVEL); 
 
    return DMA_INVALID_PARAMETER; 
  } 
 
} 
 
 
T_DMA_RET dma_queue_spec_prio_check (T_DMA_QUEUE queue, T_DMA_QUEUE specific, 
                                     T_DMA_SW_PRIORITY sw_priority) 
{ 
  T_DMA_RET return_value = DMA_PARAMS_OK; 
 
  /* 
    This function does check the 'queue', 'specific' and 'sw_priority' 
    parameter. Returns DMA_PARAMS_OK is parameters are ok and returns 
    DMA_INVALID_PARAMETER is not correct. 
  */ 
 
  switch (queue) 
  { 
    case DMA_QUEUE_DISABLE: 
    case DMA_QUEUE_ENABLE: 
      break; 
 
    default: 
    { 
      return_value = DMA_INVALID_PARAMETER; 
      DMA_SEND_TRACE("DMA Invalid parameter for dma_queue", 
                      DMA_TRACE_LEVEL); 
    } 
    break; 
  } 
 
  switch (specific) 
  { 
    case DMA_CHAN_ANY: 
    case DMA_CHAN_SPECIFIC: 
      break; 
 
    default: 
    { 
      return_value = DMA_INVALID_PARAMETER; 
      DMA_SEND_TRACE("DMA Invalid parameter for dma_specific", 
                      DMA_TRACE_LEVEL); 
    } 
    break; 
  } 
 
 /* 
  Next code is skipped now as this is always true as long as 
  DMA_SW_PRIORITY_HIGHEST == 0 and DMA_SW_PRIORITY_LOWEST == 255 
 */ 
 
 /* 
  if ((sw_priority < DMA_SW_PRIORITY_HIGHEST) !! 
      (sw_priority > DMA_SW_PRIORITY_LOWEST)) 
  { 
    return_value = DMA_INVALID_PARAMETER; 
    DMA_SEND_TRACE("DMA Invalid parameter for dma_sw_priority", 
                    DMA_TRACE_LEVEL); 
 
  } 
 */ 
 
  return return_value; 
} 
 
 
T_DMA_RET dma_check_channel_info (T_DMA_CHANNEL_PARAMETERS *channel_info) 
{ 
  T_DMA_RET return_value = DMA_PARAMS_OK; 
 
  /* 
    This function checks the channel_info struct 
  */ 
 
  if ((channel_info->sync >= DMA_SYNC_DEVICE_MAX) || 
      (channel_info->nmb_frames   == 0) || 
      (channel_info->nmb_elements == 0)) 
  { 
    return_value = DMA_INVALID_PARAMETER; 
    DMA_SEND_TRACE("DMA Invalid parameter for nmb_frames, nmb_elements or dma_sync_devicee", 
                    DMA_TRACE_LEVEL); 
  } 
  else 
  { 
    switch (channel_info->data_width) 
    { 
      case DMA_DATA_S8: 
        break; 
 
      case DMA_DATA_S16: 
        if (((channel_info->source_address % DMA_TWO_BYTES) != DMA_ZERO) || 
            ((channel_info->destination_address % DMA_TWO_BYTES) != DMA_ZERO)) 
        { 
          DMA_SEND_TRACE("DMA source or destination adress not correct aligned according to data width (16 bits) ", 
                          DMA_TRACE_LEVEL); 
          return_value = DMA_INVALID_PARAMETER; 
        } 
      break; 
 
      case DMA_DATA_S32: 
        if (((channel_info->source_address % DMA_FOUR_BYTES) != DMA_ZERO) || 
            ((channel_info->destination_address % DMA_FOUR_BYTES) != DMA_ZERO)) 
        { 
          DMA_SEND_TRACE("DMA source or destination adress not correct aligned according to data width (32 bits) ", 
                          DMA_TRACE_LEVEL); 
          return_value = DMA_INVALID_PARAMETER; 
        } 
      break; 
 
      default: 
      { 
        DMA_SEND_TRACE("DMA Invalid parameter for dma_width", 
                        DMA_TRACE_LEVEL); 
        return_value = DMA_INVALID_PARAMETER; 
      } 
      break; 
    } 
 
    switch (channel_info->hw_priority) 
    { 
      case DMA_HW_PRIORITY_LOW: 
      case DMA_HW_PRIORITY_HIGH: 
        break; 
 
      default: 
        return_value = DMA_INVALID_PARAMETER; 
        DMA_SEND_TRACE("DMA Invalid parameter for dma_priority", 
                        DMA_TRACE_LEVEL); 
      break; 
    } 
 
    switch (channel_info->dma_mode) 
    { 
      case DMA_SINGLE: 
      case DMA_CONTINIOUS: 
        break; 
 
      default: 
      { 
        return_value = DMA_INVALID_PARAMETER; 
        DMA_SEND_TRACE("DMA Invalid parameter for dma_repeat", 
                        DMA_TRACE_LEVEL); 
      } 
      break; 
    } 
 
    switch (channel_info->flush) 
    { 
      case DMA_FLUSH_DISABLED: 
      case DMA_FLUSH_ENABLED: 
        break; 
 
      default: 
      { 
        return_value = DMA_INVALID_PARAMETER; 
        DMA_SEND_TRACE("DMA Invalid parameter for dma_flush", DMA_TRACE_LEVEL); 
      } 
      break; 
    } 
 
    switch (channel_info->dma_end_notification) 
    { 
      case DMA_NO_NOTIFICATION: 
      case DMA_NOTIFICATION: 
        break; 
 
      default: 
      { 
        return_value = DMA_INVALID_PARAMETER; 
        DMA_SEND_TRACE("DMA Invalid parameter for dma_end_notification", 
                       DMA_TRACE_LEVEL); 
      } 
      break; 
    } 
 
    switch (channel_info->secure) 
    { 
      case DMA_NOT_SECURED: 
      case DMA_SECURED: 
        break; 
 
      default: 
      { 
        return_value = DMA_INVALID_PARAMETER; 
        DMA_SEND_TRACE("DMA Invalid parameter for dma_secure", DMA_TRACE_LEVEL); 
      } 
      break; 
    } 
 
    switch (channel_info->source_address_mode) 
    { 
      case DMA_ADDR_MODE_CONSTANT: 
      case DMA_ADDR_MODE_POST_INC: 
      case DMA_ADDR_MODE_FRAME_INDEX: 
        break; 
 
      default: 
      { 
        return_value = DMA_INVALID_PARAMETER; 
        DMA_SEND_TRACE("DMA Invalid parameter for dma_source_adress_mode", 
                        DMA_TRACE_LEVEL); 
        break; 
      } 
    } 
 
    switch (channel_info->destination_address_mode) 
    { 
      case DMA_ADDR_MODE_CONSTANT: 
      case DMA_ADDR_MODE_POST_INC: 
      case DMA_ADDR_MODE_FRAME_INDEX: 
        break; 
 
      default: 
      { 
        return_value = DMA_INVALID_PARAMETER; 
        DMA_SEND_TRACE("DMA Invalid parameter for dma_destination_adress_mode", 
                       DMA_TRACE_LEVEL); 
		break; 
      } 
    } 
 
    switch (channel_info->source_packet) 
    { 
      case DMA_NOT_PACKED: 
      case DMA_PACKED: 
        break; 
 
      default: 
      { 
        return_value = DMA_INVALID_PARAMETER; 
        DMA_SEND_TRACE("DMA Invalid parameter for dma_source_packet", 
                        DMA_TRACE_LEVEL); 
      } 
      break; 
    } 
 
    switch (channel_info->destination_packet) 
    { 
      case DMA_NOT_PACKED: 
      case DMA_PACKED: 
        break; 
 
      default: 
      { 
        return_value = DMA_INVALID_PARAMETER; 
        DMA_SEND_TRACE("DMA Invalid parameter for dma_destination_adress_mode", 
                        DMA_TRACE_LEVEL); 
      } 
      break; 
    } 
 
    switch (channel_info->source_burst) 
    { 
      case DMA_NO_BURST: 
        break; 
      /* If burst is enabled, the source adress must be in the IMIF range */ 
      case DMA_BURST_ENABLED: 
        if ((dma_determine_port (channel_info->source_address)) == DMA_IMIF_PORT) 
        { 
          break; 
        } 
        /* Fall through when address is not in IMIF range */ 
      default: 
      { 
        return_value = DMA_INVALID_PARAMETER; 
        DMA_SEND_TRACE("DMA Invalid parameter for dma_source_burst", 
                        DMA_TRACE_LEVEL); 
        DMA_SEND_TRACE("DMA Note: burst mode is only available on the IMIF port", 
                        DMA_TRACE_LEVEL); 
      } 
      break; 
    } 
 
    switch (channel_info->destination_burst) 
    { 
      case DMA_NO_BURST: 
        break; 
      /* If burst is enabled, the destination adress must be in the IMIF range */ 
      case DMA_BURST_ENABLED: 
        if ((dma_determine_port (channel_info->destination_address)) == DMA_IMIF_PORT) 
        { 
          break; 
        } 
        /* Fall through when address is not in IMIF range */ 
      default: 
      { 
        return_value = DMA_INVALID_PARAMETER; 
        DMA_SEND_TRACE("DMA Invalid parameter for dma_destination_burst", 
                        DMA_TRACE_LEVEL); 
        DMA_SEND_TRACE("DMA Note: burst mode is only available on the IMIF port", 
                        DMA_TRACE_LEVEL); 
      } 
      break; 
    } 
 
    switch (channel_info->dma_end_notification) 
    { 
      case DMA_NOTIFICATION: 
      case DMA_NO_NOTIFICATION: 
        break; 
 
      default: 
        return_value = DMA_INVALID_PARAMETER; 
        DMA_SEND_TRACE("DMA Invalid parameter for dma_end_notification", 
                        DMA_TRACE_LEVEL); 
    } 
  } 
 
  /* Test if the source address refers to a valid port (RHEA,API, IMIF) 
   * OR if the destination address refers to a valid port 
  */ 
  if((dma_determine_port (channel_info->source_address) == DMA_PORT_ERR) || 
     (dma_determine_port (channel_info->destination_address) == DMA_PORT_ERR)) 
  { 
    return_value = DMA_INVALID_PARAMETER; 
    DMA_SEND_TRACE("DMA Problem with the source or dest. adress given:", 
                    DMA_TRACE_LEVEL); 
    DMA_SEND_TRACE("DMA For instance: Adress out of range", 
                    DMA_TRACE_LEVEL); 
  } 
 
  return return_value; 
} 
 
 
void dma_internal_reserve_chan (T_RV_HDR *msg_p) 
{ 
  T_DMA_CHANNEL dma_channel   = DMA_ALL_CHAN_FREE; 
  T_DMA_RET     dma_status    = DMA_RESERVE_OK; 
  BOOL          dma_queue_free; 
 
  /* Create a pointer to the message information */ 
  T_DMA_RESERVE_CHANNEL_REQ_MSG* dma_reserve_channel_req_msg_p = 
                                    (T_DMA_RESERVE_CHANNEL_REQ_MSG*) msg_p; 
 
 
  /* Check if a specific or any dma channel is required */ 
  switch (dma_reserve_channel_req_msg_p->specific) 
  { 
    case DMA_CHAN_ANY: 
    { 
      /* 
         try to get a free channel 
      */ 
      dma_channel = DMA_MIN_CHANNEL; 
 
      while (dma_channel_array[dma_channel].specific != DMA_CHANNEL_POS_FREE) 
      { 
        dma_channel ++; 
        if (dma_channel == DMA_MAX_NUMBER_OF_CHANNEL) 
        { 
          break; 
        } 
      } 
 
      if (dma_channel < DMA_MAX_NUMBER_OF_CHANNEL) 
      { 
        /* 
          Channel is free 
          Occupy the channel and store the information needed 
        */ 
 
        dma_channel_array [dma_channel].specific    = 
                           dma_reserve_channel_req_msg_p->specific; 
        dma_channel_array [dma_channel].channel     = dma_channel; 
        dma_channel_array [dma_channel].return_path = 
                           dma_reserve_channel_req_msg_p->return_path; 
 
        dma_function_status [dma_channel] = DMA_FUNCTION_RESERVED; 
        dma_status                        = DMA_RESERVE_OK; 
 
        DMA_SEND_TRACE_PARAM("DMA reservated channel ", dma_channel, \ 
                              DMA_TRACE_LEVEL); 
 
        /* break out of the case switch */ 
        break; 
      } 
      else 
      { 
        /* There was no free channel available 
           In the next stage, it might be queued 
        */ 
        dma_reserve_channel_req_msg_p->channel = DMA_MIN_CHANNEL; 
      } 
 
    } 
 
    /* 
      There was no free channel available. In the case above there is no 
      break. We continue now as if a used specific channel is needed, 
      which might be queued. This saves code. 
    */ 
 
    case DMA_CHAN_SPECIFIC: 
    { 
      if (dma_channel_array[dma_reserve_channel_req_msg_p->channel].specific 
                                                     != DMA_CHANNEL_POS_FREE) 
      { 
        /* Channel is used, check if user wants it to be queued */ 
        if (dma_reserve_channel_req_msg_p->queue == DMA_QUEUE_ENABLE) 
        { 
          /* 
            Channel is not free, but user wants to have it queued. 
            Find a free queue place and store the information. 
          */ 
 
          dma_queue_free = FALSE; 
 
          /* first check if there is a queue place free */ 
          for (dma_channel=DMA_ZERO; dma_channel < DMA_MAX_QUEUED_REQUESTS; dma_channel++) 
          { 
            if (dma_queue_array[dma_channel].specific == DMA_QUEUE_POS_FREE) 
            { 
              dma_queue_free = TRUE; 
			  break; 
            } 
          } 
 
          if (dma_queue_free == TRUE) 
          { /* If a place is free in the queue the the request is inserted in 
               the queue based on its priority. This means that the queue is a 
               sorted list. This is done to protect the first-in/first-out 
               principle for similar priory requests. 
            */ 
            for (dma_channel = DMA_ZERO; dma_channel < 
                 DMA_MAX_QUEUED_REQUESTS; dma_channel++) 
            { 
              if (dma_reserve_channel_req_msg_p->sw_priority < 
                  dma_queue_array[dma_channel].sw_priority) 
              { 
                UINT8   index; 
                /* free up a place by moving the queued request one place to the back */ 
                for (index = DMA_MAX_QUEUED_REQUESTS-1; index > dma_channel; index--) 
                { 
                  dma_queue_array[index].specific    = dma_queue_array[index-1].specific; 
                  dma_queue_array[index].channel     = dma_queue_array[index-1].channel; 
                  dma_queue_array[index].sw_priority = dma_queue_array[index-1].sw_priority; 
                  dma_queue_array[index].return_path = dma_queue_array[index-1].return_path; 
                  dma_queue_array[index].queue_index = dma_queue_array[index-1].queue_index; 
                } 
 
                /* store the new request */ 
                dma_queue_array[dma_channel].specific    = dma_reserve_channel_req_msg_p->specific; 
                dma_queue_array[dma_channel].channel     = dma_reserve_channel_req_msg_p->channel; 
                dma_queue_array[dma_channel].sw_priority = dma_reserve_channel_req_msg_p->sw_priority; 
                dma_queue_array[dma_channel].return_path = dma_reserve_channel_req_msg_p->return_path; 
                dma_queue_array[dma_channel].queue_index = dma_env_ctrl_blk_p->dma_queue_index; 
 
                dma_env_ctrl_blk_p->dma_queue_index += DMA_QUEUE_INDEX_STEPSIZE; 
 
                /* if the queue index becomes too high, set it back. */ 
                if (dma_env_ctrl_blk_p->dma_queue_index == DMA_QUEUE_INDEX_MAX) 
                { 
                  dma_env_ctrl_blk_p->dma_queue_index = DMA_QUEUE_INDEX_MIN; 
                } 
 
                dma_status = DMA_QUEUED; 
 
                DMA_SEND_TRACE_PARAM("DMA Reservation has been queued. Queue index", \ 
                                     dma_queue_array[dma_channel].queue_index,\ 
                                     DMA_TRACE_LEVEL); 
                /* break out of the first FOR loop */ 
                break; 
              } 
            } 
          } 
          else 
          { 
            /* Queue is full. Too bad for the user, 
             * but the request cannot be granted 
            */ 
            DMA_SEND_TRACE("DMA Reservation not done as queue is full ",\ 
                            DMA_TRACE_LEVEL); 
 
            dma_status = DMA_TOO_MANY_REQUESTS; 
          } 
 
        } 
        else 
        { 
          /* Channel not free, and user does not want it do be queued */ 
          DMA_SEND_TRACE ("DMA Reservation is not done because no channel is available", \ 
                           DMA_TRACE_LEVEL); 
 
          dma_status = DMA_NO_CHANNEL; 
        } 
      } 
      else 
      { 
        /* A specific channel is required, and it is free */ 
 
        /* Reserve channel */ 
        dma_channel_array[dma_reserve_channel_req_msg_p->channel].specific    = dma_reserve_channel_req_msg_p->specific; 
        dma_channel_array[dma_reserve_channel_req_msg_p->channel].channel     = dma_reserve_channel_req_msg_p->channel; 
        dma_channel_array[dma_reserve_channel_req_msg_p->channel].return_path = dma_reserve_channel_req_msg_p->return_path; 
        dma_function_status[dma_reserve_channel_req_msg_p->channel]           = DMA_FUNCTION_RESERVED; 
 
        /* 
         store the channel to be reservated. it is used 
         when a message is send back to the client 
        */ 
        dma_channel = dma_reserve_channel_req_msg_p->channel; 
 
        DMA_SEND_TRACE_PARAM("DMA Reservated specific channel ", \ 
                              dma_reserve_channel_req_msg_p->channel, DMA_TRACE_LEVEL); 
 
        dma_status = DMA_RESERVE_OK; 
      } 
    } 
    break; 
  } 
 
 
  /* Send a message back to the client, with the status included */ 
  dma_send_status_message ((T_DMA_CHANNEL)(dma_status == DMA_QUEUED ? 
                           dma_queue_array[dma_channel].queue_index : 
                           dma_channel_array[dma_channel].channel), dma_status, 
                           dma_reserve_channel_req_msg_p->return_path); 
 
} 
 
 
void dma_internal_remove_from_queue (T_RV_HDR *msg_p) 
{ 
  UINT8 n; 
 
  /* Create a pointer to the message information */ 
  T_DMA_REMOVE_FROM_QUEUE_REQ_MSG* dma_remove_from_queue_msg_p = 
                                    (T_DMA_REMOVE_FROM_QUEUE_REQ_MSG*) msg_p; 
 
  DMA_SEND_TRACE("DMA Remove from queue ENTERED", DMA_TRACE_LEVEL); 
 
  if ((dma_remove_from_queue_msg_p->channel_queue_id >= DMA_QUEUE_INDEX_MIN) && 
      (dma_remove_from_queue_msg_p->channel_queue_id <= DMA_QUEUE_INDEX_MAX)) 
  { 
    /* determine from the index the corresponding information */ 
    for (n = DMA_ZERO; n < DMA_MAX_QUEUED_REQUESTS; n++) 
    { 
      if (dma_queue_array[n].queue_index == dma_remove_from_queue_msg_p->channel_queue_id) 
      { 
        break; 
      } 
    } 
 
    if (n == DMA_MAX_QUEUED_REQUESTS) 
    { 
      /* invalid parameter */ 
      DMA_SEND_TRACE("DMA Remove from queue: ILLEGAL PARAMETER", DMA_TRACE_LEVEL); 
      DMA_SEND_TRACE("DMA Remove from queue: no message send back", DMA_TRACE_LEVEL); 
    } 
    else 
    { 
      /* valid parameter found */ 
 
      /* 
        Send message back to the client. 
      */ 
      dma_send_status_message (dma_queue_array[n].queue_index, 
                               DMA_REMOVED_FROM_QUEUE, 
                               dma_queue_array[n].return_path); 
      DMA_SEND_TRACE_PARAM("DMA removed from queue with index ", 
                  dma_queue_array[n].queue_index, DMA_TRACE_LEVEL); 
 
      /* free and shift the queue place */ 
      for (; n < DMA_MAX_QUEUED_REQUESTS; n++) 
      { 
        if (n == (DMA_MAX_QUEUED_REQUESTS-1)) 
        { 
          dma_queue_array[n].specific    = DMA_QUEUE_POS_FREE; 
          dma_queue_array[n].queue_index = DMA_QUEUE_POS_FREE; 
        } 
        else 
        { 
          dma_queue_array[n].specific = 
                             dma_queue_array[n+1].specific; 
 
          dma_queue_array[n].channel = 
                             dma_queue_array[n+1].channel; 
 
          dma_queue_array[n].queue_index = 
                             dma_queue_array[n+1].queue_index; 
 
          dma_queue_array[n].sw_priority = 
                             dma_queue_array[n+1].sw_priority; 
 
          dma_queue_array[n].return_path = 
                             dma_queue_array[n+1].return_path; 
        } 
      } 
    } 
  } 
  else 
  { 
    DMA_SEND_TRACE("DMA Illegal parameter provided", DMA_TRACE_LEVEL); 
    DMA_SEND_TRACE("DMA Nomessage send back", DMA_TRACE_LEVEL); 
  } 
} 
 
 
T_DMA_INTERNAL_TYPE_CHANNEL_PORT dma_determine_port (UINT32 address) 
{ 
  /* 
    Check are made according to the chance the occur. The bigger 
    the chance, the earlier it is done to save time 
  */ 
 
/* For PC application IMIF is always returned except when the adress = 0, 
   this is used for the tests */ 
#ifdef _WINDOWS 
  if (address == 0) return DMA_PORT_ERR; 
  else return DMA_IMIF_PORT; 
#endif // _WINDOWS 
 
  /* determine which port to use, based on the address adress */ 
#if (CHIPSET == 15) 
  if ((address >= DMA_IPER_MIN) && 
      (address <= DMA_IPER_MAX)) 
  { 
    return DMA_IPER_PORT; 
  } 
#endif 
 
  if ((address >= DMA_IMIF_MIN) && 
      (address <= DMA_IMIF_MAX)) 
  { 
    return DMA_IMIF_PORT; 
  } 
 
#if (CHIPSET == 15 || CHIPSET == 15 ) 
  if ((address >= DMA_EMIF_MIN) && 
      (address <= DMA_EMIF_MAX)) 
  { 
    return DMA_EMIF_PORT; 
  } 
#endif 
 
  if ((address >= DMA_RHEA_MIN1) && 
      (address <= DMA_RHEA_MAX1)) 
  { 
    return DMA_RHEA_PORT; 
  } 
 
  if ((address >= DMA_RHEA_MIN2) && 
      (address <= DMA_RHEA_MAX2)) 
  { 
    return DMA_RHEA_PORT; 
  } 
 
  if ((address >= DMA_API_MIN1) && 
      (address <= DMA_API_MAX1)) 
  { 
    return DMA_API_PORT; 
  } 
 
 
  if ((address >= DMA_API_MAX2) && 
      (address <= DMA_API_MAX2)) 
  { 
    return DMA_API_PORT; 
  } 
 
  /* if this return is reached, a wrong address has been provided */ 
  return DMA_PORT_ERR; 
} 
 
 
 
void dma_internal_set_chan_params (T_RV_HDR *msg_p) 
{ 
 
  /* Create a pointer to the message information */ 
  T_DMA_SET_CHANNEL_PARAMETERS_REQ_MSG *dma_set_channel_parameters_req_p = (T_DMA_SET_CHANNEL_PARAMETERS_REQ_MSG*) msg_p; 
 
  /* Pointer to the channel info structure of the low level driver */ 
  T_DMA_TYPE_CHANNEL_PARAMETER dma_ll_channel_info ; 
 
  /* Check if the channel is already reserved */ 
  if (dma_function_status[dma_set_channel_parameters_req_p->channel] >= 
                                                         DMA_FUNCTION_RESERVED) 
  { 
#ifndef _WINDOWS 
    dma_ll_channel_info.pf_dma_call_back_address = dma_call_back_address[dma_set_channel_parameters_req_p->channel]; 
#endif 
 
 
    dma_ll_channel_info.d_dma_channel_number    = dma_set_channel_parameters_req_p->channel; 
 
    dma_ll_channel_info.d_dma_channel_secured   = dma_set_channel_parameters_req_p->channel_info.secure; 
    dma_ll_channel_info.d_dma_channel_data_type = dma_set_channel_parameters_req_p->channel_info.data_width; 
 
    dma_ll_channel_info.d_dma_src_channel_packed   = dma_set_channel_parameters_req_p->channel_info.source_packet; 
    dma_ll_channel_info.d_dma_src_channel_burst_en = dma_set_channel_parameters_req_p->channel_info.source_burst; 
    dma_ll_channel_info.d_dma_dst_channel_packed   = dma_set_channel_parameters_req_p->channel_info.destination_packet; 
    dma_ll_channel_info.d_dma_dst_channel_burst_en = dma_set_channel_parameters_req_p->channel_info.destination_burst; 
 
    dma_ll_channel_info.d_dma_channel_hw_synch   = dma_set_channel_parameters_req_p->channel_info.sync; 
    dma_ll_channel_info.d_dma_channel_priority   = dma_set_channel_parameters_req_p->channel_info.hw_priority; 
    dma_ll_channel_info.d_dma_channel_fifo_flush = dma_set_channel_parameters_req_p->channel_info.flush; 
    dma_ll_channel_info.d_dma_channel_auto_init  = dma_set_channel_parameters_req_p->channel_info.dma_mode; 
 
    dma_ll_channel_info.d_dma_src_channel_addr_mode = dma_set_channel_parameters_req_p->channel_info.source_address_mode; 
    dma_ll_channel_info.d_dma_dst_channel_addr_mode = dma_set_channel_parameters_req_p->channel_info.destination_address_mode; 
 
 
    dma_ll_channel_info.d_dma_channel_it_time_out   = DMA_TRUE; 
    dma_ll_channel_info.d_dma_channel_it_drop       = DMA_TRUE; 
    dma_ll_channel_info.d_dma_channel_it_frame      = DMA_ZERO; 
 
    dma_ll_channel_info.d_dma_channel_it_block      = dma_set_channel_parameters_req_p->channel_info.dma_end_notification; 
 
    /* Only use the half block interrupt when double buffering is used */ 
    if ( dma_channel_array[dma_set_channel_parameters_req_p->channel]. 
         double_buf_mode != DMA_NO_DOUBLE_BUF ) 
    { 
      dma_ll_channel_info.d_dma_channel_it_half_block = DMA_TRUE; 
    } 
    else 
    { 
      dma_ll_channel_info.d_dma_channel_it_half_block = DMA_ZERO; 
    } 
 
    dma_ll_channel_info.d_dma_channel_src_address = dma_set_channel_parameters_req_p->channel_info.source_address; 
    dma_ll_channel_info.d_dma_channel_dst_address = dma_set_channel_parameters_req_p->channel_info.destination_address; 
 
    dma_ll_channel_info.d_dma_channel_src_port = dma_determine_port (dma_ll_channel_info.d_dma_channel_src_address); 
    dma_ll_channel_info.d_dma_channel_dst_port = dma_determine_port (dma_ll_channel_info.d_dma_channel_dst_address); 
 
    dma_ll_channel_info.d_dma_channel_element_number = dma_set_channel_parameters_req_p->channel_info.nmb_elements; 
    dma_ll_channel_info.d_dma_channel_frame_number   = dma_set_channel_parameters_req_p->channel_info.nmb_frames; 
 
    /* this parameter is used in the hisr */ 
    dma_channel_array[dma_set_channel_parameters_req_p->channel].dma_end_notification_bool = 
                  dma_set_channel_parameters_req_p->channel_info.dma_end_notification; 
 
    /* Store all the information about this channel */ 
    dma_channel_array[dma_set_channel_parameters_req_p->channel]. 
                 channel_info = dma_ll_channel_info; 
 
    /* set the actual parameters */ 
    f_dma_channel_parameter_set (&dma_ll_channel_info); 
 
    DMA_SEND_TRACE_PARAM("DMA Parameters set for channel ", 
             dma_set_channel_parameters_req_p->channel, DMA_TRACE_LEVEL); 
 
    /* Send a message back to the client, with the status included */ 
    dma_send_status_message (dma_set_channel_parameters_req_p->channel, 
                             DMA_PARAM_SET, 
                      dma_channel_array 
                      [dma_set_channel_parameters_req_p->channel].return_path); 
 
    /* 
      Check if the user wants the transfer to start directly 
      or wants to start the transfer itself 
    */ 
    if (dma_set_channel_parameters_req_p->channel_info.transfer == 
                                                      DMA_MODE_TRANSFER_ENABLE) 
    { 
        f_dma_channel_enable (dma_set_channel_parameters_req_p->channel); 
 
        DMA_SEND_TRACE_PARAM("DMA TRANSFER STARTED, channel ", 
             dma_set_channel_parameters_req_p->channel, DMA_TRACE_LEVEL); 
      dma_function_status[dma_set_channel_parameters_req_p->channel] = 
                                                  DMA_FUNCTION_CHANNEL_ENABLED; 
    } 
    else 
    { 
      dma_function_status[dma_set_channel_parameters_req_p->channel] = 
                                                    DMA_FUNCTION_PARAMS_SET_UP; 
    } 
  } 
  else 
  { 
    DMA_SEND_TRACE("DMA Illegal sequence of API call", DMA_TRACE_LEVEL); 
  } 
} 
 
 
void dma_internal_rel_chan (T_DMA_CHANNEL channel) 
{ 
  T_DMA_CHANNEL dma_dummy_var = DMA_ALL_CHAN_FREE; 
  //UINT8 dma_highest_prio = 0xFF; 
  //UINT8 dma_highest_prio_chan = 0xFF; 
 
  if (dma_function_status[channel] >= DMA_FUNCTION_RESERVED) 
  { 
 
    /* disable the DMA transfer for the channel */ 
    f_dma_channel_disable (channel); 
 
    /* reset the channel to be used */ 
    f_dma_channel_soft_reset (channel); 
 
    /* send message to the client that his channel is released now */ 
    dma_send_status_message (channel, DMA_CHANNEL_RELEASED, 
                             dma_channel_array[channel].return_path); 
 
    DMA_SEND_TRACE_PARAM("DMA released channel ", 
                      channel, DMA_TRACE_LEVEL); 
 
    /* free the channel in the buffer */ 
    dma_channel_array[channel].specific = DMA_CHANNEL_POS_FREE; 
    /* default, we do not use double buffering */ 
    dma_channel_array[channel].double_buf_mode = DMA_NO_DOUBLE_BUF; 
 
    /* Get the next request from the queue. */ 
    while (dma_dummy_var < DMA_MAX_QUEUED_REQUESTS) 
    { 
      /* 
        Now we will search for the next request in the queue. 
        The request can be for any free channel or 
        it can be a specific request, but then of course, the channel 
        requested bust be equal to the channel freed. 
      */ 
      if ((dma_queue_array[dma_dummy_var].specific == DMA_CHAN_ANY) || 
 
         ((dma_queue_array[dma_dummy_var].specific == DMA_CHAN_SPECIFIC) && 
          (dma_queue_array[dma_dummy_var].channel  == channel))) 
      { 
        /* Break the while loop */ 
        break; 
      } 
      dma_dummy_var++; 
    } 
 
    if (dma_dummy_var < DMA_MAX_QUEUED_REQUESTS) 
    { 
      /* A request can be processed */ 
 
      dma_channel_array[channel].specific    = 
						             dma_queue_array[dma_dummy_var].specific; 
      dma_channel_array[channel].channel     = 
								      	 channel; /* = specific channel or freed 
	                                 *   channel (in both cases equal) */ 
      dma_channel_array[channel].return_path = 
	                                 dma_queue_array[dma_dummy_var].return_path; 
 
      /* Send a message to the original request owner that the channel is free now */ 
      dma_send_status_message (dma_queue_array[channel].queue_index + 
                               dma_channel_array[channel].channel, 
                               DMA_QUEUE_PROC, 
                               dma_channel_array[channel].return_path); 
 
      /* 
        This is the old situation. Introduced a new status message 
        dma_send_status_message (dma_channel_array[channel].channel, 
                                 DMA_RESERVE_OK, 
                                 dma_channel_array[channel].return_path); 
      */ 
 
      /* Shift the queue */ 
      for (; dma_dummy_var < DMA_MAX_QUEUED_REQUESTS; dma_dummy_var++) 
      { 
        if (dma_dummy_var == (DMA_MAX_QUEUED_REQUESTS-1)) 
        { 
          dma_queue_array[dma_dummy_var].specific = DMA_QUEUE_POS_FREE; 
        } 
        else 
        { 
          dma_queue_array[dma_dummy_var].specific = 
                            dma_queue_array[dma_dummy_var+1].specific; 
 
          dma_queue_array[dma_dummy_var].channel = 
                            dma_queue_array[dma_dummy_var+1].channel; 
 
          dma_queue_array[dma_dummy_var].return_path = 
                            dma_queue_array[dma_dummy_var+1].return_path; 
 
          dma_queue_array[dma_dummy_var].queue_index = 
                            dma_queue_array[dma_dummy_var+1].queue_index; 
 
          dma_queue_array[dma_dummy_var].sw_priority = 
                            dma_queue_array[dma_dummy_var+1].sw_priority; 
 
        } 
      } 
    } 
  } 
  else 
  { 
    DMA_SEND_TRACE("DMA Illegal sequence of API call", DMA_TRACE_LEVEL); 
  } 
} 
 
/* Function writes a destination address to HW register */ 
void write_hw_dest_adress (UINT16 dma_channel_number, UINT32 address) 
{ 
#define DMA_DEBUG 
#undef DMA_DEBUG 
#ifndef _WINDOWS 
  /* Write the lower part of the destination adress */ 
  C_DMA_CDSA_L_REG(dma_channel_number)= 
         (dma_channel_array[dma_channel_number].channel_info.d_dma_channel_dst_address); 
  /* Write the higher part of the destination adress */ 
  C_DMA_CDSA_U_REG(dma_channel_number)= 
         (dma_channel_array[dma_channel_number].channel_info.d_dma_channel_dst_address >> 16 ); 
#endif 
#ifdef DMA_DEBUG 
  DMA_HISR_SEND_TRACE_PARAM ("DMA HISR Wrote destination adress ", 
    dma_channel_array[dma_channel_number].channel_info.d_dma_channel_dst_address, 
    DMA_TRACE_LEVEL); 
#endif 
} 
 
/* Function writes a source address to HW register */ 
void write_hw_source_adress (UINT16 dma_channel_number, UINT32 address) 
{ 
#define DMA_DEBUG 
#undef DMA_DEBUG 
 
#ifndef _WINDOWS 
  /* Write the lower part of the source adress */ 
  C_DMA_CSSA_L_REG(dma_channel_number)= 
         (dma_channel_array[dma_channel_number].channel_info.d_dma_channel_src_address); 
  /* Write the higher part of the destination adress */ 
  C_DMA_CSSA_U_REG(dma_channel_number)= 
         (dma_channel_array[dma_channel_number].channel_info.d_dma_channel_src_address >> 16 ); 
#endif 
#ifdef DMA_DEBUG 
  DMA_HISR_SEND_TRACE_PARAM ("DMA HISR Wrote source adress ", 
    dma_channel_array[dma_channel_number].channel_info.d_dma_channel_src_address, 
    DMA_TRACE_LEVEL); 
#endif 
} 
 
 
 
 
#ifndef _WINDOWS 
/****************************************************************************** 
 * 
 *  FUNCTION NAME:dma_call_back_it_chan0 
 *    The address of that function will be called by the DMA interrupt handler 
 * 
 *  ARGUMENT LIST: 
 * 
 *  Argument          Type         IO  Description 
 *  ----------        ----------   --  ------------------------------------------- 
 *  dma_status       SYS_UWORD16    I 
 * 
 * 
 * RETURN VALUE: none 
 * 
 *****************************************************************************/ 
void dma_call_back_it_chan0(UINT16 dma_status) 
{ 
 
 
     /* If dma is not started, return immediately */ 
     if (dma_env_ctrl_blk_p == 0) 
     { 
       return; 
     } 
     else 
     { 
   	 dma_channel_number_tab[total_active_dma_channels] = CHANNEL0; 
	 dma_it_status_tab[total_active_dma_channels++] = dma_status; 
	 if (total_active_dma_channels==1) 
	 	{ 
	 	 
	       if(Activate_DMA_HISR() == FALSE) 
    	   { 
        	  DMA_SEND_TRACE ("DMA HISR activation FAILED", DMA_TRACE_LEVEL); 
	       } 
 		   else 
			  F_INTH_DISABLE_ONE_IT(C_INTH_DMA_IT);	    
	    } 
	} 
} 
 
 
/****************************************************************************** 
 * 
 *  FUNCTION NAME:dma_call_back_it_chan1 
 *    The address of that function will be called by the DMA interrupt handler 
 * 
 *  ARGUMENT LIST: 
 * 
 *  Argument          Type         IO  Description 
 *  ----------        ----------   --  ------------------------------------------- 
 *  dma_status       SYS_UWORD16    I 
 * 
 * 
 * RETURN VALUE: none 
 * 
 *****************************************************************************/ 
void dma_call_back_it_chan1(UINT16 dma_status) 
{ 
 
 
     /* If dma is not started, return immediately */ 
     if (dma_env_ctrl_blk_p == 0) 
     { 
       return; 
     } 
     else 
     { 
   	 dma_channel_number_tab[total_active_dma_channels] = CHANNEL1; 
	 dma_it_status_tab[total_active_dma_channels++] = dma_status; 
	 if (total_active_dma_channels==1) 
	 	{ 
	 	 
	       if(Activate_DMA_HISR() == FALSE) 
    	   { 
        	  DMA_SEND_TRACE ("DMA HISR activation FAILED", DMA_TRACE_LEVEL); 
	       } 
 		   else 
			  F_INTH_DISABLE_ONE_IT(C_INTH_DMA_IT);	    
	    } 
	} 
} 
 
/****************************************************************************** 
 * 
 *  FUNCTION NAME:dma_call_back_it_chan2 
 *    The address of that function will be called by the DMA interrupt handler 
 * 
 *  ARGUMENT LIST: 
 * 
 *  Argument          Type         IO  Description 
 *  ----------        ----------   --  ------------------------------------------- 
 *  dma_status       SYS_UWORD16    I 
 * 
 * 
 * RETURN VALUE: none 
 * 
 *****************************************************************************/ 
void dma_call_back_it_chan2(UINT16 dma_status) 
{ 
 
 
     /* If dma is not started, return immediately */ 
     if (dma_env_ctrl_blk_p == 0) 
     { 
       return; 
     } 
     else 
     { 
   	 dma_channel_number_tab[total_active_dma_channels] = CHANNEL2; 
	 dma_it_status_tab[total_active_dma_channels++] = dma_status; 
	 if (total_active_dma_channels==1) 
	 	{ 
	 	 
	       if(Activate_DMA_HISR() == FALSE) 
    	   { 
        	  DMA_SEND_TRACE ("DMA HISR activation FAILED", DMA_TRACE_LEVEL); 
	       } 
 		   else 
			  F_INTH_DISABLE_ONE_IT(C_INTH_DMA_IT);	    
	    } 
	} 
} 
 
/****************************************************************************** 
 * 
 *  FUNCTION NAME:dma_call_back_it_chan3 
 *    The address of that function will be called by the DMA interrupt handler 
 * 
 *  ARGUMENT LIST: 
 * 
 *  Argument          Type         IO  Description 
 *  ----------        ----------   --  ------------------------------------------- 
 *  dma_status       SYS_UWORD16    I 
 * 
 * 
 * RETURN VALUE: none 
 * 
 *****************************************************************************/ 
void dma_call_back_it_chan3(UINT16 dma_status) 
{ 
 
 
     /* If dma is not started, return immediately */ 
     if (dma_env_ctrl_blk_p == 0) 
     { 
       return; 
     } 
     else 
     { 
   	 dma_channel_number_tab[total_active_dma_channels] = CHANNEL3; 
	 dma_it_status_tab[total_active_dma_channels++] = dma_status; 
	 if (total_active_dma_channels==1) 
	 	{ 
	 	 
	       if(Activate_DMA_HISR() == FALSE) 
    	   { 
        	  DMA_SEND_TRACE ("DMA HISR activation FAILED", DMA_TRACE_LEVEL); 
	       } 
 		   else 
			  F_INTH_DISABLE_ONE_IT(C_INTH_DMA_IT);	    
	    } 
	} 
} 
 
 
/****************************************************************************** 
 * 
 *  FUNCTION NAME:dma_call_back_it_chan4 
 *    The address of that function will be called by the DMA interrupt handler 
 * 
 *  ARGUMENT LIST: 
 * 
 *  Argument          Type         IO  Description 
 *  ----------        ----------   --  ------------------------------------------- 
 *  dma_status       SYS_UWORD16    I 
 * 
 * 
 * RETURN VALUE: none 
 * 
 *****************************************************************************/ 
void dma_call_back_it_chan4(UINT16 dma_status) 
{ 
 
 
     /* If dma is not started, return immediately */ 
     if (dma_env_ctrl_blk_p == 0) 
     { 
       return; 
     } 
     else 
     { 
   	 dma_channel_number_tab[total_active_dma_channels] = CHANNEL4; 
	 dma_it_status_tab[total_active_dma_channels++] = dma_status; 
	 if (total_active_dma_channels==1) 
	 	{ 
	 	 
	       if(Activate_DMA_HISR() == FALSE) 
    	   { 
        	  DMA_SEND_TRACE ("DMA HISR activation FAILED", DMA_TRACE_LEVEL); 
	       } 
 		   else 
			  F_INTH_DISABLE_ONE_IT(C_INTH_DMA_IT);	    
	    } 
	} 
} 
 
 
/****************************************************************************** 
 * 
 *  FUNCTION NAME:dma_call_back_it_chan5 
 *    The address of that function will be called by the DMA interrupt handler 
 * 
 *  ARGUMENT LIST: 
 * 
 *  Argument          Type         IO  Description 
 *  ----------        ----------   --  ------------------------------------------- 
 *  dma_status       SYS_UWORD16    I 
 * 
 * 
 * RETURN VALUE: none 
 * 
 *****************************************************************************/ 
void dma_call_back_it_chan5(UINT16 dma_status) 
{ 
 
 
     /* If dma is not started, return immediately */ 
     if (dma_env_ctrl_blk_p == 0) 
     { 
       return; 
     } 
     else 
     { 
   	 dma_channel_number_tab[total_active_dma_channels] = CHANNEL5; 
	 dma_it_status_tab[total_active_dma_channels++] = dma_status; 
	 if (total_active_dma_channels==1) 
	 	{ 
	 	 
	       if(Activate_DMA_HISR() == FALSE) 
    	   { 
        	  DMA_SEND_TRACE ("DMA HISR activation FAILED", DMA_TRACE_LEVEL); 
	       } 
 		   else 
			  F_INTH_DISABLE_ONE_IT(C_INTH_DMA_IT);	    
	    } 
	} 
} 
 
#endif