Root/target/linux/generic/files/crypto/ocf/kirkwood/cesa/mvCesa.c

1/*******************************************************************************
2Copyright (C) Marvell International Ltd. and its affiliates
3
4This software file (the "File") is owned and distributed by Marvell
5International Ltd. and/or its affiliates ("Marvell") under the following
6alternative licensing terms. Once you have made an election to distribute the
7File under one of the following license alternatives, please (i) delete this
8introductory statement regarding license alternatives, (ii) delete the two
9license alternatives that you have not elected to use and (iii) preserve the
10Marvell copyright notice above.
11
12********************************************************************************
13Marvell Commercial License Option
14
15If you received this File from Marvell and you have entered into a commercial
16license agreement (a "Commercial License") with Marvell, the File is licensed
17to you under the terms of the applicable Commercial License.
18
19********************************************************************************
20Marvell GPL License Option
21
22If you received this File from Marvell, you may opt to use, redistribute and/or
23modify this File in accordance with the terms and conditions of the General
24Public License Version 2, June 1991 (the "GPL License"), a copy of which is
25available along with the File in the license.txt file or by writing to the Free
26Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
27on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
28
29THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
30WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
31DISCLAIMED. The GPL License provides additional details about this warranty
32disclaimer.
33********************************************************************************
34Marvell BSD License Option
35
36If you received this File from Marvell, you may opt to use, redistribute and/or
37modify this File under the following licensing terms.
38Redistribution and use in source and binary forms, with or without modification,
39are permitted provided that the following conditions are met:
40
41    * Redistributions of source code must retain the above copyright notice,
42        this list of conditions and the following disclaimer.
43
44    * Redistributions in binary form must reproduce the above copyright
45        notice, this list of conditions and the following disclaimer in the
46        documentation and/or other materials provided with the distribution.
47
48    * Neither the name of Marvell nor the names of its contributors may be
49        used to endorse or promote products derived from this software without
50        specific prior written permission.
51
52THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
53ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
54WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
55DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
56ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
57(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
58LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
59ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
60(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
61SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
62
63*******************************************************************************/
64
65#include "cesa/mvCesa.h"
66
67#include "ctrlEnv/mvCtrlEnvLib.h"
68#undef CESA_DEBUG
69
70
71/********** Global variables **********/
72
73/* If request size is more than MV_CESA_MAX_BUF_SIZE the
74 * request is processed as fragmented request.
75 */
76
77MV_CESA_STATS cesaStats;
78
79MV_BUF_INFO cesaSramSaBuf;
80short cesaLastSid = -1;
81MV_CESA_SA* pCesaSAD = NULL;
82MV_U16 cesaMaxSA = 0;
83
84MV_CESA_REQ* pCesaReqFirst = NULL;
85MV_CESA_REQ* pCesaReqLast = NULL;
86MV_CESA_REQ* pCesaReqEmpty = NULL;
87MV_CESA_REQ* pCesaReqProcess = NULL;
88int cesaQueueDepth = 0;
89int cesaReqResources = 0;
90
91MV_CESA_SRAM_MAP* cesaSramVirtPtr = NULL;
92MV_U32 cesaCryptEngBase = 0;
93void *cesaOsHandle = NULL;
94#if (MV_CESA_VERSION >= 3)
95MV_U32 cesaChainLength = 0;
96int chainReqNum = 0;
97MV_U32 chainIndex = 0;
98MV_CESA_REQ* pNextActiveChain = 0;
99MV_CESA_REQ* pEndCurrChain = 0;
100MV_BOOL isFirstReq = MV_TRUE;
101#endif
102
103static INLINE MV_U8* mvCesaSramAddrGet(void)
104{
105#ifdef MV_CESA_NO_SRAM
106    return (MV_U8*)cesaSramVirtPtr;
107#else
108    return (MV_U8*)cesaCryptEngBase;
109#endif /* MV_CESA_NO_SRAM */
110}
111
112static INLINE MV_ULONG mvCesaSramVirtToPhys(void* pDev, MV_U8* pSramVirt)
113{
114#ifdef MV_CESA_NO_SRAM
115    return (MV_ULONG)mvOsIoVirtToPhy(NULL, pSramVirt);
116#else
117    return (MV_ULONG)pSramVirt;
118#endif /* MV_CESA_NO_SRAM */
119}
120
121/* Internal Function prototypes */
122
123static INLINE void mvCesaSramDescrBuild(MV_U32 config, int frag,
124                                 int cryptoOffset, int ivOffset, int cryptoLength,
125                                 int macOffset, int digestOffset, int macLength, int macTotalLen,
126                                 MV_CESA_REQ *pCesaReq, MV_DMA_DESC* pDmaDesc);
127
128static INLINE void mvCesaSramSaUpdate(short sid, MV_DMA_DESC *pDmaDesc);
129
130static INLINE int mvCesaDmaCopyPrepare(MV_CESA_MBUF* pMbuf, MV_U8* pSramBuf,
131                                MV_DMA_DESC* pDmaDesc, MV_BOOL isToMbuf,
132                                int offset, int copySize, MV_BOOL skipFlush);
133
134static void mvCesaHmacIvGet(MV_CESA_MAC_MODE macMode, unsigned char key[], int keyLength,
135                                    unsigned char innerIV[], unsigned char outerIV[]);
136
137static MV_STATUS mvCesaFragAuthComplete(MV_CESA_REQ* pReq, MV_CESA_SA* pSA,
138                                          int macDataSize);
139
140static MV_CESA_COMMAND* mvCesaCtrModeInit(void);
141
142static MV_STATUS mvCesaCtrModePrepare(MV_CESA_COMMAND *pCtrModeCmd, MV_CESA_COMMAND *pCmd);
143static MV_STATUS mvCesaCtrModeComplete(MV_CESA_COMMAND *pOrgCmd, MV_CESA_COMMAND *pCmd);
144static void mvCesaCtrModeFinish(MV_CESA_COMMAND *pCmd);
145
146static INLINE MV_STATUS mvCesaReqProcess(MV_CESA_REQ* pReq);
147static MV_STATUS mvCesaFragReqProcess(MV_CESA_REQ* pReq, MV_U8 frag);
148
149static INLINE MV_STATUS mvCesaParamCheck(MV_CESA_SA* pSA, MV_CESA_COMMAND *pCmd, MV_U8* pFixOffset);
150static INLINE MV_STATUS mvCesaFragParamCheck(MV_CESA_SA* pSA, MV_CESA_COMMAND *pCmd);
151
152static INLINE void mvCesaFragSizeFind(MV_CESA_SA* pSA, MV_CESA_REQ* pReq,
153                               int cryptoOffset, int macOffset,
154                               int* pCopySize, int* pCryptoDataSize, int* pMacDataSize);
155static MV_STATUS mvCesaMbufCacheUnmap(MV_CESA_MBUF* pMbuf, int offset, int size);
156
157
158/* Go to the next request in the request queue */
159static INLINE MV_CESA_REQ* MV_CESA_REQ_NEXT_PTR(MV_CESA_REQ* pReq)
160{
161    if(pReq == pCesaReqLast)
162        return pCesaReqFirst;
163
164    return pReq+1;
165}
166
167#if (MV_CESA_VERSION >= 3)
168/* Go to the previous request in the request queue */
169static INLINE MV_CESA_REQ* MV_CESA_REQ_PREV_PTR(MV_CESA_REQ* pReq)
170{
171    if(pReq == pCesaReqFirst)
172        return pCesaReqLast;
173
174    return pReq-1;
175}
176
177#endif
178
179
180static INLINE void mvCesaReqProcessStart(MV_CESA_REQ* pReq)
181{
182    int frag;
183
184#if (MV_CESA_VERSION >= 3)
185    pReq->state = MV_CESA_CHAIN;
186#else
187    pReq->state = MV_CESA_PROCESS;
188#endif
189    cesaStats.startCount++;
190
191    if(pReq->fragMode == MV_CESA_FRAG_NONE)
192    {
193        frag = 0;
194    }
195    else
196    {
197        frag = pReq->frags.nextFrag;
198        pReq->frags.nextFrag++;
199    }
200#if (MV_CESA_VERSION >= 2)
201    /* Enable TDMA engine */
202    MV_REG_WRITE(MV_CESA_TDMA_CURR_DESC_PTR_REG, 0);
203    MV_REG_WRITE(MV_CESA_TDMA_NEXT_DESC_PTR_REG,
204            (MV_U32)mvCesaVirtToPhys(&pReq->dmaDescBuf, pReq->dma[frag].pDmaFirst));
205#else
206    /* Enable IDMA engine */
207    MV_REG_WRITE(IDMA_CURR_DESC_PTR_REG(0), 0);
208    MV_REG_WRITE(IDMA_NEXT_DESC_PTR_REG(0),
209            (MV_U32)mvCesaVirtToPhys(&pReq->dmaDescBuf, pReq->dma[frag].pDmaFirst));
210#endif /* MV_CESA_VERSION >= 2 */
211
212#if defined(MV_BRIDGE_SYNC_REORDER)
213    mvOsBridgeReorderWA();
214#endif
215
216    /* Start Accelerator */
217    MV_REG_WRITE(MV_CESA_CMD_REG, MV_CESA_CMD_CHAN_ENABLE_MASK);
218}
219
220
221/*******************************************************************************
222* mvCesaHalInit - Initialize the CESA driver
223*
224* DESCRIPTION:
225* This function initialize the CESA driver.
226* 1) Session database
227* 2) Request queue
228* 4) DMA descriptor lists - one list per request. Each list
229* has MV_CESA_MAX_DMA_DESC descriptors.
230*
231* INPUT:
232* numOfSession - maximum number of supported sessions
233* queueDepth - number of elements in the request queue.
234* pSramBase - virtual address of Sram
235* osHandle - A handle used by the OS to allocate memory for the
236* module (Passed to the OS Services layer)
237*
238* RETURN:
239* MV_OK - Success
240* MV_NO_RESOURCE - Fail, can't allocate resources:
241* Session database, request queue,
242* DMA descriptors list, LRU cache database.
243* MV_NOT_ALIGNED - Sram base address is not 8 byte aligned.
244*
245*******************************************************************************/
246MV_STATUS mvCesaHalInit (int numOfSession, int queueDepth, char* pSramBase, MV_U32 cryptEngBase,
247             void *osHandle)
248{
249    int i, req;
250    MV_U32 descOffsetReg, configReg;
251    MV_CESA_SRAM_SA *pSramSA;
252
253
254    mvOsPrintf("mvCesaInit: sessions=%d, queue=%d, pSram=%p\n",
255                numOfSession, queueDepth, pSramBase);
256
257    cesaOsHandle = osHandle;
258    /* Create Session database */
259    pCesaSAD = mvOsMalloc(sizeof(MV_CESA_SA)*numOfSession);
260    if(pCesaSAD == NULL)
261    {
262        mvOsPrintf("mvCesaInit: Can't allocate %u bytes for %d SAs\n",
263                    sizeof(MV_CESA_SA)*numOfSession, numOfSession);
264        mvCesaFinish();
265        return MV_NO_RESOURCE;
266    }
267    memset(pCesaSAD, 0, sizeof(MV_CESA_SA)*numOfSession);
268    cesaMaxSA = numOfSession;
269
270    /* Allocate imag of sramSA in the DRAM */
271    cesaSramSaBuf.bufSize = sizeof(MV_CESA_SRAM_SA)*numOfSession +
272                                    CPU_D_CACHE_LINE_SIZE;
273
274    cesaSramSaBuf.bufVirtPtr = mvOsIoCachedMalloc(osHandle,cesaSramSaBuf.bufSize,
275                          &cesaSramSaBuf.bufPhysAddr,
276                          &cesaSramSaBuf.memHandle);
277        
278    if(cesaSramSaBuf.bufVirtPtr == NULL)
279    {
280        mvOsPrintf("mvCesaInit: Can't allocate %d bytes for sramSA structures\n",
281                    cesaSramSaBuf.bufSize);
282        mvCesaFinish();
283        return MV_NO_RESOURCE;
284    }
285    memset(cesaSramSaBuf.bufVirtPtr, 0, cesaSramSaBuf.bufSize);
286    pSramSA = (MV_CESA_SRAM_SA*)MV_ALIGN_UP((MV_ULONG)cesaSramSaBuf.bufVirtPtr,
287                                                       CPU_D_CACHE_LINE_SIZE);
288    for(i=0; i<numOfSession; i++)
289    {
290        pCesaSAD[i].pSramSA = &pSramSA[i];
291    }
292
293    /* Create request queue */
294    pCesaReqFirst = mvOsMalloc(sizeof(MV_CESA_REQ)*queueDepth);
295    if(pCesaReqFirst == NULL)
296    {
297        mvOsPrintf("mvCesaInit: Can't allocate %u bytes for %d requests\n",
298                    sizeof(MV_CESA_REQ)*queueDepth, queueDepth);
299        mvCesaFinish();
300        return MV_NO_RESOURCE;
301    }
302    memset(pCesaReqFirst, 0, sizeof(MV_CESA_REQ)*queueDepth);
303    pCesaReqEmpty = pCesaReqFirst;
304    pCesaReqLast = pCesaReqFirst + (queueDepth-1);
305    pCesaReqProcess = pCesaReqEmpty;
306    cesaQueueDepth = queueDepth;
307    cesaReqResources = queueDepth;
308#if (MV_CESA_VERSION >= 3)
309    cesaChainLength = MAX_CESA_CHAIN_LENGTH;
310#endif
311    /* pSramBase must be 8 byte aligned */
312    if( MV_IS_NOT_ALIGN((MV_ULONG)pSramBase, 8) )
313    {
314        mvOsPrintf("mvCesaInit: pSramBase (%p) must be 8 byte aligned\n",
315                pSramBase);
316        mvCesaFinish();
317        return MV_NOT_ALIGNED;
318    }
319    cesaSramVirtPtr = (MV_CESA_SRAM_MAP*)pSramBase;
320    
321    cesaCryptEngBase = cryptEngBase;
322
323    /*memset(cesaSramVirtPtr, 0, sizeof(MV_CESA_SRAM_MAP));*/
324
325    /* Clear registers */
326    MV_REG_WRITE( MV_CESA_CFG_REG, 0);
327    MV_REG_WRITE( MV_CESA_ISR_CAUSE_REG, 0);
328    MV_REG_WRITE( MV_CESA_ISR_MASK_REG, 0);
329
330    /* Initialize DMA descriptor lists for all requests in Request queue */
331    descOffsetReg = configReg = 0;
332    for(req=0; req<queueDepth; req++)
333    {
334        int frag;
335        MV_CESA_REQ* pReq;
336        MV_DMA_DESC* pDmaDesc;
337
338        pReq = &pCesaReqFirst[req];
339
340        pReq->cesaDescBuf.bufSize = sizeof(MV_CESA_DESC)*MV_CESA_MAX_REQ_FRAGS +
341                                        CPU_D_CACHE_LINE_SIZE;
342
343    pReq->cesaDescBuf.bufVirtPtr =
344        mvOsIoCachedMalloc(osHandle,pReq->cesaDescBuf.bufSize,
345                   &pReq->cesaDescBuf.bufPhysAddr,
346                   &pReq->cesaDescBuf.memHandle);
347
348        if(pReq->cesaDescBuf.bufVirtPtr == NULL)
349        {
350            mvOsPrintf("mvCesaInit: req=%d, Can't allocate %d bytes for CESA descriptors\n",
351                        req, pReq->cesaDescBuf.bufSize);
352                mvCesaFinish();
353                return MV_NO_RESOURCE;
354            }
355        memset(pReq->cesaDescBuf.bufVirtPtr, 0, pReq->cesaDescBuf.bufSize);
356        pReq->pCesaDesc = (MV_CESA_DESC*)MV_ALIGN_UP((MV_ULONG)pReq->cesaDescBuf.bufVirtPtr,
357                                                                CPU_D_CACHE_LINE_SIZE);
358
359        pReq->dmaDescBuf.bufSize = sizeof(MV_DMA_DESC)*MV_CESA_MAX_DMA_DESC*MV_CESA_MAX_REQ_FRAGS +
360                                    CPU_D_CACHE_LINE_SIZE;
361
362        pReq->dmaDescBuf.bufVirtPtr =
363        mvOsIoCachedMalloc(osHandle,pReq->dmaDescBuf.bufSize,
364                   &pReq->dmaDescBuf.bufPhysAddr,
365                   &pReq->dmaDescBuf.memHandle);
366
367        if(pReq->dmaDescBuf.bufVirtPtr == NULL)
368        {
369            mvOsPrintf("mvCesaInit: req=%d, Can't allocate %d bytes for DMA descriptor list\n",
370                        req, pReq->dmaDescBuf.bufSize);
371            mvCesaFinish();
372            return MV_NO_RESOURCE;
373        }
374        memset(pReq->dmaDescBuf.bufVirtPtr, 0, pReq->dmaDescBuf.bufSize);
375        pDmaDesc = (MV_DMA_DESC*)MV_ALIGN_UP((MV_ULONG)pReq->dmaDescBuf.bufVirtPtr,
376                                                       CPU_D_CACHE_LINE_SIZE);
377
378        for(frag=0; frag<MV_CESA_MAX_REQ_FRAGS; frag++)
379        {
380            MV_CESA_DMA* pDma = &pReq->dma[frag];
381
382            pDma->pDmaFirst = pDmaDesc;
383            pDma->pDmaLast = NULL;
384            
385            for(i=0; i<MV_CESA_MAX_DMA_DESC-1; i++)
386            {
387                /* link all DMA descriptors together */
388                pDma->pDmaFirst[i].phyNextDescPtr =
389                        MV_32BIT_LE(mvCesaVirtToPhys(&pReq->dmaDescBuf, &pDmaDesc[i+1]));
390            }
391            pDma->pDmaFirst[i].phyNextDescPtr = 0;
392            mvOsCacheFlush(NULL, &pDma->pDmaFirst[0], MV_CESA_MAX_DMA_DESC*sizeof(MV_DMA_DESC));
393
394            pDmaDesc += MV_CESA_MAX_DMA_DESC;
395        }
396    }
397    /*mvCesaCryptoIvSet(NULL, MV_CESA_MAX_IV_LENGTH);*/
398    descOffsetReg = (MV_U16)((MV_U8*)&cesaSramVirtPtr->desc - mvCesaSramAddrGet());
399    MV_REG_WRITE(MV_CESA_CHAN_DESC_OFFSET_REG, descOffsetReg);
400
401    configReg |= (MV_CESA_CFG_WAIT_DMA_MASK | MV_CESA_CFG_ACT_DMA_MASK);
402#if (MV_CESA_VERSION >= 3)
403    configReg |= MV_CESA_CFG_CHAIN_MODE_MASK;
404#endif
405
406#if (MV_CESA_VERSION >= 2)
407    /* Initialize TDMA engine */
408    MV_REG_WRITE(MV_CESA_TDMA_CTRL_REG, MV_CESA_TDMA_CTRL_VALUE);
409    MV_REG_WRITE(MV_CESA_TDMA_BYTE_COUNT_REG, 0);
410    MV_REG_WRITE(MV_CESA_TDMA_CURR_DESC_PTR_REG, 0);
411#else
412    /* Initialize IDMA #0 engine */
413    MV_REG_WRITE(IDMA_CTRL_LOW_REG(0), 0);
414    MV_REG_WRITE(IDMA_BYTE_COUNT_REG(0), 0);
415    MV_REG_WRITE(IDMA_CURR_DESC_PTR_REG(0), 0);
416    MV_REG_WRITE(IDMA_CTRL_HIGH_REG(0), ICCHR_ENDIAN_LITTLE
417#ifdef MV_CPU_LE
418              | ICCHR_DESC_BYTE_SWAP_EN
419#endif
420         );
421    /* Clear Cause Byte of IDMA channel to be used */
422    MV_REG_WRITE( IDMA_CAUSE_REG, ~ICICR_CAUSE_MASK_ALL(0));
423    MV_REG_WRITE(IDMA_CTRL_LOW_REG(0), MV_CESA_IDMA_CTRL_LOW_VALUE);
424#endif /* (MV_CESA_VERSION >= 2) */
425
426    /* Set CESA configuration registers */
427    MV_REG_WRITE( MV_CESA_CFG_REG, configReg);
428    mvCesaDebugStatsClear();
429
430    return MV_OK;
431}
432
433/*******************************************************************************
434* mvCesaFinish - Shutdown the CESA driver
435*
436* DESCRIPTION:
437* This function shutdown the CESA driver and free all allocted resources.
438*
439* INPUT: None
440*
441* RETURN:
442* MV_OK - Success
443* Other - Fail
444*
445*******************************************************************************/
446MV_STATUS mvCesaFinish (void)
447{
448    int req;
449    MV_CESA_REQ* pReq;
450
451    mvOsPrintf("mvCesaFinish: \n");
452
453    cesaSramVirtPtr = NULL;
454
455    /* Free all resources: DMA list, etc. */
456    for(req=0; req<cesaQueueDepth; req++)
457    {
458        pReq = &pCesaReqFirst[req];
459        if(pReq->dmaDescBuf.bufVirtPtr != NULL)
460        {
461            mvOsIoCachedFree(cesaOsHandle,pReq->dmaDescBuf.bufSize,
462                 pReq->dmaDescBuf.bufPhysAddr,
463                 pReq->dmaDescBuf.bufVirtPtr,
464                 pReq->dmaDescBuf.memHandle);
465        }
466        if(pReq->cesaDescBuf.bufVirtPtr != NULL)
467        {
468                mvOsIoCachedFree(cesaOsHandle,pReq->cesaDescBuf.bufSize,
469                 pReq->cesaDescBuf.bufPhysAddr,
470                 pReq->cesaDescBuf.bufVirtPtr,
471                 pReq->cesaDescBuf.memHandle);
472        }
473    }
474#if (MV_CESA_VERSION < 2)
475    MV_REG_WRITE(IDMA_CTRL_LOW_REG(0), 0);
476#endif /* (MV_CESA_VERSION < 2) */
477
478    /* Free request queue */
479    if(pCesaReqFirst != NULL)
480    {
481        mvOsFree(pCesaReqFirst);
482        pCesaReqFirst = pCesaReqLast = NULL;
483        pCesaReqEmpty = pCesaReqProcess = NULL;
484        cesaQueueDepth = cesaReqResources = 0;
485    }
486    /* Free SA database */
487    if(pCesaSAD != NULL)
488    {
489        mvOsFree(pCesaSAD);
490        pCesaSAD = NULL;
491        cesaMaxSA = 0;
492    }
493    MV_REG_WRITE( MV_CESA_CFG_REG, 0);
494    MV_REG_WRITE( MV_CESA_ISR_CAUSE_REG, 0);
495    MV_REG_WRITE( MV_CESA_ISR_MASK_REG, 0);
496
497    return MV_OK;
498}
499
500/*******************************************************************************
501* mvCesaCryptoIvSet - Set IV value for Crypto algorithm working in CBC mode
502*
503* DESCRIPTION:
504* This function set IV value using by Crypto algorithms in CBC mode.
505* Each channel has its own IV value.
506* This function gets IV value from the caller. If no IV value passed from
507* the caller or only part of IV passed, the function will init the rest part
508* of IV value (or the whole IV) by random value.
509*
510* INPUT:
511* MV_U8* pIV - Pointer to IV value supplied by user. If pIV==NULL
512* the function will generate random IV value.
513* int ivSize - size (in bytes) of IV provided by user. If ivSize is
514* smaller than maximum IV size, the function will complete
515* IV by random value.
516*
517* RETURN:
518* MV_OK - Success
519* Other - Fail
520*
521*******************************************************************************/
522MV_STATUS mvCesaCryptoIvSet(MV_U8* pIV, int ivSize)
523{
524    MV_U8* pSramIV;
525#if defined(MV646xx)
526    mvOsPrintf("mvCesaCryptoIvSet: ERR. shouldn't use this call on MV64660\n");
527#endif
528    pSramIV = cesaSramVirtPtr->cryptoIV;
529    if(ivSize > MV_CESA_MAX_IV_LENGTH)
530    {
531        mvOsPrintf("mvCesaCryptoIvSet: ivSize (%d) is too large\n", ivSize);
532        ivSize = MV_CESA_MAX_IV_LENGTH;
533    }
534    if(pIV != NULL)
535    {
536        memcpy(pSramIV, pIV, ivSize);
537        ivSize = MV_CESA_MAX_IV_LENGTH - ivSize;
538        pSramIV += ivSize;
539    }
540
541    while(ivSize > 0)
542    {
543        int size, mv_random = mvOsRand();
544
545        size = MV_MIN(ivSize, sizeof(mv_random));
546        memcpy(pSramIV, (void*)&mv_random, size);
547
548        pSramIV += size;
549        ivSize -= size;
550    }
551/*
552    mvOsCacheFlush(NULL, cesaSramVirtPtr->cryptoIV,
553                                MV_CESA_MAX_IV_LENGTH);
554    mvOsCacheInvalidate(NULL, cesaSramVirtPtr->cryptoIV,
555                              MV_CESA_MAX_IV_LENGTH);
556*/
557    return MV_OK;
558}
559
560/*******************************************************************************
561* mvCesaSessionOpen - Open new uni-directional crypto session
562*
563* DESCRIPTION:
564* This function open new session.
565*
566* INPUT:
567* MV_CESA_OPEN_SESSION *pSession - pointer to new session input parameters
568*
569* OUTPUT:
570* short *pSid - session ID, should be used for all future
571* requests over this session.
572*
573* RETURN:
574* MV_OK - Session opend successfully.
575* MV_FULL - All sessions are in use, no free place in
576* SA database.
577* MV_BAD_PARAM - One of session input parameters is invalid.
578*
579*******************************************************************************/
580MV_STATUS mvCesaSessionOpen(MV_CESA_OPEN_SESSION *pSession, short* pSid)
581{
582    short sid;
583    MV_U32 config = 0;
584    int digestSize;
585
586    cesaStats.openedCount++;
587    
588    /* Find free entry in SAD */
589    for(sid=0; sid<cesaMaxSA; sid++)
590    {
591        if(pCesaSAD[sid].valid == 0)
592        {
593            break;
594        }
595    }
596    if(sid == cesaMaxSA)
597    {
598        mvOsPrintf("mvCesaSessionOpen: SA Database is FULL\n");
599        return MV_FULL;
600    }
601
602    /* Check Input parameters for Open session */
603    if (pSession->operation >= MV_CESA_MAX_OPERATION)
604    {
605        mvOsPrintf("mvCesaSessionOpen: Unexpected operation %d\n",
606                    pSession->operation);
607        return MV_BAD_PARAM;
608    }
609    config |= (pSession->operation << MV_CESA_OPERATION_OFFSET);
610
611    if( (pSession->direction != MV_CESA_DIR_ENCODE) &&
612        (pSession->direction != MV_CESA_DIR_DECODE) )
613    {
614        mvOsPrintf("mvCesaSessionOpen: Unexpected direction %d\n",
615                    pSession->direction);
616        return MV_BAD_PARAM;
617    }
618    config |= (pSession->direction << MV_CESA_DIRECTION_BIT);
619    /* Clear SA entry */
620    /* memset(&pCesaSAD[sid], 0, sizeof(pCesaSAD[sid])); */
621
622    /* Check AUTH parameters and update SA entry */
623    if(pSession->operation != MV_CESA_CRYPTO_ONLY)
624    {
625        /* For HMAC (MD5 and SHA1) - Maximum Key size is 64 bytes */
626        if( (pSession->macMode == MV_CESA_MAC_HMAC_MD5) ||
627            (pSession->macMode == MV_CESA_MAC_HMAC_SHA1) )
628        {
629            if(pSession->macKeyLength > MV_CESA_MAX_MAC_KEY_LENGTH)
630            {
631                mvOsPrintf("mvCesaSessionOpen: macKeyLength %d is too large\n",
632                            pSession->macKeyLength);
633                return MV_BAD_PARAM;
634            }
635            mvCesaHmacIvGet(pSession->macMode, pSession->macKey, pSession->macKeyLength,
636                            pCesaSAD[sid].pSramSA->macInnerIV,
637                            pCesaSAD[sid].pSramSA->macOuterIV);
638            pCesaSAD[sid].macKeyLength = pSession->macKeyLength;
639        }
640        switch(pSession->macMode)
641        {
642            case MV_CESA_MAC_MD5:
643            case MV_CESA_MAC_HMAC_MD5:
644                digestSize = MV_CESA_MD5_DIGEST_SIZE;
645                break;
646
647            case MV_CESA_MAC_SHA1:
648            case MV_CESA_MAC_HMAC_SHA1:
649                digestSize = MV_CESA_SHA1_DIGEST_SIZE;
650                break;
651
652            default:
653                mvOsPrintf("mvCesaSessionOpen: Unexpected macMode %d\n",
654                            pSession->macMode);
655                return MV_BAD_PARAM;
656        }
657        config |= (pSession->macMode << MV_CESA_MAC_MODE_OFFSET);
658
659        /* Supported digest sizes: MD5 - 16 bytes (128 bits), */
660        /* SHA1 - 20 bytes (160 bits) or 12 bytes (96 bits) for both */
661        if( (pSession->digestSize != digestSize) && (pSession->digestSize != 12))
662        {
663            mvOsPrintf("mvCesaSessionOpen: Unexpected digest size %d\n",
664                        pSession->digestSize);
665            mvOsPrintf("\t Valid values [bytes]: MD5-16, SHA1-20, Both-12\n");
666            return MV_BAD_PARAM;
667        }
668        pCesaSAD[sid].digestSize = pSession->digestSize;
669
670        if(pCesaSAD[sid].digestSize == 12)
671        {
672            /* Set MV_CESA_MAC_DIGEST_SIZE_BIT if digest size is 96 bits */
673            config |= (MV_CESA_MAC_DIGEST_96B << MV_CESA_MAC_DIGEST_SIZE_BIT);
674        }
675    }
676
677    /* Check CRYPTO parameters and update SA entry */
678    if(pSession->operation != MV_CESA_MAC_ONLY)
679    {
680        switch(pSession->cryptoAlgorithm)
681        {
682            case MV_CESA_CRYPTO_DES:
683                pCesaSAD[sid].cryptoKeyLength = MV_CESA_DES_KEY_LENGTH;
684                pCesaSAD[sid].cryptoBlockSize = MV_CESA_DES_BLOCK_SIZE;
685                break;
686
687            case MV_CESA_CRYPTO_3DES:
688                pCesaSAD[sid].cryptoKeyLength = MV_CESA_3DES_KEY_LENGTH;
689                pCesaSAD[sid].cryptoBlockSize = MV_CESA_DES_BLOCK_SIZE;
690                /* Only EDE mode is supported */
691                config |= (MV_CESA_CRYPTO_3DES_EDE <<
692                            MV_CESA_CRYPTO_3DES_MODE_BIT);
693                break;
694
695            case MV_CESA_CRYPTO_AES:
696                switch(pSession->cryptoKeyLength)
697                {
698                    case 16:
699                        pCesaSAD[sid].cryptoKeyLength = MV_CESA_AES_128_KEY_LENGTH;
700                        config |= (MV_CESA_CRYPTO_AES_KEY_128 <<
701                                       MV_CESA_CRYPTO_AES_KEY_LEN_OFFSET);
702                        break;
703
704                    case 24:
705                        pCesaSAD[sid].cryptoKeyLength = MV_CESA_AES_192_KEY_LENGTH;
706                        config |= (MV_CESA_CRYPTO_AES_KEY_192 <<
707                                       MV_CESA_CRYPTO_AES_KEY_LEN_OFFSET);
708                        break;
709
710                    case 32:
711                    default:
712                        pCesaSAD[sid].cryptoKeyLength = MV_CESA_AES_256_KEY_LENGTH;
713                        config |= (MV_CESA_CRYPTO_AES_KEY_256 <<
714                                       MV_CESA_CRYPTO_AES_KEY_LEN_OFFSET);
715                        break;
716                }
717                pCesaSAD[sid].cryptoBlockSize = MV_CESA_AES_BLOCK_SIZE;
718                break;
719
720            default:
721                mvOsPrintf("mvCesaSessionOpen: Unexpected cryptoAlgorithm %d\n",
722                            pSession->cryptoAlgorithm);
723                return MV_BAD_PARAM;
724        }
725        config |= (pSession->cryptoAlgorithm << MV_CESA_CRYPTO_ALG_OFFSET);
726
727        if(pSession->cryptoKeyLength != pCesaSAD[sid].cryptoKeyLength)
728        {
729            mvOsPrintf("cesaSessionOpen: Wrong CryptoKeySize %d != %d\n",
730                        pSession->cryptoKeyLength, pCesaSAD[sid].cryptoKeyLength);
731            return MV_BAD_PARAM;
732        }
733        
734        /* Copy Crypto key */
735        if( (pSession->cryptoAlgorithm == MV_CESA_CRYPTO_AES) &&
736            (pSession->direction == MV_CESA_DIR_DECODE))
737        {
738            /* Crypto Key for AES decode is computed from original key material */
739            /* and depend on cryptoKeyLength (128/192/256 bits) */
740            aesMakeKey(pCesaSAD[sid].pSramSA->cryptoKey, pSession->cryptoKey,
741                        pSession->cryptoKeyLength*8, MV_CESA_AES_BLOCK_SIZE*8);
742        }
743        else
744        {
745                /*panic("mvCesaSessionOpen2");*/
746                memcpy(pCesaSAD[sid].pSramSA->cryptoKey, pSession->cryptoKey,
747                    pCesaSAD[sid].cryptoKeyLength);
748            
749        }
750        
751        switch(pSession->cryptoMode)
752        {
753            case MV_CESA_CRYPTO_ECB:
754                pCesaSAD[sid].cryptoIvSize = 0;
755                break;
756
757            case MV_CESA_CRYPTO_CBC:
758                pCesaSAD[sid].cryptoIvSize = pCesaSAD[sid].cryptoBlockSize;
759                break;
760
761            case MV_CESA_CRYPTO_CTR:
762                /* Supported only for AES algorithm */
763                if(pSession->cryptoAlgorithm != MV_CESA_CRYPTO_AES)
764                {
765                    mvOsPrintf("mvCesaSessionOpen: CRYPTO CTR mode supported for AES only\n");
766                    return MV_BAD_PARAM;
767                }
768                pCesaSAD[sid].cryptoIvSize = 0;
769                pCesaSAD[sid].ctrMode = 1;
770                /* Replace to ECB mode for HW */
771                pSession->cryptoMode = MV_CESA_CRYPTO_ECB;
772                break;
773
774            default:
775                mvOsPrintf("mvCesaSessionOpen: Unexpected cryptoMode %d\n",
776                            pSession->cryptoMode);
777                return MV_BAD_PARAM;
778        }
779        
780        config |= (pSession->cryptoMode << MV_CESA_CRYPTO_MODE_BIT);
781    }
782    pCesaSAD[sid].config = config;
783    
784    mvOsCacheFlush(NULL, pCesaSAD[sid].pSramSA, sizeof(MV_CESA_SRAM_SA));
785    if(pSid != NULL)
786        *pSid = sid;
787
788    pCesaSAD[sid].valid = 1;
789    return MV_OK;
790}
791
792/*******************************************************************************
793* mvCesaSessionClose - Close active crypto session
794*
795* DESCRIPTION:
796* This function closes existing session
797*
798* INPUT:
799* short sid - Unique identifier of the session to be closed
800*
801* RETURN:
802* MV_OK - Session closed successfully.
803* MV_BAD_PARAM - Session identifier is out of valid range.
804* MV_NOT_FOUND - There is no active session with such ID.
805*
806*******************************************************************************/
807MV_STATUS mvCesaSessionClose(short sid)
808{
809    cesaStats.closedCount++;
810
811    if(sid >= cesaMaxSA)
812    {
813        mvOsPrintf("CESA Error: sid (%d) is too big\n", sid);
814        return MV_BAD_PARAM;
815    }
816    if(pCesaSAD[sid].valid == 0)
817    {
818        mvOsPrintf("CESA Warning: Session (sid=%d) is invalid\n", sid);
819        return MV_NOT_FOUND;
820    }
821    if(cesaLastSid == sid)
822        cesaLastSid = -1;
823
824    pCesaSAD[sid].valid = 0;
825    return MV_OK;
826}
827
828/*******************************************************************************
829* mvCesaAction - Perform crypto operation
830*
831* DESCRIPTION:
832* This function set new CESA request FIFO queue for further HW processing.
833* The function checks request parameters before set new request to the queue.
834* If one of the CESA channels is ready for processing the request will be
835* passed to HW. When request processing is finished the CESA interrupt will
836* be generated by HW. The caller should call mvCesaReadyGet() function to
837* complete request processing and get result.
838*
839* INPUT:
840* MV_CESA_COMMAND *pCmd - pointer to new CESA request.
841* It includes pointers to Source and Destination
842* buffers, session identifier get from
843* mvCesaSessionOpen() function, pointer to caller
844* private data and all needed crypto parameters.
845*
846* RETURN:
847* MV_OK - request successfully added to request queue
848* and will be processed.
849* MV_NO_MORE - request successfully added to request queue and will
850* be processed, but request queue became Full and next
851* request will not be accepted.
852* MV_NO_RESOURCE - request queue is FULL and the request can not
853* be processed.
854* MV_OUT_OF_CPU_MEM - memory allocation needed for request processing is
855* failed. Request can not be processed.
856* MV_NOT_ALLOWED - This mixed request (CRYPTO+MAC) can not be processed
857* as one request and should be splitted for two requests:
858* CRYPTO_ONLY and MAC_ONLY.
859* MV_BAD_PARAM - One of the request parameters is out of valid range.
860* The request can not be processed.
861*
862*******************************************************************************/
863MV_STATUS mvCesaAction (MV_CESA_COMMAND *pCmd)
864{
865    MV_STATUS status;
866    MV_CESA_REQ* pReq = pCesaReqEmpty;
867    int sid = pCmd->sessionId;
868    MV_CESA_SA* pSA = &pCesaSAD[sid];
869#if (MV_CESA_VERSION >= 3)
870     MV_CESA_REQ* pFromReq;
871     MV_CESA_REQ* pToReq;
872#endif
873    cesaStats.reqCount++;
874
875    /* Check that the request queue is not FULL */
876    if(cesaReqResources == 0)
877        return MV_NO_RESOURCE;
878
879    if( (sid >= cesaMaxSA) || (!pSA->valid) )
880    {
881        mvOsPrintf("CESA Action Error: Session sid=%d is INVALID\n", sid);
882        return MV_BAD_PARAM;
883    }
884    pSA->count++;
885
886    if(pSA->ctrMode)
887    {
888        /* AES in CTR mode can't be mixed with Authentication */
889        if( (pSA->config & MV_CESA_OPERATION_MASK) !=
890            (MV_CESA_CRYPTO_ONLY << MV_CESA_OPERATION_OFFSET) )
891        {
892            mvOsPrintf("mvCesaAction : CRYPTO CTR mode can't be mixed with AUTH\n");
893            return MV_NOT_ALLOWED;
894        }
895        /* All other request parameters should not be checked because key stream */
896        /* (not user data) processed by AES HW engine */
897        pReq->pOrgCmd = pCmd;
898        /* Allocate temporary pCmd structure for Key stream */
899        pCmd = mvCesaCtrModeInit();
900        if(pCmd == NULL)
901            return MV_OUT_OF_CPU_MEM;
902
903        /* Prepare Key stream */
904        mvCesaCtrModePrepare(pCmd, pReq->pOrgCmd);
905        pReq->fixOffset = 0;
906    }
907    else
908    {
909        /* Check request parameters and calculae fixOffset */
910        status = mvCesaParamCheck(pSA, pCmd, &pReq->fixOffset);
911        if(status != MV_OK)
912        {
913            return status;
914        }
915    }
916    pReq->pCmd = pCmd;
917
918    /* Check if the packet need fragmentation */
919    if(pCmd->pSrc->mbufSize <= sizeof(cesaSramVirtPtr->buf) )
920    {
921        /* request size is smaller than single buffer size */
922        pReq->fragMode = MV_CESA_FRAG_NONE;
923
924        /* Prepare NOT fragmented packets */
925        status = mvCesaReqProcess(pReq);
926        if(status != MV_OK)
927        {
928            mvOsPrintf("CesaReady: ReqProcess error: pReq=%p, status=0x%x\n",
929                        pReq, status);
930        }
931#if (MV_CESA_VERSION >= 3)
932    pReq->frags.numFrag = 1;
933#endif
934    }
935    else
936    {
937        MV_U8 frag = 0;
938
939        /* request size is larger than buffer size - needs fragmentation */
940
941        /* Check restrictions for processing fragmented packets */
942        status = mvCesaFragParamCheck(pSA, pCmd);
943        if(status != MV_OK)
944            return status;
945
946        pReq->fragMode = MV_CESA_FRAG_FIRST;
947        pReq->frags.nextFrag = 0;
948
949        /* Prepare Process Fragmented packets */
950        while(pReq->fragMode != MV_CESA_FRAG_LAST)
951        {
952            if(frag >= MV_CESA_MAX_REQ_FRAGS)
953            {
954                mvOsPrintf("mvCesaAction Error: Too large request frag=%d\n", frag);
955                return MV_OUT_OF_CPU_MEM;
956            }
957            status = mvCesaFragReqProcess(pReq, frag);
958            if(status == MV_OK) {
959#if (MV_CESA_VERSION >= 3)
960        if(frag) {
961            pReq->dma[frag-1].pDmaLast->phyNextDescPtr =
962                MV_32BIT_LE(mvCesaVirtToPhys(&pReq->dmaDescBuf, pReq->dma[frag].pDmaFirst));
963            mvOsCacheFlush(NULL, pReq->dma[frag-1].pDmaLast, sizeof(MV_DMA_DESC));
964        }
965#endif
966                frag++;
967        }
968        }
969        pReq->frags.numFrag = frag;
970#if (MV_CESA_VERSION >= 3)
971    if(chainReqNum) {
972        chainReqNum += pReq->frags.numFrag;
973        if(chainReqNum >= MAX_CESA_CHAIN_LENGTH)
974            chainReqNum = MAX_CESA_CHAIN_LENGTH;
975    }
976#endif
977    }
978
979    pReq->state = MV_CESA_PENDING;
980
981    pCesaReqEmpty = MV_CESA_REQ_NEXT_PTR(pReq);
982    cesaReqResources -= 1;
983
984/* #ifdef CESA_DEBUG */
985    if( (cesaQueueDepth - cesaReqResources) > cesaStats.maxReqCount)
986        cesaStats.maxReqCount = (cesaQueueDepth - cesaReqResources);
987/* #endif CESA_DEBUG */
988
989    cesaLastSid = sid;
990
991#if (MV_CESA_VERSION >= 3)
992    /* Are we within chain bounderies and follows the first request ? */
993    if((chainReqNum > 0) && (chainReqNum < MAX_CESA_CHAIN_LENGTH)) {
994    if(chainIndex) {
995        pFromReq = MV_CESA_REQ_PREV_PTR(pReq);
996        pToReq = pReq;
997        pReq->state = MV_CESA_CHAIN;
998        /* assume concatenating is possible */
999        pFromReq->dma[pFromReq->frags.numFrag-1].pDmaLast->phyNextDescPtr =
1000            MV_32BIT_LE(mvCesaVirtToPhys(&pToReq->dmaDescBuf, pToReq->dma[0].pDmaFirst));
1001        mvOsCacheFlush(NULL, pFromReq->dma[pFromReq->frags.numFrag-1].pDmaLast, sizeof(MV_DMA_DESC));
1002            
1003        /* align active & next pointers */
1004        if(pNextActiveChain->state != MV_CESA_PENDING)
1005            pEndCurrChain = pNextActiveChain = MV_CESA_REQ_NEXT_PTR(pReq);
1006    }
1007    else { /* we have only one chain, start new one */
1008        chainReqNum = 0;
1009        chainIndex++;
1010        /* align active & next pointers */
1011        if(pNextActiveChain->state != MV_CESA_PENDING)
1012            pEndCurrChain = pNextActiveChain = pReq;
1013    }
1014    }
1015    else {
1016        /* In case we concatenate full chain */
1017        if(chainReqNum == MAX_CESA_CHAIN_LENGTH) {
1018            chainIndex++;
1019            if(pNextActiveChain->state != MV_CESA_PENDING)
1020                pEndCurrChain = pNextActiveChain = pReq;
1021            chainReqNum = 0;
1022        }
1023        
1024        pReq = pCesaReqProcess;
1025        if(pReq->state == MV_CESA_PENDING) {
1026            pNextActiveChain = pReq;
1027            pEndCurrChain = MV_CESA_REQ_NEXT_PTR(pReq);
1028                /* Start Process new request */
1029                   mvCesaReqProcessStart(pReq);
1030            }
1031    }
1032
1033    chainReqNum++;
1034
1035    if((chainIndex < MAX_CESA_CHAIN_LENGTH) && (chainReqNum > cesaStats.maxChainUsage))
1036    cesaStats.maxChainUsage = chainReqNum;
1037
1038#else
1039
1040    /* Check status of CESA channels and process requests if possible */
1041    pReq = pCesaReqProcess;
1042    if(pReq->state == MV_CESA_PENDING)
1043    {
1044        /* Start Process new request */
1045        mvCesaReqProcessStart(pReq);
1046    }
1047#endif
1048    /* If request queue became FULL - return MV_NO_MORE */
1049    if(cesaReqResources == 0)
1050        return MV_NO_MORE;
1051
1052    return MV_OK;
1053
1054}
1055
1056/*******************************************************************************
1057* mvCesaReadyGet - Get crypto request that processing is finished
1058*
1059* DESCRIPTION:
1060* This function complete request processing and return ready request to
1061* caller. To don't miss interrupts the caller must call this function
1062* while MV_OK or MV_TERMINATE values returned.
1063*
1064* INPUT:
1065* MV_U32 chanMap - map of CESA channels finished thier job
1066* accordingly with CESA Cause register.
1067* MV_CESA_RESULT* pResult - pointer to structure contains information
1068* about ready request. It includes pointer to
1069* user private structure "pReqPrv", session identifier
1070* for this request "sessionId" and return code.
1071* Return code set to MV_FAIL if calculated digest value
1072* on decode direction is different than digest value
1073* in the packet.
1074*
1075* RETURN:
1076* MV_OK - Success, ready request is returned.
1077* MV_NOT_READY - Next request is not ready yet. New interrupt will
1078* be generated for futher request processing.
1079* MV_EMPTY - There is no more request for processing.
1080* MV_BUSY - Fragmented request is not ready yet.
1081* MV_TERMINATE - Call this function once more to complete processing
1082* of fragmented request.
1083*
1084*******************************************************************************/
1085MV_STATUS mvCesaReadyGet(MV_CESA_RESULT* pResult)
1086{
1087    MV_STATUS status, readyStatus = MV_NOT_READY;
1088    MV_U32 statusReg;
1089    MV_CESA_REQ* pReq;
1090    MV_CESA_SA* pSA;
1091
1092#if (MV_CESA_VERSION >= 3)
1093    if(isFirstReq == MV_TRUE) {
1094    if(chainIndex == 0)
1095        chainReqNum = 0;
1096    
1097    isFirstReq = MV_FALSE;
1098
1099    if(pNextActiveChain->state == MV_CESA_PENDING) {
1100        /* Start request Process */
1101        mvCesaReqProcessStart(pNextActiveChain);
1102        pEndCurrChain = pNextActiveChain;
1103        if(chainIndex > 0)
1104            chainIndex--;
1105        /* Update pNextActiveChain to next chain head */
1106           while(pNextActiveChain->state == MV_CESA_CHAIN)
1107            pNextActiveChain = MV_CESA_REQ_NEXT_PTR(pNextActiveChain);
1108        }
1109    }
1110    
1111    /* Check if there are more processed requests - can we remove pEndCurrChain ??? */
1112    if(pCesaReqProcess == pEndCurrChain) {
1113        isFirstReq = MV_TRUE;
1114        pEndCurrChain = pNextActiveChain;
1115#else
1116    if(pCesaReqProcess->state != MV_CESA_PROCESS) {
1117#endif
1118        return MV_EMPTY;
1119    }
1120
1121#ifdef CESA_DEBUG
1122    statusReg = MV_REG_READ(MV_CESA_STATUS_REG);
1123    if( statusReg & MV_CESA_STATUS_ACTIVE_MASK )
1124    {
1125        mvOsPrintf("mvCesaReadyGet: Not Ready, Status = 0x%x\n", statusReg);
1126        cesaStats.notReadyCount++;
1127        return MV_NOT_READY;
1128    }
1129#endif /* CESA_DEBUG */
1130
1131    cesaStats.readyCount++;
1132
1133    pReq = pCesaReqProcess;
1134    pSA = &pCesaSAD[pReq->pCmd->sessionId];
1135
1136    pResult->retCode = MV_OK;
1137    if(pReq->fragMode != MV_CESA_FRAG_NONE)
1138    {
1139        MV_U8* pNewDigest;
1140      int frag;
1141#if (MV_CESA_VERSION >= 3)
1142      pReq->frags.nextFrag = 1;
1143      while(pReq->frags.nextFrag <= pReq->frags.numFrag) {
1144#endif
1145    frag = (pReq->frags.nextFrag - 1);
1146
1147        /* Restore DMA descriptor list */
1148        pReq->dma[frag].pDmaLast->phyNextDescPtr =
1149                MV_32BIT_LE(mvCesaVirtToPhys(&pReq->dmaDescBuf, &pReq->dma[frag].pDmaLast[1]));
1150        pReq->dma[frag].pDmaLast = NULL;
1151
1152        /* Special processing for finished fragmented request */
1153        if(pReq->frags.nextFrag >= pReq->frags.numFrag)
1154        {
1155            mvCesaMbufCacheUnmap(pReq->pCmd->pDst, 0, pReq->pCmd->pDst->mbufSize);
1156
1157            /* Fragmented packet is ready */
1158            if( (pSA->config & MV_CESA_OPERATION_MASK) !=
1159                (MV_CESA_CRYPTO_ONLY << MV_CESA_OPERATION_OFFSET) )
1160            {
1161                int macDataSize = pReq->pCmd->macLength - pReq->frags.macSize;
1162
1163                if(macDataSize != 0)
1164                {
1165                    /* Calculate all other blocks by SW */
1166                    mvCesaFragAuthComplete(pReq, pSA, macDataSize);
1167                }
1168
1169                /* Copy new digest from SRAM to the Destination buffer */
1170                pNewDigest = cesaSramVirtPtr->buf + pReq->frags.newDigestOffset;
1171                status = mvCesaCopyToMbuf(pNewDigest, pReq->pCmd->pDst,
1172                                   pReq->pCmd->digestOffset, pSA->digestSize);
1173
1174                /* For decryption: Compare new digest value with original one */
1175                if((pSA->config & MV_CESA_DIRECTION_MASK) ==
1176                            (MV_CESA_DIR_DECODE << MV_CESA_DIRECTION_BIT))
1177                {
1178                    if( memcmp(pNewDigest, pReq->frags.orgDigest, pSA->digestSize) != 0)
1179                    {
1180/*
1181                        mvOsPrintf("Digest error: chan=%d, newDigest=%p, orgDigest=%p, status = 0x%x\n",
1182                            chan, pNewDigest, pReq->frags.orgDigest, MV_REG_READ(MV_CESA_STATUS_REG));
1183*/
1184                        /* Signiture verification is failed */
1185                        pResult->retCode = MV_FAIL;
1186                    }
1187                }
1188            }
1189            readyStatus = MV_OK;
1190        }
1191#if (MV_CESA_VERSION >= 3)
1192    pReq->frags.nextFrag++;
1193      }
1194#endif
1195    }
1196    else
1197    {
1198        mvCesaMbufCacheUnmap(pReq->pCmd->pDst, 0, pReq->pCmd->pDst->mbufSize);
1199
1200        /* Restore DMA descriptor list */
1201        pReq->dma[0].pDmaLast->phyNextDescPtr =
1202                MV_32BIT_LE(mvCesaVirtToPhys(&pReq->dmaDescBuf, &pReq->dma[0].pDmaLast[1]));
1203        pReq->dma[0].pDmaLast = NULL;
1204        if( ((pSA->config & MV_CESA_OPERATION_MASK) !=
1205                (MV_CESA_CRYPTO_ONLY << MV_CESA_OPERATION_OFFSET) ) &&
1206            ((pSA->config & MV_CESA_DIRECTION_MASK) ==
1207                        (MV_CESA_DIR_DECODE << MV_CESA_DIRECTION_BIT)) )
1208        {
1209            /* For AUTH on decode : Check Digest result in Status register */
1210            statusReg = MV_REG_READ(MV_CESA_STATUS_REG);
1211            if(statusReg & MV_CESA_STATUS_DIGEST_ERR_MASK)
1212            {
1213/*
1214                mvOsPrintf("Digest error: chan=%d, status = 0x%x\n",
1215                        chan, statusReg);
1216*/
1217                /* Signiture verification is failed */
1218                pResult->retCode = MV_FAIL;
1219            }
1220        }
1221        readyStatus = MV_OK;
1222    }
1223
1224    if(readyStatus == MV_OK)
1225    {
1226        /* If Request is ready - Prepare pResult structure */
1227        pResult->pReqPrv = pReq->pCmd->pReqPrv;
1228        pResult->sessionId = pReq->pCmd->sessionId;
1229
1230        pReq->state = MV_CESA_IDLE;
1231        pCesaReqProcess = MV_CESA_REQ_NEXT_PTR(pReq);
1232        cesaReqResources++;
1233
1234        if(pSA->ctrMode)
1235        {
1236            /* For AES CTR mode - complete processing and free allocated resources */
1237            mvCesaCtrModeComplete(pReq->pOrgCmd, pReq->pCmd);
1238            mvCesaCtrModeFinish(pReq->pCmd);
1239            pReq->pOrgCmd = NULL;
1240        }
1241    }
1242
1243#if (MV_CESA_VERSION < 3)
1244    if(pCesaReqProcess->state == MV_CESA_PROCESS)
1245    {
1246        /* Start request Process */
1247        mvCesaReqProcessStart(pCesaReqProcess);
1248        if(readyStatus == MV_NOT_READY)
1249            readyStatus = MV_BUSY;
1250    }
1251    else if(pCesaReqProcess != pCesaReqEmpty)
1252    {
1253        /* Start process new request from the queue */
1254        mvCesaReqProcessStart(pCesaReqProcess);
1255    }
1256#endif
1257    return readyStatus;
1258}
1259
1260/***************** Functions to work with CESA_MBUF structure ******************/
1261
1262/*******************************************************************************
1263* mvCesaMbufOffset - Locate offset in the Mbuf structure
1264*
1265* DESCRIPTION:
1266* This function locates offset inside Multi-Bufeer structure.
1267* It get fragment number and place in the fragment where the offset
1268* is located.
1269*
1270*
1271* INPUT:
1272* MV_CESA_MBUF* pMbuf - Pointer to multi-buffer structure
1273* int offset - Offset from the beginning of the data presented by
1274* the Mbuf structure.
1275*
1276* OUTPUT:
1277* int* pBufOffset - Offset from the beginning of the fragment where
1278* the offset is located.
1279*
1280* RETURN:
1281* int - Number of fragment, where the offset is located\
1282*
1283*******************************************************************************/
1284int mvCesaMbufOffset(MV_CESA_MBUF* pMbuf, int offset, int* pBufOffset)
1285{
1286    int frag = 0;
1287
1288    while(offset > 0)
1289    {
1290        if(frag >= pMbuf->numFrags)
1291        {
1292            mvOsPrintf("mvCesaMbufOffset: Error: frag (%d) > numFrags (%d)\n",
1293                    frag, pMbuf->numFrags);
1294            return MV_INVALID;
1295        }
1296        if(offset < pMbuf->pFrags[frag].bufSize)
1297        {
1298            break;
1299        }
1300        offset -= pMbuf->pFrags[frag].bufSize;
1301        frag++;
1302    }
1303    if(pBufOffset != NULL)
1304        *pBufOffset = offset;
1305
1306    return frag;
1307}
1308
1309/*******************************************************************************
1310* mvCesaCopyFromMbuf - Copy data from the Mbuf structure to continuous buffer
1311*
1312* DESCRIPTION:
1313*
1314*
1315* INPUT:
1316* MV_U8* pDstBuf - Pointer to continuous buffer, where data is
1317* copied to.
1318* MV_CESA_MBUF* pSrcMbuf - Pointer to multi-buffer structure where data is
1319* copied from.
1320* int offset - Offset in the Mbuf structure where located first
1321* byte of data should be copied.
1322* int size - Size of data should be copied
1323*
1324* RETURN:
1325* MV_OK - Success, all data is copied successfully.
1326* MV_OUT_OF_RANGE - Failed, offset is out of Multi-buffer data range.
1327* No data is copied.
1328* MV_EMPTY - Multi-buffer structure has not enough data to copy
1329* Data from the offset to end of Mbuf data is copied.
1330*
1331*******************************************************************************/
1332MV_STATUS mvCesaCopyFromMbuf(MV_U8* pDstBuf, MV_CESA_MBUF* pSrcMbuf,
1333                               int offset, int size)
1334{
1335    int frag, fragOffset, bufSize;
1336    MV_U8* pBuf;
1337
1338    if(size == 0)
1339        return MV_OK;
1340
1341    frag = mvCesaMbufOffset(pSrcMbuf, offset, &fragOffset);
1342    if(frag == MV_INVALID)
1343    {
1344        mvOsPrintf("CESA Mbuf Error: offset (%d) out of range\n", offset);
1345        return MV_OUT_OF_RANGE;
1346    }
1347
1348    bufSize = pSrcMbuf->pFrags[frag].bufSize - fragOffset;
1349    pBuf = pSrcMbuf->pFrags[frag].bufVirtPtr + fragOffset;
1350    while(MV_TRUE)
1351    {
1352        if(size <= bufSize)
1353        {
1354            memcpy(pDstBuf, pBuf, size);
1355            return MV_OK;
1356        }
1357        memcpy(pDstBuf, pBuf, bufSize);
1358        size -= bufSize;
1359        frag++;
1360        pDstBuf += bufSize;
1361        if(frag >= pSrcMbuf->numFrags)
1362            break;
1363
1364        bufSize = pSrcMbuf->pFrags[frag].bufSize;
1365        pBuf = pSrcMbuf->pFrags[frag].bufVirtPtr;
1366    }
1367    mvOsPrintf("mvCesaCopyFromMbuf: Mbuf is EMPTY - %d bytes isn't copied\n",
1368                size);
1369    return MV_EMPTY;
1370}
1371
1372/*******************************************************************************
1373* mvCesaCopyToMbuf - Copy data from continuous buffer to the Mbuf structure
1374*
1375* DESCRIPTION:
1376*
1377*
1378* INPUT:
1379* MV_U8* pSrcBuf - Pointer to continuous buffer, where data is
1380* copied from.
1381* MV_CESA_MBUF* pDstMbuf - Pointer to multi-buffer structure where data is
1382* copied to.
1383* int offset - Offset in the Mbuf structure where located first
1384* byte of data should be copied.
1385* int size - Size of data should be copied
1386*
1387* RETURN:
1388* MV_OK - Success, all data is copied successfully.
1389* MV_OUT_OF_RANGE - Failed, offset is out of Multi-buffer data range.
1390* No data is copied.
1391* MV_FULL - Multi-buffer structure has not enough place to copy
1392* all data. Data from the offset to end of Mbuf data
1393* is copied.
1394*
1395*******************************************************************************/
1396MV_STATUS mvCesaCopyToMbuf(MV_U8* pSrcBuf, MV_CESA_MBUF* pDstMbuf,
1397                               int offset, int size)
1398{
1399    int frag, fragOffset, bufSize;
1400    MV_U8* pBuf;
1401
1402    if(size == 0)
1403        return MV_OK;
1404
1405    frag = mvCesaMbufOffset(pDstMbuf, offset, &fragOffset);
1406    if(frag == MV_INVALID)
1407    {
1408        mvOsPrintf("CESA Mbuf Error: offset (%d) out of range\n", offset);
1409        return MV_OUT_OF_RANGE;
1410    }
1411
1412    bufSize = pDstMbuf->pFrags[frag].bufSize - fragOffset;
1413    pBuf = pDstMbuf->pFrags[frag].bufVirtPtr + fragOffset;
1414    while(MV_TRUE)
1415    {
1416        if(size <= bufSize)
1417        {
1418            memcpy(pBuf, pSrcBuf, size);
1419            return MV_OK;
1420        }
1421        memcpy(pBuf, pSrcBuf, bufSize);
1422        size -= bufSize;
1423        frag++;
1424        pSrcBuf += bufSize;
1425        if(frag >= pDstMbuf->numFrags)
1426            break;
1427
1428        bufSize = pDstMbuf->pFrags[frag].bufSize;
1429        pBuf = pDstMbuf->pFrags[frag].bufVirtPtr;
1430    }
1431    mvOsPrintf("mvCesaCopyToMbuf: Mbuf is FULL - %d bytes isn't copied\n",
1432                size);
1433    return MV_FULL;
1434}
1435
1436/*******************************************************************************
1437* mvCesaMbufCopy - Copy data from one Mbuf structure to the other Mbuf structure
1438*
1439* DESCRIPTION:
1440*
1441*
1442* INPUT:
1443*
1444* MV_CESA_MBUF* pDstMbuf - Pointer to multi-buffer structure where data is
1445* copied to.
1446* int dstMbufOffset - Offset in the dstMbuf structure where first byte
1447* of data should be copied to.
1448* MV_CESA_MBUF* pSrcMbuf - Pointer to multi-buffer structure where data is
1449* copied from.
1450* int srcMbufOffset - Offset in the srcMbuf structure where first byte
1451* of data should be copied from.
1452* int size - Size of data should be copied
1453*
1454* RETURN:
1455* MV_OK - Success, all data is copied successfully.
1456* MV_OUT_OF_RANGE - Failed, srcMbufOffset or dstMbufOffset is out of
1457* srcMbuf or dstMbuf structure correspondently.
1458* No data is copied.
1459* MV_BAD_SIZE - srcMbuf or dstMbuf structure is too small to copy
1460* all data. Partial data is copied
1461*
1462*******************************************************************************/
1463MV_STATUS mvCesaMbufCopy(MV_CESA_MBUF* pMbufDst, int dstMbufOffset,
1464                           MV_CESA_MBUF* pMbufSrc, int srcMbufOffset, int size)
1465{
1466    int srcFrag, dstFrag, srcSize, dstSize, srcOffset, dstOffset;
1467    int copySize;
1468    MV_U8 *pSrc, *pDst;
1469
1470    if(size == 0)
1471        return MV_OK;
1472
1473    srcFrag = mvCesaMbufOffset(pMbufSrc, srcMbufOffset, &srcOffset);
1474    if(srcFrag == MV_INVALID)
1475    {
1476        mvOsPrintf("CESA srcMbuf Error: offset (%d) out of range\n", srcMbufOffset);
1477        return MV_OUT_OF_RANGE;
1478    }
1479    pSrc = pMbufSrc->pFrags[srcFrag].bufVirtPtr + srcOffset;
1480    srcSize = pMbufSrc->pFrags[srcFrag].bufSize - srcOffset;
1481
1482    dstFrag = mvCesaMbufOffset(pMbufDst, dstMbufOffset, &dstOffset);
1483    if(dstFrag == MV_INVALID)
1484    {
1485        mvOsPrintf("CESA dstMbuf Error: offset (%d) out of range\n", dstMbufOffset);
1486        return MV_OUT_OF_RANGE;
1487    }
1488    pDst = pMbufDst->pFrags[dstFrag].bufVirtPtr + dstOffset;
1489    dstSize = pMbufDst->pFrags[dstFrag].bufSize - dstOffset;
1490
1491    while(size > 0)
1492    {
1493        copySize = MV_MIN(srcSize, dstSize);
1494        if(size <= copySize)
1495        {
1496            memcpy(pDst, pSrc, size);
1497            return MV_OK;
1498        }
1499        memcpy(pDst, pSrc, copySize);
1500        size -= copySize;
1501        srcSize -= copySize;
1502        dstSize -= copySize;
1503
1504        if(srcSize == 0)
1505        {
1506            srcFrag++;
1507            if(srcFrag >= pMbufSrc->numFrags)
1508                break;
1509
1510            pSrc = pMbufSrc->pFrags[srcFrag].bufVirtPtr;
1511            srcSize = pMbufSrc->pFrags[srcFrag].bufSize;
1512        }
1513
1514        if(dstSize == 0)
1515        {
1516            dstFrag++;
1517            if(dstFrag >= pMbufDst->numFrags)
1518                break;
1519
1520            pDst = pMbufDst->pFrags[dstFrag].bufVirtPtr;
1521            dstSize = pMbufDst->pFrags[dstFrag].bufSize;
1522        }
1523    }
1524    mvOsPrintf("mvCesaMbufCopy: BAD size - %d bytes isn't copied\n",
1525                size);
1526
1527    return MV_BAD_SIZE;
1528}
1529
1530static MV_STATUS mvCesaMbufCacheUnmap(MV_CESA_MBUF* pMbuf, int offset, int size)
1531{
1532    int frag, fragOffset, bufSize;
1533    MV_U8* pBuf;
1534
1535    if(size == 0)
1536        return MV_OK;
1537
1538    frag = mvCesaMbufOffset(pMbuf, offset, &fragOffset);
1539    if(frag == MV_INVALID)
1540    {
1541        mvOsPrintf("CESA Mbuf Error: offset (%d) out of range\n", offset);
1542        return MV_OUT_OF_RANGE;
1543    }
1544
1545    bufSize = pMbuf->pFrags[frag].bufSize - fragOffset;
1546    pBuf = pMbuf->pFrags[frag].bufVirtPtr + fragOffset;
1547    while(MV_TRUE)
1548    {
1549        if(size <= bufSize)
1550        {
1551            mvOsCacheUnmap(NULL, mvOsIoVirtToPhy(NULL, pBuf), size);
1552            return MV_OK;
1553        }
1554
1555        mvOsCacheUnmap(NULL, mvOsIoVirtToPhy(NULL, pBuf), bufSize);
1556        size -= bufSize;
1557        frag++;
1558        if(frag >= pMbuf->numFrags)
1559            break;
1560
1561        bufSize = pMbuf->pFrags[frag].bufSize;
1562        pBuf = pMbuf->pFrags[frag].bufVirtPtr;
1563    }
1564    mvOsPrintf("%s: Mbuf is FULL - %d bytes isn't Unmapped\n",
1565                __FUNCTION__, size);
1566    return MV_FULL;
1567}
1568
1569
1570/*************************************** Local Functions ******************************/
1571
1572/*******************************************************************************
1573* mvCesaFragReqProcess - Process fragmented request
1574*
1575* DESCRIPTION:
1576* This function processes a fragment of fragmented request (First, Middle or Last)
1577*
1578*
1579* INPUT:
1580* MV_CESA_REQ* pReq - Pointer to the request in the request queue.
1581*
1582* RETURN:
1583* MV_OK - The fragment is successfully passed to HW for processing.
1584* MV_TERMINATE - Means, that HW finished its work on this packet and no more
1585* interrupts will be generated for this request.
1586* Function mvCesaReadyGet() must be called to complete request
1587* processing and get request result.
1588*
1589*******************************************************************************/
1590static MV_STATUS mvCesaFragReqProcess(MV_CESA_REQ* pReq, MV_U8 frag)
1591{
1592    int i, copySize, cryptoDataSize, macDataSize, sid;
1593    int cryptoIvOffset, digestOffset;
1594    MV_U32 config;
1595    MV_CESA_COMMAND* pCmd = pReq->pCmd;
1596    MV_CESA_SA* pSA;
1597    MV_CESA_MBUF* pMbuf;
1598    MV_DMA_DESC* pDmaDesc = pReq->dma[frag].pDmaFirst;
1599    MV_U8* pSramBuf = cesaSramVirtPtr->buf;
1600    int macTotalLen = 0;
1601    int fixOffset, cryptoOffset, macOffset;
1602
1603    cesaStats.fragCount++;
1604
1605    sid = pReq->pCmd->sessionId;
1606
1607    pSA = &pCesaSAD[sid];
1608
1609    cryptoIvOffset = digestOffset = 0;
1610    i = macDataSize = 0;
1611    cryptoDataSize = 0;
1612
1613    /* First fragment processing */
1614    if(pReq->fragMode == MV_CESA_FRAG_FIRST)
1615    {
1616        /* pReq->frags monitors processing of fragmented request between fragments */
1617        pReq->frags.bufOffset = 0;
1618        pReq->frags.cryptoSize = 0;
1619        pReq->frags.macSize = 0;
1620
1621        config = pSA->config | (MV_CESA_FRAG_FIRST << MV_CESA_FRAG_MODE_OFFSET);
1622
1623        /* fixOffset can be not equal to zero only for FIRST fragment */
1624        fixOffset = pReq->fixOffset;
1625        /* For FIRST fragment crypto and mac offsets are taken from pCmd */
1626        cryptoOffset = pCmd->cryptoOffset;
1627        macOffset = pCmd->macOffset;
1628
1629        copySize = sizeof(cesaSramVirtPtr->buf) - pReq->fixOffset;
1630
1631        /* Find fragment size: Must meet all requirements for CRYPTO and MAC
1632         * cryptoDataSize - size of data will be encrypted/decrypted in this fragment
1633         * macDataSize - size of data will be signed/verified in this fragment
1634         * copySize - size of data will be copied from srcMbuf to SRAM and
1635         * back to dstMbuf for this fragment
1636         */
1637        mvCesaFragSizeFind(pSA, pReq, cryptoOffset, macOffset,
1638                        &copySize, &cryptoDataSize, &macDataSize);
1639
1640        if( (pSA->config & MV_CESA_OPERATION_MASK) !=
1641                (MV_CESA_MAC_ONLY << MV_CESA_OPERATION_OFFSET))
1642        {
1643            /* CryptoIV special processing */
1644            if( (pSA->config & MV_CESA_CRYPTO_MODE_MASK) ==
1645                (MV_CESA_CRYPTO_CBC << MV_CESA_CRYPTO_MODE_BIT) )
1646            {
1647                /* In CBC mode for encode direction when IV from user */
1648                if( (pCmd->ivFromUser) &&
1649                    ((pSA->config & MV_CESA_DIRECTION_MASK) ==
1650                        (MV_CESA_DIR_ENCODE << MV_CESA_DIRECTION_BIT)) )
1651                {
1652
1653                    /* For Crypto Encode in CBC mode HW always takes IV from SRAM IVPointer,
1654                    * (not from IVBufPointer). So when ivFromUser==1, we should copy IV from user place
1655                    * in the buffer to SRAM IVPointer
1656                    */
1657                    i += mvCesaDmaCopyPrepare(pCmd->pSrc, cesaSramVirtPtr->cryptoIV, &pDmaDesc[i],
1658                                    MV_FALSE, pCmd->ivOffset, pSA->cryptoIvSize, pCmd->skipFlush);
1659                }
1660
1661                /* Special processing when IV is not located in the first fragment */
1662                if(pCmd->ivOffset > (copySize - pSA->cryptoIvSize))
1663                {
1664                    /* Prepare dummy place for cryptoIV in SRAM */
1665                    cryptoIvOffset = cesaSramVirtPtr->tempCryptoIV - mvCesaSramAddrGet();
1666
1667                    /* For Decryption: Copy IV value from pCmd->ivOffset to Special SRAM place */
1668                    if((pSA->config & MV_CESA_DIRECTION_MASK) ==
1669                            (MV_CESA_DIR_DECODE << MV_CESA_DIRECTION_BIT))
1670                    {
1671                        i += mvCesaDmaCopyPrepare(pCmd->pSrc, cesaSramVirtPtr->tempCryptoIV, &pDmaDesc[i],
1672                                    MV_FALSE, pCmd->ivOffset, pSA->cryptoIvSize, pCmd->skipFlush);
1673                    }
1674                    else
1675                    {
1676                        /* For Encryption when IV is NOT from User: */
1677                        /* Copy IV from SRAM to buffer (pCmd->ivOffset) */
1678                        if(pCmd->ivFromUser == 0)
1679                        {
1680                            /* copy IV value from cryptoIV to Buffer (pCmd->ivOffset) */
1681                            i += mvCesaDmaCopyPrepare(pCmd->pSrc, cesaSramVirtPtr->cryptoIV, &pDmaDesc[i],
1682                                    MV_TRUE, pCmd->ivOffset, pSA->cryptoIvSize, pCmd->skipFlush);
1683                        }
1684                    }
1685                }
1686                else
1687                {
1688                    cryptoIvOffset = pCmd->ivOffset;
1689                }
1690            }
1691        }
1692
1693        if( (pSA->config & MV_CESA_OPERATION_MASK) !=
1694                (MV_CESA_CRYPTO_ONLY << MV_CESA_OPERATION_OFFSET) )
1695        {
1696            /* MAC digest special processing on Decode direction */
1697            if((pSA->config & MV_CESA_DIRECTION_MASK) ==
1698                        (MV_CESA_DIR_DECODE << MV_CESA_DIRECTION_BIT))
1699            {
1700                /* Save digest from pCmd->digestOffset */
1701                mvCesaCopyFromMbuf(pReq->frags.orgDigest,
1702                               pCmd->pSrc, pCmd->digestOffset, pSA->digestSize);
1703
1704                /* If pCmd->digestOffset is not located on the first */
1705                if(pCmd->digestOffset > (copySize - pSA->digestSize))
1706                {
1707                    MV_U8 digestZero[MV_CESA_MAX_DIGEST_SIZE];
1708
1709                    /* Set zeros to pCmd->digestOffset (DRAM) */
1710                    memset(digestZero, 0, MV_CESA_MAX_DIGEST_SIZE);
1711                    mvCesaCopyToMbuf(digestZero, pCmd->pSrc, pCmd->digestOffset, pSA->digestSize);
1712
1713                    /* Prepare dummy place for digest in SRAM */
1714                    digestOffset = cesaSramVirtPtr->tempDigest - mvCesaSramAddrGet();
1715                }
1716                else
1717                {
1718                    digestOffset = pCmd->digestOffset;
1719                }
1720            }
1721        }
1722        /* Update SA in SRAM */
1723        if(cesaLastSid != sid)
1724        {
1725            mvCesaSramSaUpdate(sid, &pDmaDesc[i]);
1726            i++;
1727        }
1728
1729        pReq->fragMode = MV_CESA_FRAG_MIDDLE;
1730    }
1731    else
1732    {
1733        /* Continue fragment */
1734        fixOffset = 0;
1735        cryptoOffset = 0;
1736        macOffset = 0;
1737        if( (pCmd->pSrc->mbufSize - pReq->frags.bufOffset) <= sizeof(cesaSramVirtPtr->buf))
1738        {
1739            /* Last fragment */
1740            config = pSA->config | (MV_CESA_FRAG_LAST << MV_CESA_FRAG_MODE_OFFSET);
1741            pReq->fragMode = MV_CESA_FRAG_LAST;
1742            copySize = pCmd->pSrc->mbufSize - pReq->frags.bufOffset;
1743
1744            if( (pSA->config & MV_CESA_OPERATION_MASK) !=
1745                (MV_CESA_CRYPTO_ONLY << MV_CESA_OPERATION_OFFSET) )
1746            {
1747                macDataSize = pCmd->macLength - pReq->frags.macSize;
1748
1749                /* If pCmd->digestOffset is not located on last fragment */
1750                if(pCmd->digestOffset < pReq->frags.bufOffset)
1751                {
1752                    /* Prepare dummy place for digest in SRAM */
1753                    digestOffset = cesaSramVirtPtr->tempDigest - mvCesaSramAddrGet();
1754                }
1755                else
1756                {
1757                    digestOffset = pCmd->digestOffset - pReq->frags.bufOffset;
1758                }
1759                pReq->frags.newDigestOffset = digestOffset;
1760                macTotalLen = pCmd->macLength;
1761
1762                /* HW can't calculate the Digest correctly for fragmented packets
1763                 * in the following cases:
1764                 * - MV88F5182 ||
1765                 * - MV88F5181L when total macLength more that 16 Kbytes ||
1766                 * - total macLength more that 64 Kbytes
1767                 */
1768                if( (mvCtrlModelGet() == MV_5182_DEV_ID) ||
1769                    ( (mvCtrlModelGet() == MV_5181_DEV_ID) &&
1770                      (mvCtrlRevGet() >= MV_5181L_A0_REV) &&
1771                      (pCmd->macLength >= (1 << 14)) ) )
1772                {
1773                    return MV_TERMINATE;
1774                }
1775            }
1776            if( (pSA->config & MV_CESA_OPERATION_MASK) !=
1777                (MV_CESA_MAC_ONLY << MV_CESA_OPERATION_OFFSET) )
1778            {
1779                cryptoDataSize = pCmd->cryptoLength - pReq->frags.cryptoSize;
1780            }
1781
1782            /* cryptoIvOffset - don't care */
1783        }
1784        else
1785        {
1786            /* WA for MV88F5182 SHA1 and MD5 fragmentation mode */
1787            if( (mvCtrlModelGet() == MV_5182_DEV_ID) &&
1788                (((pSA->config & MV_CESA_MAC_MODE_MASK) ==
1789                    (MV_CESA_MAC_MD5 << MV_CESA_MAC_MODE_OFFSET)) ||
1790                ((pSA->config & MV_CESA_MAC_MODE_MASK) ==
1791                    (MV_CESA_MAC_SHA1 << MV_CESA_MAC_MODE_OFFSET))) )
1792            {
1793                pReq->frags.newDigestOffset = cesaSramVirtPtr->tempDigest - mvCesaSramAddrGet();
1794                pReq->fragMode = MV_CESA_FRAG_LAST;
1795
1796                return MV_TERMINATE;
1797            }
1798            /* Middle fragment */
1799            config = pSA->config | (MV_CESA_FRAG_MIDDLE << MV_CESA_FRAG_MODE_OFFSET);
1800            copySize = sizeof(cesaSramVirtPtr->buf);
1801            /* digestOffset and cryptoIvOffset - don't care */
1802
1803            /* Find fragment size */
1804            mvCesaFragSizeFind(pSA, pReq, cryptoOffset, macOffset,
1805                            &copySize, &cryptoDataSize, &macDataSize);
1806        }
1807    }
1808    /********* Prepare DMA descriptors to copy from pSrc to SRAM *********/
1809    pMbuf = pCmd->pSrc;
1810    i += mvCesaDmaCopyPrepare(pMbuf, pSramBuf + fixOffset, &pDmaDesc[i],
1811                                MV_FALSE, pReq->frags.bufOffset, copySize, pCmd->skipFlush);
1812
1813    /* Prepare CESA descriptor to copy from DRAM to SRAM by DMA */
1814    mvCesaSramDescrBuild(config, frag,
1815                cryptoOffset + fixOffset, cryptoIvOffset + fixOffset,
1816                cryptoDataSize, macOffset + fixOffset,
1817                digestOffset + fixOffset, macDataSize, macTotalLen,
1818                pReq, &pDmaDesc[i]);
1819    i++;
1820
1821   /* Add special descriptor Ownership for CPU */
1822    pDmaDesc[i].byteCnt = 0;
1823    pDmaDesc[i].phySrcAdd = 0;
1824    pDmaDesc[i].phyDestAdd = 0;
1825    i++;
1826
1827    /********* Prepare DMA descriptors to copy from SRAM to pDst *********/
1828    pMbuf = pCmd->pDst;
1829    i += mvCesaDmaCopyPrepare(pMbuf, pSramBuf + fixOffset, &pDmaDesc[i],
1830                                MV_TRUE, pReq->frags.bufOffset, copySize, pCmd->skipFlush);
1831
1832    /* Next field of Last DMA descriptor must be NULL */
1833    pDmaDesc[i-1].phyNextDescPtr = 0;
1834    pReq->dma[frag].pDmaLast = &pDmaDesc[i-1];
1835    mvOsCacheFlush(NULL, pReq->dma[frag].pDmaFirst,
1836                    i*sizeof(MV_DMA_DESC));
1837
1838    /*mvCesaDebugDescriptor(&cesaSramVirtPtr->desc[frag]);*/
1839
1840    pReq->frags.bufOffset += copySize;
1841    pReq->frags.cryptoSize += cryptoDataSize;
1842    pReq->frags.macSize += macDataSize;
1843
1844    return MV_OK;
1845}
1846
1847
1848/*******************************************************************************
1849* mvCesaReqProcess - Process regular (Non-fragmented) request
1850*
1851* DESCRIPTION:
1852* This function processes the whole (not fragmented) request
1853*
1854* INPUT:
1855* MV_CESA_REQ* pReq - Pointer to the request in the request queue.
1856*
1857* RETURN:
1858* MV_OK - The request is successfully passed to HW for processing.
1859* Other - Failure. The request will not be processed
1860*
1861*******************************************************************************/
1862static MV_STATUS mvCesaReqProcess(MV_CESA_REQ* pReq)
1863{
1864    MV_CESA_MBUF *pMbuf;
1865    MV_DMA_DESC *pDmaDesc;
1866    MV_U8 *pSramBuf;
1867    int sid, i, fixOffset;
1868    MV_CESA_SA *pSA;
1869    MV_CESA_COMMAND *pCmd = pReq->pCmd;
1870
1871    cesaStats.procCount++;
1872
1873    sid = pCmd->sessionId;
1874    pSA = &pCesaSAD[sid];
1875    pDmaDesc = pReq->dma[0].pDmaFirst;
1876    pSramBuf = cesaSramVirtPtr->buf;
1877    fixOffset = pReq->fixOffset;
1878
1879/*
1880    mvOsPrintf("mvCesaReqProcess: sid=%d, pSA=%p, pDmaDesc=%p, pSramBuf=%p\n",
1881                sid, pSA, pDmaDesc, pSramBuf);
1882*/
1883    i = 0;
1884
1885    /* Crypto IV Special processing in CBC mode for Encryption direction */
1886    if( ((pSA->config & MV_CESA_OPERATION_MASK) != (MV_CESA_MAC_ONLY << MV_CESA_OPERATION_OFFSET)) &&
1887        ((pSA->config & MV_CESA_CRYPTO_MODE_MASK) == (MV_CESA_CRYPTO_CBC << MV_CESA_CRYPTO_MODE_BIT)) &&
1888        ((pSA->config & MV_CESA_DIRECTION_MASK) == (MV_CESA_DIR_ENCODE << MV_CESA_DIRECTION_BIT)) &&
1889        (pCmd->ivFromUser) )
1890    {
1891        /* For Crypto Encode in CBC mode HW always takes IV from SRAM IVPointer,
1892         * (not from IVBufPointer). So when ivFromUser==1, we should copy IV from user place
1893         * in the buffer to SRAM IVPointer
1894         */
1895        i += mvCesaDmaCopyPrepare(pCmd->pSrc, cesaSramVirtPtr->cryptoIV, &pDmaDesc[i],
1896                                    MV_FALSE, pCmd->ivOffset, pSA->cryptoIvSize, pCmd->skipFlush);
1897    }
1898
1899    /* Update SA in SRAM */
1900    if(cesaLastSid != sid)
1901    {
1902        mvCesaSramSaUpdate(sid, &pDmaDesc[i]);
1903        i++;
1904    }
1905
1906    /********* Prepare DMA descriptors to copy from pSrc to SRAM *********/
1907    pMbuf = pCmd->pSrc;
1908    i += mvCesaDmaCopyPrepare(pMbuf, pSramBuf + fixOffset, &pDmaDesc[i],
1909                                MV_FALSE, 0, pMbuf->mbufSize, pCmd->skipFlush);
1910
1911    /* Prepare Security Accelerator descriptor to SRAM words 0 - 7 */
1912    mvCesaSramDescrBuild(pSA->config, 0, pCmd->cryptoOffset + fixOffset,
1913                        pCmd->ivOffset + fixOffset, pCmd->cryptoLength,
1914                        pCmd->macOffset + fixOffset, pCmd->digestOffset + fixOffset,
1915                        pCmd->macLength, pCmd->macLength, pReq, &pDmaDesc[i]);
1916    i++;
1917
1918   /* Add special descriptor Ownership for CPU */
1919    pDmaDesc[i].byteCnt = 0;
1920    pDmaDesc[i].phySrcAdd = 0;
1921    pDmaDesc[i].phyDestAdd = 0;
1922    i++;
1923
1924    /********* Prepare DMA descriptors to copy from SRAM to pDst *********/
1925    pMbuf = pCmd->pDst;
1926    i += mvCesaDmaCopyPrepare(pMbuf, pSramBuf + fixOffset, &pDmaDesc[i],
1927                                MV_TRUE, 0, pMbuf->mbufSize, pCmd->skipFlush);
1928
1929    /* Next field of Last DMA descriptor must be NULL */
1930    pDmaDesc[i-1].phyNextDescPtr = 0;
1931    pReq->dma[0].pDmaLast = &pDmaDesc[i-1];
1932    mvOsCacheFlush(NULL, pReq->dma[0].pDmaFirst, i*sizeof(MV_DMA_DESC));
1933            
1934    return MV_OK;
1935}
1936
1937
1938/*******************************************************************************
1939* mvCesaSramDescrBuild - Set CESA descriptor in SRAM
1940*
1941* DESCRIPTION:
1942* This function builds CESA descriptor in SRAM from all Command parameters
1943*
1944*
1945* INPUT:
1946* int chan - CESA channel uses the descriptor
1947* MV_U32 config - 32 bits of WORD_0 in CESA descriptor structure
1948* int cryptoOffset - Offset from the beginning of SRAM buffer where
1949* data for encryption/decription is started.
1950* int ivOffset - Offset of crypto IV from the SRAM base. Valid only
1951* for first fragment.
1952* int cryptoLength - Size (in bytes) of data for encryption/descryption
1953* operation on this fragment.
1954* int macOffset - Offset from the beginning of SRAM buffer where
1955* data for Authentication is started
1956* int digestOffset - Offset from the beginning of SRAM buffer where
1957* digest is located. Valid for first and last fragments.
1958* int macLength - Size (in bytes) of data for Authentication
1959* operation on this fragment.
1960* int macTotalLen - Toatl size (in bytes) of data for Authentication
1961* operation on the whole request (packet). Valid for
1962* last fragment only.
1963*
1964* RETURN: None
1965*
1966*******************************************************************************/
1967static void mvCesaSramDescrBuild(MV_U32 config, int frag,
1968                             int cryptoOffset, int ivOffset, int cryptoLength,
1969                             int macOffset, int digestOffset, int macLength,
1970                             int macTotalLen, MV_CESA_REQ* pReq, MV_DMA_DESC* pDmaDesc)
1971{
1972    MV_CESA_DESC* pCesaDesc = &pReq->pCesaDesc[frag];
1973    MV_CESA_DESC* pSramDesc = pSramDesc = &cesaSramVirtPtr->desc;
1974    MV_U16 sramBufOffset = (MV_U16)((MV_U8*)cesaSramVirtPtr->buf - mvCesaSramAddrGet());
1975
1976    pCesaDesc->config = MV_32BIT_LE(config);
1977
1978    if( (config & MV_CESA_OPERATION_MASK) !=
1979         (MV_CESA_MAC_ONLY << MV_CESA_OPERATION_OFFSET) )
1980    {
1981        /* word 1 */
1982        pCesaDesc->cryptoSrcOffset = MV_16BIT_LE(sramBufOffset + cryptoOffset);
1983        pCesaDesc->cryptoDstOffset = MV_16BIT_LE(sramBufOffset + cryptoOffset);
1984        /* word 2 */
1985        pCesaDesc->cryptoDataLen = MV_16BIT_LE(cryptoLength);
1986        /* word 3 */
1987        pCesaDesc->cryptoKeyOffset = MV_16BIT_LE((MV_U16)(cesaSramVirtPtr->sramSA.cryptoKey -
1988                                                            mvCesaSramAddrGet()));
1989        /* word 4 */
1990        pCesaDesc->cryptoIvOffset = MV_16BIT_LE((MV_U16)(cesaSramVirtPtr->cryptoIV -
1991                                                            mvCesaSramAddrGet()));
1992        pCesaDesc->cryptoIvBufOffset = MV_16BIT_LE(sramBufOffset + ivOffset);
1993    }
1994
1995    if( (config & MV_CESA_OPERATION_MASK) !=
1996         (MV_CESA_CRYPTO_ONLY << MV_CESA_OPERATION_OFFSET) )
1997    {
1998        /* word 5 */
1999        pCesaDesc->macSrcOffset = MV_16BIT_LE(sramBufOffset + macOffset);
2000        pCesaDesc->macTotalLen = MV_16BIT_LE(macTotalLen);
2001
2002        /* word 6 */
2003        pCesaDesc->macDigestOffset = MV_16BIT_LE(sramBufOffset + digestOffset);
2004        pCesaDesc->macDataLen = MV_16BIT_LE(macLength);
2005
2006        /* word 7 */
2007        pCesaDesc->macInnerIvOffset = MV_16BIT_LE((MV_U16)(cesaSramVirtPtr->sramSA.macInnerIV -
2008                                 mvCesaSramAddrGet()));
2009        pCesaDesc->macOuterIvOffset = MV_16BIT_LE((MV_U16)(cesaSramVirtPtr->sramSA.macOuterIV -
2010                                 mvCesaSramAddrGet()));
2011    }
2012    /* Prepare DMA descriptor to CESA descriptor from DRAM to SRAM */
2013    pDmaDesc->phySrcAdd = MV_32BIT_LE(mvCesaVirtToPhys(&pReq->cesaDescBuf, pCesaDesc));
2014    pDmaDesc->phyDestAdd = MV_32BIT_LE(mvCesaSramVirtToPhys(NULL, (MV_U8*)pSramDesc));
2015    pDmaDesc->byteCnt = MV_32BIT_LE(sizeof(MV_CESA_DESC) | BIT31);
2016                                
2017    /* flush Source buffer */
2018    mvOsCacheFlush(NULL, pCesaDesc, sizeof(MV_CESA_DESC));
2019}
2020
2021/*******************************************************************************
2022* mvCesaSramSaUpdate - Move required SA information to SRAM if needed.
2023*
2024* DESCRIPTION:
2025* Copy to SRAM values of the required SA.
2026*
2027*
2028* INPUT:
2029* short sid - Session ID needs SRAM Cache update
2030* MV_DMA_DESC *pDmaDesc - Pointer to DMA descriptor used to
2031* copy SA values from DRAM to SRAM.
2032*
2033* RETURN:
2034* MV_OK - Cache entry for this SA copied to SRAM.
2035* MV_NO_CHANGE - Cache entry for this SA already exist in SRAM
2036*
2037*******************************************************************************/
2038static INLINE void mvCesaSramSaUpdate(short sid, MV_DMA_DESC *pDmaDesc)
2039{
2040    MV_CESA_SA *pSA = &pCesaSAD[sid];
2041
2042    /* Prepare DMA descriptor to Copy CACHE_SA from SA database in DRAM to SRAM */
2043     pDmaDesc->byteCnt = MV_32BIT_LE(sizeof(MV_CESA_SRAM_SA) | BIT31);
2044    pDmaDesc->phySrcAdd = MV_32BIT_LE(mvCesaVirtToPhys(&cesaSramSaBuf, pSA->pSramSA));
2045     pDmaDesc->phyDestAdd =
2046          MV_32BIT_LE(mvCesaSramVirtToPhys(NULL, (MV_U8*)&cesaSramVirtPtr->sramSA));
2047
2048    /* Source buffer is already flushed during OpenSession*/
2049    /*mvOsCacheFlush(NULL, &pSA->sramSA, sizeof(MV_CESA_SRAM_SA));*/
2050}
2051
2052/*******************************************************************************
2053* mvCesaDmaCopyPrepare - prepare DMA descriptor list to copy data presented by
2054* Mbuf structure from DRAM to SRAM
2055*
2056* DESCRIPTION:
2057*
2058*
2059* INPUT:
2060* MV_CESA_MBUF* pMbuf - pointer to Mbuf structure contains request
2061* data in DRAM
2062* MV_U8* pSramBuf - pointer to buffer in SRAM where data should
2063* be copied to.
2064* MV_DMA_DESC* pDmaDesc - pointer to first DMA descriptor for this copy.
2065* The function set number of DMA descriptors needed
2066* to copy the copySize bytes from Mbuf.
2067* MV_BOOL isToMbuf - Copy direction.
2068* MV_TRUE means copy from SRAM buffer to Mbuf in DRAM.
2069* MV_FALSE means copy from Mbuf in DRAM to SRAM buffer.
2070* int offset - Offset in the Mbuf structure that copy should be
2071* started from.
2072* int copySize - Size of data should be copied.
2073*
2074* RETURN:
2075* int - number of DMA descriptors used for the copy.
2076*
2077*******************************************************************************/
2078#ifndef MV_NETBSD
2079static INLINE int mvCesaDmaCopyPrepare(MV_CESA_MBUF* pMbuf, MV_U8* pSramBuf,
2080                        MV_DMA_DESC* pDmaDesc, MV_BOOL isToMbuf,
2081                        int offset, int copySize, MV_BOOL skipFlush)
2082{
2083    int bufOffset, bufSize, size, frag, i;
2084    MV_U8* pBuf;
2085
2086    i = 0;
2087
2088    /* Calculate start place for copy: fragment number and offset in the fragment */
2089    frag = mvCesaMbufOffset(pMbuf, offset, &bufOffset);
2090    bufSize = pMbuf->pFrags[frag].bufSize - bufOffset;
2091    pBuf = pMbuf->pFrags[frag].bufVirtPtr + bufOffset;
2092
2093    /* Size accumulate total copy size */
2094    size = 0;
2095
2096    /* Create DMA lists to copy mBuf from pSrc to SRAM */
2097    while(size < copySize)
2098    {
2099        /* Find copy size for each DMA descriptor */
2100        bufSize = MV_MIN(bufSize, (copySize - size));
2101        pDmaDesc[i].byteCnt = MV_32BIT_LE(bufSize | BIT31);
2102        if(isToMbuf)
2103        {
2104            pDmaDesc[i].phyDestAdd = MV_32BIT_LE(mvOsIoVirtToPhy(NULL, pBuf));
2105            pDmaDesc[i].phySrcAdd =
2106                MV_32BIT_LE(mvCesaSramVirtToPhys(NULL, (pSramBuf + size)));
2107            /* invalidate the buffer */
2108        if(skipFlush == MV_FALSE)
2109                mvOsCacheInvalidate(NULL, pBuf, bufSize);
2110        }
2111        else
2112        {
2113            pDmaDesc[i].phySrcAdd = MV_32BIT_LE(mvOsIoVirtToPhy(NULL, pBuf));
2114            pDmaDesc[i].phyDestAdd =
2115                MV_32BIT_LE(mvCesaSramVirtToPhys(NULL, (pSramBuf + size)));
2116            /* flush the buffer */
2117        if(skipFlush == MV_FALSE)
2118                mvOsCacheFlush(NULL, pBuf, bufSize);
2119        }
2120
2121        /* Count number of used DMA descriptors */
2122        i++;
2123        size += bufSize;
2124
2125        /* go to next fragment in the Mbuf */
2126        frag++;
2127        pBuf = pMbuf->pFrags[frag].bufVirtPtr;
2128        bufSize = pMbuf->pFrags[frag].bufSize;
2129    }
2130    return i;
2131}
2132#else /* MV_NETBSD */
2133static int mvCesaDmaCopyPrepare(MV_CESA_MBUF* pMbuf, MV_U8* pSramBuf,
2134                        MV_DMA_DESC* pDmaDesc, MV_BOOL isToMbuf,
2135                        int offset, int copySize, MV_BOOL skipFlush)
2136{
2137    int bufOffset, bufSize, thisSize, size, frag, i;
2138    MV_ULONG bufPhys, sramPhys;
2139    MV_U8* pBuf;
2140
2141    /*
2142     * Calculate start place for copy: fragment number and offset in
2143     * the fragment
2144     */
2145    frag = mvCesaMbufOffset(pMbuf, offset, &bufOffset);
2146
2147    /*
2148     * Get SRAM physical address only once. We can update it in-place
2149     * as we build the descriptor chain.
2150     */
2151    sramPhys = mvCesaSramVirtToPhys(NULL, pSramBuf);
2152
2153    /*
2154     * 'size' accumulates total copy size, 'i' counts desccriptors.
2155     */
2156    size = i = 0;
2157
2158    /* Create DMA lists to copy mBuf from pSrc to SRAM */
2159    while (size < copySize) {
2160        /*
2161         * Calculate # of bytes to copy from the current fragment,
2162         * and the pointer to the start of data
2163         */
2164    bufSize = pMbuf->pFrags[frag].bufSize - bufOffset;
2165    pBuf = pMbuf->pFrags[frag].bufVirtPtr + bufOffset;
2166        bufOffset = 0; /* First frag may be non-zero */
2167        frag++;
2168
2169        /*
2170         * As long as there is data in the current fragment...
2171         */
2172        while (bufSize > 0) {
2173            /*
2174             * Ensure we don't cross an MMU page boundary.
2175             * XXX: This is NetBSD-specific, but it is a
2176             * quick and dirty way to fix the problem.
2177             * A true HAL would rely on the OS-specific
2178             * driver to do this...
2179             */
2180            thisSize = PAGE_SIZE -
2181                (((MV_ULONG)pBuf) & (PAGE_SIZE - 1));
2182            thisSize = MV_MIN(bufSize, thisSize);
2183            /*
2184             * Make sure we don't copy more than requested
2185             */
2186            if (thisSize > (copySize - size)) {
2187                thisSize = copySize - size;
2188                bufSize = 0;
2189            }
2190
2191            /*
2192             * Physicall address of this fragment
2193             */
2194            bufPhys = MV_32BIT_LE(mvOsIoVirtToPhy(NULL, pBuf));
2195
2196            /*
2197             * Set up the descriptor
2198             */
2199                pDmaDesc[i].byteCnt = MV_32BIT_LE(thisSize | BIT31);
2200                if(isToMbuf) {
2201                pDmaDesc[i].phyDestAdd = bufPhys;
2202                pDmaDesc[i].phySrcAdd = MV_32BIT_LE(sramPhys);
2203            /* invalidate the buffer */
2204                if(skipFlush == MV_FALSE)
2205                    mvOsCacheInvalidate(NULL, pBuf, thisSize);
2206            } else {
2207                pDmaDesc[i].phySrcAdd = bufPhys;
2208                pDmaDesc[i].phyDestAdd = MV_32BIT_LE(sramPhys);
2209            /* flush the buffer */
2210                if(skipFlush == MV_FALSE)
2211                    mvOsCacheFlush(NULL, pBuf, thisSize);
2212            }
2213
2214            pDmaDesc[i].phyNextDescPtr =
2215                MV_32BIT_LE(mvOsIoVirtToPhy(NULL,(&pDmaDesc[i+1])));
2216
2217        /* flush the DMA desc */
2218        mvOsCacheFlush(NULL, &pDmaDesc[i], sizeof(MV_DMA_DESC));
2219
2220            /* Update state */
2221            bufSize -= thisSize;
2222            sramPhys += thisSize;
2223            pBuf += thisSize;
2224            size += thisSize;
2225        i++;
2226        }
2227    }
2228
2229    return i;
2230}
2231#endif /* MV_NETBSD */
2232/*******************************************************************************
2233* mvCesaHmacIvGet - Calculate Inner and Outter values from HMAC key
2234*
2235* DESCRIPTION:
2236* This function calculate Inner and Outer values used for HMAC algorithm.
2237* This operation allows improve performance fro the whole HMAC processing.
2238*
2239* INPUT:
2240* MV_CESA_MAC_MODE macMode - Authentication mode: HMAC_MD5 or HMAC_SHA1.
2241* unsigned char key[] - Pointer to HMAC key.
2242* int keyLength - Size of HMAC key (maximum 64 bytes)
2243*
2244* OUTPUT:
2245* unsigned char innerIV[] - HASH(key^inner)
2246* unsigned char outerIV[] - HASH(key^outter)
2247*
2248* RETURN: None
2249*
2250*******************************************************************************/
2251static void mvCesaHmacIvGet(MV_CESA_MAC_MODE macMode, unsigned char key[], int keyLength,
2252                     unsigned char innerIV[], unsigned char outerIV[])
2253{
2254    unsigned char inner[MV_CESA_MAX_MAC_KEY_LENGTH];
2255    unsigned char outer[MV_CESA_MAX_MAC_KEY_LENGTH];
2256    int i, digestSize = 0;
2257#if defined(MV_CPU_LE) || defined(MV_PPC)
2258    MV_U32 swapped32, val32, *pVal32;
2259#endif
2260    for(i=0; i<keyLength; i++)
2261    {
2262        inner[i] = 0x36 ^ key[i];
2263        outer[i] = 0x5c ^ key[i];
2264    }
2265
2266    for(i=keyLength; i<MV_CESA_MAX_MAC_KEY_LENGTH; i++)
2267    {
2268        inner[i] = 0x36;
2269        outer[i] = 0x5c;
2270    }
2271    if(macMode == MV_CESA_MAC_HMAC_MD5)
2272    {
2273        MV_MD5_CONTEXT ctx;
2274
2275        mvMD5Init(&ctx);
2276        mvMD5Update(&ctx, inner, MV_CESA_MAX_MAC_KEY_LENGTH);
2277
2278        memcpy(innerIV, ctx.buf, MV_CESA_MD5_DIGEST_SIZE);
2279        memset(&ctx, 0, sizeof(ctx));
2280
2281        mvMD5Init(&ctx);
2282        mvMD5Update(&ctx, outer, MV_CESA_MAX_MAC_KEY_LENGTH);
2283        memcpy(outerIV, ctx.buf, MV_CESA_MD5_DIGEST_SIZE);
2284        memset(&ctx, 0, sizeof(ctx));
2285        digestSize = MV_CESA_MD5_DIGEST_SIZE;
2286    }
2287    else if(macMode == MV_CESA_MAC_HMAC_SHA1)
2288    {
2289        MV_SHA1_CTX ctx;
2290
2291        mvSHA1Init(&ctx);
2292        mvSHA1Update(&ctx, inner, MV_CESA_MAX_MAC_KEY_LENGTH);
2293        memcpy(innerIV, ctx.state, MV_CESA_SHA1_DIGEST_SIZE);
2294        memset(&ctx, 0, sizeof(ctx));
2295
2296        mvSHA1Init(&ctx);
2297        mvSHA1Update(&ctx, outer, MV_CESA_MAX_MAC_KEY_LENGTH);
2298        memcpy(outerIV, ctx.state, MV_CESA_SHA1_DIGEST_SIZE);
2299        memset(&ctx, 0, sizeof(ctx));
2300        digestSize = MV_CESA_SHA1_DIGEST_SIZE;
2301    }
2302    else
2303    {
2304        mvOsPrintf("hmacGetIV: Unexpected macMode %d\n", macMode);
2305    }
2306#if defined(MV_CPU_LE) || defined(MV_PPC)
2307    /* 32 bits Swap of Inner and Outer values */
2308    pVal32 = (MV_U32*)innerIV;
2309    for(i=0; i<digestSize/4; i++)
2310    {
2311        val32 = *pVal32;
2312        swapped32 = MV_BYTE_SWAP_32BIT(val32);
2313        *pVal32 = swapped32;
2314        pVal32++;
2315    }
2316    pVal32 = (MV_U32*)outerIV;
2317    for(i=0; i<digestSize/4; i++)
2318    {
2319        val32 = *pVal32;
2320        swapped32 = MV_BYTE_SWAP_32BIT(val32);
2321        *pVal32 = swapped32;
2322        pVal32++;
2323    }
2324#endif /* defined(MV_CPU_LE) || defined(MV_PPC) */
2325}
2326
2327
2328/*******************************************************************************
2329* mvCesaFragSha1Complete - Complete SHA1 authentication started by HW using SW
2330*
2331* DESCRIPTION:
2332*
2333*
2334* INPUT:
2335* MV_CESA_MBUF* pMbuf - Pointer to Mbuf structure where data
2336* for SHA1 is placed.
2337* int offset - Offset in the Mbuf structure where
2338* unprocessed data for SHA1 is started.
2339* MV_U8* pOuterIV - Pointer to OUTER for this session.
2340* If pOuterIV==NULL - MAC mode is HASH_SHA1
2341* If pOuterIV!=NULL - MAC mode is HMAC_SHA1
2342* int macLeftSize - Size of unprocessed data for SHA1.
2343* int macTotalSize - Total size of data for SHA1 in the
2344* request (processed + unprocessed)
2345*
2346* OUTPUT:
2347* MV_U8* pDigest - Pointer to place where calculated Digest will
2348* be stored.
2349*
2350* RETURN: None
2351*
2352*******************************************************************************/
2353static void mvCesaFragSha1Complete(MV_CESA_MBUF* pMbuf, int offset,
2354                                      MV_U8* pOuterIV, int macLeftSize,
2355                                      int macTotalSize, MV_U8* pDigest)
2356{
2357    MV_SHA1_CTX ctx;
2358    MV_U8 *pData;
2359    int i, frag, fragOffset, size;
2360
2361    /* Read temporary Digest from HW */
2362    for(i=0; i<MV_CESA_SHA1_DIGEST_SIZE/4; i++)
2363    {
2364        ctx.state[i] = MV_REG_READ(MV_CESA_AUTH_INIT_VAL_DIGEST_REG(i));
2365    }
2366    /* Initialize MV_SHA1_CTX structure */
2367    memset(ctx.buffer, 0, 64);
2368    /* Set count[0] in bits. 32 bits is enough for 512 MBytes */
2369    /* so count[1] is always 0 */
2370    ctx.count[0] = ((macTotalSize - macLeftSize) * 8);
2371    ctx.count[1] = 0;
2372
2373    /* If HMAC - add size of Inner block (64 bytes) ro count[0] */
2374    if(pOuterIV != NULL)
2375        ctx.count[0] += (64 * 8);
2376
2377    /* Get place of unprocessed data in the Mbuf structure */
2378    frag = mvCesaMbufOffset(pMbuf, offset, &fragOffset);
2379    if(frag == MV_INVALID)
2380    {
2381        mvOsPrintf("CESA Mbuf Error: offset (%d) out of range\n", offset);
2382        return;
2383    }
2384
2385    pData = pMbuf->pFrags[frag].bufVirtPtr + fragOffset;
2386    size = pMbuf->pFrags[frag].bufSize - fragOffset;
2387
2388    /* Complete Inner part */
2389    while(macLeftSize > 0)
2390    {
2391        if(macLeftSize <= size)
2392        {
2393            mvSHA1Update(&ctx, pData, macLeftSize);
2394            break;
2395        }
2396        mvSHA1Update(&ctx, pData, size);
2397        macLeftSize -= size;
2398        frag++;
2399        pData = pMbuf->pFrags[frag].bufVirtPtr;
2400        size = pMbuf->pFrags[frag].bufSize;
2401    }
2402    mvSHA1Final(pDigest, &ctx);
2403/*
2404    mvOsPrintf("mvCesaFragSha1Complete: pOuterIV=%p, macLeftSize=%d, macTotalSize=%d\n",
2405                pOuterIV, macLeftSize, macTotalSize);
2406    mvDebugMemDump(pDigest, MV_CESA_SHA1_DIGEST_SIZE, 1);
2407*/
2408
2409    if(pOuterIV != NULL)
2410    {
2411        /* If HMAC - Complete Outer part */
2412        for(i=0; i<MV_CESA_SHA1_DIGEST_SIZE/4; i++)
2413        {
2414#if defined(MV_CPU_LE) || defined(MV_ARM)
2415            ctx.state[i] = MV_BYTE_SWAP_32BIT(((MV_U32*)pOuterIV)[i]);
2416#else
2417        ctx.state[i] = ((MV_U32*)pOuterIV)[i];
2418#endif
2419    }
2420        memset(ctx.buffer, 0, 64);
2421
2422        ctx.count[0] = 64*8;
2423        ctx.count[1] = 0;
2424        mvSHA1Update(&ctx, pDigest, MV_CESA_SHA1_DIGEST_SIZE);
2425        mvSHA1Final(pDigest, &ctx);
2426    }
2427}
2428
2429/*******************************************************************************
2430* mvCesaFragMd5Complete - Complete MD5 authentication started by HW using SW
2431*
2432* DESCRIPTION:
2433*
2434*
2435* INPUT:
2436* MV_CESA_MBUF* pMbuf - Pointer to Mbuf structure where data
2437* for SHA1 is placed.
2438* int offset - Offset in the Mbuf structure where
2439* unprocessed data for MD5 is started.
2440* MV_U8* pOuterIV - Pointer to OUTER for this session.
2441* If pOuterIV==NULL - MAC mode is HASH_MD5
2442* If pOuterIV!=NULL - MAC mode is HMAC_MD5
2443* int macLeftSize - Size of unprocessed data for MD5.
2444* int macTotalSize - Total size of data for MD5 in the
2445* request (processed + unprocessed)
2446*
2447* OUTPUT:
2448* MV_U8* pDigest - Pointer to place where calculated Digest will
2449* be stored.
2450*
2451* RETURN: None
2452*
2453*******************************************************************************/
2454static void mvCesaFragMd5Complete(MV_CESA_MBUF* pMbuf, int offset,
2455                                     MV_U8* pOuterIV, int macLeftSize,
2456                                     int macTotalSize, MV_U8* pDigest)
2457{
2458    MV_MD5_CONTEXT ctx;
2459    MV_U8 *pData;
2460    int i, frag, fragOffset, size;
2461
2462    /* Read temporary Digest from HW */
2463    for(i=0; i<MV_CESA_MD5_DIGEST_SIZE/4; i++)
2464    {
2465        ctx.buf[i] = MV_REG_READ(MV_CESA_AUTH_INIT_VAL_DIGEST_REG(i));
2466    }
2467    memset(ctx.in, 0, 64);
2468
2469    /* Set count[0] in bits. 32 bits is enough for 512 MBytes */
2470    /* so count[1] is always 0 */
2471    ctx.bits[0] = ((macTotalSize - macLeftSize) * 8);
2472    ctx.bits[1] = 0;
2473
2474    /* If HMAC - add size of Inner block (64 bytes) ro count[0] */
2475    if(pOuterIV != NULL)
2476        ctx.bits[0] += (64 * 8);
2477
2478    frag = mvCesaMbufOffset(pMbuf, offset, &fragOffset);
2479    if(frag == MV_INVALID)
2480    {
2481        mvOsPrintf("CESA Mbuf Error: offset (%d) out of range\n", offset);
2482        return;
2483    }
2484
2485    pData = pMbuf->pFrags[frag].bufVirtPtr + fragOffset;
2486    size = pMbuf->pFrags[frag].bufSize - fragOffset;
2487
2488    /* Complete Inner part */
2489    while(macLeftSize > 0)
2490    {
2491        if(macLeftSize <= size)
2492        {
2493            mvMD5Update(&ctx, pData, macLeftSize);
2494            break;
2495        }
2496        mvMD5Update(&ctx, pData, size);
2497        macLeftSize -= size;
2498        frag++;
2499        pData = pMbuf->pFrags[frag].bufVirtPtr;
2500        size = pMbuf->pFrags[frag].bufSize;
2501    }
2502    mvMD5Final(pDigest, &ctx);
2503
2504/*
2505    mvOsPrintf("mvCesaFragMd5Complete: pOuterIV=%p, macLeftSize=%d, macTotalSize=%d\n",
2506                pOuterIV, macLeftSize, macTotalSize);
2507    mvDebugMemDump(pDigest, MV_CESA_MD5_DIGEST_SIZE, 1);
2508*/
2509    if(pOuterIV != NULL)
2510    {
2511        /* Complete Outer part */
2512        for(i=0; i<MV_CESA_MD5_DIGEST_SIZE/4; i++)
2513        {
2514#if defined(MV_CPU_LE) || defined(MV_ARM)
2515            ctx.buf[i] = MV_BYTE_SWAP_32BIT(((MV_U32*)pOuterIV)[i]);
2516#else
2517        ctx.buf[i] = ((MV_U32*)pOuterIV)[i];
2518#endif
2519    }
2520        memset(ctx.in, 0, 64);
2521
2522        ctx.bits[0] = 64*8;
2523        ctx.bits[1] = 0;
2524        mvMD5Update(&ctx, pDigest, MV_CESA_MD5_DIGEST_SIZE);
2525        mvMD5Final(pDigest, &ctx);
2526    }
2527}
2528
2529/*******************************************************************************
2530* mvCesaFragAuthComplete -
2531*
2532* DESCRIPTION:
2533*
2534*
2535* INPUT:
2536* MV_CESA_REQ* pReq,
2537* MV_CESA_SA* pSA,
2538* int macDataSize
2539*
2540* RETURN:
2541* MV_STATUS
2542*
2543*******************************************************************************/
2544static MV_STATUS mvCesaFragAuthComplete(MV_CESA_REQ* pReq, MV_CESA_SA* pSA,
2545                               int macDataSize)
2546{
2547    MV_CESA_COMMAND* pCmd = pReq->pCmd;
2548    MV_U8* pDigest;
2549    MV_CESA_MAC_MODE macMode;
2550    MV_U8* pOuterIV = NULL;
2551
2552    /* Copy data from Source fragment to Destination */
2553    if(pCmd->pSrc != pCmd->pDst)
2554    {
2555        mvCesaMbufCopy(pCmd->pDst, pReq->frags.bufOffset,
2556                       pCmd->pSrc, pReq->frags.bufOffset, macDataSize);
2557    }
2558
2559/*
2560    mvCesaCopyFromMbuf(cesaSramVirtPtr->buf[0], pCmd->pSrc, pReq->frags.bufOffset, macDataSize);
2561    mvCesaCopyToMbuf(cesaSramVirtPtr->buf[0], pCmd->pDst, pReq->frags.bufOffset, macDataSize);
2562*/
2563    pDigest = (mvCesaSramAddrGet() + pReq->frags.newDigestOffset);
2564
2565    macMode = (pSA->config & MV_CESA_MAC_MODE_MASK) >> MV_CESA_MAC_MODE_OFFSET;
2566/*
2567    mvOsPrintf("macDataSize=%d, macLength=%d, digestOffset=%d, macMode=%d\n",
2568            macDataSize, pCmd->macLength, pCmd->digestOffset, macMode);
2569*/
2570    switch(macMode)
2571    {
2572        case MV_CESA_MAC_HMAC_MD5:
2573            pOuterIV = pSA->pSramSA->macOuterIV;
2574
2575        case MV_CESA_MAC_MD5:
2576            mvCesaFragMd5Complete(pCmd->pDst, pReq->frags.bufOffset, pOuterIV,
2577                               macDataSize, pCmd->macLength, pDigest);
2578        break;
2579
2580        case MV_CESA_MAC_HMAC_SHA1:
2581            pOuterIV = pSA->pSramSA->macOuterIV;
2582
2583        case MV_CESA_MAC_SHA1:
2584            mvCesaFragSha1Complete(pCmd->pDst, pReq->frags.bufOffset, pOuterIV,
2585                               macDataSize, pCmd->macLength, pDigest);
2586        break;
2587
2588        default:
2589            mvOsPrintf("mvCesaFragAuthComplete: Unexpected macMode %d\n", macMode);
2590            return MV_BAD_PARAM;
2591    }
2592    return MV_OK;
2593}
2594
2595/*******************************************************************************
2596* mvCesaCtrModeInit -
2597*
2598* DESCRIPTION:
2599*
2600*
2601* INPUT: NONE
2602*
2603*
2604* RETURN:
2605* MV_CESA_COMMAND*
2606*
2607*******************************************************************************/
2608static MV_CESA_COMMAND* mvCesaCtrModeInit(void)
2609{
2610    MV_CESA_MBUF *pMbuf;
2611    MV_U8 *pBuf;
2612    MV_CESA_COMMAND *pCmd;
2613
2614    pBuf = mvOsMalloc(sizeof(MV_CESA_COMMAND) +
2615                      sizeof(MV_CESA_MBUF) + sizeof(MV_BUF_INFO) + 100);
2616    if(pBuf == NULL)
2617    {
2618        mvOsPrintf("mvCesaSessionOpen: Can't allocate %u bytes for CTR Mode\n",
2619                    sizeof(MV_CESA_COMMAND) + sizeof(MV_CESA_MBUF) + sizeof(MV_BUF_INFO) );
2620        return NULL;
2621    }
2622    pCmd = (MV_CESA_COMMAND*)pBuf;
2623    pBuf += sizeof(MV_CESA_COMMAND);
2624
2625    pMbuf = (MV_CESA_MBUF*)pBuf;
2626    pBuf += sizeof(MV_CESA_MBUF);
2627
2628    pMbuf->pFrags = (MV_BUF_INFO*)pBuf;
2629
2630    pMbuf->numFrags = 1;
2631    pCmd->pSrc = pMbuf;
2632    pCmd->pDst = pMbuf;
2633/*
2634    mvOsPrintf("CtrModeInit: pCmd=%p, pSrc=%p, pDst=%p, pFrags=%p\n",
2635                pCmd, pCmd->pSrc, pCmd->pDst,
2636                pMbuf->pFrags);
2637*/
2638    return pCmd;
2639}
2640
2641/*******************************************************************************
2642* mvCesaCtrModePrepare -
2643*
2644* DESCRIPTION:
2645*
2646*
2647* INPUT:
2648* MV_CESA_COMMAND *pCtrModeCmd, MV_CESA_COMMAND *pCmd
2649*
2650* RETURN:
2651* MV_STATUS
2652*
2653*******************************************************************************/
2654static MV_STATUS mvCesaCtrModePrepare(MV_CESA_COMMAND *pCtrModeCmd, MV_CESA_COMMAND *pCmd)
2655{
2656    MV_CESA_MBUF *pMbuf;
2657    MV_U8 *pBuf, *pIV;
2658    MV_U32 counter, *pCounter;
2659    int cryptoSize = MV_ALIGN_UP(pCmd->cryptoLength, MV_CESA_AES_BLOCK_SIZE);
2660/*
2661    mvOsPrintf("CtrModePrepare: pCmd=%p, pCtrSrc=%p, pCtrDst=%p, pOrgCmd=%p, pOrgSrc=%p, pOrgDst=%p\n",
2662                pCmd, pCmd->pSrc, pCmd->pDst,
2663                pCtrModeCmd, pCtrModeCmd->pSrc, pCtrModeCmd->pDst);
2664*/
2665    pMbuf = pCtrModeCmd->pSrc;
2666
2667    /* Allocate buffer for Key stream */
2668    pBuf = mvOsIoCachedMalloc(cesaOsHandle,cryptoSize,
2669                  &pMbuf->pFrags[0].bufPhysAddr,
2670                  &pMbuf->pFrags[0].memHandle);
2671    if(pBuf == NULL)
2672    {
2673        mvOsPrintf("mvCesaCtrModePrepare: Can't allocate %d bytes\n", cryptoSize);
2674        return MV_OUT_OF_CPU_MEM;
2675    }
2676    memset(pBuf, 0, cryptoSize);
2677    mvOsCacheFlush(NULL, pBuf, cryptoSize);
2678
2679    pMbuf->pFrags[0].bufVirtPtr = pBuf;
2680    pMbuf->mbufSize = cryptoSize;
2681    pMbuf->pFrags[0].bufSize = cryptoSize;
2682
2683    pCtrModeCmd->pReqPrv = pCmd->pReqPrv;
2684    pCtrModeCmd->sessionId = pCmd->sessionId;
2685
2686    /* ivFromUser and ivOffset are don't care */
2687    pCtrModeCmd->cryptoOffset = 0;
2688    pCtrModeCmd->cryptoLength = cryptoSize;
2689
2690    /* digestOffset, macOffset and macLength are don't care */
2691
2692    mvCesaCopyFromMbuf(pBuf, pCmd->pSrc, pCmd->ivOffset, MV_CESA_AES_BLOCK_SIZE);
2693    pCounter = (MV_U32*)(pBuf + (MV_CESA_AES_BLOCK_SIZE - sizeof(counter)));
2694    counter = *pCounter;
2695    counter = MV_32BIT_BE(counter);
2696    pIV = pBuf;
2697    cryptoSize -= MV_CESA_AES_BLOCK_SIZE;
2698
2699    /* fill key stream */
2700    while(cryptoSize > 0)
2701    {
2702        pBuf += MV_CESA_AES_BLOCK_SIZE;
2703        memcpy(pBuf, pIV, MV_CESA_AES_BLOCK_SIZE - sizeof(counter));
2704        pCounter = (MV_U32*)(pBuf + (MV_CESA_AES_BLOCK_SIZE - sizeof(counter)));
2705        counter++;
2706        *pCounter = MV_32BIT_BE(counter);
2707        cryptoSize -= MV_CESA_AES_BLOCK_SIZE;
2708    }
2709
2710    return MV_OK;
2711}
2712
2713/*******************************************************************************
2714* mvCesaCtrModeComplete -
2715*
2716* DESCRIPTION:
2717*
2718*
2719* INPUT:
2720* MV_CESA_COMMAND *pOrgCmd, MV_CESA_COMMAND *pCmd
2721*
2722* RETURN:
2723* MV_STATUS
2724*
2725*******************************************************************************/
2726static MV_STATUS mvCesaCtrModeComplete(MV_CESA_COMMAND *pOrgCmd, MV_CESA_COMMAND *pCmd)
2727{
2728    int srcFrag, dstFrag, srcOffset, dstOffset, keyOffset, srcSize, dstSize;
2729    int cryptoSize = pCmd->cryptoLength;
2730    MV_U8 *pSrc, *pDst, *pKey;
2731    MV_STATUS status = MV_OK;
2732/*
2733    mvOsPrintf("CtrModeComplete: pCmd=%p, pCtrSrc=%p, pCtrDst=%p, pOrgCmd=%p, pOrgSrc=%p, pOrgDst=%p\n",
2734                pCmd, pCmd->pSrc, pCmd->pDst,
2735                pOrgCmd, pOrgCmd->pSrc, pOrgCmd->pDst);
2736*/
2737    /* XOR source data with key stream to destination data */
2738    pKey = pCmd->pDst->pFrags[0].bufVirtPtr;
2739    keyOffset = 0;
2740
2741    if( (pOrgCmd->pSrc != pOrgCmd->pDst) &&
2742        (pOrgCmd->cryptoOffset > 0) )
2743    {
2744        /* Copy Prefix from source buffer to destination buffer */
2745
2746        status = mvCesaMbufCopy(pOrgCmd->pDst, 0,
2747                                pOrgCmd->pSrc, 0, pOrgCmd->cryptoOffset);
2748/*
2749        status = mvCesaCopyFromMbuf(tempBuf, pOrgCmd->pSrc,
2750                       0, pOrgCmd->cryptoOffset);
2751        status = mvCesaCopyToMbuf(tempBuf, pOrgCmd->pDst,
2752                       0, pOrgCmd->cryptoOffset);
2753*/
2754    }
2755
2756    srcFrag = mvCesaMbufOffset(pOrgCmd->pSrc, pOrgCmd->cryptoOffset, &srcOffset);
2757    pSrc = pOrgCmd->pSrc->pFrags[srcFrag].bufVirtPtr;
2758    srcSize = pOrgCmd->pSrc->pFrags[srcFrag].bufSize;
2759
2760    dstFrag = mvCesaMbufOffset(pOrgCmd->pDst, pOrgCmd->cryptoOffset, &dstOffset);
2761    pDst = pOrgCmd->pDst->pFrags[dstFrag].bufVirtPtr;
2762    dstSize = pOrgCmd->pDst->pFrags[dstFrag].bufSize;
2763
2764    while(cryptoSize > 0)
2765    {
2766        pDst[dstOffset] = (pSrc[srcOffset] ^ pKey[keyOffset]);
2767
2768        cryptoSize--;
2769        dstOffset++;
2770        srcOffset++;
2771        keyOffset++;
2772
2773        if(srcOffset >= srcSize)
2774        {
2775            srcFrag++;
2776            srcOffset = 0;
2777            pSrc = pOrgCmd->pSrc->pFrags[srcFrag].bufVirtPtr;
2778            srcSize = pOrgCmd->pSrc->pFrags[srcFrag].bufSize;
2779        }
2780
2781        if(dstOffset >= dstSize)
2782        {
2783            dstFrag++;
2784            dstOffset = 0;
2785            pDst = pOrgCmd->pDst->pFrags[dstFrag].bufVirtPtr;
2786            dstSize = pOrgCmd->pDst->pFrags[dstFrag].bufSize;
2787        }
2788    }
2789
2790    if(pOrgCmd->pSrc != pOrgCmd->pDst)
2791    {
2792        /* Copy Suffix from source buffer to destination buffer */
2793        srcOffset = pOrgCmd->cryptoOffset + pOrgCmd->cryptoLength;
2794
2795        if( (pOrgCmd->pDst->mbufSize - srcOffset) > 0)
2796        {
2797            status = mvCesaMbufCopy(pOrgCmd->pDst, srcOffset,
2798                                    pOrgCmd->pSrc, srcOffset,
2799                                    pOrgCmd->pDst->mbufSize - srcOffset);
2800        }
2801
2802/*
2803        status = mvCesaCopyFromMbuf(tempBuf, pOrgCmd->pSrc,
2804                                srcOffset, pOrgCmd->pSrc->mbufSize - srcOffset);
2805        status = mvCesaCopyToMbuf(tempBuf, pOrgCmd->pDst,
2806                       srcOffset, pOrgCmd->pDst->mbufSize - srcOffset);
2807*/
2808    }
2809
2810    /* Free buffer used for Key stream */
2811    mvOsIoCachedFree(cesaOsHandle,pCmd->pDst->pFrags[0].bufSize,
2812             pCmd->pDst->pFrags[0].bufPhysAddr,
2813                     pCmd->pDst->pFrags[0].bufVirtPtr,
2814             pCmd->pDst->pFrags[0].memHandle);
2815
2816    return MV_OK;
2817}
2818
2819/*******************************************************************************
2820* mvCesaCtrModeFinish -
2821*
2822* DESCRIPTION:
2823*
2824*
2825* INPUT:
2826* MV_CESA_COMMAND* pCmd
2827*
2828* RETURN:
2829* MV_STATUS
2830*
2831*******************************************************************************/
2832static void mvCesaCtrModeFinish(MV_CESA_COMMAND* pCmd)
2833{
2834    mvOsFree(pCmd);
2835}
2836
2837/*******************************************************************************
2838* mvCesaParamCheck -
2839*
2840* DESCRIPTION:
2841*
2842*
2843* INPUT:
2844* MV_CESA_SA* pSA, MV_CESA_COMMAND *pCmd, MV_U8* pFixOffset
2845*
2846* RETURN:
2847* MV_STATUS
2848*
2849*******************************************************************************/
2850static MV_STATUS mvCesaParamCheck(MV_CESA_SA* pSA, MV_CESA_COMMAND *pCmd,
2851                                    MV_U8* pFixOffset)
2852{
2853    MV_U8 fixOffset = 0xFF;
2854
2855    /* Check AUTH operation parameters */
2856    if( ((pSA->config & MV_CESA_OPERATION_MASK) !=
2857                (MV_CESA_CRYPTO_ONLY << MV_CESA_OPERATION_OFFSET)) )
2858    {
2859        /* MAC offset should be at least 4 byte aligned */
2860        if( MV_IS_NOT_ALIGN(pCmd->macOffset, 4) )
2861        {
2862            mvOsPrintf("mvCesaAction: macOffset %d must be 4 byte aligned\n",
2863                    pCmd->macOffset);
2864            return MV_BAD_PARAM;
2865        }
2866        /* Digest offset must be 4 byte aligned */
2867        if( MV_IS_NOT_ALIGN(pCmd->digestOffset, 4) )
2868        {
2869            mvOsPrintf("mvCesaAction: digestOffset %d must be 4 byte aligned\n",
2870                    pCmd->digestOffset);
2871            return MV_BAD_PARAM;
2872        }
2873        /* In addition all offsets should be the same alignment: 8 or 4 */
2874        if(fixOffset == 0xFF)
2875        {
2876            fixOffset = (pCmd->macOffset % 8);
2877        }
2878        else
2879        {
2880            if( (pCmd->macOffset % 8) != fixOffset)
2881            {
2882                mvOsPrintf("mvCesaAction: macOffset %d mod 8 must be equal %d\n",
2883                                pCmd->macOffset, fixOffset);
2884                return MV_BAD_PARAM;
2885            }
2886        }
2887        if( (pCmd->digestOffset % 8) != fixOffset)
2888        {
2889            mvOsPrintf("mvCesaAction: digestOffset %d mod 8 must be equal %d\n",
2890                                pCmd->digestOffset, fixOffset);
2891            return MV_BAD_PARAM;
2892        }
2893    }
2894    /* Check CRYPTO operation parameters */
2895    if( ((pSA->config & MV_CESA_OPERATION_MASK) !=
2896                (MV_CESA_MAC_ONLY << MV_CESA_OPERATION_OFFSET)) )
2897    {
2898        /* CryptoOffset should be at least 4 byte aligned */
2899        if( MV_IS_NOT_ALIGN(pCmd->cryptoOffset, 4) )
2900        {
2901            mvOsPrintf("CesaAction: cryptoOffset=%d must be 4 byte aligned\n",
2902                        pCmd->cryptoOffset);
2903            return MV_BAD_PARAM;
2904        }
2905        /* cryptoLength should be the whole number of blocks */
2906        if( MV_IS_NOT_ALIGN(pCmd->cryptoLength, pSA->cryptoBlockSize) )
2907        {
2908            mvOsPrintf("mvCesaAction: cryptoLength=%d must be %d byte aligned\n",
2909                        pCmd->cryptoLength, pSA->cryptoBlockSize);
2910            return MV_BAD_PARAM;
2911        }
2912        if(fixOffset == 0xFF)
2913        {
2914            fixOffset = (pCmd->cryptoOffset % 8);
2915        }
2916        else
2917        {
2918            /* In addition all offsets should be the same alignment: 8 or 4 */
2919            if( (pCmd->cryptoOffset % 8) != fixOffset)
2920            {
2921                mvOsPrintf("mvCesaAction: cryptoOffset %d mod 8 must be equal %d \n",
2922                                pCmd->cryptoOffset, fixOffset);
2923                return MV_BAD_PARAM;
2924            }
2925        }
2926
2927        /* check for CBC mode */
2928        if(pSA->cryptoIvSize > 0)
2929        {
2930            /* cryptoIV must not be part of CryptoLength */
2931            if( ((pCmd->ivOffset + pSA->cryptoIvSize) > pCmd->cryptoOffset) &&
2932                (pCmd->ivOffset < (pCmd->cryptoOffset + pCmd->cryptoLength)) )
2933            {
2934                mvOsPrintf("mvCesaFragParamCheck: cryptoIvOffset (%d) is part of cryptoLength (%d+%d)\n",
2935                        pCmd->ivOffset, pCmd->macOffset, pCmd->macLength);
2936                return MV_BAD_PARAM;
2937            }
2938
2939            /* ivOffset must be 4 byte aligned */
2940            if( MV_IS_NOT_ALIGN(pCmd->ivOffset, 4) )
2941            {
2942                mvOsPrintf("CesaAction: ivOffset=%d must be 4 byte aligned\n",
2943                            pCmd->ivOffset);
2944                return MV_BAD_PARAM;
2945            }
2946            /* In addition all offsets should be the same alignment: 8 or 4 */
2947            if( (pCmd->ivOffset % 8) != fixOffset)
2948            {
2949                mvOsPrintf("mvCesaAction: ivOffset %d mod 8 must be %d\n",
2950                                pCmd->ivOffset, fixOffset);
2951                return MV_BAD_PARAM;
2952            }
2953        }
2954    }
2955    return MV_OK;
2956}
2957
2958/*******************************************************************************
2959* mvCesaFragParamCheck -
2960*
2961* DESCRIPTION:
2962*
2963*
2964* INPUT:
2965* MV_CESA_SA* pSA, MV_CESA_COMMAND *pCmd
2966*
2967* RETURN:
2968* MV_STATUS
2969*
2970*******************************************************************************/
2971static MV_STATUS mvCesaFragParamCheck(MV_CESA_SA* pSA, MV_CESA_COMMAND *pCmd)
2972{
2973    int offset;
2974
2975    if( ((pSA->config & MV_CESA_OPERATION_MASK) !=
2976                (MV_CESA_CRYPTO_ONLY << MV_CESA_OPERATION_OFFSET)) )
2977    {
2978        /* macOffset must be less that SRAM buffer size */
2979        if(pCmd->macOffset > (sizeof(cesaSramVirtPtr->buf) - MV_CESA_AUTH_BLOCK_SIZE))
2980        {
2981            mvOsPrintf("mvCesaFragParamCheck: macOffset is too large (%d)\n",
2982                        pCmd->macOffset);
2983            return MV_BAD_PARAM;
2984        }
2985        /* macOffset+macSize must be more than mbufSize - SRAM buffer size */
2986        if( ((pCmd->macOffset + pCmd->macLength) > pCmd->pSrc->mbufSize) ||
2987            ((pCmd->pSrc->mbufSize - (pCmd->macOffset + pCmd->macLength)) >=
2988             sizeof(cesaSramVirtPtr->buf)) )
2989        {
2990            mvOsPrintf("mvCesaFragParamCheck: macLength is too large (%d), mbufSize=%d\n",
2991                        pCmd->macLength, pCmd->pSrc->mbufSize);
2992            return MV_BAD_PARAM;
2993        }
2994    }
2995
2996    if( ((pSA->config & MV_CESA_OPERATION_MASK) !=
2997                (MV_CESA_MAC_ONLY << MV_CESA_OPERATION_OFFSET)) )
2998    {
2999        /* cryptoOffset must be less that SRAM buffer size */
3000        /* 4 for possible fixOffset */
3001        if( (pCmd->cryptoOffset + 4) > (sizeof(cesaSramVirtPtr->buf) - pSA->cryptoBlockSize))
3002        {
3003            mvOsPrintf("mvCesaFragParamCheck: cryptoOffset is too large (%d)\n",
3004                        pCmd->cryptoOffset);
3005            return MV_BAD_PARAM;
3006        }
3007
3008        /* cryptoOffset+cryptoSize must be more than mbufSize - SRAM buffer size */
3009        if( ((pCmd->cryptoOffset + pCmd->cryptoLength) > pCmd->pSrc->mbufSize) ||
3010            ((pCmd->pSrc->mbufSize - (pCmd->cryptoOffset + pCmd->cryptoLength)) >=
3011             (sizeof(cesaSramVirtPtr->buf) - pSA->cryptoBlockSize)) )
3012        {
3013            mvOsPrintf("mvCesaFragParamCheck: cryptoLength is too large (%d), mbufSize=%d\n",
3014                        pCmd->cryptoLength, pCmd->pSrc->mbufSize);
3015            return MV_BAD_PARAM;
3016        }
3017    }
3018
3019    /* When MAC_THEN_CRYPTO or CRYPTO_THEN_MAC */
3020    if( ((pSA->config & MV_CESA_OPERATION_MASK) ==
3021            (MV_CESA_MAC_THEN_CRYPTO << MV_CESA_OPERATION_OFFSET)) ||
3022        ((pSA->config & MV_CESA_OPERATION_MASK) ==
3023            (MV_CESA_CRYPTO_THEN_MAC << MV_CESA_OPERATION_OFFSET)) )
3024    {
3025        if( (mvCtrlModelGet() == MV_5182_DEV_ID) ||
3026            ( (mvCtrlModelGet() == MV_5181_DEV_ID) &&
3027              (mvCtrlRevGet() >= MV_5181L_A0_REV) &&
3028              (pCmd->macLength >= (1 << 14)) ) )
3029        {
3030            return MV_NOT_ALLOWED;
3031        }
3032
3033        /* abs(cryptoOffset-macOffset) must be aligned cryptoBlockSize */
3034        if(pCmd->cryptoOffset > pCmd->macOffset)
3035        {
3036            offset = pCmd->cryptoOffset - pCmd->macOffset;
3037        }
3038        else
3039        {
3040            offset = pCmd->macOffset - pCmd->cryptoOffset;
3041        }
3042
3043        if( MV_IS_NOT_ALIGN(offset, pSA->cryptoBlockSize) )
3044        {
3045/*
3046            mvOsPrintf("mvCesaFragParamCheck: (cryptoOffset - macOffset) must be %d byte aligned\n",
3047                        pSA->cryptoBlockSize);
3048*/
3049            return MV_NOT_ALLOWED;
3050        }
3051        /* Digest must not be part of CryptoLength */
3052        if( ((pCmd->digestOffset + pSA->digestSize) > pCmd->cryptoOffset) &&
3053            (pCmd->digestOffset < (pCmd->cryptoOffset + pCmd->cryptoLength)) )
3054        {
3055/*
3056            mvOsPrintf("mvCesaFragParamCheck: digestOffset (%d) is part of cryptoLength (%d+%d)\n",
3057                        pCmd->digestOffset, pCmd->cryptoOffset, pCmd->cryptoLength);
3058*/
3059            return MV_NOT_ALLOWED;
3060        }
3061    }
3062    return MV_OK;
3063}
3064
3065/*******************************************************************************
3066* mvCesaFragSizeFind -
3067*
3068* DESCRIPTION:
3069*
3070*
3071* INPUT:
3072* MV_CESA_SA* pSA, MV_CESA_COMMAND *pCmd,
3073* int cryptoOffset, int macOffset,
3074*
3075* OUTPUT:
3076* int* pCopySize, int* pCryptoDataSize, int* pMacDataSize
3077*
3078* RETURN:
3079* MV_STATUS
3080*
3081*******************************************************************************/
3082static void mvCesaFragSizeFind(MV_CESA_SA* pSA, MV_CESA_REQ* pReq,
3083                                 int cryptoOffset, int macOffset,
3084                          int* pCopySize, int* pCryptoDataSize, int* pMacDataSize)
3085{
3086    MV_CESA_COMMAND *pCmd = pReq->pCmd;
3087    int cryptoDataSize, macDataSize, copySize;
3088
3089    cryptoDataSize = macDataSize = 0;
3090    copySize = *pCopySize;
3091
3092    if( (pSA->config & MV_CESA_OPERATION_MASK) !=
3093                (MV_CESA_MAC_ONLY << MV_CESA_OPERATION_OFFSET) )
3094    {
3095        cryptoDataSize = MV_MIN( (copySize - cryptoOffset),
3096                                 (pCmd->cryptoLength - (pReq->frags.cryptoSize + 1)) );
3097
3098        /* cryptoSize for each fragment must be the whole number of blocksSize */
3099        if( MV_IS_NOT_ALIGN(cryptoDataSize, pSA->cryptoBlockSize) )
3100        {
3101            cryptoDataSize = MV_ALIGN_DOWN(cryptoDataSize, pSA->cryptoBlockSize);
3102            copySize = cryptoOffset + cryptoDataSize;
3103        }
3104    }
3105    if( (pSA->config & MV_CESA_OPERATION_MASK) !=
3106             (MV_CESA_CRYPTO_ONLY << MV_CESA_OPERATION_OFFSET) )
3107    {
3108        macDataSize = MV_MIN( (copySize - macOffset),
3109                              (pCmd->macLength - (pReq->frags.macSize + 1)));
3110
3111        /* macSize for each fragment (except last) must be the whole number of blocksSize */
3112        if( MV_IS_NOT_ALIGN(macDataSize, MV_CESA_AUTH_BLOCK_SIZE) )
3113        {
3114            macDataSize = MV_ALIGN_DOWN(macDataSize, MV_CESA_AUTH_BLOCK_SIZE);
3115            copySize = macOffset + macDataSize;
3116        }
3117        cryptoDataSize = copySize - cryptoOffset;
3118    }
3119    *pCopySize = copySize;
3120
3121    if(pCryptoDataSize != NULL)
3122        *pCryptoDataSize = cryptoDataSize;
3123
3124    if(pMacDataSize != NULL)
3125        *pMacDataSize = macDataSize;
3126}
3127

Archive Download this file



interactive