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 /*****************************************************************************
36 * @(#) n8_memory.c 1.47@(#)
37 *****************************************************************************/
39 /*****************************************************************************/
40 /** @file n8_memory.c *
41 * @brief Memory Services - Cross-Platform *
43 * This file implements the kernel only portions of the memory allocation *
44 * and management service for the NSP2000 devices, to accomplish two basic *
47 * - Size limitations in allocation requests. Linux only allows up to *
48 * 128K to be allocated in a single call. n8_memory enables the api *
49 * to allocate larger physically contiguous space. *
52 * Obtains the large allocated space. It allocates the large pool *
53 * with n8_GetLargeAllocation (platform-specific). *
54 * n8_memory_Release - *
55 * Purges the allocation map and deallocates the large allocation space.*
57 *****************************************************************************/
59 /*****************************************************************************
61 * 02/17/04 jpw Change n8_memoryInit() memory allocation failure messages
62 * to kernel warning level and make it clear that the driver
63 * has not loaded. Suggest reserving space with bigphysarea
64 * 05/08/03 brr Reworked user pools to make better use of multiple driver
65 * banks. Moved user pool setup into the kernel.
66 * 05/02/03 brr Reset global pointer when memory is freed.
67 * 04/30/03 brr Reconcile differences between 2.4 & 3.0 baselines.
68 * 04/22/03 brr Correct semaphore initialization problem.
69 * 04/22/03 brr Removed redundant parameter from n8_FreeLargeAllocation.
70 * 04/21/03 brr Added support for multiple memory banks.
71 * 11/25/02 brr Clean up comments and format to coding standards.
72 * 11/01/02 brr Correct order of resource deallocation in n8_memoryRelease.
73 * 10/25/02 brr Clean up function prototypes & include files.
74 * 07/02/02 brr Added N8_QueryMemStatistics & access curAllocated as an
76 * 06/26/02 brr Remove bank parameter from calls to N8_PhysToVirt.
77 * 06/25/02 brr Rework user pool allocation to only mmap portion used by
78 * the individual process.
79 * 06/14/02 hml Change the type of an allocated buffer to
80 * N8_MEMORY_KERNEL_BUFFER and store the physical address of the
81 * bank in the memory struct.
82 * 06/12/02 hml Calls to N8_PhysToVirt now take the bank parameter. We
83 * also set the bank index in N8_BufferAllocate call.
84 * 06/11/02 hml Added include of n8_semaphore.h.
85 * 06/11/02 hml Use the new process sem calls instead of *Atomic*.
86 * 06/11/02 hml Removed some dangling prototypes.
87 * 06/10/02 hml Make n8_memoryRelease check for a NULL pointer.
88 * 06/10/02 hml Moved some functionality into n8_manage_memory.c.
89 * 05/22/02 hml Removed use of global variables and moved allocation map
90 * into the allocated space.
91 * 04/30/02 brr Do not memset the buffer to zero in N8_AllocateBuffer.
92 * 04/06/02 brr Make print for memory init already complete conditional.
93 * 03/27/02 brr Removed semaphore from free function since they are called
94 * from interrupt context and are not needed. Rework allocation
95 * so they are done in a round robin fashon.
96 * 03/26/02 brr Modified pfreeSessID to not free buffers on the command queue.
97 * 03/22/02 brr Move clearing of memory out of n8_pmalloc to avoid two calls
99 * 03/22/02 hml N8_AllocateBuffer now calls N8_GET_SESSION_ID instead of
100 * hardcoding a session id.
101 * 03/18/02 brr Pass sessionID into allocate & free functions.
102 * 03/13/02 brr Make n8_memoryInit reentrant to support BSD initialization.
103 * 03/08/02 brr Removed use of N8_UTIL_MALLOC.
104 * 02/26/02 brr Redo some of the print statements.
105 * 02/22/02 spm Converted printk's to DBG's. Added include of n8_OS_intf.h.
106 * 02/18/02 brr Renamed management fuctions to match those in n8_driver_api.c
107 * 02/14/02 brr Reconcile memory management differences with 2.0.
108 * 01/17/02 brr Function name cleanup.
109 * 01/11/02 bac Added debug messages to warn if the driver is forced to clean
110 * up after an exiting process. Also, track the users requested
111 * allocation size in bytes.
112 * 12/20/01 brr Use numBlocks instead of sessionID to determine availability.
113 * This allows driver to do static allocations with session ID 0.
114 * 12/19/01 brr Reset firstFreeIndex in n8_pfreeSessID.
115 * 12/18/01 brr Added n8_pfreeSessID.
116 * 12/14/01 brr Memory management performance improvements.
117 * 05/17/01 mmd Original version.
118 ****************************************************************************/
119 /** @defgroup NSP2000Driver Memory Allocation Services - Cross-Platform.
123 #include "n8_OS_intf.h"
125 #include "n8_driver_parms.h"
126 #include "n8_driver_api.h"
127 #include "n8_malloc_common.h"
128 #include "n8_memory.h"
129 #include "n8_semaphore.h"
130 #include "n8_version.h"
131 #include "userPool.h"
133 /* Local global that indicates whether debugging messages are enabled */
134 static int DebugFlag_g
= 0;
136 /* The control structures for all memory banks */
137 MemBankCtl_t
*memBankCtl_gp
[N8_MEMBANK_MAX
+ DEF_USER_POOL_BANKS
] = {NULL
};
139 void n8_calculateSize(MemBankCtl_t
*memCtl_p
, unsigned long size
);
140 void n8_setupAllocatedMemory(MemBankCtl_t
*memCtl_p
, unsigned long size
);
141 /*****************************************************************************
143 *****************************************************************************/
144 /** @ingroup NSP2000Driver
145 * @brief Enable/disable debug messages.
147 * This routine enables or disables debug messages in the n8 memory module.
150 * DebugFlag_g RO: Switch to enable/disable debug messages.
156 * See return section for error information.
157 *****************************************************************************/
159 void n8_memoryDebug(int enable
)
161 DebugFlag_g
= enable
;
165 /*****************************************************************************
167 *****************************************************************************/
168 /** @ingroup NSP2000Driver
169 * @brief Display contents of allocation map.
171 * This debugging routine simply displays the contents of the allocation map
172 * via the standard kernel debugging message facility. It also assumes that
173 * the caller has properly locked the allocation map.
175 * @param memCtl_p RW: The memory bank in question. The result of this
176 * function is stored in the maxEntries field.
182 * See return section for error information.
183 *****************************************************************************/
185 void n8_memoryDisplay(N8_MemoryType_t bank
)
188 MemCtlList_t
* memCtlList_p
;
189 MemBankCtl_t
*memCtl_p
= memBankCtl_gp
[bank
];
191 if (memCtl_p
->maxEntries
== 0)
195 N8_PRINT( "n8_memory: " N8_VERSION_STRING
);
196 N8_PRINT( "n8_memory: <******* PHYSICAL ALLOCATION MAP STATISTICS ******>\n");
198 N8_PRINT( "n8_memory: Memory Allocated for bank %d - %d KB\n",
199 bank
, memCtl_p
->allocSize
/ N8_ONE_KILOBYTE
);
200 N8_PRINT( "n8_memory: Memory Granularity for this bank - %ld \n",
201 memCtl_p
->granularity
);
202 N8_PRINT( "n8_memory: Current Allocation - %d / %d blocks %d %%\n",
203 n8_atomic_read(memCtl_p
->curAllocated
), memCtl_p
->maxEntries
,
204 ((n8_atomic_read(memCtl_p
->curAllocated
) * 100)/ memCtl_p
->maxEntries
));
205 N8_PRINT( "n8_memory: Maximum Allocation - %d / %d blocks %d %%\n",
206 memCtl_p
->maxAllocated
, memCtl_p
->maxEntries
,
207 ((memCtl_p
->maxAllocated
* 100)/ memCtl_p
->maxEntries
));
208 N8_PRINT( "n8_memory: Failed Allocations - %d, Next Index - %d\n",
209 memCtl_p
->failedAllocs
, memCtl_p
->nextIndex
);
211 N8_PRINT( "n8_memory: <******* PHYSICAL ALLOCATION MAP START at %lx *******>\n",
212 memCtl_p
->memBaseAddress
);
213 memCtlList_p
= (MemCtlList_t
*)
214 N8_PhysToVirt(memCtl_p
->memBaseAddress
+ sizeof(MemBankCtl_t
));
216 while (idx
< memCtl_p
->maxEntries
)
218 if (memCtlList_p
[idx
].numBlocks
)
220 N8_PRINT( "n8_memory: #%04d-Addr=%08lx SessID=%08d Num Blocks=%d \n",
222 (int)memCtl_p
->memBankPtr
+ (idx
* memCtl_p
->granularity
),
223 memCtlList_p
[idx
].sessionID
,
224 memCtlList_p
[idx
].numBlocks
);
225 idx
+= memCtlList_p
[idx
].numBlocks
;
232 N8_PRINT( "n8_memory: <********* PHYSICAL ALLOCATION MAP END ***********>\n");
236 /*****************************************************************************
238 *****************************************************************************/
239 /** @ingroup NSP2000Driver
240 * @brief Calculate the number of blocks of a given granularity that can
241 * be carved out of a contiguous memory area of a given size, given
242 * the need for the management structure to be part of the memory area.
244 * Time to revisit Algebra I!
246 * The diagram below shows the layout of the
247 * allocated space. First we have the space for the MemBankCtl_t
248 * structure. This is the constant M. Next we have the
249 * space for the memory control list for the area. The size of this
250 * area = sizeof(MemCtlList_t) (N) * the number of data blocks that can
251 * fit in the remainder of the buffer (C). This depends on the total size
252 * of the buffer. The remainder of the used space in the buffer (D) is
253 * composed of C data blocks each of size granularity (G). Of course, we
254 * have between 0 and G - 1 bytes wasted at the end of the buffer.
256 * ////////////////////////////////////////////////////////////////
258 * /<--- M -------->/<--- N * C ------->/<------- D ------------->/
259 * / (MemBankCtl_t) / (MemCtlList_t * /<----- C * G ----------->/
260 * / / Count of blocks) / (Data = C * Granularity)/
262 * ////////////////////////////////////////////////////////////////
264 * |<----- S (Total size of buffer) ----->|
266 * This gives us the following equations:
268 * 1) S = M + (N * C) + D
271 * Substiting D/G for C in 1 gives
273 * 3) S = M + (N * (D/G) + D
275 * By combining terms and subtraction we have
277 * 4) S - M = (N * D)/ G + D
279 * Multiplying both sides by G yields
281 * 5) G * (S - M) = (N * D) + (G * D) = (N + G) * D
283 * Now divide both sides by (N + G) to get
285 * 6) (G * (S - M))/(N + G) = D
287 * What we actually want is C. Since C = D/G, we can divide both sides by
290 * 7) (S - M)/(N + G) = C
292 * Since G, S, M and N are all constant we can now get the number of data
295 * @param memCtl_p RW: The memory bank in question. The result of this
296 * function is stored in the maxEntries field.
297 * @param size RO: The size of the memory bank.
300 * Debug_g RO: Switch to enable/disable debug messages. <BR>
303 * NULL pointer if process failed
306 * We will set the maxEntries field to 0 if size is NULL.
307 *****************************************************************************/
308 void n8_calculateSize(MemBankCtl_t
*memCtl_p
, unsigned long size
)
310 unsigned int dividend
; /* dividend of equation 7 */
311 unsigned int divisor
; /* divisor of equation 7 */
313 /* Do some minimal error checking */
314 if (memCtl_p
== NULL
)
319 else if (size
<= sizeof(MemBankCtl_t
))
321 memCtl_p
->maxEntries
= 0;
326 dividend
= size
- sizeof(MemBankCtl_t
);
327 divisor
= sizeof(MemCtlList_t
) + memCtl_p
->granularity
;
329 /* Integer divide is good, since we want complete blocks */
330 memCtl_p
->maxEntries
= dividend
/ divisor
;
332 /*****************************************************************************
333 * n8_setupAllocatedMemory
334 *****************************************************************************/
335 /** @ingroup NSP2000Driver
336 * @brief API - n8_memory initialization after the large allocation.
338 * This routine should be called after a large memory block such as a
339 * bank or a pool is allocated. The routine sets up the memBankCtl structure
340 * and initializes the allocation map. It does not do the initilization of the
341 * lock, which can be done before or after this routine is called.
343 * @param memCtl_p RW: Virtual pointer to the memBankCtl_t to initialize.
344 * @param size RO: The size of the allocated block.
347 * Debug_g RO: Switch to enable/disable debug messages. <BR>
350 * NULL pointer if process failed
351 * non-NULL void physical pointer to the base of the big allocation
354 * See return section for error information.
357 * We assume that the granularity field of the MemBankCtl_t structure is set
358 * before this routine is called and that memCtl_p is a virtual pointer
359 *****************************************************************************/
360 void n8_setupAllocatedMemory(MemBankCtl_t
*memCtl_p
, unsigned long size
)
364 /* Save the total size of the allocated block */
365 memCtl_p
->allocSize
= size
;
367 /* Calculate the maximum number of entries */
368 n8_calculateSize(memCtl_p
, size
);
370 /* INITIALIZE ALLOCATION LIST AND MARK BANK BOUNDARIES */
371 memCtl_p
->nextIndex
= 0;
372 n8_atomic_set(memCtl_p
->curAllocated
, 0);
373 memCtl_p
->maxAllocated
= 0;
374 memCtl_p
->failedAllocs
= 0;
376 /* Set the mem bank ptr to the address after the bank control structure
377 and the allocation map rounded up to next granularity. */
378 memCtl_p
->memBankPtr
= (char *)(memCtl_p
->memBaseAddress
+
379 (((size
/memCtl_p
->granularity
) - memCtl_p
->maxEntries
) *memCtl_p
->granularity
));
381 /* Clear the allocation map */
382 ctlListSize
= sizeof(MemCtlList_t
) * memCtl_p
->maxEntries
;
383 memset(&memCtl_p
->memCtlList
, 0, ctlListSize
);
388 /*****************************************************************************
390 *****************************************************************************/
391 /** @ingroup NSP2000Driver
392 * @brief API - n8_memory initialization and large allocation.
394 * This routine should be called when a driver is loaded and initialized,
395 * before making any other n8_memory calls. It first performs some OS-specific
396 * tasks to allocate the requested large memory size, from physically
397 * contiguous memory. If it fails, we immediately free everything and return
398 * a NULL pointer. If successful, we return a pointer to the base of the
399 * entire big allocation. which the caller may use or discard as it sees fit -
400 * it is not needed again.
402 * @param bank RO: Index which specifies the enumerated bank type
403 * @param size RO: Specifies the desired allocation size per bank
404 * @param granularity RO: The size of the smallest allocation.
407 * memBankCtl_gp RW: Global pointers to memory control structures<BR>
410 * NULL pointer if process failed
411 * non-NULL void physical pointer to the base of the allocation
414 * See return section for error information.
415 *****************************************************************************/
417 void *n8_memoryInit(N8_MemoryType_t bank
,
419 unsigned long granularity
)
421 MemBankCtl_t tmpBankCtl
;
422 MemBankCtl_t
*memBankCtl_p
= memBankCtl_gp
[bank
];
424 if (bank
>= N8_MEMBANK_MAX
+DEF_USER_POOL_BANKS
)
429 if (memBankCtl_p
!= NULL
)
433 N8_PRINT(KERN_CRIT
"n8_memoryInit: Initialize already complete exiting...\n");
435 return (void *)((memBankCtl_p
)->memBaseAddress
);
440 N8_PRINT(KERN_CRIT
"n8_memoryInit: size = %ld.\n", size
);
443 /* We are using the temporary bank pointer because on at least one
444 OS we support (linux) we need some of the space in the memBankCtl
445 to complete the large allocation. Because we want to end up with
446 the memBankCtl in the allocated space, we use a temporary that
447 is allocated automatically, then copy the temp structure into the
448 allocated space after the large allocation is complete. */
450 /* Insure everything starts nice and clean */
451 memset(&tmpBankCtl
, 0x0, sizeof(tmpBankCtl
));
453 /* Set the desired granularity and bank */
454 tmpBankCtl
.granularity
= granularity
;
455 tmpBankCtl
.bankIndex
= bank
;
457 /* Perform OS-specific large allocation */
458 tmpBankCtl
.memBaseAddress
= n8_GetLargeAllocation(bank
, size
, DebugFlag_g
);
459 if (!tmpBankCtl
.memBaseAddress
)
461 N8_PRINT(KERN_WARNING
"NSP2000: n8_memoryInit: Failed to allocate %ld bytes, bank %d .\n", size
, bank
);
462 N8_PRINT(KERN_WARNING
"NSP2000: Driver NOT loaded. \n");
463 N8_PRINT(KERN_WARNING
"NSP2000: Reserve space with bigphysarea patch \n");
464 N8_PRINT(KERN_WARNING
"NSP2000: or decrease EA or PK Pool request.\n");
468 /* Set the memBankCtl pointer to the virtual address of the beginning
470 memBankCtl_p
= (MemBankCtl_t
*) N8_PhysToVirt(tmpBankCtl
.memBaseAddress
);
472 /* Copy the tmp structure to inside the allocated block */
473 memcpy(memBankCtl_p
, &tmpBankCtl
, sizeof(MemBankCtl_t
));
475 /* Set up the atomic lock */
476 N8_initProcessSem(&(memBankCtl_p
->allocationMapLock
));
478 /* Setup the memBankCtl_p and the allocation map */
479 n8_setupAllocatedMemory(memBankCtl_p
, size
);
481 memBankCtl_gp
[bank
] = memBankCtl_p
;
485 N8_PRINT(KERN_CRIT
"n8_memoryInit: returning %lx.\n", memBankCtl_p
->memBaseAddress
);
488 /* Return the physical (non-zero) address */
489 return (void *)((memBankCtl_p
)->memBaseAddress
);
494 /*****************************************************************************
496 *****************************************************************************/
497 /** @ingroup NSP2000Driver
498 * @brief API - Memory deactivation and release.
500 * This routine deallocates and releases the large space allocated with
503 * @param bank RO: Index which specifies the enumerated bank type
506 * memBankCtl_gp RO: Global pointers to memory control structures<BR>
512 * See return section for error information.
513 *****************************************************************************/
515 void n8_memoryRelease(N8_MemoryType_t bank
)
517 MemBankCtl_t
*memCtl_p
= memBankCtl_gp
[bank
];
521 N8_PRINT(KERN_CRIT
"n8_memoryRelease: bank = %d, memCtl_p %p.\n", bank
, memCtl_p
);
524 /* Check for null in case this is called because the second memory
525 segment was not created. */
526 if (memCtl_p
== NULL
)
531 N8_acquireProcessSem(&memCtl_p
->allocationMapLock
);
533 memBankCtl_gp
[bank
] = NULL
;
535 N8_releaseProcessSem(&memCtl_p
->allocationMapLock
);
537 memCtl_p
->memBaseAddress
= 0;
539 N8_deleteProcessSem(&memCtl_p
->allocationMapLock
);
541 n8_FreeLargeAllocation(bank
, DebugFlag_g
);
545 /*****************************************************************************
547 *****************************************************************************/
548 /** @ingroup NSP2000Driver
549 * @brief API - Releases a all allocations of a given session ID.
552 * @param bank RO: Index which specifies the enumerated bank type
553 * @param sessionID R0: Session ID of the exiting process.
556 * memBankCtl_gp RO: Global pointers to memory control structures<BR>
557 * Debug_g RO: Global flag that indicates whether debugging<BR>
558 * messages are enabled. <BR>
564 * See return section for error information.
565 *****************************************************************************/
567 void n8_pfreeSessID(N8_MemoryType_t bank
, unsigned long sessionID
)
570 MemCtlList_t
*memCtlList_p
;
573 N8_MemoryHandle_t
*kmem_p
;
574 MemBankCtl_t
*memCtl_p
= memBankCtl_gp
[bank
];
576 if (memCtl_p
== NULL
)
582 N8_PRINT(KERN_CRIT
"n8_pfreeSessID: sessionID %ld, for bank %d\n",
586 /* Retrieve the memCltList_p in the bank structure. */
587 memCtlList_p
= &memCtl_p
->memCtlList
[0];
590 while (index
< memCtl_p
->maxEntries
)
592 /* If this entry been allocated, see if it matches our session ID */
593 if (memCtlList_p
[index
].numBlocks
)
596 numBlocks
= memCtlList_p
[index
].numBlocks
;
598 /* Determine whether this entry matches the sessionID passed int */
599 if (memCtlList_p
[index
].sessionID
== sessionID
)
602 ptr
= index
* memCtl_p
->granularity
+ memCtl_p
->memBankPtr
;
604 /* If we have a match on the session ID, convert the pointer to */
605 /* a virtual address to determine whether it is currently in use */
606 /* by one of the command queues. */
607 kmem_p
= (N8_MemoryHandle_t
*)N8_PhysToVirt((int)ptr
);
609 if (kmem_p
->bufferState
!= N8_BUFFER_QUEUED
)
612 /* The Buffer is not on a command queue, free it. */
615 N8_PRINT("Kernel mem leak on exit %d bytes at %lx\n",
616 memCtlList_p
[index
].reqSize
, (unsigned long) ptr
);
619 n8_pfree(memCtl_p
->bankIndex
, ptr
);
623 /* Mark the buffer so QMgr frees it
624 when the command has completed */
627 N8_PRINT(KERN_CRIT
"Kernel mem leak on exit"
628 "skipped queued buffer %d bytes at %lx\n",
629 memCtlList_p
[index
].reqSize
, (unsigned long) ptr
);
631 kmem_p
->bufferState
= N8_BUFFER_SESS_DELETED
;
648 /*****************************************************************************
650 *****************************************************************************/
651 /** @ingroup NSP2000_Driver_API
652 * @brief Allocates a buffer and maps it between user and kernel space.
654 * This routine first requests that the driver allocate a physically
655 * contiguous memory space of a specified size. With the returned physical
656 * base address, it then maps it to user-space.
658 * The N8_MemoryHandle_t should be treated as read-only upon return from this
659 * call, for subsequent calls to N8_TestBuffer and N8_FreeBuffer.
661 * @param size RO: Amount of memory to allocate.
664 * MemBankCtl_p RW: Bank control structure to allocate from.
667 * Address of the new memory handle or NULL if the allocation could not be
670 * See return section for error information.
671 *****************************************************************************/
673 N8_MemoryHandle_t
*N8_AllocateBuffer(const unsigned int size
)
677 N8_MemoryHandle_t
*buffPtr
;
678 unsigned long physaddr
;
679 unsigned long sessionID
= N8_GET_KERNEL_ID
;
681 /* Do not attempt allocations of zero size */
688 /* Allocate a buffer from the physically contigious pool */
689 if ((physaddr
= n8_pmalloc(N8_MEMBANK_EA
,size
+ N8_BUFFER_HEADER_SIZE
, sessionID
)) == 0)
694 /* Set up a N8_MemoryHandle in the head of the buffer */
695 buffPtr
= (N8_MemoryHandle_t
*)N8_PhysToVirt(physaddr
);
697 /* Ensure the buffer is cleared */
698 /* memset(buffPtr, 0x0, size + N8_BUFFER_HEADER_SIZE); */
699 buffPtr
->Size
= size
;
700 buffPtr
->PhysicalAddress
= physaddr
+ N8_BUFFER_HEADER_SIZE
;
701 buffPtr
->VirtualAddress
= (unsigned long *)((int)buffPtr
+ N8_BUFFER_HEADER_SIZE
);
702 buffPtr
->bankPhysAddress
= memBankCtl_gp
[N8_MEMBANK_EA
]->memBaseAddress
;
703 buffPtr
->bankAddress
= (unsigned long) memBankCtl_gp
[N8_MEMBANK_EA
];
704 buffPtr
->bankIndex
= N8_MEMBANK_EA
;
710 N8_MemoryHandle_t
*N8_AllocateBufferPK(const unsigned int size
)
714 N8_MemoryHandle_t
*buffPtr
;
715 unsigned long physaddr
;
716 unsigned long sessionID
= N8_GET_KERNEL_ID
;
718 /* Do not attempt allocations of zero size */
725 /* Allocate a buffer from the physically contigious pool */
726 if ((physaddr
= n8_pmalloc(N8_MEMBANK_PK
,size
+ N8_BUFFER_HEADER_SIZE
, sessionID
)) == 0)
731 /* Set up a N8_MemoryHandle in the head of the buffer */
733 (N8_MemoryHandle_t
*)N8_PhysToVirt(physaddr
);
735 /* Ensure the buffer is cleared */
736 /* memset(buffPtr, 0x0, size + N8_BUFFER_HEADER_SIZE); */
737 buffPtr
->Size
= size
;
738 buffPtr
->PhysicalAddress
= physaddr
+ N8_BUFFER_HEADER_SIZE
;
739 buffPtr
->VirtualAddress
= (unsigned long *)((int)buffPtr
+ N8_BUFFER_HEADER_SIZE
);
740 buffPtr
->bankPhysAddress
= memBankCtl_gp
[N8_MEMBANK_PK
]->memBaseAddress
;
741 buffPtr
->bankAddress
= (unsigned long) memBankCtl_gp
[N8_MEMBANK_PK
];
742 buffPtr
->bankIndex
= N8_MEMBANK_PK
;
750 /*****************************************************************************
752 *****************************************************************************/
753 /** @ingroup NSP2000_Driver_API
754 * @brief Releases and unmaps buffers allocated with N8_AllocateBuffer.
756 * This routine follows two steps. It first unmaps the specified buffer from
757 * user-space. It then requests that the driver free the buffer. Because
758 * unique keys are used to identify buffers, only if a corresponding buffer is
759 * located, is anything freed. If not found, nothing happens.
761 * @param MemoryStruct RO: Pointer to a struct that associates the necessary
762 * parameters that completely identify an allocated
772 * See return section for error information.
774 * NOTE: THIS FUNCTION MAY BE CALLED FROM INTERRUPT CONTEXT and cannot take
775 * semaphores or print. It also assumes it will only be called to free
776 * buffers allocted from the kernel buffer allocation pool.
777 *****************************************************************************/
779 void N8_FreeBuffer(N8_MemoryHandle_t
*MemoryStruct_p
)
782 /* DIRECT DRIVER TO DEALLOCATE THE BUSMASTERED BUFFER */
783 n8_pfree(MemoryStruct_p
->bankIndex
,
784 (void *)(MemoryStruct_p
->PhysicalAddress
- N8_BUFFER_HEADER_SIZE
));
787 N8_Status_t
N8_QueryMemStatistics(MemStats_t
*memStatsPtr
)
790 MemBankCtl_t
*memCtl_p
;
792 for (bankIndex
= 0; bankIndex
<= N8_MEMBANK_PK
; bankIndex
++)
795 memCtl_p
= memBankCtl_gp
[bankIndex
];
797 /* Retrieve stats for the base kernel buffer pool */
798 memStatsPtr
->curAllocated
= n8_atomic_read(memCtl_p
->curAllocated
);
799 memStatsPtr
->maxAllocated
= memCtl_p
->maxAllocated
;
800 memStatsPtr
->maxEntries
= memCtl_p
->maxEntries
;
801 memStatsPtr
->failedAllocs
= memCtl_p
->failedAllocs
;
805 return (N8_STATUS_OK
);