source: svn/newcon3bcm2_21bu/nexus/modules/dma/7552/src/nexus_dma.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: 27.9 KB
Line 
1/***************************************************************************
2 *     (c)2007-2011 Broadcom Corporation
3 *
4 *  This program is the proprietary software of Broadcom Corporation and/or its licensors,
5 *  and may only be used, duplicated, modified or distributed pursuant to the terms and
6 *  conditions of a separate, written license agreement executed between you and Broadcom
7 *  (an "Authorized License").  Except as set forth in an Authorized License, Broadcom grants
8 *  no license (express or implied), right to use, or waiver of any kind with respect to the
9 *  Software, and Broadcom expressly reserves all rights in and to the Software and all
10 *  intellectual property rights therein.  IF YOU HAVE NO AUTHORIZED LICENSE, THEN YOU
11 *  HAVE NO RIGHT TO USE THIS SOFTWARE IN ANY WAY, AND SHOULD IMMEDIATELY
12 *  NOTIFY BROADCOM AND DISCONTINUE ALL USE OF THE SOFTWARE.
13 *
14 *  Except as expressly set forth in the Authorized License,
15 *
16 *  1.     This program, including its structure, sequence and organization, constitutes the valuable trade
17 *  secrets of Broadcom, and you shall use all reasonable efforts to protect the confidentiality thereof,
18 *  and to use this information only in connection with your use of Broadcom integrated circuit products.
19 *
20 *  2.     TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
21 *  AND WITH ALL FAULTS AND BROADCOM MAKES NO PROMISES, REPRESENTATIONS OR
22 *  WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO
23 *  THE SOFTWARE.  BROADCOM SPECIFICALLY DISCLAIMS ANY AND ALL IMPLIED WARRANTIES
24 *  OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE,
25 *  LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION
26 *  OR CORRESPONDENCE TO DESCRIPTION. YOU ASSUME THE ENTIRE RISK ARISING OUT OF
27 *  USE OR PERFORMANCE OF THE SOFTWARE.
28 *
29 *  3.     TO THE MAXIMUM EXTENT PERMITTED BY LAW, IN NO EVENT SHALL BROADCOM OR ITS
30 *  LICENSORS BE LIABLE FOR (i) CONSEQUENTIAL, INCIDENTAL, SPECIAL, INDIRECT, OR
31 *  EXEMPLARY DAMAGES WHATSOEVER ARISING OUT OF OR IN ANY WAY RELATING TO YOUR
32 *  USE OF OR INABILITY TO USE THE SOFTWARE EVEN IF BROADCOM HAS BEEN ADVISED OF
33 *  THE POSSIBILITY OF SUCH DAMAGES; OR (ii) ANY AMOUNT IN EXCESS OF THE AMOUNT
34 *  ACTUALLY PAID FOR THE SOFTWARE ITSELF OR U.S. $1, WHICHEVER IS GREATER. THESE
35 *  LIMITATIONS SHALL APPLY NOTWITHSTANDING ANY FAILURE OF ESSENTIAL PURPOSE OF
36 *  ANY LIMITED REMEDY.
37 *
38 * $brcm_Workfile: nexus_dma.c $
39 * $brcm_Revision: 42 $
40 * $brcm_Date: 12/14/11 3:41p $
41 *
42 * Module Description:
43 *
44 * Revision History:
45 *
46 * $brcm_Log: /nexus/modules/dma/7550/src/nexus_dma.c $
47 *
48 * 42   12/14/11 3:41p jtna
49 * SW7550-774: sharf dma descriptor translation
50 *
51 * 41   11/8/11 3:05p jtna
52 * SW7425-1079: move power management from nexus_dma to bmmd
53 *
54 * 40   10/3/11 11:10a erickson
55 * SW7420-1995: cannot unregister handles is module is being
56 *  uninitialized. requires special case.
57 *
58 * 39   9/22/11 2:44p erickson
59 * SW7420-1995: unregister handles from objdb when doing automatic close
60 *
61 * 38   6/2/11 4:30p jtna
62 * SW7405-5344: add NEXUS_DmaJobBlockOffsetSettings and related functions
63 *
64 * 37   5/13/11 12:24p jtna
65 * SW7400-3026: add NEXUS_DmaJob_GetSettings() and SetSettings()
66 *
67 * 36   5/12/11 2:52p jtna
68 * SW7550-739: merge SHARF support
69 *
70 * 35   4/29/11 4:23p jtna
71 * SW7420-420: update comments
72 *
73 * 34   4/25/11 5:29p jtna
74 * SW7422-416: add check for invalid SG crypto start/end indicators
75 *
76 * 33   4/22/11 6:49p jtna
77 * SW7420-420: merge BMMD-based Nexus DMA module
78 *
79 **************************************************************************/
80#include "nexus_dma_module.h"
81#include "nexus_base.h"
82#include "blst_squeue.h"
83#include "nexus_class_verification.h"
84
85#if NEXUS_HAS_SECURITY
86#include "priv/nexus_core_security.h"
87#endif
88
89#if NEXUS_NUM_SHARF_DMA_CHANNELS && (!NEXUS_NUM_DMA_CHANNELS)
90#define NEXUS_SHARF_DMA_KEY_REQUIRES_DESCRIPTOR 1 /* requires key and IV to be in a separate descriptor */
91#endif
92
93BDBG_MODULE(nexus_dma);
94#define BDBG_MSG_TRACE(x) /* BDBG_MSG(x) */
95
96typedef struct NEXUS_DmaJob
97{
98    BDBG_OBJECT(NEXUS_DmaJob)
99    BLST_S_ENTRY(NEXUS_DmaJob) jobNode;
100    BLST_SQ_ENTRY(NEXUS_DmaJob) activeNode;
101
102    BMMD_ContextHandle ctx;   
103    NEXUS_DmaHandle parent;
104    NEXUS_IsrCallbackHandle completionCallback_isr;
105    enum {
106        NEXUS_DmaJob_P_StateIdle,
107        NEXUS_DmaJob_P_StateQueued /* job is queued in activeNode */
108    } state;
109    BKNI_EventHandle nexusEvent; /* event that is used to notify nexus module */
110    NEXUS_DmaJobSettings settings;
111    BMMD_ContextBlockSettings blockSettings[1]; /* variable size array, must be last entry in the structure */
112} NEXUS_DmaJob;
113
114typedef struct NEXUS_Dma
115{
116    BDBG_OBJECT(NEXUS_Dma)
117    BLST_S_ENTRY(NEXUS_Dma) link;
118    unsigned pubIndex; /* this is the index that NEXUS_Dma_Open was called with */
119    unsigned privIndex; /* this is the internal index. on platforms that have both MEM_DMA and SHARF_DMA cores,
120                           the MEM_DMA cores are numbered first from 0, then followed by SHARF_DMA cores */
121    NEXUS_DmaSettings settings;
122    BLST_S_HEAD(JobList, NEXUS_DmaJob) jobList; /* this keeps track of the opened BMMD_Context's */
123} NEXUS_Dma;
124
125static void NEXUS_Dma_P_CompleteCallback_isr(void *pParam, int iParam);
126
127
128void NEXUS_Dma_GetDefaultSettings(
129    NEXUS_DmaSettings *pSettings
130    )
131{
132    BDBG_ASSERT(NULL != pSettings);
133    BKNI_Memset(pSettings, 0, sizeof(*pSettings));
134    return;
135}
136
137NEXUS_Error NEXUS_Dma_P_ApplySettings(
138    NEXUS_DmaHandle handle, 
139    const NEXUS_DmaSettings *pSettings
140    )
141{
142    NEXUS_DmaJobHandle pJob;
143    BMMD_ContextSettings ctxSettings;
144    BERR_Code rc;
145   
146    BDBG_OBJECT_ASSERT(handle, NEXUS_Dma);
147    BDBG_ASSERT(pSettings);
148
149    BDBG_CASSERT(BMMD_EndianMode_eMax==(BMMD_EndianMode)NEXUS_DmaEndianMode_eMax);
150    BDBG_CASSERT(BMMD_SwapMode_eMax==(BMMD_SwapMode)NEXUS_DmaSwapMode_eMax);
151
152    /* apply settings to all MMD contexts */
153    for (pJob=BLST_S_FIRST(&handle->jobList); pJob; pJob=BLST_S_NEXT(pJob, jobNode)) {
154        BMMD_Context_GetSettings(pJob->ctx, &ctxSettings);
155        ctxSettings.endianMode = pSettings->endianMode;
156        ctxSettings.swapMode = pSettings->swapMode;
157        rc = BMMD_Context_SetSettings(pJob->ctx, &ctxSettings);
158        if (rc!=BERR_SUCCESS) {
159            rc = BERR_TRACE(rc);
160            return NEXUS_INVALID_PARAMETER;
161        }
162    }
163       
164    BKNI_Memcpy(&handle->settings, pSettings, sizeof(*pSettings));
165    return NEXUS_SUCCESS;
166}
167
168NEXUS_DmaHandle NEXUS_Dma_Open(
169    unsigned index,
170    const NEXUS_DmaSettings *pSettings  /* may be NULL for default settings */
171    )
172{
173    NEXUS_Error errCode;
174    NEXUS_DmaHandle dma;
175    NEXUS_DmaSettings settings;
176
177    if (!pSettings) {
178        NEXUS_Dma_GetDefaultSettings(&settings);
179        pSettings = &settings;
180    }
181
182    if (pSettings->coreType==NEXUS_DmaCoreType_eM2m && (int)index>=NEXUS_NUM_DMA_CHANNELS) { /* the cast to int suppresses a benign compiler warning */
183        BDBG_ERR(("DMA channel %d is not supported on this chipset", index));
184        errCode = BERR_TRACE(NEXUS_INVALID_PARAMETER);
185        return NULL;
186    }
187    if (pSettings->coreType==NEXUS_DmaCoreType_eSharf && (int)index>=NEXUS_NUM_SHARF_DMA_CHANNELS) {
188        BDBG_ERR(("SHARF DMA channel %d is not supported on this chipset", index));
189        errCode = BERR_TRACE(NEXUS_INVALID_PARAMETER);
190        return NULL;
191    }
192
193    dma = BKNI_Malloc(sizeof(*dma));
194    if (!dma) {
195        errCode = BERR_TRACE(NEXUS_OUT_OF_SYSTEM_MEMORY);
196        return NULL;
197    }
198
199    BKNI_Memset(dma, 0, sizeof(*dma));
200    BDBG_OBJECT_SET(dma, NEXUS_Dma);
201
202    dma->pubIndex = index;
203    dma->privIndex = pSettings->coreType==NEXUS_DmaCoreType_eM2m ? index : index+NEXUS_NUM_DMA_CHANNELS;
204
205    BLST_S_INIT(&dma->jobList);
206
207    errCode = NEXUS_Dma_P_ApplySettings(dma, pSettings);
208    if (errCode) {
209        goto error;
210    }
211
212    BLST_S_INSERT_HEAD(&g_NEXUS_dmaModuleData.channel[dma->privIndex].dmaHandles, dma, link);
213    return dma;
214   
215error:
216    NEXUS_Dma_Close(dma);
217    return NULL;   
218}
219
220void NEXUS_Dma_Close(
221    NEXUS_DmaHandle handle
222    )
223{
224    NEXUS_DmaJob *pJob;
225
226    BDBG_OBJECT_ASSERT(handle, NEXUS_Dma);
227
228    while ((pJob = BLST_S_FIRST(&handle->jobList))) {
229        BDBG_WRN(("NEXUS_Dma_Close: stale job %#lx", (unsigned long)pJob));
230        /* if module is being shutdown, we cannot unregister. */
231        if (!g_NEXUS_dmaModuleData.shutdown) {
232            nexus_unregister_NEXUS_DmaJobHandle(nexus_dma_client(), pJob, false);
233        }
234        NEXUS_DmaJob_Destroy(pJob);
235    }
236
237    BLST_S_REMOVE(&g_NEXUS_dmaModuleData.channel[handle->privIndex].dmaHandles, handle, NEXUS_Dma, link);
238    BDBG_OBJECT_DESTROY(handle, NEXUS_Dma);
239    BKNI_Free(handle);
240}
241
242NEXUS_Error NEXUS_Dma_GetSettings(
243    NEXUS_DmaHandle handle,
244    NEXUS_DmaSettings *pSettings
245    )
246{
247    BDBG_OBJECT_ASSERT(handle, NEXUS_Dma);
248    BDBG_ASSERT(NULL != pSettings);
249    *pSettings = handle->settings;
250    return BERR_SUCCESS;
251}
252
253NEXUS_Error NEXUS_Dma_SetSettings(
254    NEXUS_DmaHandle handle,
255    const NEXUS_DmaSettings *pSettings
256    )
257{
258    NEXUS_Error errCode;
259
260    BDBG_OBJECT_ASSERT(handle, NEXUS_Dma);
261    BDBG_ASSERT(pSettings);
262
263    if (handle->settings.coreType != pSettings->coreType) {
264        return BERR_TRACE(NEXUS_INVALID_PARAMETER);
265    }
266    errCode = NEXUS_Dma_P_ApplySettings(handle, pSettings);
267    if (errCode!=BERR_SUCCESS) {
268        return BERR_TRACE(errCode);
269    }
270
271    return NEXUS_SUCCESS;
272}
273
274void NEXUS_DmaJob_GetDefaultSettings(
275    NEXUS_DmaJobSettings *pSettings
276    )
277{
278    BDBG_ASSERT(NULL != pSettings);
279    BKNI_Memset(pSettings, 0, sizeof(*pSettings));
280    pSettings->numBlocks = 1;
281    pSettings->keySlot = NULL;
282}
283
284NEXUS_Error NEXUS_Dma_P_ApplyJobSettings(
285    NEXUS_DmaJobHandle handle, 
286    const NEXUS_DmaJobSettings *pSettings
287    )
288{
289    NEXUS_Error rc;
290    BMMD_ContextSettings ctxSettings;
291
292    if (pSettings->numBlocks != handle->settings.numBlocks) {
293        rc = BERR_TRACE(NEXUS_INVALID_PARAMETER);
294        goto error;
295    }
296
297    BMMD_Context_GetSettings(handle->ctx, &ctxSettings);
298    ctxSettings.endianMode = handle->parent->settings.endianMode;
299    ctxSettings.swapMode = handle->parent->settings.swapMode;
300    ctxSettings.callback_isr = NEXUS_Dma_P_CompleteCallback_isr;
301    ctxSettings.pParm1 = handle;
302    /* BMMD will ignore sharf settings if not needed */
303    BDBG_CASSERT(BMMD_SharfMode_eMax==(BMMD_SharfMode)NEXUS_DmaSharfMode_eMax);
304    ctxSettings.sharf.useBspKey = pSettings->sharf.useBspKey;
305    ctxSettings.sharf.mode = pSettings->sharf.mode;
306    ctxSettings.sharf.shaContext = pSettings->sharf.shaContext;
307
308    if (pSettings->keySlot == NULL) {
309        ctxSettings.scramMode = BMMD_ScramMode_eNone;
310        ctxSettings.keyslot = 0; /* don't care */
311    }
312    else {
313#if NEXUS_HAS_SECURITY
314        NEXUS_SecurityKeySlotInfo keySlotInfo;
315
316        switch (pSettings->dataFormat) {
317            default:
318            case NEXUS_DmaDataFormat_eBlock:
319                ctxSettings.scramMode = BMMD_ScramMode_eBlock;
320                break;
321            case NEXUS_DmaDataFormat_eMpeg:
322                ctxSettings.scramMode = BMMD_ScramMode_eMpeg;
323                break;
324            case NEXUS_DmaDataFormat_eDss:
325                ctxSettings.scramMode = BMMD_ScramMode_eDss;
326                break;
327        }
328        NEXUS_P_Core_GetKeySlotInfo(pSettings->keySlot, &keySlotInfo);
329        if (keySlotInfo.keySlotEngine!=NEXUS_SecurityEngine_eM2m) {
330            rc = BERR_TRACE(BERR_INVALID_PARAMETER);
331            goto error;
332        }
333        ctxSettings.keyslot = keySlotInfo.keySlotNumber;
334#else
335        rc = BERR_TRACE(NEXUS_NOT_SUPPORTED);
336        goto error;
337#endif
338    }
339    rc = BMMD_Context_SetSettings(handle->ctx, &ctxSettings);
340    if (rc!=BERR_SUCCESS) {
341        rc = NEXUS_UNKNOWN;
342        goto error;
343    }
344
345    NEXUS_IsrCallback_Set(handle->completionCallback_isr, &pSettings->completionCallback);
346    handle->settings = *pSettings;
347    return NEXUS_SUCCESS;
348
349error:
350    return rc;
351}
352
353NEXUS_DmaJobHandle NEXUS_DmaJob_Create(
354    NEXUS_DmaHandle dmaHandle,
355    const NEXUS_DmaJobSettings *pSettings
356    )
357{
358    NEXUS_DmaJob *pJob;
359    NEXUS_DmaJobSettings jobSettings;
360    NEXUS_Error rc;
361    BMMD_ContextSettings ctxSettings;
362
363    BDBG_OBJECT_ASSERT(dmaHandle, NEXUS_Dma);
364
365    if (NULL == pSettings) {
366        NEXUS_DmaJob_GetDefaultSettings(&jobSettings);
367        pSettings = &jobSettings;
368    }
369    if (pSettings->numBlocks<=0) {
370        rc = BERR_TRACE(BERR_INVALID_PARAMETER);
371        return NULL;
372    }
373   
374    pJob = BKNI_Malloc(sizeof(*pJob)+sizeof(BMMD_ContextBlockSettings)*(pSettings->numBlocks+1)); /* +1 for NEXUS_SHARF_DMA_KEY_REQUIRES_DESCRIPTOR */
375    if (NULL == pJob) {
376        rc = BERR_TRACE(BERR_OUT_OF_SYSTEM_MEMORY);
377        return NULL;
378    }
379
380    BKNI_Memset(pJob, 0, sizeof(*pJob)+sizeof(BMMD_ContextBlockSettings)*(pSettings->numBlocks+1));
381    BDBG_OBJECT_SET(pJob, NEXUS_DmaJob);
382    BDBG_ASSERT(pSettings->dataFormat < NEXUS_DmaDataFormat_eMax);
383    pJob->nexusEvent = NULL;
384    pJob->parent = dmaHandle;
385    pJob->settings = *pSettings;
386    pJob->completionCallback_isr = NEXUS_IsrCallback_Create(pJob, NULL);
387
388    /* create the context with maxNumBlocks. change the settings afterwards */
389    BMMD_Context_GetDefaultSettings(&ctxSettings);
390    ctxSettings.maxNumBlocks = pSettings->numBlocks+1;
391    pJob->ctx = BMMD_Context_Create(g_NEXUS_dmaModuleData.channel[dmaHandle->privIndex].mmd, &ctxSettings);
392    if (!pJob->ctx) {
393        goto error;
394    }
395
396    rc = NEXUS_Dma_P_ApplyJobSettings(pJob, pSettings);
397    if (rc!=NEXUS_SUCCESS) {
398        BMMD_Context_Destroy(pJob->ctx);
399        goto error;
400    }
401   
402    BLST_S_INSERT_HEAD(&dmaHandle->jobList, pJob, jobNode);
403    return pJob;
404
405error:
406    NEXUS_IsrCallback_Destroy(pJob->completionCallback_isr);
407    BDBG_OBJECT_DESTROY(pJob, NEXUS_DmaJob);
408    BKNI_Free(pJob);
409    return NULL;   
410}
411
412void NEXUS_DmaJob_Destroy(
413    NEXUS_DmaJobHandle handle
414    )
415{
416    BDBG_OBJECT_ASSERT(handle, NEXUS_DmaJob);
417
418    BMMD_Context_Destroy(handle->ctx);
419    /* the assumption is that after BMMD_Context_Destroy() has been called, the ISR callback will not fire */
420    BLST_S_REMOVE(&handle->parent->jobList, handle, NEXUS_DmaJob, jobNode);
421    NEXUS_IsrCallback_Destroy(handle->completionCallback_isr);
422    BDBG_OBJECT_DESTROY(handle, NEXUS_DmaJob);
423    BKNI_Free(handle);
424    return;
425}
426
427void NEXUS_DmaJob_GetSettings(
428    NEXUS_DmaJobHandle handle,
429    NEXUS_DmaJobSettings *pSettings
430    )
431{
432    BDBG_OBJECT_ASSERT(handle, NEXUS_DmaJob);
433    BDBG_ASSERT(NULL != pSettings);
434    *pSettings = handle->settings;
435    return;
436}
437
438NEXUS_Error NEXUS_DmaJob_SetSettings(
439    NEXUS_DmaJobHandle handle,
440    const NEXUS_DmaJobSettings *pSettings
441    )
442{
443    return NEXUS_Dma_P_ApplyJobSettings(handle, pSettings);
444}
445
446void NEXUS_DmaJob_GetDefaultBlockSettings(
447    NEXUS_DmaJobBlockSettings *pSettings
448    )
449{
450    BDBG_ASSERT(NULL != pSettings);
451    BKNI_Memset(pSettings, 0, sizeof(*pSettings));
452    pSettings->cached = true;
453    return;
454}
455
456void NEXUS_DmaJob_GetDefaultBlockOffsetSettings(
457    NEXUS_DmaJobBlockOffsetSettings *pSettings
458    )
459{
460    BDBG_ASSERT(NULL != pSettings);
461    BKNI_Memset(pSettings, 0, sizeof(*pSettings));
462    return;
463}
464
465NEXUS_Error NEXUS_DmaJob_SetBlockSettings(
466    NEXUS_DmaJobHandle handle,
467    unsigned blockIndex,
468    const NEXUS_DmaJobBlockSettings *pSettings
469    )
470{
471    /* DEPRECATED: use NEXUS_DmaJob_ProcessBlocks() instead */
472    BSTD_UNUSED(handle);
473    BSTD_UNUSED(blockIndex);
474    BSTD_UNUSED(pSettings);
475    return BERR_TRACE(NEXUS_NOT_SUPPORTED);
476}
477
478NEXUS_Error NEXUS_DmaJob_Start(
479    NEXUS_DmaJobHandle handle
480    )
481{
482    /* DEPRECATED: use NEXUS_DmaJob_ProcessBlocks() instead */
483    BSTD_UNUSED(handle);
484    return BERR_TRACE(NEXUS_NOT_SUPPORTED);
485}
486
487NEXUS_Error NEXUS_DmaJob_GetStatus(
488    NEXUS_DmaJobHandle handle,
489    NEXUS_DmaJobStatus *pStatus
490    )
491{
492    NEXUS_Error errCode;
493    BMMD_ContextStatus ctxStatus;
494
495    BDBG_OBJECT_ASSERT(handle, NEXUS_DmaJob);
496    BDBG_ASSERT(NULL != pStatus);
497    BDBG_MSG_TRACE(("NEXUS_DmaJob_GetStatus>:%#lx", (unsigned long)handle));
498
499    errCode = BMMD_Context_GetStatus(handle->ctx, &ctxStatus);
500    if (errCode) {
501        pStatus->currentState = NEXUS_DmaJobState_eUnknown;
502        return BERR_TRACE(errCode);
503    }
504
505    switch (ctxStatus.state) {
506        case BMMD_ContextState_eIdle:
507            pStatus->currentState = NEXUS_DmaJobState_eComplete; /* in MMD, eIdle may mean eComplete, but Nexus users are expecting eComplete */
508            break;
509        case BMMD_ContextState_eInProgress:
510            pStatus->currentState = NEXUS_DmaJobState_eInProgress;
511            break;
512        default:
513            pStatus->currentState = NEXUS_DmaJobState_eUnknown;
514            break;
515    }
516
517    BDBG_MSG_TRACE(("NEXUS_DmaJob_GetStatus<:%#lx", (unsigned long)handle));
518    return BERR_SUCCESS;
519}
520
521static void NEXUS_Dma_P_CompleteCallback_isr(void *pParam, int iParam)
522{
523    NEXUS_DmaJobHandle handle = (NEXUS_DmaJobHandle)pParam;
524
525    BDBG_OBJECT_ASSERT(handle, NEXUS_DmaJob);
526    BSTD_UNUSED(iParam);
527
528    BDBG_MSG(("completed job:%#lx", (unsigned long)handle));
529    handle->state = NEXUS_DmaJob_P_StateIdle;
530
531    if(handle->nexusEvent) {
532        BKNI_SetEvent_isr(handle->nexusEvent);
533    } 
534    else {
535        NEXUS_IsrCallback_Fire_isr(handle->completionCallback_isr);
536    }
537}
538
539#if NEXUS_SHARF_DMA_KEY_REQUIRES_DESCRIPTOR
540unsigned NEXUS_DmaJob_P_KeySize(NEXUS_DmaSharfMode mode) {
541    unsigned rv = 0;
542   
543    switch (mode) {
544    case NEXUS_DmaSharfMode_eSha1:
545        rv = 16;
546        break;
547    case NEXUS_DmaSharfMode_eAes128CbcDecrypt:
548    case NEXUS_DmaSharfMode_eAes128CbcEncrypt:
549    case NEXUS_DmaSharfMode_eAes128EcbDecrypt:
550    case NEXUS_DmaSharfMode_eAes128EcbEncrypt:
551    case NEXUS_DmaSharfMode_eCmac:
552        rv = 16;
553        break;
554    default:
555        BERR_TRACE(NEXUS_INVALID_PARAMETER);
556        break;
557    }
558    return rv;
559}
560
561unsigned NEXUS_DmaJob_P_IVSize(NEXUS_DmaSharfMode mode) {
562    unsigned rv = 0;
563   
564    switch (mode) {
565    case NEXUS_DmaSharfMode_eSha1:
566        rv = 16;
567        break;
568    case NEXUS_DmaSharfMode_eAes128CbcDecrypt:
569    case NEXUS_DmaSharfMode_eAes128CbcEncrypt:
570    case NEXUS_DmaSharfMode_eAes128EcbDecrypt:
571    case NEXUS_DmaSharfMode_eAes128EcbEncrypt:
572    case NEXUS_DmaSharfMode_eCmac:
573        rv = 16;
574        break;
575    default:
576        BERR_TRACE(NEXUS_INVALID_PARAMETER);
577        break;
578    }
579    return rv;
580}
581 #endif /* NEXUS_SHARF_DMA_KEY_REQUIRES_DESCRIPTOR */
582
583
584static NEXUS_Error
585NEXUS_DmaJob_P_ProcessBlocks(NEXUS_DmaJobHandle handle, const NEXUS_DmaJobBlockSettings *pSettings, unsigned nBlocks)
586{
587    NEXUS_Error errCode;
588    BMMD_ContextBlockSettings *blockSettings = handle->blockSettings;
589    uint32_t srcOffset, dstOffset;
590    unsigned i = 0, dmaLength = 0;
591    int sgIndex = -1;
592
593    if (nBlocks > handle->settings.numBlocks) {
594        return BERR_TRACE(BERR_INVALID_PARAMETER);
595    }
596
597    BDBG_MSG(("  started job:%#lx nBlocks:%u", (unsigned long)handle, nBlocks));
598
599    for (i=0; i<nBlocks; i++,pSettings++) {
600        /* convert to offset */
601        srcOffset = NEXUS_AddrToOffset((void *)pSettings->pSrcAddr);
602        if (0 == srcOffset) {
603            BDBG_ERR(("Invalid Source Address: [%u]%#lx", i, (unsigned long)pSettings->pSrcAddr));
604            return BERR_TRACE(BERR_INVALID_PARAMETER);
605        }
606        if (pSettings->cached) {
607            NEXUS_FlushCache(pSettings->pSrcAddr, pSettings->blockSize);
608        }
609        if (pSettings->pSrcAddr == pSettings->pDestAddr) {
610            dstOffset = srcOffset;
611        }
612        else {
613            dstOffset = NEXUS_AddrToOffset(pSettings->pDestAddr);
614            if (0 == dstOffset) {
615                BDBG_ERR(("Invalid Destination Address: [%u]%#lx", i, (unsigned long)pSettings->pDestAddr));
616                return BERR_TRACE(BERR_INVALID_PARAMETER);
617            }
618            if (pSettings->cached) {
619                NEXUS_FlushCache(pSettings->pDestAddr, pSettings->blockSize);
620            }
621        }
622
623        BMMD_Context_GetDefaultBlockSettings(&blockSettings[i]);
624        blockSettings[i].src = srcOffset;
625        blockSettings[i].dst = dstOffset;
626        blockSettings[i].size = pSettings->blockSize;
627        blockSettings[i].resetCrypto = pSettings->resetCrypto;
628        blockSettings[i].sgScramStart = pSettings->scatterGatherCryptoStart;
629        blockSettings[i].sgScramEnd = pSettings->scatterGatherCryptoEnd;
630        /* BMMD will ignore sharf settings if not needed */
631        blockSettings[i].sharf.keyPresent = pSettings->sharf.keyPresent;
632        blockSettings[i].sharf.digestPresent = pSettings->sharf.digestPresent;
633        dmaLength += pSettings->blockSize;
634
635        /* sanity check on scatter-gather crypto start/end. magnum defers this to nexus at the moment */
636        if (pSettings->scatterGatherCryptoStart) {
637            if (sgIndex==-1) {
638                sgIndex = i;
639            }
640            else {
641                BDBG_ERR(("Unpaired scatter-gather crypto start indicator"));
642                return NEXUS_INVALID_PARAMETER;
643            }
644        }
645        if (pSettings->scatterGatherCryptoEnd) {
646            if (sgIndex==-1) {
647                BDBG_ERR(("Unpaired scatter-gather crypto end indicator"));
648                return NEXUS_INVALID_PARAMETER;
649            }
650            else {
651                sgIndex = -1;
652            }
653        }
654    }
655    if (sgIndex!=-1) {
656        BDBG_ERR(("Scatter-gather crypto start without end"));
657        return NEXUS_INVALID_PARAMETER;
658    }
659
660#if NEXUS_SHARF_DMA_KEY_REQUIRES_DESCRIPTOR
661{
662    unsigned dataOffset = 0; /* used to track how much key/IV needs to be peeled off the first descriptor */
663    int j;
664
665    /* this is a fixup of the first descriptor for hardware (such as 7550) which requires that a provided
666       key and IV are in their own, initial descriptor.  If the caller does not pass in the data blocks
667       in the correct format, this prepends a block to hold the key and iv and performs the
668       necessary fixup */
669    pSettings -= nBlocks;
670   
671    if (pSettings[0].sharf.keyPresent) {
672        dataOffset += NEXUS_DmaJob_P_KeySize(handle->settings.sharf.mode);
673    }
674    if (pSettings[0].sharf.digestPresent) {
675        dataOffset += NEXUS_DmaJob_P_IVSize(handle->settings.sharf.mode);
676    }
677    /* if data and key or IV are combined in the first block, perform the fixup */
678    if (dataOffset>0 && pSettings[0].blockSize>dataOffset) {
679        for (j=nBlocks; j>=0 ; j--) {
680            blockSettings[j+1] = blockSettings[j];
681        }
682        blockSettings[0].size = dataOffset;
683        blockSettings[1].size -= dataOffset;
684        blockSettings[1].src += dataOffset;
685        blockSettings[1].sgScramStart = false;
686        blockSettings[1].sharf.keyPresent = false;
687        blockSettings[1].sharf.digestPresent = false;
688    }
689    nBlocks++;
690}
691#endif /* NEXUS_SHARF_DMA_KEY_REQUIRES_DESCRIPTOR */
692
693    handle->state = NEXUS_DmaJob_P_StateQueued;
694    errCode = BMMD_Context_Enqueue(handle->ctx, blockSettings, nBlocks); /* ISR callback may fire before this function returns, which is fine */
695    switch (errCode) {
696        case BERR_SUCCESS: /* completed */
697            handle->state = NEXUS_DmaJob_P_StateIdle;
698            goto completed;
699            break;
700        case BMMD_QUEUED:
701            if (dmaLength <= handle->settings.busyWaitThreshold) {
702                unsigned busyWait = handle->settings.busyWait;
703                for(; busyWait>0; busyWait--) {
704                    BKNI_Delay(1);
705                    if (handle->state==NEXUS_DmaJob_P_StateIdle) {
706                        goto completed;
707                    }
708                }
709            }
710            break;
711        default:
712            handle->state = NEXUS_DmaJob_P_StateIdle;
713            return BERR_TRACE(errCode);
714    }
715
716    BDBG_MSG(("   queued job:%#lx", (unsigned long)handle));
717    return NEXUS_DMA_QUEUED;
718completed:
719    return NEXUS_SUCCESS;
720}
721
722NEXUS_Error
723NEXUS_DmaJob_ProcessBlocks(
724    NEXUS_DmaJobHandle handle, 
725    const NEXUS_DmaJobBlockSettings *pSettings, 
726    unsigned nBlocks
727    )
728{
729    NEXUS_Error rc;
730
731    BDBG_OBJECT_ASSERT(handle, NEXUS_DmaJob);
732    BDBG_ASSERT(NULL != pSettings);
733    BDBG_MSG_TRACE(("NEXUS_DmaJob_ProcessBlocks>:%#lx", (unsigned long)handle));
734    rc = NEXUS_DmaJob_P_ProcessBlocks(handle, pSettings, nBlocks);
735    BDBG_MSG_TRACE(("NEXUS_DmaJob_ProcessBlocks<:%#lx", (unsigned long)handle));
736    return rc;
737}
738
739static NEXUS_Error
740NEXUS_DmaJob_P_ProcessBlocksOffset(NEXUS_DmaJobHandle handle, const NEXUS_DmaJobBlockOffsetSettings *pSettings, unsigned nBlocks)
741{
742    NEXUS_Error errCode;
743    BMMD_ContextBlockSettings *blockSettings = handle->blockSettings;
744    uint32_t srcOffset, dstOffset;
745    unsigned i, dmaLength = 0;
746    int sgIndex = -1;
747
748    BDBG_MSG(("  started job:%#lx nBlocks:%u", (unsigned long)handle, nBlocks));
749
750    for (i=0; i<nBlocks; i++,pSettings++) {
751        srcOffset = pSettings->srcOffset;
752        dstOffset = pSettings->destOffset;
753
754        BMMD_Context_GetDefaultBlockSettings(&blockSettings[i]);
755        blockSettings[i].src = srcOffset;
756        blockSettings[i].dst = dstOffset;
757        blockSettings[i].size = pSettings->blockSize;
758        blockSettings[i].resetCrypto = pSettings->resetCrypto;
759        blockSettings[i].sgScramStart = pSettings->scatterGatherCryptoStart;
760        blockSettings[i].sgScramEnd = pSettings->scatterGatherCryptoEnd;
761        /* BMMD will ignore sharf settings if not needed */
762        blockSettings[i].sharf.keyPresent = pSettings->sharf.keyPresent;
763        blockSettings[i].sharf.digestPresent = pSettings->sharf.digestPresent;
764        dmaLength += pSettings->blockSize;
765
766        /* sanity check on scatter-gather crypto start/end. magnum defers this to nexus at the moment */
767        if (pSettings->scatterGatherCryptoStart) {
768            if (sgIndex==-1) {
769                sgIndex = i;
770            }
771            else {
772                BDBG_ERR(("Unpaired scatter-gather crypto start indicator"));
773                return NEXUS_INVALID_PARAMETER;
774            }
775        }
776        if (pSettings->scatterGatherCryptoEnd) {
777            if (sgIndex==-1) {
778                BDBG_ERR(("Unpaired scatter-gather crypto end indicator"));
779                return NEXUS_INVALID_PARAMETER;
780            }
781            else {
782                sgIndex = -1;
783            }
784        }
785    }
786    if (sgIndex!=-1) {
787        BDBG_ERR(("Scatter-gather crypto start without end"));
788        return NEXUS_INVALID_PARAMETER;
789    }
790
791    handle->state = NEXUS_DmaJob_P_StateQueued;
792    errCode = BMMD_Context_Enqueue(handle->ctx, blockSettings, nBlocks); /* ISR callback may fire before this function returns, which is fine */
793    switch (errCode) {
794        case BERR_SUCCESS: /* completed */
795            handle->state = NEXUS_DmaJob_P_StateIdle;
796            goto completed;
797            break;
798        case BMMD_QUEUED:
799            if (dmaLength <= handle->settings.busyWaitThreshold) {
800                unsigned busyWait = handle->settings.busyWait;
801                for(; busyWait>0; busyWait--) {
802                    BKNI_Delay(1);
803                    if (handle->state==NEXUS_DmaJob_P_StateIdle) {
804                        goto completed;
805                    }
806                }
807            }
808            break;
809        default:
810            handle->state = NEXUS_DmaJob_P_StateIdle;
811            return BERR_TRACE(errCode);
812    }
813
814    BDBG_MSG(("   queued job:%#lx", (unsigned long)handle));
815    return NEXUS_DMA_QUEUED;
816completed:
817    return NEXUS_SUCCESS;
818}
819
820NEXUS_Error
821NEXUS_DmaJob_ProcessBlocksOffset(
822    NEXUS_DmaJobHandle handle,
823    const NEXUS_DmaJobBlockOffsetSettings *pSettings,
824    unsigned nBlocks
825    )
826{
827    NEXUS_Error rc;
828
829    BDBG_OBJECT_ASSERT(handle, NEXUS_DmaJob);
830    BDBG_ASSERT(NULL != pSettings);
831    BDBG_MSG_TRACE(("NEXUS_DmaJob_ProcessBlocksOffset>:%#lx", (unsigned long)handle));
832    rc = NEXUS_DmaJob_P_ProcessBlocksOffset(handle, pSettings, nBlocks);
833    BDBG_MSG_TRACE(("NEXUS_DmaJob_ProcessBlocksOffset<:%#lx", (unsigned long)handle));
834    return rc;
835}
836
837
838/* used by nexus_playpump_crypto.c, nexus_recpump.c, etc */
839NEXUS_Error
840NEXUS_DmaJob_ProcessBlocks_priv(NEXUS_DmaJobHandle handle, const NEXUS_DmaJobBlockSettings *pSettings, unsigned nBlocks, BKNI_EventHandle event)
841{
842    NEXUS_ASSERT_MODULE();
843    BDBG_OBJECT_ASSERT(handle, NEXUS_DmaJob);
844    BDBG_ASSERT(NULL != pSettings);
845
846    handle->nexusEvent = event;
847    return NEXUS_DmaJob_P_ProcessBlocks(handle, pSettings, nBlocks);
848}
849
Note: See TracBrowser for help on using the repository browser.