rename target/linux/generic-2.6 to generic
[15.05/openwrt.git] / target / linux / generic / files / crypto / ocf / kirkwood / cesa / mvCesa.c
1 /*******************************************************************************
2 Copyright (C) Marvell International Ltd. and its affiliates
3
4 This software file (the "File") is owned and distributed by Marvell
5 International Ltd. and/or its affiliates ("Marvell") under the following
6 alternative licensing terms.  Once you have made an election to distribute the
7 File under one of the following license alternatives, please (i) delete this
8 introductory statement regarding license alternatives, (ii) delete the two
9 license alternatives that you have not elected to use and (iii) preserve the
10 Marvell copyright notice above.
11
12 ********************************************************************************
13 Marvell Commercial License Option
14
15 If you received this File from Marvell and you have entered into a commercial
16 license agreement (a "Commercial License") with Marvell, the File is licensed
17 to you under the terms of the applicable Commercial License.
18
19 ********************************************************************************
20 Marvell GPL License Option
21
22 If you received this File from Marvell, you may opt to use, redistribute and/or
23 modify this File in accordance with the terms and conditions of the General
24 Public License Version 2, June 1991 (the "GPL License"), a copy of which is
25 available along with the File in the license.txt file or by writing to the Free
26 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
27 on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
28
29 THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
30 WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
31 DISCLAIMED.  The GPL License provides additional details about this warranty
32 disclaimer.
33 ********************************************************************************
34 Marvell BSD License Option
35
36 If you received this File from Marvell, you may opt to use, redistribute and/or
37 modify this File under the following licensing terms.
38 Redistribution and use in source and binary forms, with or without modification,
39 are 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
52 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
53 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
54 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
55 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
56 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
57 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
58 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
59 ANY 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
61 SOFTWARE, 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
77 MV_CESA_STATS           cesaStats;
78
79 MV_BUF_INFO             cesaSramSaBuf;
80 short                   cesaLastSid = -1;
81 MV_CESA_SA*             pCesaSAD = NULL;
82 MV_U16                  cesaMaxSA = 0;
83
84 MV_CESA_REQ*            pCesaReqFirst = NULL;
85 MV_CESA_REQ*            pCesaReqLast = NULL;
86 MV_CESA_REQ*            pCesaReqEmpty = NULL;
87 MV_CESA_REQ*            pCesaReqProcess = NULL;
88 int                     cesaQueueDepth = 0;
89 int                     cesaReqResources = 0;
90
91 MV_CESA_SRAM_MAP*       cesaSramVirtPtr = NULL;
92 MV_U32                  cesaCryptEngBase = 0;
93 void                    *cesaOsHandle = NULL;
94 #if (MV_CESA_VERSION >= 3)
95 MV_U32                  cesaChainLength = 0;
96 int                     chainReqNum = 0;
97 MV_U32                  chainIndex = 0;
98 MV_CESA_REQ*            pNextActiveChain = 0;
99 MV_CESA_REQ*            pEndCurrChain = 0;
100 MV_BOOL                 isFirstReq = MV_TRUE;
101 #endif
102
103 static 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
112 static 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
123 static 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
128 static INLINE void      mvCesaSramSaUpdate(short sid, MV_DMA_DESC *pDmaDesc);
129
130 static 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
134 static void        mvCesaHmacIvGet(MV_CESA_MAC_MODE macMode, unsigned char key[], int keyLength,
135                                     unsigned char innerIV[], unsigned char outerIV[]);
136
137 static MV_STATUS   mvCesaFragAuthComplete(MV_CESA_REQ* pReq, MV_CESA_SA* pSA,
138                                           int macDataSize);
139
140 static MV_CESA_COMMAND*   mvCesaCtrModeInit(void);
141
142 static MV_STATUS   mvCesaCtrModePrepare(MV_CESA_COMMAND *pCtrModeCmd, MV_CESA_COMMAND *pCmd);
143 static MV_STATUS   mvCesaCtrModeComplete(MV_CESA_COMMAND *pOrgCmd, MV_CESA_COMMAND *pCmd);
144 static void        mvCesaCtrModeFinish(MV_CESA_COMMAND *pCmd);
145
146 static INLINE MV_STATUS mvCesaReqProcess(MV_CESA_REQ* pReq);
147 static MV_STATUS   mvCesaFragReqProcess(MV_CESA_REQ* pReq, MV_U8 frag);
148
149 static INLINE MV_STATUS mvCesaParamCheck(MV_CESA_SA* pSA, MV_CESA_COMMAND *pCmd, MV_U8* pFixOffset);
150 static INLINE MV_STATUS mvCesaFragParamCheck(MV_CESA_SA* pSA, MV_CESA_COMMAND *pCmd);
151
152 static INLINE void      mvCesaFragSizeFind(MV_CESA_SA* pSA, MV_CESA_REQ* pReq, 
153                                int cryptoOffset, int macOffset,
154                                int* pCopySize, int* pCryptoDataSize, int* pMacDataSize);
155 static MV_STATUS        mvCesaMbufCacheUnmap(MV_CESA_MBUF* pMbuf, int offset, int size);
156
157
158 /* Go to the next request in the request queue */
159 static 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 */
169 static 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
180 static 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 *******************************************************************************/
246 MV_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 *******************************************************************************/
446 MV_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 *******************************************************************************/
522 MV_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 *******************************************************************************/
580 MV_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 *******************************************************************************/
807 MV_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 *******************************************************************************/
863 MV_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 *******************************************************************************/
1085 MV_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 *******************************************************************************/
1284 int     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 *******************************************************************************/
1332 MV_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 *******************************************************************************/
1396 MV_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 *******************************************************************************/
1463 MV_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
1530 static 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 *******************************************************************************/
1590 static 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 *******************************************************************************/
1862 static 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 *******************************************************************************/
1967 static 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 *******************************************************************************/
2038 static 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
2079 static 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 */
2133 static 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 *******************************************************************************/
2251 static 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 *******************************************************************************/
2353 static 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 *******************************************************************************/
2454 static 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 *******************************************************************************/
2544 static 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 *******************************************************************************/
2608 static 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 *******************************************************************************/
2654 static 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 *******************************************************************************/
2726 static 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 *******************************************************************************/
2832 static 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 *******************************************************************************/
2850 static 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 *******************************************************************************/
2971 static 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 *******************************************************************************/
3082 static 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 }