- Main Page
- Modules
- Data Structures
- Files

- File List
- Globals

# /space/home/slher/rel/Beken/v6_4_5/macsw/ip/lmac/src/hal/hal_dma.c

Go to the documentation of this file.

    00001
    00020 /*
    00021  * INCLUDE FILES
    00022  ****************************************************************************************
    00023  */
    00024 // for mem* functions
    00025 #include <string.h>
    00026
    00027 // for assertions
    00028 #include "dbg_assert.h"
    00029
    00030 #include "ke_event.h"
    00031
    00032 #include "hal_dma.h"
    00033
    00034 #include "dbg.h"
    00035
    00036 #if NX_GP_DMA
    00038 const uint8_t dma2chan[DMA_MAX] =
    00039 {
    00040     [DMA_DL] = IPC_DMA_CHANNEL_CTRL_TX,
    00041     [DMA_UL] = IPC_DMA_CHANNEL_CTRL_RX,
    00042 };
    00043
    00045 const uint8_t dma2lli[DMA_MAX] =
    00046 {
    00047     [DMA_DL] = IPC_DMA_LLI_GP_DL,
    00048     [DMA_UL] = IPC_DMA_LLI_GP_UL,
    00049 };
    00050
    00052 #define DMA_LLICTRL(index) (IPC_DMA_LLI_COUNTER_EN|(dma2lli[index]<<IPC_DMA_LLI_COUNTER_POS) \
    00053                            | IPC_DMA_LLI_IRQ_EN|(dma2lli[index] << IPC_DMA_LLI_IRQ_POS))
    00054
    00055
    00056 /*
    00057  * GLOBAL VARIABLES DEFINITIONS
    00058  ****************************************************************************************
    00059  */
    00060 struct hal_dma_env_tag hal_dma_env;
    00061
    00062 #if (HAL_DMA_POOL)
    00064 struct hal_dma_desc_tag hal_dma_desc_pool[HAL_DMA_DESC_POOL_SIZE];
    00065 #endif //(HAL_DMA_POOL)
    00066
    00067 /*
    00068  * FUNCTION DEFINITIONS
    00069  ****************************************************************************************
    00070  */
    00071 #if (HAL_DMA_POOL)
    00072
    00082 __INLINE bool hal_dma_is_in_pool(struct hal_dma_desc_tag *desc)
    00083 {
    00084     return((desc >= &hal_dma_desc_pool[0]) &&
    00085            (desc <= &hal_dma_desc_pool[HAL_DMA_DESC_POOL_SIZE - 1]));
    00086 }
    00087 #endif //(HAL_DMA_POOL)
    00088
    00089 void hal_dma_init(void)
    00090 {
    00091     int i;
    00092
    00093     // Initialize DMA lists
    00094     for (i = 0; i < DMA_MAX; i++)
    00095     {
    00096         co_list_init(&hal_dma_env.prog[i]);
    00097         hal_dma_env.lli_cnt[i] = dma_lli_counter_get(dma2lli[i]);
    00098     }
    00099
    00100     #if (HAL_DMA_POOL)
    00101     // Fully reset content of the GP DMA descriptors
    00102     memset(&hal_dma_desc_pool[0], 0, HAL_DMA_DESC_POOL_SIZE * sizeof(struct hal_dma_desc_tag));
    00103
    00104     // Initialize pool of GP DMA descriptors
    00105     co_list_init(&hal_dma_env.free_gp_dma_descs);
    00106
    00107     for (i = 0; i < HAL_DMA_DESC_POOL_SIZE; i++)
    00108     {
    00109         // Insert the descriptor in the list of free descriptors
    00110         co_list_push_back(&hal_dma_env.free_gp_dma_descs, &hal_dma_desc_pool[i].hdr);
    00111     }
    00112     #endif //(HAL_DMA_POOL)
    00113 }
    00114
    00115
    00116 void hal_dma_push(struct hal_dma_desc_tag *desc, int type)
    00117 {
    00118     struct dma_desc *dma_desc = desc->dma_desc;
    00119     struct co_list *list = &hal_dma_env.prog[type];
    00120
    00121     // Check if a callback function is programmed
    00122     if ((desc->cb != NULL)
    00123         #if (HAL_DMA_POOL)
    00124         || hal_dma_is_in_pool(desc)
    00125         #endif //(HAL_DMA_POOL)
    00126        )
    00127     {
    00128         // Enable interrupt and LLI counter increment
    00129         dma_desc->ctrl = DMA_LLICTRL(type);
    00130
    00131         // Push the descriptor to the list - Done in critical section as this function
    00132         // is sometimes called from interrupt
    00133         GLOBAL_INT_DISABLE();
    00134         co_list_push_back(list, &desc->hdr);
    00135         GLOBAL_INT_RESTORE();
    00136     }
    00137     else
    00138     {
    00139         // Disable interrupt and LLI counter increment
    00140         dma_desc->ctrl = 0;
    00141     }
    00142
    00143     // Push the DMA descriptor to the DMA engine
    00144     dma_push(dma_desc, dma_desc, dma2chan[type]);
    00145 }
    00146
    00147 void hal_dma_evt(int dma_queue)
    00148 {
    00149     int lli = dma2lli[dma_queue];
    00150
    00151     // Trigger the kernel event
    00152     if (dma_queue == DMA_DL)
    00153     {
    00154         ke_evt_clear(KE_EVT_GP_DMA_DL_BIT);
    00155     }
    00156     else
    00157     {
    00158         ke_evt_clear(KE_EVT_GP_DMA_UL_BIT);
    00159     }
    00160
    00161     // Go through the list of DMA programmed and flush the ones that are completed
    00162     while (hal_dma_env.lli_cnt[dma_queue] != dma_lli_counter_get(lli))
    00163     {
    00164         struct hal_dma_desc_tag *desc;
    00165
    00166         // Done in critical section as the list might be accessed from interrupt
    00167         GLOBAL_INT_DISABLE();
    00168         desc = (struct hal_dma_desc_tag *) co_list_pop_front(&hal_dma_env.prog[dma_queue]);
    00169         GLOBAL_INT_RESTORE();
    00170
    00171         // Sanity check - We shall have a descriptor available
    00172         ASSERT_ERR(desc != NULL);
    00173
    00174         // Acknowledge the DMA interrupt
    00175         dma_int_ack_clear(CO_BIT(lli + DMA_LLI_IRQ_LSB));
    00176
    00177         // Call the callback function if any
    00178         if (desc->cb != NULL)
    00179         {
    00180             desc->cb(desc->env, dma_queue);
    00181         }
    00182
    00183         #if (HAL_DMA_POOL)
    00184         // Check if descriptor has been taken in the pool of descriptors
    00185         if (hal_dma_is_in_pool(desc))
    00186         {
    00187             co_list_push_back(&hal_dma_env.free_gp_dma_descs, &desc->hdr);
    00188         }
    00189         #endif //(HAL_DMA_POOL)
    00190
    00191         // Increase the LLI counter
    00192         hal_dma_env.lli_cnt[dma_queue]++;
    00193     }
    00194
    00195     // Reenable DMA LLI IRQ
    00196     dma_lli_enable(lli);
    00197 }
    00198
    00199 void hal_dma_dl_irq(void)
    00200 {
    00201     // Disable DMA IRQ for this LLI
    00202     dma_lli_disable(IPC_DMA_LLI_GP_DL);
    00203
    00204     // Acknowledge the DMA interrupt
    00205     dma_int_ack_clear(CO_BIT(IPC_DMA_LLI_GP_DL + DMA_LLI_IRQ_LSB));
    00206
    00207     // Trigger the associated kernel event
    00208     ke_evt_set(KE_EVT_GP_DMA_DL_BIT);
    00209 }
    00210
    00211 void hal_dma_ul_irq(void)
    00212 {
    00213     // Disable DMA IRQ for this LLI
    00214     dma_lli_disable(IPC_DMA_LLI_GP_UL);
    00215
    00216     // Acknowledge the DMA interrupt
    00217     dma_int_ack_clear(CO_BIT(IPC_DMA_LLI_GP_UL + DMA_LLI_IRQ_LSB));
    00218
    00219     // Trigger the associated kernel event
    00220     ke_evt_set(KE_EVT_GP_DMA_UL_BIT);
    00221 }
    00222
    00223 #if (HAL_DMA_POOL)
    00224 struct hal_dma_desc_tag *hal_dma_get_desc(void)
    00225 {
    00226     return ((struct hal_dma_desc_tag *)co_list_pop_front(&hal_dma_env.free_gp_dma_descs));
    00227 }
    00228
    00229 void hal_dma_release_desc(struct hal_dma_desc_tag *gp_dma_desc)
    00230 {
    00231     co_list_push_back(&hal_dma_env.free_gp_dma_descs, &gp_dma_desc->hdr);
    00232 }
    00233 #endif //(HAL_DMA_POOL)
    00234
    00235 #endif
    00236