2 * Copyright (C) 2001-2003 by NBMK Encryption Technologies.
5 * NBMK Encryption Technologies provides no support of any kind for
6 * this software. Questions or concerns about it may be addressed to
7 * the members of the relevant open-source community at
8 * <tech-crypto@netbsd.org>.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions are
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above
18 * copyright notice, this list of conditions and the following
19 * disclaimer in the documentation and/or other materials provided
20 * with the distribution.
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 static char const n8_id
[] = "$Id: contextMem.c,v 1.1 2008/10/30 12:02:14 darran Exp $";
36 /*****************************************************************************/
37 /** @file contextMem.c
38 * @brief NSP2000 Device Driver Context Memory Manager.
40 * This file manages the context memory resource for the NSP2000 device driver.
42 *****************************************************************************/
44 /*****************************************************************************
46 * 01/16/04 jpw Add N8_NO_64_BURST to prevent 64bit bursts to 32 bit regs
47 * during sequential slave io accesses.
48 * 05/08/03 brr Modified kernel functions to use N8_GET_KERNEL_ID instead
49 * of N8_GET_SESSION_ID.
50 * 04/18/03 brr Allocate Context memory map using vmalloc instead of
51 * requesting it from the continuous driver pool. (Bug 718)
52 * 10/25/02 brr Clean up function prototypes & include files.
53 * 06/26/02 brr Remove bank parameter from calls to N8_PhysToVirt.
54 * 06/12/02 hml Calls to N8_PhysToVirt now take the bank parameter.
55 * 06/10/02 hml Pass memBankCtl as a parameter when needed.
56 * 04/29/02 brr Modified N8_ContextMemInit to correctly check allocation of
57 * contextMemMap & also initialize the semaphore even when
58 * there is no context memory installed.
59 * 04/02/02 bac Changed n8_contextalloc to look across all chips if
60 * N8_ANY_UNIT is specified and no more resources are
61 * encountered. (BUG 515)
62 * 03/29/02 hml Added N8_ContextMemValidate. (BUGS 657 658).
63 * 03/27/02 hml Delete of unused variable.
64 * 03/26/02 hml Converted the context memory free functions to match the
65 * paradigm used by the memory implementation. Also added
66 * status returns. (Bug 637).
67 * 03/22/02 hml Converted the context memory allocation functions to match
68 * the paradigm used by the memory implementation.
69 * 03/19/02 brr Correctly limit Allocation index to contextMemEntries.
70 * 03/18/02 brr Pass sessionID into allocation function.
71 * 03/08/02 brr Memset context memory map allocation to zero since KMALLOC
72 * is no longer doing it.
73 * 02/22/02 spm Converted printk's to DBG's.
74 * 02/25/02 brr Removed references to qmgrData.
75 * 02/18/02 brr Support chip selection.
76 * 02/15/02 brr Integrate with VxWorks, added mutual exclusion semaphore.
77 * 02/05/02 brr File created.
78 ****************************************************************************/
79 /** @defgroup NSP2000Driver NSP2000 Device Driver Context Memory Manager.
83 #include "contextMem.h"
84 #include "n8_pub_errors.h"
85 #include "n8_memory.h"
86 #include "n8_common.h"
87 #include "n8_driver_main.h"
88 #include "nsp2000_regs.h"
90 #include "n8_driver_api.h"
92 extern NspInstance_t NSPDeviceTable_g
[DEF_MAX_SIMON_INSTANCES
];
93 extern int NSPcount_g
;
95 /*****************************************************************************
96 * N8_ReadContextMemory
97 *****************************************************************************/
98 /** @ingroup NSP2000Driver
99 * @brief Reads a value from a specified address in context memory.
101 * This routine reads a 32-bit value from the specified location
104 * @param NSPinstance_p RO: Pointer to the information structure for an
105 * NSP2000 hardware instance, containing a
106 * pointer to its control register set.
107 * @param address RO: Specifies the context memory address.
108 * @param value RW: Returns the read value.
114 * See return section for error information.
115 *****************************************************************************/
117 static unsigned char N8_ReadContextMemory(NspInstance_t
*NSPinstance_p
,
118 unsigned long address
,
119 unsigned long *value
)
121 volatile NSP2000REGS_t
*nsp
= (NSP2000REGS_t
*)NSPinstance_p
->NSPregs_p
;
124 /* FIRST CHECK FOR PENDING OPERATIONS */
125 if (nsp
->cch_context_addr
& 0xc0000000)
130 /* SPECIFY ADDRESS TO READ, ENABLE OPERATION, AND AWAIT COMPLETION */
131 nsp
->cch_context_addr
= address
| 0x80000000;
132 reg
= nsp
->cch_context_addr
;
133 if (nsp
->cch_context_addr
& 0xc0000000)
135 /* ANY ACCESS SHOULD COMPLETE WITHIN THE SPACE OF 2 ACCESSES */
139 /* RETURN READ VALUE */
140 *value
= (unsigned long)(nsp
->cch_context_data0
);
142 } /* N8_ReadContextMemory */
146 /*****************************************************************************
147 * N8_WriteContextMemory
148 *****************************************************************************/
149 /** @ingroup NSP2000Driver
150 * @brief Writes a value to a specified address in context memory.
152 * This routine writes the specified 32-bit value to the specified location
155 * @param NSPinstance_p RO: Pointer to the information structure for an
156 * NSP2000 hardware instance, containing a
157 * pointer to its control register set.
158 * @param address RO: Specifies the context memory address.
159 * @param value RO: Specifies the data to write.
162 * 0 Failure - the write failed.
166 * See return section for error information.
167 *****************************************************************************/
169 static unsigned char N8_WriteContextMemory( NspInstance_t
*NSPinstance_p
,
170 unsigned long address
,
171 unsigned long value
)
173 volatile NSP2000REGS_t
*nsp
= (NSP2000REGS_t
*)NSPinstance_p
->NSPregs_p
;
176 /* FIRST CHECK FOR PENDING OPERATIONS */
177 if (nsp
->cch_context_addr
& 0xc0000000)
182 /* SPECIFY ADDRESS TO BE WRITTEN */
183 nsp
->cch_context_addr
= address
;
185 /* SPECIFY VALUE TO WRITE, INITIATE WRITE OPERATION, AND AWAIT COMPLETION */
186 nsp
->cch_context_data1
= 0;
188 nsp
->cch_context_data0
= value
;
189 reg
= nsp
->cch_context_addr
;
190 if (nsp
->cch_context_addr
& 0xc0000000)
192 /* ANY ACCESS SHOULD COMPLETE WITHIN THE SPACE OF 2 ACCESSES */
196 } /* N8_WriteContextMemory */
200 /*****************************************************************************
201 * N8_GetContextMemSize
202 *****************************************************************************/
203 /** @ingroup NSP2000Driver
204 * @brief Determine the size of context memory.
206 * This routine probes the context memory to determine how large it is.
208 * @param NSPinstance_p RO: Pointer to the information structure for an
209 * NSP2000 hardware instance, containing a
210 * pointer to its control register set.
213 * Returns the amount of detected memory. If any accesses fail, we return
214 * 0 bytes (no memory installed).
217 * See return section for error information.
218 *****************************************************************************/
220 static unsigned long N8_GetContextMemSize(NspInstance_t
*NSPinstance_p
)
222 unsigned long tmp
= 32, size
= 0, readvalue1
, readvalue2
;
224 /* FIRST TEST FOR THE EXISTENCE OF CONTEXT MEMORY */
225 printf("N8_GetContextMemSize: testing for context memory\n");
226 if ( !N8_WriteContextMemory(NSPinstance_p
, 0, 0x12345678) ||
227 !N8_WriteContextMemory(NSPinstance_p
, 10, 0x87654321) ||
228 !N8_ReadContextMemory (NSPinstance_p
, 0, &readvalue1
) ||
229 !N8_ReadContextMemory (NSPinstance_p
, 10, &readvalue2
) )
231 printf("N8_GetContextMemSize: no context memory\n");
234 if ((0x12345678 != readvalue1
) || (0x87654321 != readvalue2
))
236 /* NO CONTEXT MEMORY APPEARS TO BE PRESENT */
237 /* CANNOT TEST THIS WITH FPGA, BECAUSE THE CTX REGISTERS */
238 /* ARE NOT IMPLEMENTED, AND READS/WRITES WILL FAIL. */
239 printf("N8_GetContextMemSize: no context memory again\n");
243 /* USING SIZING ALGORITHM AS IN NSP2000 DATASHEET P. 4-5 */
244 printf("N8_GetContextMemSize: initializing\n");
245 if ( !N8_WriteContextMemory(NSPinstance_p
, 0, 64) ||
246 !N8_WriteContextMemory(NSPinstance_p
, 0x400000, tmp
) ||
247 !N8_ReadContextMemory (NSPinstance_p
, 0, &tmp
) ||
248 !N8_WriteContextMemory(NSPinstance_p
, 0, 128) ||
249 !N8_WriteContextMemory(NSPinstance_p
, 0x800000, tmp
) ||
250 !N8_ReadContextMemory (NSPinstance_p
, 0, &size
) )
256 /* DO ADDITIONAL CONFIGURATION */
259 /* SET ref_8k_i = 0 */
263 /* SET ref_8k_i = 1 */
266 /* TRANSLATE Mb VALUE INTO BYTES */
267 return (size
* 1024 * 1024);
268 } /* N8_GetContextMemSize */
270 /*****************************************************************************
272 *****************************************************************************/
273 /** @ingroup NSP2000Driver
274 * @brief Initialize all data necessary to manage the context memory.
276 * This routine initializes all the data structures necessary to manage the
277 * the context memory on an NPS2000.
279 * @param NSPinstance_p RO: Pointer to the information structure for an
280 * NSP2000 hardware instance.
284 *****************************************************************************/
286 void N8_ContextMemInit(int chip
)
290 NspInstance_t
*NSPinstance_p
= &NSPDeviceTable_g
[chip
];
293 printf("N8_ContextMemInit(chip=%d)\n", chip
);
294 NSPinstance_p
->contextMemSize
= N8_GetContextMemSize(NSPinstance_p
);
295 printf("N8_ContextMemInit(chip=%d): still ok\n", chip
);
296 if (NSPinstance_p
->contextMemSize
)
298 ctxEntries
= NSPinstance_p
->contextMemSize
/CONTEXT_ENTRY_SIZE
;
299 size
= ctxEntries
* sizeof(ContextMemoryMap_t
);
300 NSPinstance_p
->contextMemMap_p
= vmalloc(size
);
302 if (NSPinstance_p
->contextMemMap_p
)
304 memset(NSPinstance_p
->contextMemMap_p
, 0, size
);
305 NSPinstance_p
->contextMemEntries
= ctxEntries
;
309 /* Initialize the semaphore even though there is no context memory. This */
310 /* simplifies the allocation in case there is a mixture of NSP2000's with */
311 /* and without context memory. */
312 printf("N8_ContextMemInit(chip=%d): N8_AtomicLockInit\n", chip
);
313 N8_AtomicLockInit(NSPinstance_p
->contextMemSem
);
315 } /* N8_ContextMemInit */
317 /*****************************************************************************
318 * N8_ContextMemRemove
319 *****************************************************************************/
320 /** @ingroup NSP2000Driver
321 * @brief Deallocates all resources allocated to manage the context memory.
323 * This routine deallocates all the resources allocated to manage the
324 * the context memory on an NPS2000.
326 * @param NSPinstance_p RO: Pointer to the information structure for an
327 * NSP2000 hardware instance.
331 *****************************************************************************/
333 void N8_ContextMemRemove(int chip
)
336 NspInstance_t
*NSPinstance_p
= &NSPDeviceTable_g
[chip
];
338 if (NSPinstance_p
->contextMemMap_p
)
340 vfree(NSPinstance_p
->contextMemMap_p
);
341 NSPinstance_p
->contextMemMap_p
= NULL
;
343 N8_AtomicLockDel(NSPinstance_p
->contextMemSem
);
344 NSPinstance_p
->contextMemSize
= 0;
345 NSPinstance_p
->contextMemNext
= 0;
346 } /* N8_ContextMemRemove */
348 /*****************************************************************************
350 *****************************************************************************/
351 /** @ingroup NSP2000Driver
352 * @brief Allocate an entry from the context memory.
354 * This routine is called from the kernel space version of N8_AllocateContext.
355 * Since we aren't coming in through the ioctl, we have to calculate the
356 * session ID. Then we call the common lower level function to do the work.
358 * @param chip RO: User specified chip, which must be validated.
361 * Returns the index of the context memory allocation.
362 * -1 - The allocation has failed.
365 * See return section for error information.
366 *****************************************************************************/
368 N8_Status_t
N8_ContextMemAlloc(N8_Unit_t
*chip
, unsigned int *index_p
)
370 unsigned long sessionID
;
372 sessionID
= N8_GET_KERNEL_ID
;
374 return (n8_contextalloc(chip
, sessionID
, index_p
));
375 } /* N8_ContextMemAlloc */
378 /*****************************************************************************
380 *****************************************************************************/
381 /** @ingroup NSP2000Driver
382 * @brief Allocate an entry from the context memory.
384 * This routine allocates and entry from the context memory on an NPS2000.
386 * @param chip RO: User specified chip, which must be validated.
387 * @param sessionID RO: ID of the allocating session.
390 * Returns the index of the context memory allocation.
391 * -1 - The allocation has failed.
394 * See return section for error information.
395 *****************************************************************************/
397 N8_Status_t
n8_contextalloc(N8_Unit_t
*chip
,
398 unsigned long sessionID
,
399 unsigned int *index_p
)
401 N8_Unit_t selectedChip
;
403 NspInstance_t
*NSPinstance_p
;
405 int numberOfUnitsToCheck
= 1;
407 N8_Status_t ret
= N8_STATUS_OK
;
409 /* Determine which queue to use, and set the queue_p in the API request */
410 ret
= QMgr_get_valid_unit_num(N8_EA
, *chip
, &selectedChip
);
411 if (ret
== N8_STATUS_OK
)
413 /* if the user requests any unit, we must check them all and give up only
414 * if there is no context available on any of the chips. if a specific
415 * unit is specified, then the loop only checks the specfied unit.
417 if (*chip
== N8_ANY_UNIT
)
419 numberOfUnitsToCheck
= NSPcount_g
;
422 for (i
= 0; i
< numberOfUnitsToCheck
; i
++)
424 static int active
= 0;
425 NSPinstance_p
= &NSPDeviceTable_g
[selectedChip
];
426 index
= NSPinstance_p
->contextMemNext
;
428 N8_AtomicLock(NSPinstance_p
->contextMemSem
);
431 printf("%s.%d: context unprotected - active=%d\n", __FILE__
, __LINE__
, active
);
433 for (ctr
= 0; ctr
< NSPinstance_p
->contextMemEntries
; ctr
++)
435 if (NSPinstance_p
->contextMemMap_p
[index
].userID
== 0)
437 NSPinstance_p
->contextMemMap_p
[index
].userID
= sessionID
;
438 NSPinstance_p
->contextMemNext
= (index
+ 1) % NSPinstance_p
->contextMemEntries
;
442 index
= (index
+ 1) % NSPinstance_p
->contextMemEntries
;
445 N8_AtomicUnlock(NSPinstance_p
->contextMemSem
);
447 if (ctr
!= NSPinstance_p
->contextMemEntries
)
449 /* a free context was found -- stop looking */
450 DBG(("Found context %d on chip %d\n", *index_p
, selectedChip
));
453 /* no context was found on this unit. try another. */
454 DBG(("Context not found. Rolling to a new chip.\n"));
455 selectedChip
= (selectedChip
+ 1) % NSPcount_g
;
457 if (i
== numberOfUnitsToCheck
)
459 /* No more context memory */
460 ret
= N8_NO_MORE_RESOURCE
;
464 *chip
= selectedChip
;
468 } /* n8_contextalloc */
470 /*****************************************************************************
472 *****************************************************************************/
473 /** @ingroup NSP2000Driver
474 * @brief Free a context memory entry.
476 * This routine frees a context memory entry on an NPS2000.
478 * @param NSPinstance_p RO: Pointer to the information structure for an
479 * NSP2000 hardware instance.
480 * entry R0: The index of the entry to be freed.
484 *****************************************************************************/
486 N8_Status_t
N8_ContextMemFree(int chip
, unsigned long entry
)
488 unsigned long sessionID
;
490 sessionID
= N8_GET_KERNEL_ID
;
492 return (n8_contextfree(chip
, sessionID
, entry
));
493 } /* N8_ContextMemFree */
495 /*****************************************************************************
497 *****************************************************************************/
498 /** @ingroup NSP2000Driver
499 * @brief Free a context memory entry.
501 * This routine frees a context memory entry on an NPS2000.
503 * @param NSPinstance_p RO: Pointer to the information structure for an
504 * NSP2000 hardware instance.
505 * entry R0: The index of the entry to be freed.
509 *****************************************************************************/
512 n8_contextfree(int chip
, unsigned long sessionID
, unsigned long entry
)
514 NspInstance_t
*NSPinstance_p
= &NSPDeviceTable_g
[chip
];
515 N8_Status_t retCode
= N8_STATUS_OK
;
517 /* Check for a valid entry */
518 if (entry
< NSPinstance_p
->contextMemEntries
)
520 if (NSPinstance_p
->contextMemMap_p
[entry
].userID
== 0)
522 /* Attempting to free a context that is already free */
523 retCode
= N8_UNALLOCATED_CONTEXT
;
525 else if (sessionID
== NSPinstance_p
->contextMemMap_p
[entry
].userID
)
527 /* Session ID matches the session ID that allocated this
529 NSPinstance_p
->contextMemMap_p
[entry
].userID
= 0;
533 /* Wrong session ID */
534 retCode
= N8_INVALID_VALUE
;
539 /* entry specified is invalid */
540 retCode
= N8_INVALID_PARAMETER
;
544 } /* n8_contextfree */
546 /*****************************************************************************
547 * N8_ContextMemValidate
548 *****************************************************************************/
549 /** @ingroup NSP2000Driver
550 * @brief Validate a context memory entry.
552 * This routine frees a context memory entry on an NPS2000.
554 * @param chip RO: The chip.
555 * entry R0: The index of the entry to be freed.
559 *****************************************************************************/
561 N8_Status_t
N8_ContextMemValidate(N8_Unit_t chip
, unsigned int entry
)
563 unsigned long sessionID
;
565 sessionID
= N8_GET_KERNEL_ID
;
567 return (n8_contextvalidate(chip
, sessionID
, entry
));
568 } /* N8_ContextMemValidate */
570 /*****************************************************************************
572 *****************************************************************************/
573 /** @ingroup NSP2000Driver
574 * @brief Validate a context memory entry.
576 * This routine validates a context memory entry on an NPS2000. This in
577 * intended only to be called from the ContextRead and ContextWrite functions.
579 * @param chip RO: The chip.
580 * sessionID RO: The sessionID for the entry.
581 * entry RO: The index of the entry to be freed.
585 *****************************************************************************/
588 n8_contextvalidate(N8_Unit_t chip
, unsigned long sessionID
, unsigned int entry
)
590 NspInstance_t
*NSPinstance_p
= &NSPDeviceTable_g
[chip
];
591 N8_Status_t retCode
= N8_STATUS_OK
;
593 /* Check for a valid entry */
594 if (entry
< NSPinstance_p
->contextMemEntries
)
596 if (NSPinstance_p
->contextMemMap_p
[entry
].userID
== 0)
598 /* Attempting to free a context that is already free */
599 retCode
= N8_UNALLOCATED_CONTEXT
;
601 else if (sessionID
!= NSPinstance_p
->contextMemMap_p
[entry
].userID
)
603 /* Session ID does not match the session ID that allocated this
605 retCode
= N8_INVALID_VALUE
;
610 /* entry specified is invalid */
611 retCode
= N8_INVALID_VALUE
;
615 } /* n8_contextvalidate */
617 /*****************************************************************************
619 *****************************************************************************/
620 /** @ingroup NSP2000Driver
621 * @brief Free all of the entries for a singles session on a single chip.
623 * This routine marks all of the context entries owned by the specified session
624 * on the specified chip as free. This routine is called as part of the session
625 * cleanup in the exit handler of the driver.
627 * We do not get the lock at any time during this operation.
629 * IMPORTANT NOTE: This algorithm currently used in this routine is the most
630 * brute force (and consequently the slowest) imaginable. In
631 * order to optimize the speed of this routine we should
632 * probably move towards a session based management scheme.
635 * @param chip RO: The chip number for which to clear the context memory.
636 * @param sessionID RO: The session id for which to clear the context memory.
639 * None. What would the user do if this function failed?
642 *****************************************************************************/
644 void N8_ContextMemFreeAll(N8_Unit_t chip
, unsigned long sessionID
)
647 NspInstance_t
*NSPinstance_p
;
649 NSPinstance_p
= &NSPDeviceTable_g
[chip
];
651 /* Look through the whole table and clear any entries whose
652 sessionID matches our target. */
653 for (ctr
= 0; ctr
< NSPinstance_p
->contextMemEntries
; ctr
++)
655 if (NSPinstance_p
->contextMemMap_p
[ctr
].userID
== sessionID
)
657 NSPinstance_p
->contextMemMap_p
[ctr
].userID
= 0;
660 } /* N8_ContextMemFreeAll */
662 /*****************************************************************************
664 *****************************************************************************/
665 /** @ingroup NSP2000Driver
666 * @brief Display contents of contex allocation map.
668 * This debugging routine simply displays the contents of the context map
669 * via the standard kernel debugging message facility. It also assumes that
670 * the caller has properly locked the allocation map.
672 * Note that Debug_g must be set, for this routine to do anything.
675 * NSPDeviceTable_g RO: Global allocation map. <BR>
681 * See return section for error information.
682 *****************************************************************************/
684 void n8_contextDisplay(void)
689 NspInstance_t
*NSPinstance_p
;
691 N8_PRINT( "n8_context: <******* CONTEXT MEMORY STATISTICS ******>\n");
692 for (chip
= 0; chip
< NSPcount_g
; chip
++)
694 N8_PRINT( "n8_context: <******* CHIP %d STATISTICS ******>\n", chip
);
696 NSPinstance_p
= &NSPDeviceTable_g
[chip
];
697 for (ctr
= 0; ctr
< NSPinstance_p
->contextMemEntries
; ctr
++)
699 if (NSPinstance_p
->contextMemMap_p
[ctr
].userID
!= 0)
702 if (nUsed
<= N8_CONTEXT_MAX_PRINT
)
704 N8_PRINT( "n8_context: Slot %d used by Session %d\n",
705 ctr
, NSPinstance_p
->contextMemMap_p
[ctr
].userID
);
710 if (nUsed
> N8_CONTEXT_MAX_PRINT
)
712 N8_PRINT( "n8_context: Only printed first %d details\n",
713 N8_CONTEXT_MAX_PRINT
) ;
716 "n8_context: <******* CHIP %d TOTAL CONTEXT ALLOCATION %d ******>\n",
718 N8_PRINT("n8_context: <******* END CHIP %d STATISTICS ******>\n", chip
);
722 N8_PRINT( "n8_context: <********* CONTEXT MEMORY END ***********>\n");
724 } /* n8_contextDisplay */