1 /*---------------------------------------------------------------------------*
2   Project:  TwlSDK - CARD - libraries
3   File:     card_dma.c
4 
5   Copyright 2008 Nintendo. All rights reserved.
6 
7   These coded instructions, statements, and computer programs contain
8   proprietary information of Nintendo of America Inc. and/or Nintendo
9   Company Ltd., and are protected by Federal copyright law. They may
10   not be disclosed to third parties or copied or duplicated in any form,
11   in whole or in part, without the prior written consent of Nintendo.
12 
13   $Date:: 2008-04-21#$
14   $Rev: 5625 $
15   $Author: yosizaki $
16 
17  *---------------------------------------------------------------------------*/
18 
19 
20 #include <nitro.h>
21 
22 #include "../include/card_utility.h"
23 
24 
25 /*---------------------------------------------------------------------------*/
26 /* Constants */
27 
28 static const CARDDmaInterface CARDiDmaUsingFormer =
29 {
30     MIi_CardDmaCopy32,
31     MI_StopDma,
32 };
33 #ifdef SDK_TWL
34 #include <twl/ltdmain_begin.h>
35 static CARDDmaInterface CARDiDmaUsingNew =
36 {
37     MI_Card_A_NDmaCopy,
38     MI_StopNDma,
39 };
40 #include <twl/ltdmain_end.h>
41 #endif
42 
43 /*---------------------------------------------------------------------------*/
44 /* Functions */
45 
46 /*---------------------------------------------------------------------------*
47   Name:         CARDi_GetDmaInterface
48 
49   Description:  Determines appropriately from the DMA channel, and get either the new or the old DMA command interface.
50 
51 
52   Arguments:    channel: DMA channel
53                           The range from 0 to MI_DMA_MAX_NUM; if MI_DMA_USING_NEW is valid, indicates that it is a new DMA.
54 
55 
56   Returns:      Either the corresponding new or old DMA interface
57  *---------------------------------------------------------------------------*/
CARDi_GetDmaInterface(u32 channel)58 const CARDDmaInterface* CARDi_GetDmaInterface(u32 channel)
59 {
60     const CARDDmaInterface *retval = NULL;
61     // Use DMA from the valid channel range.
62     BOOL    isNew = ((channel & MI_DMA_USING_NEW) != 0);
63     channel &= ~MI_DMA_USING_NEW;
64     if (channel <= MI_DMA_MAX_NUM)
65     {
66         // Existing DMA
67         if (!isNew)
68         {
69             retval = &CARDiDmaUsingFormer;
70         }
71         // New DMA can be used only when running in TWL environments
72         else if (!OS_IsRunOnTwl())
73         {
74             OS_TPanic("NDMA can use only TWL!");
75         }
76 #ifdef SDK_TWL
77         else
78         {
79             retval = &CARDiDmaUsingNew;
80         }
81 #endif
82     }
83     return retval;
84 }
85 
86 #ifdef SDK_ARM9
87 
88 /*---------------------------------------------------------------------------*
89   Name:         CARDi_ICInvalidateSmart
90 
91   Description:  Selects either the IC_InvalidateAll or IC_InvalidateRange function based on the threshold value.
92 
93   Arguments:    buffer: Buffer to be invalidated
94                 length: Size to be invalidated
95                 threshold: Threshold value that switches processes
96 
97   Returns:      None.
98  *---------------------------------------------------------------------------*/
CARDi_ICInvalidateSmart(void * buffer,u32 length,u32 threshold)99 void CARDi_ICInvalidateSmart(void *buffer, u32 length, u32 threshold)
100 {
101     if (length >= threshold)
102     {
103         IC_InvalidateAll();
104     }
105     else
106     {
107         IC_InvalidateRange((void *)buffer, length);
108     }
109 }
110 
111 /*---------------------------------------------------------------------------*
112   Name:         CARDi_DCInvalidateSmart
113 
114   Description:  Selects either the DC_FlushAll or DC_InvalidateRange function based on the threshold value.
115                 If the buffer is not aligned with the cache line, the Store operation also is automatic only for the beginning or end.
116 
117 
118   Arguments:    buffer: Buffer to be invalidated
119                 length: Size to be invalidated
120                 threshold: Threshold value that switches processes
121 
122   Returns:      None.
123  *---------------------------------------------------------------------------*/
CARDi_DCInvalidateSmart(void * buffer,u32 length,u32 threshold)124 void CARDi_DCInvalidateSmart(void *buffer, u32 length, u32 threshold)
125 {
126     if (length >= threshold)
127     {
128         DC_FlushAll();
129     }
130     else
131     {
132         u32     len = length;
133         u32     pos = (u32)buffer;
134         u32     mod = (pos & (HW_CACHE_LINE_SIZE - 1));
135         if (mod)
136         {
137             pos -= mod;
138             DC_StoreRange((void *)(pos), HW_CACHE_LINE_SIZE);
139             DC_StoreRange((void *)(pos + length), HW_CACHE_LINE_SIZE);
140             length += HW_CACHE_LINE_SIZE;
141         }
142         DC_InvalidateRange((void *)pos, length);
143         DC_WaitWriteBufferEmpty();
144     }
145 }
146 
147 #endif // SDK_ARM9
148