source: svn/newcon3bcm2_21bu/magnum/portinginterface/dma/7552/bdma_pci_priv.c

Last change on this file was 76, checked in by megakiss, 10 years ago

1W 대기전력을 만족시키기 위하여 POWEROFF시 튜너를 Standby 상태로 함

  • Property svn:executable set to *
File size: 41.4 KB
Line 
1/***************************************************************************
2 *     Copyright (c) 2003-2011, Broadcom Corporation
3 *     All Rights Reserved
4 *     Confidential Property of Broadcom Corporation
5 *
6 *  THIS SOFTWARE MAY ONLY BE USED SUBJECT TO AN EXECUTED SOFTWARE LICENSE
7 *  AGREEMENT  BETWEEN THE USER AND BROADCOM.  YOU HAVE NO RIGHT TO USE OR
8 *  EXPLOIT THIS MATERIAL EXCEPT SUBJECT TO THE TERMS OF SUCH AN AGREEMENT.
9 *
10 * $brcm_Workfile: bdma_pci_priv.c $
11 * $brcm_Revision: Hydra_Software_Devel/7 $
12 * $brcm_Date: 3/22/11 10:04a $
13 *
14 * Module Description:
15 *
16 *
17 * Revision History:
18 * $brcm_Log: /magnum/portinginterface/dma/7400/bdma_pci_priv.c $
19 *
20 * Hydra_Software_Devel/7   3/22/11 10:04a vanessah
21 * SW7420-1431: get rid of further warning msg
22 *
23 * Hydra_Software_Devel/6   3/22/11 9:45a vanessah
24 * SW7420-1431: fix pci compile error
25 *
26 * Hydra_Software_Devel/5   3/21/11 6:38p vanessah
27 * SW7420-1431: support oflarge DMA descriptor list subset
28 *
29 * Hydra_Software_Devel/4   11/9/10 5:11p vanessah
30 * SW35125-11:  DMA PI support for 35125
31 *
32 * Hydra_Software_Devel/3   8/17/10 12:16p vanessah
33 * SW7335-791:  After customer verification, merged into main
34 *
35 * Hydra_Software_Devel/SW7335-791/1   8/4/10 10:17p vanessah
36 * SW7335-791:  DMA engine hangs when continuous descriptors using
37 * different scram modes
38 *
39 * Hydra_Software_Devel/2   9/23/08 10:38a syang
40 * PR 34606:  left shift 4 bits for curr_desc reading
41 *
42 * Hydra_Software_Devel/28   5/28/08 12:33p syang
43 * PR 34606: clean LAST bit during dyn link even if AUTO_PEND supported;
44 * clean up
45 *
46 * Hydra_Software_Devel/27   5/19/08 1:58p syang
47 * PR 34606:  clean up
48 *
49 * Hydra_Software_Devel/26   5/19/08 11:48a syang
50 * PR 34606:  add validation for HW reg reading
51 *
52 * Hydra_Software_Devel/25   12/12/07 3:40p syang
53 * PR 31923: added auto-append support to PI
54 *
55 * Hydra_Software_Devel/24   12/11/07 10:54a syang
56 * PR 34606: more small clean up after big rewriting
57 *
58 * Hydra_Software_Devel/23   12/7/07 4:09p syang
59 * PR 34606: rewrite more than half of code to support hw sharing for
60 * kernel and user-mode sides
61 *
62 * Hydra_Software_Devel/22   10/15/07 3:38p syang
63 * PR 35947: add "_isr" to call back func name
64 *
65 * Hydra_Software_Devel/21   3/21/07 12:47p syang
66 * PR 28173: dyn link works now after fixing next_desc shift and status
67 * proc  tran loop break. fixed cur hw desc left shift
68 *
69 * Hydra_Software_Devel/20   3/16/07 12:52p syang
70 * PR 28173: add dynamic link support (not turn on yet)
71 *
72 * Hydra_Software_Devel/18   2/5/07 4:43p syang
73 * PR 23354: allow mem addr in mem_1; cleanup cip specific code section
74 * macro usage
75 *
76 * Hydra_Software_Devel/17   1/16/07 4:44p syang
77 * PR 26224: cleanup
78 *
79 * Hydra_Software_Devel/16   1/8/07 12:53p tdo
80 * PR 26224:  Add second DMA MEM engine support for 7400 B0
81 *
82 * Hydra_Software_Devel/15   12/28/06 6:24p syang
83 * PR 26618: update to use BCHP_PCI_DMA_CTRL_DMA_BURST_SIZE_SINGLE/BURST
84 * for 7403
85 *
86 * Hydra_Software_Devel/14   10/3/06 4:01p syang
87 * PR 24634: replace critical section with private mutex for
88 * mem/pci_dma_handle create/destroy.
89 *
90 * Hydra_Software_Devel/13   8/4/04 4:38p syang
91 * PR 12172: fix warning with release build
92 *
93 * Hydra_Software_Devel/12   5/24/04 6:00p jasonh
94 * PR 11189: Merge down from B0 to main-line
95 *
96 * Hydra_Software_Devel/Refsw_Devel_7038_B0/1   4/20/04 11:35a syang
97 * PR 10685: updated HW register reading / setting to B0, added
98 * ClearCallback before EnableCallback.
99 *
100 * Hydra_Software_Devel/11   3/8/04 6:17p syang
101 * PR 10012: added shift to "Next Desc Addr" in desc word 3
102 *
103 * Hydra_Software_Devel/10   3/8/04 3:18p syang
104 * PR 10012: Added 4 bits shift for Desc offset
105 *
106 * Hydra_Software_Devel/9   2/6/04 4:48p syang
107 * PR 9655: added low 4 bits cutting for "next desc" setting
108 *
109 * Hydra_Software_Devel/8   2/4/04 3:01p syang
110 * PR 9608: 1). added init for hMemDma / hPciDma of Channel, hDma of
111 * MemDma / PciDma and hChannel of Queue; 2). split CallBackFunc type def
112 * to mem and pci versions; 3). fixed typo in TranHandle def; 4).leave
113 * critical section before calling BINT func; 5). fixed a bug with
114 * nextDesc in Desc info setting; 6). use wake to start dma as in sleep
115 * mode; 7). corrected typo in the asserts of Queue_CreateTran.
116 *
117 * Hydra_Software_Devel/7   12/29/03 3:59p marcusk
118 * PR9117: Updated with changes required to support interrupt ids rather
119 * than strings.
120 *
121 * Hydra_Software_Devel/6   11/19/03 6:54p syang
122 * added desc addr conv from virtual to mem bus offset
123 *
124 * Hydra_Software_Devel/5   10/24/03 2:53p syang
125 * changed to use PciBusAddr and MemBusAddr from SrcBusAddr and
126 * DstBusAddr. I think the new addr model is more natural to the way how
127 * user gets the addr
128 *
129 * Hydra_Software_Devel/4   10/23/03 6:18p syang
130 * to make linux comipler silent
131 *
132 * Hydra_Software_Devel/3   10/23/03 4:20p syang
133 * adjusted sub-module implementaion overview
134 *
135 * Hydra_Software_Devel/2   10/23/03 3:16p syang
136 * added real pci dma implementation
137 *
138 * Hydra_Software_Devel/1   9/25/03 7:01p syang
139 * init version, from scratch
140 *
141 ***************************************************************************/
142
143#include "bdma_pci_priv.h"
144#include "bkni.h"
145#include "bchp_pci_dma.h"
146#include "bchp_common.h"
147#include "bchp_hif_intr2.h"
148#include "bchp_int_id_hif_intr2.h"
149
150BDBG_MODULE(BDMA_PCI_PRIV);
151
152#define BDMA_P_PCI_LAST_BLK                 1
153#define BDMA_P_PCI_FIRE_INTR                1
154
155/***************************************************************************
156 *
157 * Utility functions used by BDMA
158 *
159 ***************************************************************************/
160/*--------------------------------------------------------------------------
161 * To be called by BDMA API func before taking real action, to get dma mutex
162 * WITH block, ideally for user mode
163 */
164BERR_Code BDMA_P_Pci_AcquireMutex(
165        BDMA_Pci_Handle          hPciDma,
166        BKNI_MutexHandle        *phMutex )
167{
168        BDMA_P_Pci_Context  * pPciDma;
169        BERR_Code  eResult = BERR_SUCCESS;
170
171        BDMA_P_PCI_GET_CONTEXT(hPciDma, pPciDma);
172        if ( NULL == pPciDma )
173        {
174                eResult = BERR_TRACE(BERR_INVALID_PARAMETER);
175                goto BDMA_P_Done_Pci_AcquireMutex;
176        }
177
178        BDBG_ASSERT( NULL != phMutex );
179        *phMutex = pPciDma->hDma->hMutex;
180
181        /* hPciDma passed the magic check, we trust every thing pointed by it now */
182        eResult = BKNI_AcquireMutex(pPciDma->hDma->hMutex);
183
184  BDMA_P_Done_Pci_AcquireMutex:
185        return BERR_TRACE(eResult);
186}
187
188
189/***************************************************************************
190 *
191 * Static tool functions used in this file
192 *
193 ***************************************************************************/
194
195/*--------------------------------------------------------------------------
196 * To be called to get PciDma context ptr from a Tran ptr. The PciDma handle
197 * from the Tran record is validated by black magic, and the Engine Id is
198 * checked to make sure the Tran was really created with PciDma handle
199 */
200static BERR_Code BDMA_P_Pci_GetPciDmaPtrFromTran_isr(
201        BDMA_P_QueueEntry *    pTran,
202        BDMA_P_Pci_Context **  ppPciDma )
203{
204        /* assert para from our private code */
205        BDBG_ASSERT( NULL != pTran );
206        BDBG_ASSERT( NULL != ppPciDma );
207
208        *ppPciDma = (BDMA_P_Pci_Context *) BDMA_P_Queue_GetEngine_isr( pTran->hQueue );
209
210        if (NULL != *ppPciDma)
211                return BERR_SUCCESS;
212        else
213                return BERR_TRACE(BERR_INVALID_PARAMETER);
214}
215
216#define BDMA_P_PCI_WORD_ALIGN_MASK          0x3
217/*--------------------------------------------------------------------------
218 * To be called to set block info for a block, it does validate the block
219 * info provided
220 */
221static BERR_Code BDMA_P_Pci_SetBlockDesc_isr(
222        BDMA_P_Pci_Context *        pPciDma,
223        BDMA_P_QueueEntry *         pBlock,
224        bool                        bCachedDscrp,
225        uint32_t                    ulMemBusAddr,
226        uint32_t                    ulPciBusAddr,
227        uint32_t                    ulBlockSize,
228        BDMA_TranDir                eTranDirection )
229{
230        BERR_Code  eResult = BERR_SUCCESS;
231        uint32_t *pulDesc;
232        uint32_t  ulTranDir;
233        uint32_t  ulSwapMode;
234       
235        /* assert para from our private code */
236        BDBG_ASSERT( NULL != pPciDma );
237        BDBG_ASSERT( NULL != pBlock );
238
239        /* validate the parameters passed in from user */
240        if ( eTranDirection >= BDMA_TranDir_eInvalid )
241        {
242                eResult = BERR_TRACE(BERR_INVALID_PARAMETER);
243                goto BDMA_P_Done_Pci_SetBlockDesc;
244        }
245       
246        if ( (ulPciBusAddr | ulMemBusAddr | ulBlockSize) &
247                 BDMA_P_PCI_WORD_ALIGN_MASK )
248        {
249                eResult = BERR_TRACE(BDMA_ERR_NOT_WORD_ALIGNED);
250                goto BDMA_P_Done_Pci_SetBlockDesc;
251        }
252        if ( (4>ulBlockSize) || (ulBlockSize>BDMA_P_PCI_MAX_BLOCK_SIZE) )
253        {
254                eResult = BERR_TRACE(BDMA_ERR_SIZE_OUT_RANGE);
255                goto BDMA_P_Done_Pci_SetBlockDesc;
256        }
257
258        /* calc HW value for tran dir and swap mode */
259        ulTranDir = ( (BDMA_TranDir_ePciDeviceToSdram == eTranDirection)? 
260                                  (BCHP_PCI_DMA_DESC_WORD2_DMA_DIRECTION_PCI_TO_MEMORY) :
261                                  (BCHP_PCI_DMA_DESC_WORD2_DMA_DIRECTION_MEMORY_TO_PCI) );
262        if ( BDMA_SwapMode_eNoSwap == pPciDma->eSwapMode )
263        {
264                ulSwapMode = BCHP_PCI_DMA_DESC_WORD3_ENDIAN_XLATE_MODE_NO_SWAP;
265        }
266        else if ( BDMA_SwapMode_e0123To3210 == pPciDma->eSwapMode )
267        {
268                ulSwapMode = BCHP_PCI_DMA_DESC_WORD3_ENDIAN_XLATE_MODE_SWAP_32;
269        }
270        else
271        {
272                ulSwapMode = BCHP_PCI_DMA_DESC_WORD3_ENDIAN_XLATE_MODE_SWAP_16_IN_32;
273        }
274
275        pulDesc = (bCachedDscrp)? pBlock->pulCachedDescAddr : pBlock->pulDescAddr;
276       
277        /* set descriptor: only the last block needs to set INTR_ENABLE and LAST bits,
278         * and the INTR_ENABLE is always set, on matter it is a sync or async Tran. */
279        *(pulDesc  ) = BCHP_FIELD_DATA( PCI_DMA_DESC_WORD0, MEMORY_ADDRESS,  ulMemBusAddr );
280        *(pulDesc+1) = BCHP_FIELD_DATA( PCI_DMA_DESC_WORD1, PCI_ADDRESS, ulPciBusAddr );
281        *(pulDesc+2) =
282                BCHP_FIELD_DATA( PCI_DMA_DESC_WORD2, DMA_DIRECTION, ulTranDir ) |
283                BCHP_FIELD_DATA( PCI_DMA_DESC_WORD2, DMA_TRANSFER_SIZE, ulBlockSize );
284        *(pulDesc+3) =
285                BCHP_FIELD_DATA( PCI_DMA_DESC_WORD3, NEXT_DESC_ADDR,
286                                                 (pBlock + 1)->ulDescPhysAddr >>
287                                                 BCHP_PCI_DMA_DESC_WORD3_NEXT_DESC_ADDR_SHIFT ) |
288                BCHP_FIELD_DATA( PCI_DMA_DESC_WORD3, ENDIAN_XLATE_MODE, ulSwapMode );
289
290  BDMA_P_Done_Pci_SetBlockDesc:
291        return eResult;
292}
293
294#define BDMA_P_PCI_STATUS_IDLE    BCHP_PCI_DMA_STATUS_DMA_STATUS_IDLE_STATE
295#define BDMA_P_PCI_STATUS_BUSY    BCHP_PCI_DMA_STATUS_DMA_STATUS_BUSY_STATE
296#define BDMA_P_PCI_STATUS_SLEEP   BCHP_PCI_DMA_STATUS_DMA_STATUS_SLEEP_STATE
297#define BDMA_P_PCI_WAKE_1ST_DESC  1
298#define BDMA_P_PCI_WAKE_LAST_DESC 0
299
300#ifndef BCHP_PCI_DMA_CTRL_DMA_BURST_SIZE_SINGLE
301#define BCHP_PCI_DMA_CTRL_DMA_BURST_SIZE_SINGLE BCHP_PCI_DMA_CTRL_DMA_BURST_SIZE_BURST_1
302#endif
303#ifndef BCHP_PCI_DMA_CTRL_DMA_BURST_SIZE_BURST
304#define BCHP_PCI_DMA_CTRL_DMA_BURST_SIZE_BURST  BCHP_PCI_DMA_CTRL_DMA_BURST_SIZE_BURST_16
305#endif
306
307/*--------------------------------------------------------------------------
308 * To be called to modify the last act block's desc to work as last block,
309 * and to flush cached descriptors
310 */
311static BERR_Code BDMA_P_Pci_Tran_PrepareStart_isr(
312        BDMA_P_QueueEntry *      pTran,
313        BDMA_P_QueueHandle       hQueue,
314        BMEM_Handle              hMemory,
315        uint32_t                 ulNumActBlocks )  /* new NumActBlocks */
316{
317        BDMA_P_QueueContext * pQueue;
318        BDMA_P_QueueEntry *pBlock;
319        uint32_t *pulDesc;
320        uint32_t  ulNextOffset;
321        uint32_t  ulWord3;
322        volatile uint32_t  ulCheck;
323#if BDMA_P_CHECK_NEXT_DESC     
324        int iLoopCntr;
325#endif
326       
327        BDMA_P_QUEUE_GET_CONTEXT( hQueue, pQueue );
328        BDBG_ASSERT( NULL != pQueue );
329       
330        /* in the case of re-use, the previous "last act block" might have wrong NEXT_DESC */
331        pBlock = pTran + (pTran->ulNumActBlocks - 1);
332        if ((ulNumActBlocks != pTran->ulNumActBlocks) &&
333                (0 < pTran->ulNumActBlocks))
334        {
335                pulDesc = (pTran->bCachedDscrp)? pBlock->pulCachedDescAddr : pBlock->pulDescAddr;
336
337                *(pulDesc+2) &= ~(
338                        BCHP_MASK(PCI_DMA_DESC_WORD2, INTERRUPT_ENABLE));
339                ulWord3 = *(pulDesc+3) & ~(
340                        BCHP_MASK(PCI_DMA_DESC_WORD3, LAST_RECORD_INDICATOR) |
341                        BCHP_MASK(PCI_DMA_DESC_WORD3, NEXT_DESC_ADDR));
342
343                ulNextOffset =
344                        (pBlock + 1)->ulDescPhysAddr >> BCHP_PCI_DMA_DESC_WORD3_NEXT_DESC_ADDR_SHIFT;
345         
346                *(pulDesc+3) = ulWord3 |
347                        BCHP_FIELD_DATA( PCI_DMA_DESC_WORD3, NEXT_DESC_ADDR, ulNextOffset);
348        }
349
350        /* modify new "last act block" desc */
351        pBlock = pTran + (ulNumActBlocks - 1);
352        pulDesc = (pTran->bCachedDscrp)? pBlock->pulCachedDescAddr : pBlock->pulDescAddr;
353        *(pulDesc+2) |= 
354                BCHP_FIELD_DATA(PCI_DMA_DESC_WORD2, INTERRUPT_ENABLE, BDMA_P_PCI_FIRE_INTR);
355        ulWord3 = *(pulDesc+3) & ~(
356                BCHP_MASK(PCI_DMA_DESC_WORD3, NEXT_DESC_ADDR));
357        *(pulDesc+3) = ulWord3 |
358                BCHP_FIELD_DATA(PCI_DMA_DESC_WORD3, LAST_RECORD_INDICATOR, BDMA_P_PCI_LAST_BLK);
359       
360        /* check block setting */
361#if BDMA_P_CHECK_NEXT_DESC     
362        pBlock = pTran;
363        for ( iLoopCntr = 0; iLoopCntr < (int) ulNumActBlocks; iLoopCntr++ )
364        {
365                uint32_t ulSeeNextOffset;
366               
367                ulNextOffset =
368                        (pBlock + 1)->ulDescPhysAddr >> BCHP_MEM_DMA_DESC_WORD3_NEXT_DESC_ADDR_SHIFT;
369                pulDesc = (pTran->bCachedDscrp)? pBlock->pulCachedDescAddr : pBlock->pulDescAddr;
370                ulSeeNextOffset = BCHP_GET_FIELD_DATA(*(pulDesc+3), PCI_DMA_DESC_WORD3, NEXT_DESC_ADDR);
371                if ((false == pBlock->bBlockInfoSet) ||
372                        (ulNextOffset != ulSeeNextOffset))
373                {
374                        BDBG_ASSERT((false == pBlock->bBlockInfoSet) ||
375                                                (ulNextOffset == ulSeeNextOffset));
376                        return BERR_TRACE(BDMA_ERR_BLOCK_INFO_UNSET);
377                }
378
379                pBlock += 1;
380        }
381#endif
382       
383        if (pTran->bCachedDscrp)
384                BMEM_FlushCache_isr(hMemory, pTran->pulCachedDescAddr,
385                                                        ulNumActBlocks * BDMA_P_PCI_NUM_WORDS_PER_DESC * 4);
386
387        /* read back with un-cached addr to ensure previous writing completes */
388        ulCheck = *((pTran + (ulNumActBlocks - 1))->pulDescAddr + 3);
389        if ((ulCheck & BCHP_MASK(PCI_DMA_DESC_WORD3, NEXT_DESC_ADDR)) != 0)     
390        {
391                BDBG_ERR(("desc writing error with preparing start"));
392        }
393       
394        return BERR_SUCCESS;
395}
396/*--------------------------------------------------------------------------
397 * To be called to modify the last act block's desc to work as last block,
398 * and to flush cached descriptors
399 */
400static BERR_Code BDMA_P_Pci_Tran_PrepareStartSubset_isr(
401        BDMA_P_QueueEntry *      pTran,
402        BDMA_P_QueueHandle       hQueue,
403        BMEM_Handle              hMemory,
404        uint32_t                 ulFirstBlock,
405        uint32_t                 ulNumActBlocks)  /* new NumActBlocks */
406
407{
408        BDMA_P_QueueContext * pQueue;
409        BDMA_P_QueueEntry *pBlock;
410        uint32_t *pulDesc;
411        uint32_t  ulNextOffset, i=0;
412        uint32_t  ulWord3;
413        volatile uint32_t  ulCheck;
414#if ((BDMA_P_CHECK_NEXT_DESC) && (BDBG_DEBUG_BUILD)) || \
415        ((BDMA_P_CHECK_SCATTER_GATHER) && (BDBG_DEBUG_BUILD))
416        int iLoopCntr;
417#endif
418        BDMA_P_QUEUE_GET_CONTEXT( hQueue, pQueue );
419        BDBG_ASSERT( NULL != pQueue );
420
421        /* in the case of re-use, the previous "last act block" might have wrong NEXT_DESC */
422        if ((ulNumActBlocks != pTran->ulNumActBlocks) &&
423                (0 < pTran->ulNumActBlocks))
424        {
425                pBlock = pTran + pTran->ulFirstBlock + (pTran->ulNumActBlocks - 1);
426                pulDesc = (pTran->bCachedDscrp)? pBlock->pulCachedDescAddr : pBlock->pulDescAddr;
427
428                *(pulDesc+2) &= ~(
429                        BCHP_MASK(PCI_DMA_DESC_WORD2, INTERRUPT_ENABLE));
430                ulWord3 = *(pulDesc+3) & ~(
431                        BCHP_MASK(PCI_DMA_DESC_WORD3, LAST_RECORD_INDICATOR) |
432                        BCHP_MASK(PCI_DMA_DESC_WORD3, NEXT_DESC_ADDR));
433
434                ulNextOffset =
435                        (pBlock + 1)->ulDescPhysAddr >> BCHP_PCI_DMA_DESC_WORD3_NEXT_DESC_ADDR_SHIFT;
436         
437                *(pulDesc+3) = ulWord3 |
438                        BCHP_FIELD_DATA( PCI_DMA_DESC_WORD3, NEXT_DESC_ADDR, ulNextOffset);
439        }
440
441    pTran->ulFirstBlock = ulFirstBlock;
442        pBlock = pTran + ulFirstBlock;
443        while (i<(ulNumActBlocks - 1))
444        {
445                pBlock = pTran + ulFirstBlock + i;
446                pulDesc = (pTran->bCachedDscrp)? pBlock->pulCachedDescAddr : pBlock->pulDescAddr;
447
448                *(pulDesc+2) &=~
449                        BCHP_FIELD_DATA( PCI_DMA_DESC_WORD2, INTERRUPT_ENABLE,  BDMA_P_PCI_FIRE_INTR );
450
451
452                ulNextOffset = (pBlock + 1)->ulDescPhysAddr >> BCHP_MEM_DMA_DESC_WORD3_NEXT_DESC_ADDR_SHIFT;
453
454                *(pulDesc+3) |= BCHP_FIELD_DATA( PCI_DMA_DESC_WORD3, NEXT_DESC_ADDR, ulNextOffset );
455                i++;
456        }
457        /* modify new "last act block" desc */
458        pBlock = pTran + ulFirstBlock + (ulNumActBlocks - 1);
459        pulDesc = (pTran->bCachedDscrp)? pBlock->pulCachedDescAddr : pBlock->pulDescAddr;
460        *(pulDesc+2) |= 
461                BCHP_FIELD_DATA(PCI_DMA_DESC_WORD2, INTERRUPT_ENABLE, BDMA_P_PCI_FIRE_INTR);
462        ulWord3 = *(pulDesc+3) & ~(
463                BCHP_MASK(PCI_DMA_DESC_WORD3, NEXT_DESC_ADDR));
464        *(pulDesc+3) = ulWord3 |
465                BCHP_FIELD_DATA(PCI_DMA_DESC_WORD3, LAST_RECORD_INDICATOR, BDMA_P_PCI_LAST_BLK);
466
467#if (BDMA_P_CHECK_NEXT_DESC) && (BDBG_DEBUG_BUILD)
468        pBlock = pTran;
469        for ( iLoopCntr = 0; iLoopCntr < (int) ulNumActBlocks; iLoopCntr++ )
470        {
471                uint32_t ulSeeNextOffset;
472
473                ulNextOffset =
474                        (pBlock + 1)->ulDescPhysAddr >> BCHP_PCI_DMA_DESC_WORD3_NEXT_DESC_ADDR_SHIFT;
475                pulDesc = (pTran->bCachedDscrp)? pBlock->pulCachedDescAddr : pBlock->pulDescAddr;
476                ulSeeNextOffset = BCHP_GET_FIELD_DATA(*(pulDesc+3), PCI_DMA_DESC_WORD3, NEXT_DESC_ADDR);
477
478                if ((ulNextOffset != ulSeeNextOffset) ||
479                        (false == pBlock->bBlockInfoSet))
480                {
481                        BDBG_ASSERT((ulNextOffset == ulSeeNextOffset) ||
482                                                (false == pBlock->bBlockInfoSet));
483                        return BERR_TRACE(BDMA_ERR_BLOCK_INFO_UNSET);
484                }
485        }
486#endif
487
488        /* flush cached desc mem */
489        if (pTran->bCachedDscrp)
490                BMEM_FlushCache_isr(hMemory, pTran->pulCachedDescAddr,
491                                                        ulNumActBlocks * BDMA_P_PCI_NUM_WORDS_PER_DESC * 4);
492
493        /* read back with un-cached addr to ensure previous writing completes */
494        ulCheck = *((pTran + ulFirstBlock + (ulNumActBlocks - 1))->pulDescAddr + 3);
495        if ((ulCheck & BCHP_MASK(PCI_DMA_DESC_WORD3, NEXT_DESC_ADDR)) != 0)
496        {
497                BDBG_ERR(("desc writing error with preparing start"));
498        }
499
500        return BERR_SUCCESS;
501}
502
503#ifndef BCHP_PCI_DMA_SCRATCH0
504#define BCHP_PCI_DMA_SCRATCH0 BCHP_PCI_DMA_DMA_SCRATCH0
505#endif
506/*--------------------------------------------------------------------------
507Callback from base-module queue to wait till next descriptor safe to send to HW
508*/
509static void BDMA_P_Pci_SafeSendToHw_isr(
510                                                                                BDMA_P_QueueHandle      hQueue, 
511                                                                                BDMA_P_HwStatus*        peHwStatus
512                                                                                )
513{
514
515        uint32_t  eStatus = (uint32_t)(*peHwStatus);
516        BDMA_P_Pci_Context *pPciDma;
517        BREG_Handle  hRegister;
518        uint32_t   ulRegValue;
519        BDMA_P_QueueContext * pQueue;
520
521       
522
523        BDMA_P_QUEUE_GET_CONTEXT( hQueue, pQueue );
524
525        if (NULL == pQueue->pHeadTranInQ)
526                return;
527
528
529        pPciDma = (BDMA_P_Pci_Context *)(pQueue->hEngine);
530        hRegister = BDMA_P_GetRegisterHandle(pPciDma->hDma);
531        while (eStatus ==BDMA_P_PCI_STATUS_BUSY)
532        {
533                /* read CUR_DESC after STATUS, --> less chance to get wrong CUR_DESC?  */
534                ulRegValue = BREG_Read32( hRegister, BCHP_PCI_DMA_STATUS);
535                eStatus    = BCHP_GET_FIELD_DATA( ulRegValue, PCI_DMA_STATUS, DMA_STATUS );
536        }
537
538        switch (eStatus){
539                   case (BDMA_P_PCI_STATUS_IDLE):
540                           *peHwStatus = BDMA_P_HwStatus_eIdle;
541                           break;
542                   case (BDMA_P_PCI_STATUS_SLEEP):
543                           *peHwStatus = BDMA_P_HwStatus_eSleep;
544                           break;
545        }
546}
547
548/*--------------------------------------------------------------------------
549 * Callback from base-module queue to read the HW status
550 */
551static void BDMA_P_Pci_ReadHwRegs_isr(
552        void  *               pvEngine,
553        BDMA_P_HwStatus  *    peHwStatus,
554        uint32_t  *           pulCurrDesc,
555        uint32_t  *           pulScratchReg )
556{
557        BDMA_P_Pci_Context *pPciDma;
558        BREG_Handle  hRegister;
559        uint32_t   ulRegValue;
560        uint32_t   ulStatus;
561       
562        /* assert para from our private code */
563        BDBG_ASSERT( NULL != pvEngine);
564        BDBG_ASSERT( NULL != peHwStatus );
565        BDBG_ASSERT( NULL != pulCurrDesc );
566        BDBG_ASSERT( NULL != pulScratchReg );
567
568        pPciDma = (BDMA_P_Pci_Context *)(pvEngine);
569        hRegister = BDMA_P_GetRegisterHandle(pPciDma->hDma);
570 
571        /* read CUR_DESC after STATUS, --> less chance to get wrong CUR_DESC?  */
572        ulRegValue = BREG_Read32( hRegister, BCHP_PCI_DMA_STATUS );
573        ulStatus  = BCHP_GET_FIELD_DATA( ulRegValue, PCI_DMA_STATUS, DMA_STATUS );
574
575        ulRegValue = BREG_Read32( hRegister, BCHP_PCI_DMA_CUR_DESC_ADDR );
576        *pulCurrDesc =
577                BCHP_GET_FIELD_DATA( ulRegValue, PCI_DMA_CUR_DESC_ADDR, DMA_CUR_DESC ) << 4;
578
579        *pulScratchReg = BREG_Read32( hRegister, BCHP_PCI_DMA_SCRATCH0 );
580
581        if ( BDMA_P_PCI_STATUS_IDLE == ulStatus )
582        {
583                BDBG_MSG(( "Pci DMA engine in idle state!" ));
584                *peHwStatus = BDMA_P_HwStatus_eIdle;
585        }
586        else if ( BDMA_P_PCI_STATUS_BUSY == ulStatus )
587        {
588                *peHwStatus = BDMA_P_HwStatus_eBusy;
589        }
590        else if ( BDMA_P_PCI_STATUS_SLEEP == ulStatus )
591        {
592                *peHwStatus = BDMA_P_HwStatus_eSleep;
593        }
594        else 
595        {
596                BDBG_ERR(( "PCI DMA engine in Reservered state!!!" ));
597                *peHwStatus = BDMA_P_HwStatus_eUnknown;
598                BDBG_ASSERT(0);
599        }
600}
601
602/*--------------------------------------------------------------------------
603 * Callback from base-module queue to append two Trans' descriptors
604 */
605static void BDMA_P_Pci_AppendTranDesc_isr(
606        BDMA_P_QueueEntry *      pCurrTran,
607        BDMA_P_QueueEntry *      pNextTran )
608{
609        uint32_t  *pulLastDesc ;
610        uint32_t  ulNewDescPhysAddr;
611        uint32_t  ulWord3;
612       
613        BDBG_ASSERT( NULL != pCurrTran );
614        BDBG_ASSERT( NULL != pNextTran );
615
616        ulNewDescPhysAddr = pNextTran->ulDescPhysAddr; 
617        pulLastDesc = (pCurrTran + (pCurrTran->ulNumActBlocks - 1))->pulDescAddr;
618        ulWord3 = *(pulLastDesc+3) & ~(
619                        BCHP_MASK(PCI_DMA_DESC_WORD3, LAST_RECORD_INDICATOR) |
620                        BCHP_MASK(PCI_DMA_DESC_WORD3, NEXT_DESC_ADDR));
621        *(pulLastDesc+3) = ulWord3 |
622                BCHP_FIELD_DATA( PCI_DMA_DESC_WORD3, NEXT_DESC_ADDR,
623                        ulNewDescPhysAddr >> BCHP_PCI_DMA_DESC_WORD3_NEXT_DESC_ADDR_SHIFT );
624}
625
626/*--------------------------------------------------------------------------
627 * Callback from base-module queue to send one Tran to HW.
628 *
629 * Note: It assume block info is already set for all blocks in this Tran
630 */
631static void BDMA_P_Pci_SendToHw_isr(
632        BDMA_P_QueueHandle       hQueue,
633        BDMA_P_HwStatus          eHwStatus,
634        bool                     bAppendInHw )
635{
636        BDMA_P_Pci_Context *pPciDma;
637        BDMA_P_QueueContext * pQueue;
638        BDMA_P_QueueEntry * p1stTran;
639        BDMA_P_QueueEntry * pLastTran;
640        BREG_Handle  hRegister;
641        uint32_t  ulNewDescPhysAddr;
642        uint32_t  ulWord3;
643        uint32_t  *pulLastDesc;
644        uint32_t  ulMaxBurstSize;
645        volatile uint32_t  ulCheck;
646       
647        BDMA_P_QUEUE_GET_CONTEXT( hQueue, pQueue );
648        BDBG_ASSERT( NULL != pQueue );
649
650        pPciDma = (BDMA_P_Pci_Context *)(pQueue->hEngine);
651        hRegister = BDMA_P_GetRegisterHandle(pPciDma->hDma);
652       
653        p1stTran = pQueue->pHeadTranInQ;
654        if (NULL == p1stTran)
655        {
656                BDBG_ASSERT( p1stTran );
657                return;
658        }
659        ulNewDescPhysAddr = pQueue->pHeadTranInQ->ulDescPhysAddr;
660               
661        /* write scratch reg so that other BDMA instance could check our status */
662        pLastTran = pQueue->pTailTranInQ;
663        BDBG_ASSERT( pLastTran );
664        BREG_Write32( hRegister, BCHP_PCI_DMA_SCRATCH0,
665                                  pQueue->ul1stDescPhysAddr | BDMA_P_WATER_MARK_SG_CLOSE );
666
667        /* send Trans queued in SW into HW */
668        pLastTran = pQueue->pTailTranInHw;
669        if (bAppendInHw && (NULL != pLastTran))
670        {
671                /* dynamically link to last tran in hw, which might and might not finished */
672                pulLastDesc = (pLastTran + (pLastTran->ulNumActBlocks - 1))->pulDescAddr;
673                ulWord3 = *(pulLastDesc+3) & ~(
674                        BCHP_MASK( PCI_DMA_DESC_WORD3, LAST_RECORD_INDICATOR) |
675                        BCHP_MASK( PCI_DMA_DESC_WORD3, NEXT_DESC_ADDR));
676                *(pulLastDesc+3) = ulWord3 |
677                        BCHP_FIELD_DATA( PCI_DMA_DESC_WORD3, NEXT_DESC_ADDR,
678                                 ulNewDescPhysAddr >> BCHP_PCI_DMA_DESC_WORD3_NEXT_DESC_ADDR_SHIFT);
679
680                /* read back to force that mem writing completes before reg writing */
681                ulCheck = *(pulLastDesc+3);
682               
683                BREG_Write32( hRegister, BCHP_PCI_DMA_LIST_CTRL,
684                        BCHP_FIELD_DATA(PCI_DMA_LIST_CTRL, WAKE_MODE, BDMA_P_PCI_WAKE_LAST_DESC) |
685                        BCHP_FIELD_DATA(PCI_DMA_LIST_CTRL, WAKE,      1) );
686        }
687        else
688        {
689        ulNewDescPhysAddr = pQueue->pHeadTranInQ->ulDescPhysAddr
690                        + ( pQueue->pHeadTranInQ->ulFirstBlock * 4 * BDMA_P_PCI_NUM_WORDS_PER_DESC);
691                /* must start from FIRST_DESC now */
692                BREG_Write32( hRegister, BCHP_PCI_DMA_FIRST_DESC_ADRS,
693                        BCHP_FIELD_DATA(PCI_DMA_FIRST_DESC_ADRS, DESC_ADRS,
694                        ulNewDescPhysAddr >> BCHP_PCI_DMA_FIRST_DESC_ADRS_DESC_ADRS_SHIFT) );
695
696                ulMaxBurstSize = ( (BDMA_MaxBurstSize_eBurst1 == pPciDma->eMaxBurstSize )?
697                                                   (BCHP_PCI_DMA_CTRL_DMA_BURST_SIZE_SINGLE) :
698                                                   (BCHP_PCI_DMA_CTRL_DMA_BURST_SIZE_BURST) );
699
700                if ( BDMA_P_HwStatus_eIdle != eHwStatus )
701                {
702                        BREG_Write32( hRegister, BCHP_PCI_DMA_CTRL,
703                                BCHP_FIELD_DATA( PCI_DMA_CTRL, DMA_BURST_SIZE, ulMaxBurstSize ) |
704                                BCHP_FIELD_DATA( PCI_DMA_CTRL, DMA_RUN_STOP,
705                                        BCHP_PCI_DMA_CTRL_DMA_RUN_STOP_RUN ) );
706
707                        BREG_Write32( hRegister, BCHP_PCI_DMA_LIST_CTRL,
708                                BCHP_FIELD_DATA(PCI_DMA_LIST_CTRL, WAKE_MODE, BDMA_P_PCI_WAKE_1ST_DESC) |
709                                BCHP_FIELD_DATA(PCI_DMA_LIST_CTRL, WAKE,      1) );             
710                }
711                else /* never started */
712                {
713                        BREG_Write32( hRegister, BCHP_PCI_DMA_CTRL,
714                                BCHP_FIELD_DATA( PCI_DMA_CTRL, DMA_BURST_SIZE, ulMaxBurstSize ) |
715                                BCHP_FIELD_DATA( PCI_DMA_CTRL, DMA_RUN_STOP,
716                                        BCHP_PCI_DMA_CTRL_DMA_RUN_STOP_RUN ) );
717                }
718        }
719}
720
721/*--------------------------------------------------------------------------
722 * Callback from base-module queue to check NEXT_DESC_ADDR and print err msg
723 * dma engine reg read error happens
724 */
725static void BDMA_P_Pci_CheckNextDesc_isr(
726        BDMA_P_QueueEntry *      pCurrTran,
727        BDMA_P_QueueEntry *      pNextTran )
728{
729        BDMA_P_QueueEntry *pBlock;
730        uint32_t  *pulDesc;
731        uint32_t  ulSeeNextOffset, ulNextOffset;
732        int  iLoopCntr;
733       
734        BDBG_ASSERT( NULL != pCurrTran );
735
736        pBlock = pCurrTran;                     
737        for ( iLoopCntr = 0; iLoopCntr < (int) pCurrTran->ulNumActBlocks; iLoopCntr++ )
738        {
739        {
740                if (NULL != pNextTran)
741                        ulNextOffset = ((iLoopCntr < (int) (pCurrTran->ulNumActBlocks - 1))?
742                                                        (pBlock + 1)->ulDescPhysAddr : pNextTran->ulDescPhysAddr);
743                else
744                        ulNextOffset = ((iLoopCntr < (int) (pCurrTran->ulNumActBlocks - 1))?
745                                                        (pBlock + 1)->ulDescPhysAddr : 0);
746                pulDesc = pBlock->pulDescAddr;
747                ulSeeNextOffset = (BCHP_GET_FIELD_DATA(*(pulDesc+3), PCI_DMA_DESC_WORD3, NEXT_DESC_ADDR) <<
748                                                   BCHP_PCI_DMA_DESC_WORD3_NEXT_DESC_ADDR_SHIFT);
749               
750                if (ulNextOffset != ulSeeNextOffset)
751                {
752                        BDBG_ERR(("Bad next_desc: desc 0x%08lx, next_desc 0x%08lx (should be 0x%08lx)",
753                                          pBlock->ulDescPhysAddr, ulSeeNextOffset, ulNextOffset));
754                        BDBG_ERR(("tran_desc 0x%08lx, NumActBlk %d, Blck %d",
755                                          pCurrTran->ulDescPhysAddr, pCurrTran->ulNumActBlocks, iLoopCntr));
756
757                        /*BDBG_ASSERT(ulNextOffset != ulSeeNextOffset);*/
758                }
759#if 0
760                else if (iLoopCntr == (int) (pCurrTran->ulNumActBlocks - 1))
761                {
762                        /* XXX extra print make system busy, and shows HW reg reading problem */
763                        BDBG_MSG(("good next_desc: desc 0x%08lx (blck %d), next_desc 0x%08lx",
764                                          pBlock->ulDescPhysAddr, iLoopCntr, ulSeeNextOffset));
765                }
766#endif
767                pBlock++;
768        }
769
770
771
772               
773                ulNextOffset = ((iLoopCntr == (int) (pCurrTran->ulNumActBlocks - 1)) &&
774                                                (NULL != pNextTran))?
775                        pNextTran->ulDescPhysAddr : (pBlock + 1)->ulDescPhysAddr;
776                pulDesc = (pCurrTran->bCachedDscrp)? pBlock->pulCachedDescAddr : pBlock->pulDescAddr;
777                ulSeeNextOffset = (BCHP_GET_FIELD_DATA(*(pulDesc+3), PCI_DMA_DESC_WORD3, NEXT_DESC_ADDR) <<
778                                                   BCHP_PCI_DMA_DESC_WORD3_NEXT_DESC_ADDR_SHIFT);
779               
780                if (ulNextOffset != ulSeeNextOffset)
781                {
782                        BDBG_ERR(("Bad next_desc: desc 0x%80x, next_desc 0x%80x (should be 0x%80x)",
783                                          pulDesc, ulSeeNextOffset, ulNextOffset));
784                        /*BDBG_ASSERT(ulNextOffset != ulSeeNextOffset);*/
785                }
786        }
787}
788
789
790/***************************************************************************
791 *
792 * "Dma Done" interrupt handler (call back ) function
793 *
794 ***************************************************************************/
795
796/***************************************************************************
797 * To be called by the BINT module as the "dma done" interrupt handler (call
798 * back func). It records the just completed Tran's result, calls the user's
799 * call back function to futher process the DMA result if the Tran is async,
800 * (i.e. if it has a user's call back func).
801 */
802static void BDMA_P_Pci_DoneCallBack_isr(
803        void *                pParm1,  /* pPciDma */
804        int                   parm2 )  /* not used */
805{
806        BERR_Code  eResult = BERR_SUCCESS;
807        BDMA_P_Pci_Context *  pPciDma;
808
809        BSTD_UNUSED(parm2);
810        BDMA_P_PCI_GET_CONTEXT(pParm1, pPciDma);
811        if ( NULL == pPciDma )
812        {
813                eResult = BERR_TRACE( BERR_INVALID_PARAMETER );
814                BDBG_ERR(( "Invaid pParm1 to BDMA_P_Pci_DoneCallBack_isr_isr!" ));
815                goto BDMA_P_Done_Pci_DoneCallBack_isr;
816        }
817
818        /* read status from HW and update records */
819        BDMA_P_Queue_CheckHwAndSendNewReq_isr( pPciDma->hQueue );
820
821  BDMA_P_Done_Pci_DoneCallBack_isr:
822        return;
823}
824
825
826/***************************************************************************
827 *
828 * API support functions
829 *
830 ***************************************************************************/
831
832/*--------------------------------------------------------------------------
833 * To be called to init pci dma engine: 1). init Hw, 2). create queue, 3).
834 * create call-back, 4). init crpto setting.
835 */
836BERR_Code BDMA_P_Pci_Init(
837        BDMA_P_Pci_Context  * pPciDma,
838        const BDMA_Pci_Settings *pSettings,     
839        uint32_t              ulL2IntrBintId )
840{
841        BERR_Code  eResult = BERR_SUCCESS;
842        BDMA_Handle  hDma;
843        BMEM_Handle  hMemory = NULL;  /* init to silence linux comipler */
844        BDMA_P_QueueHandle  hQueue = NULL;
845        BINT_CallbackHandle  hCallBack = NULL;
846
847        BDBG_ASSERT( NULL != pPciDma);
848       
849        BDMA_P_PCI_SET_BLACK_MAGIC( pPciDma );
850
851        /* init HW */
852        hDma = pPciDma->hDma;
853       
854        /* create Tran queue */
855        hMemory = BDMA_P_GetMemoryHandle( hDma );
856        eResult = BDMA_P_Queue_Create(
857                &hQueue, (void *) pPciDma, hMemory, BDMA_P_PCI_NUM_WORDS_PER_DESC,
858                (BDMA_P_CmnSettings *)pSettings, BDMA_P_Pci_ReadHwRegs_isr,
859                BDMA_P_Pci_AppendTranDesc_isr, BDMA_P_Pci_SendToHw_isr,
860                BDMA_P_Pci_CheckNextDesc_isr, BDMA_P_Pci_SafeSendToHw_isr);
861        BDMA_P_END_IF_ERR( eResult, BDMA_P_Err_Pci_Init );
862        pPciDma->hQueue = hQueue;
863
864        if (pSettings->bSupportCallBack)
865        {       
866                /* create done-interrupt call back
867                 * no need to create call back for BCHP_INT_ID_PCI_DMA_ERR_INTR,
868                 * since PI already checks size / error without sending HW ??? */
869                /* BCHP_INT_ID_PCI_DMA_0_INTR, or BCHP_INT_ID_PCI_DMA_1_INTR */
870                eResult = BINT_CreateCallback(
871                        &hCallBack, BDMA_P_GetInterruptHandle( hDma ),
872                        ulL2IntrBintId, BDMA_P_Pci_DoneCallBack_isr,
873                        (void *)pPciDma, 0 );
874                BDMA_P_END_IF_ERR( eResult, BDMA_P_Err_Pci_Init );
875                pPciDma->hCallBack = hCallBack;
876       
877                eResult = BINT_ClearCallback( hCallBack );
878                BDMA_P_END_IF_ERR( eResult, BDMA_P_Err_Pci_Init );
879                eResult = BINT_EnableCallback( hCallBack );
880                BDMA_P_END_IF_ERR( eResult, BDMA_P_Err_Pci_Init );
881        }
882       
883        /* init op */
884        pPciDma->eSwapMode = BDMA_SwapMode_eNoSwap;
885        pPciDma->eMaxBurstSize = BDMA_MaxBurstSize_eBurst16;
886
887        return eResult;
888       
889  BDMA_P_Err_Pci_Init:
890        BDMA_P_Pci_UnInit( pPciDma );
891
892        return BERR_TRACE(eResult);     
893}
894
895/*--------------------------------------------------------------------------
896 * To be called to uninit pci dma engine: destroy queue and call-back
897 */
898BERR_Code BDMA_P_Pci_UnInit(
899        BDMA_P_Pci_Context  * pPciDma )
900{
901        BDBG_ASSERT( NULL != pPciDma);
902
903        if ( NULL != pPciDma->hCallBack )
904        {
905                BINT_DisableCallback( pPciDma->hCallBack );
906                BINT_DestroyCallback( pPciDma->hCallBack );
907        }
908        if ( NULL != pPciDma->hQueue )
909                BDMA_P_Queue_Destroy( pPciDma->hQueue, BDMA_P_GetMemoryHandle(pPciDma->hDma) );
910
911        return BERR_SUCCESS;
912}
913
914
915/***************************************************************************
916 *
917 */
918BERR_Code BDMA_P_Pci_Create(
919        BDMA_Handle           hDma,
920        BDMA_PciDmaEngine     eEngine,
921        const BDMA_Pci_Settings *pSettings,     
922        BDMA_Pci_Handle *     phPciDma )
923{
924        BERR_Code  eResult = BERR_SUCCESS;
925        BDMA_P_Context *  pDma;
926        BDMA_P_Pci_Context  *pPciDma = NULL;
927
928        uint32_t  ulL2IntrBintId;
929
930        if ( NULL != phPciDma )
931                *phPciDma = NULL;
932       
933        BDMA_P_MAIN_GET_CONTEXT( hDma, pDma );
934        if ( (NULL == phPciDma) || (NULL == pDma) || (eEngine >= BDMA_PciDmaEngine_eUnknown))
935        {
936                eResult = BERR_TRACE(BERR_INVALID_PARAMETER);
937                goto BDMA_P_Err_Pci_Create;             
938        }
939       
940        if ( NULL != BDMA_P_GetPciDmaHandle(hDma, eEngine) )
941        {
942                /* memeory dma engine sub-module is already created */
943                eResult = BERR_TRACE(BDMA_ERR_ENGINE_OCCUPIED);
944                goto BDMA_P_Err_Pci_Create;             
945        }
946       
947        /* allocate pci dma sub-module's main context */
948        pPciDma = (BDMA_P_Pci_Context *)BKNI_Malloc( sizeof(BDMA_P_Pci_Context) );
949        if ( NULL == pPciDma )
950        {
951                eResult = BERR_TRACE(BERR_OUT_OF_SYSTEM_MEMORY);
952                goto BDMA_P_Err_Pci_Create;
953        }
954        BKNI_Memset((void*)pPciDma, 0x0, sizeof(BDMA_P_Pci_Context));
955
956        ulL2IntrBintId = BCHP_INT_ID_PCI_DMA_DONE;
957
958        /* init pci dma */
959        pPciDma->hDma = hDma;
960        pPciDma->eEngine = eEngine;
961        eResult = BDMA_P_Pci_Init( pPciDma, pSettings, ulL2IntrBintId );
962        BDMA_P_END_IF_ERR( eResult, BDMA_P_Err_Pci_Create );
963
964        /* connect pci dma sub-module to dma module's main context */
965        BDMA_P_SetPciDmaHandle( hDma, eEngine, pPciDma );
966
967        *phPciDma = pPciDma;
968        return eResult;
969
970  BDMA_P_Err_Pci_Create:
971
972        if ( NULL != pPciDma )
973                BDMA_P_PCI_DESTROY_CONTEXT( pPciDma );
974
975        return BERR_TRACE(eResult);
976}
977
978/***************************************************************************
979 *
980 */
981BERR_Code BDMA_P_Pci_Destroy(
982        BDMA_Pci_Handle       hPciDma )
983{
984        BERR_Code  eResult = BERR_SUCCESS;
985        BDMA_P_Pci_Context *  pPciDma;
986       
987        BDMA_P_PCI_GET_CONTEXT(hPciDma, pPciDma);
988        if ( NULL == pPciDma )
989        {
990                eResult = BERR_TRACE(BERR_INVALID_PARAMETER);
991                goto BDMA_P_Done_Pci_Destroy;
992        }
993
994        /* disconnect pci dma sub-module to dma module's main context */
995        BDMA_P_SetPciDmaHandle( pPciDma->hDma, pPciDma->eEngine, NULL );
996
997        /* destroy callBack and queue */
998        BDMA_P_Pci_UnInit( pPciDma );
999        BDMA_P_PCI_DESTROY_CONTEXT( pPciDma );
1000
1001  BDMA_P_Done_Pci_Destroy:
1002        return eResult; 
1003}
1004
1005/***************************************************************************
1006 *
1007 */
1008BERR_Code BDMA_P_Pci_SetSwapMode_isr(
1009        BDMA_Pci_Handle       hPciDma,
1010        BDMA_SwapMode         eSwapMode )
1011{
1012        BERR_Code  eResult = BERR_SUCCESS;
1013        BDMA_P_Pci_Context *  pPciDma;
1014       
1015        BDMA_P_PCI_GET_CONTEXT(hPciDma, pPciDma);
1016        if ( (NULL == pPciDma) ||
1017                 (eSwapMode >= BDMA_SwapMode_eInvalid) )
1018        {
1019                eResult = BERR_TRACE(BERR_INVALID_PARAMETER);
1020                goto BDMA_P_Done_Pci_SetSwapMode;               
1021        }
1022
1023        pPciDma->eSwapMode = eSwapMode;
1024
1025  BDMA_P_Done_Pci_SetSwapMode:
1026        return eResult;
1027}
1028
1029/***************************************************************************
1030 *
1031 */
1032BERR_Code BDMA_P_Pci_SetMaxBurstSize_isr(
1033        BDMA_Pci_Handle       hPciDma,
1034        BDMA_MaxBurstSize     eMaxBurstSize )
1035{
1036        BERR_Code  eResult = BERR_SUCCESS;
1037        BDMA_P_Pci_Context *  pPciDma;
1038       
1039        BDMA_P_PCI_GET_CONTEXT(hPciDma, pPciDma);
1040        if ( (NULL == pPciDma) ||
1041                 (eMaxBurstSize >= BDMA_MaxBurstSize_eInvalid) )
1042        {
1043                eResult = BERR_TRACE(BERR_INVALID_PARAMETER);
1044                goto BDMA_P_Done_Pci_SetMaxBurstSize;           
1045        }
1046
1047        pPciDma->eMaxBurstSize = eMaxBurstSize;
1048
1049  BDMA_P_Done_Pci_SetMaxBurstSize:
1050        return eResult;
1051}
1052
1053/***************************************************************************
1054 * To be called to created a new Tran
1055 */
1056BERR_Code BDMA_P_Pci_Tran_Create_isr(
1057        BDMA_Pci_Handle          hPciDma,
1058        uint32_t                 ulNumBlocks,
1059        bool                     bCachedDesc,
1060        BDMA_Pci_Tran_Handle  *  phTran )
1061{
1062        BERR_Code  eResult = BERR_SUCCESS;
1063        BDMA_P_Pci_Context *  pPciDma;
1064        BDMA_P_QueueEntry * pTran;
1065
1066        if ( NULL != phTran )
1067                *phTran = NULL;
1068       
1069        BDMA_P_PCI_GET_CONTEXT( hPciDma, pPciDma );
1070        if ( (NULL == pPciDma) || (NULL == phTran) )
1071        {
1072                eResult = BERR_TRACE(BERR_INVALID_PARAMETER);
1073                goto BDMA_P_Done_Pci_Tran_Create;
1074        }
1075
1076        eResult = BDMA_P_Queue_CreateTran_isr(
1077                pPciDma->hQueue, ulNumBlocks, bCachedDesc, &pTran );
1078        if ( BERR_SUCCESS == eResult )
1079                *phTran = (BDMA_Pci_Tran_Handle ) pTran;
1080
1081  BDMA_P_Done_Pci_Tran_Create:
1082        return BERR_TRACE(eResult);
1083}
1084
1085/***************************************************************************
1086 * To be called to set the block info for a Tran block. Input block info are
1087 * validated against the current engine state.
1088 */
1089BERR_Code BDMA_P_Pci_Tran_SetBlockInfo_isr(
1090        BDMA_Pci_Tran_Handle     hTran,
1091        uint32_t                 ulBlockId,
1092        uint32_t                 ulMemBusAddr,
1093        uint32_t                 ulPciBusAddr,
1094        uint32_t                 ulBlockSize,
1095        BDMA_TranDir             eTranDirection )
1096{
1097        BERR_Code  eResult = BERR_SUCCESS;
1098        BDMA_P_Pci_Context *  pPciDma;
1099        BDMA_P_QueueEntry * pTran;
1100        BDMA_P_QueueEntry * pBlock;
1101        bool bLastBlock;       
1102
1103        BDMA_P_TRAN_GET_CONTEXT( hTran, pTran );
1104        if ( NULL == pTran )
1105        {
1106                eResult = BERR_TRACE(BERR_INVALID_PARAMETER);
1107                goto BDMA_P_Done_Pci_Tran_SetBlockInfo;
1108        }
1109
1110        if ( pTran->ulNumTranBlocks <= ulBlockId )
1111        {
1112                eResult = BERR_TRACE(BERR_INVALID_PARAMETER);
1113                goto BDMA_P_Done_Pci_Tran_SetBlockInfo;
1114        }
1115
1116        eResult = BDMA_P_Pci_GetPciDmaPtrFromTran_isr( pTran, &pPciDma );
1117        BDMA_P_END_IF_ERR( eResult, BDMA_P_Done_Pci_Tran_SetBlockInfo );
1118
1119        /* validate addr, size and set desc */
1120        bLastBlock = (pTran->ulNumTranBlocks == (ulBlockId+1)); 
1121        pBlock = pTran + ulBlockId;
1122        eResult = BDMA_P_Pci_SetBlockDesc_isr( pPciDma,
1123                                                                                   pBlock,
1124                                                                                   pTran->bCachedDscrp,
1125                                                                                   ulMemBusAddr, ulPciBusAddr,
1126                                                                                   ulBlockSize,
1127                                                                                   eTranDirection );
1128        if ( BERR_SUCCESS == eResult )
1129                pBlock->bBlockInfoSet = true;
1130
1131  BDMA_P_Done_Pci_Tran_SetBlockInfo:
1132        return BERR_TRACE( eResult );   
1133}
1134
1135/***************************************************************************
1136 * To be called by both BDMA_P_Pci_Tran_Start_isrAndCallBack and
1137 * BDMA_P_Pci_Tran_Start_isr. BDMA_P_Pci_Tran_Start_isr should pass NULL for
1138 * pCallBackFunc_isr and pUserCallBackParam
1139 *
1140 * Note: when a Tran is sent to HW, interrupt is alwayas enabled. If the
1141 * Tran is async, the module's interrupt handler BDMA_P_Pci_DoneCallBack_isr
1142 * will call user's callback function. In the sync case, there is no user's
1143 * call back function to call, BDMA_P_Pci_DoneCallBack_isr_isr only sets the
1144 * internal record of the status, the ideal is that the user will check the
1145 * Tran's status in a waiting loop and process the Tran result synchronously.
1146 */
1147BERR_Code BDMA_P_Pci_Tran_Start_isr(
1148        BDMA_Pci_Tran_Handle     hTran,
1149        uint32_t                 ulNumActBlocks,
1150        BDMA_Pci_CallbackFunc    pCallBackFunc_isr,
1151        void *                   pUserCallBackParam )
1152{
1153        BERR_Code  eResult = BERR_SUCCESS;
1154        BDMA_P_Pci_Context *  pPciDma;
1155        BDMA_P_QueueEntry * pTran;
1156       
1157        BDMA_P_TRAN_GET_CONTEXT( hTran, pTran );
1158        if ( NULL == pTran )
1159        {
1160                eResult = BERR_TRACE(BERR_INVALID_PARAMETER);
1161                goto BDMA_P_Done_Pci_Tran_Start;
1162        }
1163
1164        eResult = BDMA_P_Pci_GetPciDmaPtrFromTran_isr( pTran, &pPciDma );
1165        BDMA_P_END_IF_ERR( eResult, BDMA_P_Done_Pci_Tran_Start );
1166
1167        eResult = BDMA_P_Pci_Tran_PrepareStart_isr( pTran, pPciDma->hQueue,
1168                BDMA_P_GetMemoryHandle(pPciDma->hDma), ulNumActBlocks);
1169        BDMA_P_END_IF_ERR( eResult, BDMA_P_Done_Pci_Tran_Start );
1170
1171        eResult = BDMA_P_Queue_StartTran_isr (
1172                pPciDma->hQueue, pTran, ulNumActBlocks, false,
1173                (BDMA_P_CallbackFunc) pCallBackFunc_isr, pUserCallBackParam );
1174
1175  BDMA_P_Done_Pci_Tran_Start:
1176        return BERR_TRACE(eResult);
1177}
1178
1179/***************************************************************************
1180 */
1181
1182BERR_Code BDMA_P_Pci_Tran_StartSubset_isr(
1183        BDMA_Mem_Tran_Handle     hTran,
1184        uint32_t                 ulFirstBlock,
1185        uint32_t                 ulNumActBlocks,
1186        BDMA_Mem_CallbackFunc    pCallBackFunc_isr,
1187        void *                   pUserCallBackParam )
1188{
1189        BERR_Code  eResult = BERR_SUCCESS;
1190        BDMA_P_Pci_Context *  pPciDma;
1191        BDMA_P_QueueEntry * pTran;
1192
1193
1194        BDMA_P_TRAN_GET_CONTEXT( hTran, pTran );
1195        if ( NULL == pTran )
1196        {
1197                eResult = BERR_TRACE(BERR_INVALID_PARAMETER);
1198                goto BDMA_P_Done_Pci_Tran_Start;
1199        }
1200
1201        eResult = BDMA_P_Pci_GetPciDmaPtrFromTran_isr( pTran, &pPciDma );
1202        BDMA_P_END_IF_ERR( eResult, BDMA_P_Done_Pci_Tran_Start );
1203
1204        eResult = BDMA_P_Pci_Tran_PrepareStartSubset_isr( pTran, pPciDma->hQueue,
1205                BDMA_P_GetMemoryHandle(pPciDma->hDma), ulFirstBlock, ulNumActBlocks);
1206        BDMA_P_END_IF_ERR( eResult, BDMA_P_Done_Pci_Tran_Start );
1207
1208        eResult = BDMA_P_Queue_StartTran_isr (
1209                pPciDma->hQueue, pTran, ulNumActBlocks, false,
1210                (BDMA_P_CallbackFunc) pCallBackFunc_isr, pUserCallBackParam );
1211
1212  BDMA_P_Done_Pci_Tran_Start:
1213        return BERR_TRACE(eResult);
1214}
1215
1216/***************************************************************************
1217 * To be called by BDMA_Pci_Tran_GetStatus. It outputs the internal records
1218 * of the Tran directly.
1219 */
1220BERR_Code BDMA_P_Pci_Tran_GetStatus_isr(
1221        BDMA_Pci_Tran_Handle     hTran,
1222        BDMA_TranStatus *        peTranStatus )
1223{
1224        BERR_Code  eResult = BERR_SUCCESS;
1225        BDMA_P_Pci_Context *  pPciDma;
1226        BDMA_P_QueueEntry * pTran;
1227
1228        BDMA_P_TRAN_GET_CONTEXT( hTran, pTran );
1229        if ( NULL == pTran )
1230        {
1231                eResult = BERR_TRACE(BERR_INVALID_PARAMETER);
1232                goto BDMA_P_Done_Pci_Tran_GetStatus;
1233        }
1234
1235        eResult = BDMA_P_Pci_GetPciDmaPtrFromTran_isr( pTran, &pPciDma );
1236        BDMA_P_END_IF_ERR( eResult, BDMA_P_Done_Pci_Tran_GetStatus );
1237
1238        /* read status from HW and update Trans' records */
1239        BDMA_P_Queue_CheckHwAndSendNewReq_isr( pPciDma->hQueue );
1240        *peTranStatus = pTran->eStatus; 
1241        return BERR_SUCCESS;
1242
1243  BDMA_P_Done_Pci_Tran_GetStatus:
1244        return BERR_TRACE(eResult);
1245}
1246
1247
1248/***************************************************************************
1249 * To be called by BDMA_Pci_Tran_Destroy. It free the queue entries occupied
1250 * this Tran
1251 */
1252BERR_Code BDMA_P_Pci_Tran_Destroy_isr(
1253        BDMA_Pci_Tran_Handle     hTran )
1254{
1255        BERR_Code  eResult = BERR_SUCCESS;
1256        BDMA_P_Pci_Context *  pPciDma;
1257        BDMA_P_QueueEntry * pTran;
1258
1259        BDMA_P_TRAN_GET_CONTEXT( hTran, pTran );
1260        if ( NULL == pTran )
1261        {
1262                eResult = BERR_TRACE(BERR_INVALID_PARAMETER);
1263                goto BDMA_P_Done_Pci_Tran_Destroy;
1264        }
1265
1266        eResult = BDMA_P_Pci_GetPciDmaPtrFromTran_isr( pTran, &pPciDma );
1267        BDMA_P_END_IF_ERR( eResult, BDMA_P_Done_Pci_Tran_Destroy );
1268
1269        /* tell queue module to free the queue entries of this */
1270        eResult = BDMA_P_Queue_DestroyTran_isr ( pPciDma->hQueue,
1271                                                                                         pTran );
1272        BDMA_P_END_IF_ERR( eResult, BDMA_P_Done_Pci_Tran_Destroy );
1273       
1274        return BERR_SUCCESS;
1275
1276  BDMA_P_Done_Pci_Tran_Destroy:
1277        return BERR_TRACE(eResult);
1278}
1279
1280/***************************************************************************
1281 * To be called by BDMA_Pci_Tran_Reset. It resets the Tran into its
1282 * initially created state
1283 */
1284BERR_Code BDMA_P_Pci_Tran_Reset_isr(
1285        BDMA_Pci_Tran_Handle     hTran )
1286{
1287        BERR_Code  eResult = BERR_SUCCESS;
1288        BDMA_P_Pci_Context *  pPciDma;
1289        BDMA_P_QueueEntry * pTran;
1290
1291        BDMA_P_TRAN_GET_CONTEXT( hTran, pTran );
1292        if ( NULL == pTran )
1293        {
1294                eResult = BERR_TRACE(BERR_INVALID_PARAMETER);
1295                goto BDMA_P_Done_Pci_Tran_Reset;
1296        }
1297
1298        eResult = BDMA_P_Pci_GetPciDmaPtrFromTran_isr( pTran, &pPciDma );
1299        BDMA_P_END_IF_ERR( eResult, BDMA_P_Done_Pci_Tran_Reset );
1300
1301        /* tell queue module to reset this Tran into initially created state */
1302        eResult = BDMA_P_Queue_ResetTran_isr ( pPciDma->hQueue,
1303                                                                                   pTran );
1304        BDMA_P_END_IF_ERR( eResult, BDMA_P_Done_Pci_Tran_Reset );
1305       
1306        return BERR_SUCCESS;
1307
1308  BDMA_P_Done_Pci_Tran_Reset:
1309        return BERR_TRACE(eResult);
1310}
1311
1312
1313/* End of File */
Note: See TracBrowser for help on using the repository browser.