1296177Sjhibbits/******************************************************************************
2296177Sjhibbits
3296177Sjhibbits � 1995-2003, 2004, 2005-2011 Freescale Semiconductor, Inc.
4296177Sjhibbits All rights reserved.
5296177Sjhibbits
6296177Sjhibbits This is proprietary source code of Freescale Semiconductor Inc.,
7296177Sjhibbits and its use is subject to the NetComm Device Drivers EULA.
8296177Sjhibbits The copyright notice above does not evidence any actual or intended
9296177Sjhibbits publication of such source code.
10296177Sjhibbits
11296177Sjhibbits ALTERNATIVELY, redistribution and use in source and binary forms, with
12296177Sjhibbits or without modification, are permitted provided that the following
13296177Sjhibbits conditions are met:
14296177Sjhibbits     * Redistributions of source code must retain the above copyright
15296177Sjhibbits       notice, this list of conditions and the following disclaimer.
16296177Sjhibbits     * Redistributions in binary form must reproduce the above copyright
17296177Sjhibbits       notice, this list of conditions and the following disclaimer in the
18296177Sjhibbits       documentation and/or other materials provided with the distribution.
19296177Sjhibbits     * Neither the name of Freescale Semiconductor nor the
20296177Sjhibbits       names of its contributors may be used to endorse or promote products
21296177Sjhibbits       derived from this software without specific prior written permission.
22296177Sjhibbits
23296177Sjhibbits THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
24296177Sjhibbits EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25296177Sjhibbits WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26296177Sjhibbits DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
27296177Sjhibbits DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28296177Sjhibbits (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29296177Sjhibbits LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
30296177Sjhibbits ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31296177Sjhibbits (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32296177Sjhibbits SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33296177Sjhibbits *
34296177Sjhibbits
35296177Sjhibbits **************************************************************************/
36296177Sjhibbits#include "error_ext.h"
37296177Sjhibbits#include "part_ext.h"
38296177Sjhibbits#include "std_ext.h"
39296177Sjhibbits#include "string_ext.h"
40296177Sjhibbits#include "mem_ext.h"
41296177Sjhibbits#include "mem.h"
42296177Sjhibbits#include "xx_ext.h"
43296177Sjhibbits
44296177Sjhibbits
45296177Sjhibbits#define PAD_ALIGNMENT(align, x) (((x)%(align)) ? ((align)-((x)%(align))) : 0)
46296177Sjhibbits
47296177Sjhibbits#define ALIGN_BLOCK(p_Block, prefixSize, alignment)                 \
48296177Sjhibbits    do {                                                            \
49296177Sjhibbits        p_Block += (prefixSize);                                    \
50296177Sjhibbits        p_Block += PAD_ALIGNMENT((alignment), (uintptr_t)(p_Block)); \
51296177Sjhibbits    } while (0)
52296177Sjhibbits
53296177Sjhibbits#if defined(__GNUC__)
54296177Sjhibbits#define GET_CALLER_ADDR \
55296177Sjhibbits    __asm__ ("mflr  %0" : "=r" (callerAddr))
56296177Sjhibbits#elif defined(__MWERKS__)
57296177Sjhibbits/* NOTE: This implementation is only valid for CodeWarrior for PowerPC */
58296177Sjhibbits#define GET_CALLER_ADDR \
59296177Sjhibbits    __asm__("add  %0, 0, %0" : : "r" (callerAddr))
60296177Sjhibbits#endif /* defined(__GNUC__) */
61296177Sjhibbits
62296177Sjhibbits
63296177Sjhibbits/*****************************************************************************/
64296177Sjhibbitsstatic __inline__ void * MemGet(t_MemorySegment *p_Mem)
65296177Sjhibbits{
66296177Sjhibbits    uint8_t *p_Block;
67296177Sjhibbits
68296177Sjhibbits    /* check if there is an available block */
69296177Sjhibbits    if (p_Mem->current == p_Mem->num)
70296177Sjhibbits    {
71296177Sjhibbits        p_Mem->getFailures++;
72296177Sjhibbits        return NULL;
73296177Sjhibbits    }
74296177Sjhibbits
75296177Sjhibbits    /* get the block */
76296177Sjhibbits    p_Block = p_Mem->p_BlocksStack[p_Mem->current];
77296177Sjhibbits#ifdef DEBUG
78296177Sjhibbits    p_Mem->p_BlocksStack[p_Mem->current] = NULL;
79296177Sjhibbits#endif /* DEBUG */
80296177Sjhibbits    /* advance current index */
81296177Sjhibbits    p_Mem->current++;
82296177Sjhibbits
83296177Sjhibbits    return (void *)p_Block;
84296177Sjhibbits}
85296177Sjhibbits
86296177Sjhibbits/*****************************************************************************/
87296177Sjhibbitsstatic __inline__ t_Error MemPut(t_MemorySegment *p_Mem, void *p_Block)
88296177Sjhibbits{
89296177Sjhibbits    /* check if blocks stack is full */
90296177Sjhibbits    if (p_Mem->current > 0)
91296177Sjhibbits    {
92296177Sjhibbits        /* decrease current index */
93296177Sjhibbits        p_Mem->current--;
94296177Sjhibbits        /* put the block */
95296177Sjhibbits        p_Mem->p_BlocksStack[p_Mem->current] = (uint8_t *)p_Block;
96296177Sjhibbits        return E_OK;
97296177Sjhibbits    }
98296177Sjhibbits
99296177Sjhibbits    RETURN_ERROR(MAJOR, E_FULL, NO_MSG);
100296177Sjhibbits}
101296177Sjhibbits
102296177Sjhibbits
103296177Sjhibbits#ifdef DEBUG_MEM_LEAKS
104296177Sjhibbits
105296177Sjhibbits/*****************************************************************************/
106296177Sjhibbitsstatic t_Error InitMemDebugDatabase(t_MemorySegment *p_Mem)
107296177Sjhibbits{
108296177Sjhibbits    p_Mem->p_MemDbg = (void *)XX_Malloc(sizeof(t_MemDbg) * p_Mem->num);
109296177Sjhibbits    if (!p_Mem->p_MemDbg)
110296177Sjhibbits    {
111296177Sjhibbits        RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Memory debug object"));
112296177Sjhibbits    }
113296177Sjhibbits
114296177Sjhibbits    memset(p_Mem->p_MemDbg, ILLEGAL_BASE, sizeof(t_MemDbg) * p_Mem->num);
115296177Sjhibbits
116296177Sjhibbits    return E_OK;
117296177Sjhibbits}
118296177Sjhibbits
119296177Sjhibbits
120296177Sjhibbits/*****************************************************************************/
121296177Sjhibbitsstatic t_Error DebugMemGet(t_Handle h_Mem, void *p_Block, uintptr_t ownerAddress)
122296177Sjhibbits{
123296177Sjhibbits    t_MemorySegment *p_Mem = (t_MemorySegment *)h_Mem;
124296177Sjhibbits    t_MemDbg        *p_MemDbg = (t_MemDbg *)p_Mem->p_MemDbg;
125296177Sjhibbits    uint32_t        blockIndex;
126296177Sjhibbits
127296177Sjhibbits    ASSERT_COND(ownerAddress != ILLEGAL_BASE);
128296177Sjhibbits
129296177Sjhibbits    /* Find block num */
130296177Sjhibbits    if (p_Mem->consecutiveMem)
131296177Sjhibbits    {
132296177Sjhibbits        blockIndex =
133296177Sjhibbits            (((uint8_t *)p_Block - (p_Mem->p_Bases[0] + p_Mem->blockOffset)) / p_Mem->blockSize);
134296177Sjhibbits    }
135296177Sjhibbits    else
136296177Sjhibbits    {
137296177Sjhibbits        blockIndex = *(uint32_t *)((uint8_t *)p_Block - 4);
138296177Sjhibbits    }
139296177Sjhibbits
140296177Sjhibbits    ASSERT_COND(blockIndex < p_Mem->num);
141296177Sjhibbits    ASSERT_COND(p_MemDbg[blockIndex].ownerAddress == ILLEGAL_BASE);
142296177Sjhibbits
143296177Sjhibbits    p_MemDbg[blockIndex].ownerAddress = ownerAddress;
144296177Sjhibbits
145296177Sjhibbits    return E_OK;
146296177Sjhibbits}
147296177Sjhibbits
148296177Sjhibbits/*****************************************************************************/
149296177Sjhibbitsstatic t_Error DebugMemPut(t_Handle h_Mem, void *p_Block)
150296177Sjhibbits{
151296177Sjhibbits    t_MemorySegment *p_Mem = (t_MemorySegment *)h_Mem;
152296177Sjhibbits    t_MemDbg        *p_MemDbg = (t_MemDbg *)p_Mem->p_MemDbg;
153296177Sjhibbits    uint32_t        blockIndex;
154296177Sjhibbits    uint8_t         *p_Temp;
155296177Sjhibbits
156296177Sjhibbits    /* Find block num */
157296177Sjhibbits    if (p_Mem->consecutiveMem)
158296177Sjhibbits    {
159296177Sjhibbits        blockIndex =
160296177Sjhibbits            (((uint8_t *)p_Block - (p_Mem->p_Bases[0] + p_Mem->blockOffset)) / p_Mem->blockSize);
161296177Sjhibbits
162296177Sjhibbits        if (blockIndex >= p_Mem->num)
163296177Sjhibbits        {
164296177Sjhibbits            RETURN_ERROR(MAJOR, E_INVALID_ADDRESS,
165296177Sjhibbits                         ("Freed address (0x%08x) does not belong to this pool", p_Block));
166296177Sjhibbits        }
167296177Sjhibbits    }
168296177Sjhibbits    else
169296177Sjhibbits    {
170296177Sjhibbits        blockIndex = *(uint32_t *)((uint8_t *)p_Block - 4);
171296177Sjhibbits
172296177Sjhibbits        if (blockIndex >= p_Mem->num)
173296177Sjhibbits        {
174296177Sjhibbits            RETURN_ERROR(MAJOR, E_INVALID_ADDRESS,
175296177Sjhibbits                         ("Freed address (0x%08x) does not belong to this pool", p_Block));
176296177Sjhibbits        }
177296177Sjhibbits
178296177Sjhibbits        /* Verify that the block matches the corresponding base */
179296177Sjhibbits        p_Temp = p_Mem->p_Bases[blockIndex];
180296177Sjhibbits
181296177Sjhibbits        ALIGN_BLOCK(p_Temp, p_Mem->prefixSize, p_Mem->alignment);
182296177Sjhibbits
183296177Sjhibbits        if (p_Temp == p_Mem->p_Bases[blockIndex])
184296177Sjhibbits            p_Temp += p_Mem->alignment;
185296177Sjhibbits
186296177Sjhibbits        if (p_Temp != p_Block)
187296177Sjhibbits        {
188296177Sjhibbits            RETURN_ERROR(MAJOR, E_INVALID_ADDRESS,
189296177Sjhibbits                         ("Freed address (0x%08x) does not belong to this pool", p_Block));
190296177Sjhibbits        }
191296177Sjhibbits    }
192296177Sjhibbits
193296177Sjhibbits    if (p_MemDbg[blockIndex].ownerAddress == ILLEGAL_BASE)
194296177Sjhibbits    {
195296177Sjhibbits        RETURN_ERROR(MAJOR, E_ALREADY_FREE,
196296177Sjhibbits                     ("Attempt to free unallocated address (0x%08x)", p_Block));
197296177Sjhibbits    }
198296177Sjhibbits
199296177Sjhibbits    p_MemDbg[blockIndex].ownerAddress = (uintptr_t)ILLEGAL_BASE;
200296177Sjhibbits
201296177Sjhibbits    return E_OK;
202296177Sjhibbits}
203296177Sjhibbits
204296177Sjhibbits#endif /* DEBUG_MEM_LEAKS */
205296177Sjhibbits
206296177Sjhibbits
207296177Sjhibbits/*****************************************************************************/
208296177Sjhibbitsuint32_t MEM_ComputePartitionSize(uint32_t num,
209296177Sjhibbits                                  uint16_t dataSize,
210296177Sjhibbits                                  uint16_t prefixSize,
211296177Sjhibbits                                  uint16_t postfixSize,
212296177Sjhibbits                                  uint16_t alignment)
213296177Sjhibbits{
214296177Sjhibbits    uint32_t  blockSize = 0, pad1 = 0, pad2 = 0;
215296177Sjhibbits
216296177Sjhibbits    /* Make sure that the alignment is at least 4 */
217296177Sjhibbits    if (alignment < 4)
218296177Sjhibbits    {
219296177Sjhibbits        alignment = 4;
220296177Sjhibbits    }
221296177Sjhibbits
222296177Sjhibbits    pad1 = (uint32_t)PAD_ALIGNMENT(4, prefixSize);
223296177Sjhibbits    /* Block size not including 2nd padding */
224296177Sjhibbits    blockSize = pad1 + prefixSize + dataSize + postfixSize;
225296177Sjhibbits    pad2 = PAD_ALIGNMENT(alignment, blockSize);
226296177Sjhibbits    /* Block size including 2nd padding */
227296177Sjhibbits    blockSize += pad2;
228296177Sjhibbits
229296177Sjhibbits    return ((num * blockSize) + alignment);
230296177Sjhibbits}
231296177Sjhibbits
232296177Sjhibbits/*****************************************************************************/
233296177Sjhibbitst_Error MEM_Init(char       name[],
234296177Sjhibbits                 t_Handle   *p_Handle,
235296177Sjhibbits                 uint32_t   num,
236296177Sjhibbits                 uint16_t   dataSize,
237296177Sjhibbits                 uint16_t   prefixSize,
238296177Sjhibbits                 uint16_t   postfixSize,
239296177Sjhibbits                 uint16_t   alignment)
240296177Sjhibbits{
241296177Sjhibbits    uint8_t     *p_Memory;
242296177Sjhibbits    uint32_t    allocSize;
243296177Sjhibbits    t_Error     errCode;
244296177Sjhibbits
245296177Sjhibbits    allocSize = MEM_ComputePartitionSize(num,
246296177Sjhibbits                                         dataSize,
247296177Sjhibbits                                         prefixSize,
248296177Sjhibbits                                         postfixSize,
249296177Sjhibbits                                         alignment);
250296177Sjhibbits
251296177Sjhibbits    p_Memory = (uint8_t *)XX_Malloc(allocSize);
252296177Sjhibbits    if (!p_Memory)
253296177Sjhibbits    {
254296177Sjhibbits        RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Memory segment"));
255296177Sjhibbits    }
256296177Sjhibbits
257296177Sjhibbits    errCode = MEM_InitByAddress(name,
258296177Sjhibbits                                p_Handle,
259296177Sjhibbits                                num,
260296177Sjhibbits                                dataSize,
261296177Sjhibbits                                prefixSize,
262296177Sjhibbits                                postfixSize,
263296177Sjhibbits                                alignment,
264296177Sjhibbits                                p_Memory);
265296177Sjhibbits    if (errCode != E_OK)
266296177Sjhibbits    {
267296177Sjhibbits        RETURN_ERROR(MAJOR, errCode, NO_MSG);
268296177Sjhibbits    }
269296177Sjhibbits
270296177Sjhibbits    ((t_MemorySegment *)(*p_Handle))->allocOwner = e_MEM_ALLOC_OWNER_LOCAL;
271296177Sjhibbits
272296177Sjhibbits    return E_OK;
273296177Sjhibbits}
274296177Sjhibbits
275296177Sjhibbits
276296177Sjhibbits/*****************************************************************************/
277296177Sjhibbitst_Error MEM_InitByAddress(char      name[],
278296177Sjhibbits                          t_Handle  *p_Handle,
279296177Sjhibbits                          uint32_t  num,
280296177Sjhibbits                          uint16_t  dataSize,
281296177Sjhibbits                          uint16_t  prefixSize,
282296177Sjhibbits                          uint16_t  postfixSize,
283296177Sjhibbits                          uint16_t  alignment,
284296177Sjhibbits                          uint8_t   *p_Memory)
285296177Sjhibbits{
286296177Sjhibbits    t_MemorySegment *p_Mem;
287296177Sjhibbits    uint32_t        i, blockSize;
288296177Sjhibbits    uint16_t        alignPad, endPad;
289296177Sjhibbits    uint8_t         *p_Blocks;
290296177Sjhibbits
291296177Sjhibbits     /* prepare in case of error */
292296177Sjhibbits    *p_Handle = NULL;
293296177Sjhibbits
294296177Sjhibbits    if (!p_Memory)
295296177Sjhibbits    {
296296177Sjhibbits        RETURN_ERROR(MAJOR, E_NULL_POINTER, ("Memory blocks"));
297296177Sjhibbits    }
298296177Sjhibbits
299296177Sjhibbits    p_Blocks = p_Memory;
300296177Sjhibbits
301296177Sjhibbits    /* make sure that the alignment is at least 4 and power of 2 */
302296177Sjhibbits    if (alignment < 4)
303296177Sjhibbits    {
304296177Sjhibbits        alignment = 4;
305296177Sjhibbits    }
306296177Sjhibbits    else if (!POWER_OF_2(alignment))
307296177Sjhibbits    {
308296177Sjhibbits        RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Alignment (should be power of 2)"));
309296177Sjhibbits    }
310296177Sjhibbits
311296177Sjhibbits    /* first allocate the segment descriptor */
312296177Sjhibbits    p_Mem = (t_MemorySegment *)XX_Malloc(sizeof(t_MemorySegment));
313296177Sjhibbits    if (!p_Mem)
314296177Sjhibbits    {
315296177Sjhibbits        RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Memory segment structure"));
316296177Sjhibbits    }
317296177Sjhibbits
318296177Sjhibbits    /* allocate the blocks stack */
319296177Sjhibbits    p_Mem->p_BlocksStack = (uint8_t **)XX_Malloc(num * sizeof(uint8_t*));
320296177Sjhibbits    if (!p_Mem->p_BlocksStack)
321296177Sjhibbits    {
322296177Sjhibbits        XX_Free(p_Mem);
323296177Sjhibbits        RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Memory segment block pointers stack"));
324296177Sjhibbits    }
325296177Sjhibbits
326296177Sjhibbits    /* allocate the blocks bases array */
327296177Sjhibbits    p_Mem->p_Bases = (uint8_t **)XX_Malloc(sizeof(uint8_t*));
328296177Sjhibbits    if (!p_Mem->p_Bases)
329296177Sjhibbits    {
330296177Sjhibbits        MEM_Free(p_Mem);
331296177Sjhibbits        RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Memory segment base pointers array"));
332296177Sjhibbits    }
333296177Sjhibbits    memset(p_Mem->p_Bases, 0, sizeof(uint8_t*));
334296177Sjhibbits
335296177Sjhibbits    /* store info about this segment */
336296177Sjhibbits    p_Mem->num = num;
337296177Sjhibbits    p_Mem->current = 0;
338296177Sjhibbits    p_Mem->dataSize = dataSize;
339296177Sjhibbits    p_Mem->p_Bases[0] = p_Blocks;
340296177Sjhibbits    p_Mem->getFailures = 0;
341296177Sjhibbits    p_Mem->allocOwner = e_MEM_ALLOC_OWNER_EXTERNAL;
342296177Sjhibbits    p_Mem->consecutiveMem = TRUE;
343296177Sjhibbits    p_Mem->prefixSize = prefixSize;
344296177Sjhibbits    p_Mem->postfixSize = postfixSize;
345296177Sjhibbits    p_Mem->alignment = alignment;
346296177Sjhibbits    /* store name */
347296177Sjhibbits    strncpy(p_Mem->name, name, MEM_MAX_NAME_LENGTH-1);
348296177Sjhibbits
349296177Sjhibbits    p_Mem->h_Spinlock = XX_InitSpinlock();
350296177Sjhibbits    if (!p_Mem->h_Spinlock)
351296177Sjhibbits    {
352296177Sjhibbits        MEM_Free(p_Mem);
353296177Sjhibbits        RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Can't create spinlock!"));
354296177Sjhibbits    }
355296177Sjhibbits
356296177Sjhibbits    alignPad = (uint16_t)PAD_ALIGNMENT(4, prefixSize);
357296177Sjhibbits    /* Make sure the entire size is a multiple of alignment */
358296177Sjhibbits    endPad = (uint16_t)PAD_ALIGNMENT(alignment, (alignPad + prefixSize + dataSize + postfixSize));
359296177Sjhibbits
360296177Sjhibbits    /* The following manipulation places the data of block[0] in an aligned address,
361296177Sjhibbits       since block size is aligned the following block datas will all be aligned */
362296177Sjhibbits    ALIGN_BLOCK(p_Blocks, prefixSize, alignment);
363296177Sjhibbits
364296177Sjhibbits    blockSize = (uint32_t)(alignPad + prefixSize + dataSize + postfixSize + endPad);
365296177Sjhibbits
366296177Sjhibbits    /* initialize the blocks */
367296177Sjhibbits    for (i=0; i < num; i++)
368296177Sjhibbits    {
369296177Sjhibbits        p_Mem->p_BlocksStack[i] = p_Blocks;
370296177Sjhibbits        p_Blocks += blockSize;
371296177Sjhibbits    }
372296177Sjhibbits
373296177Sjhibbits    /* return handle to caller */
374296177Sjhibbits    *p_Handle = (t_Handle)p_Mem;
375296177Sjhibbits
376296177Sjhibbits#ifdef DEBUG_MEM_LEAKS
377296177Sjhibbits    {
378296177Sjhibbits        t_Error errCode = InitMemDebugDatabase(p_Mem);
379296177Sjhibbits
380296177Sjhibbits        if (errCode != E_OK)
381296177Sjhibbits            RETURN_ERROR(MAJOR, errCode, NO_MSG);
382296177Sjhibbits
383296177Sjhibbits        p_Mem->blockOffset = (uint32_t)(p_Mem->p_BlocksStack[0] - p_Mem->p_Bases[0]);
384296177Sjhibbits        p_Mem->blockSize = blockSize;
385296177Sjhibbits    }
386296177Sjhibbits#endif /* DEBUG_MEM_LEAKS */
387296177Sjhibbits
388296177Sjhibbits    return E_OK;
389296177Sjhibbits}
390296177Sjhibbits
391296177Sjhibbits
392296177Sjhibbits/*****************************************************************************/
393296177Sjhibbitst_Error MEM_InitSmart(char      name[],
394296177Sjhibbits                      t_Handle  *p_Handle,
395296177Sjhibbits                      uint32_t  num,
396296177Sjhibbits                      uint16_t  dataSize,
397296177Sjhibbits                      uint16_t  prefixSize,
398296177Sjhibbits                      uint16_t  postfixSize,
399296177Sjhibbits                      uint16_t  alignment,
400296177Sjhibbits                      uint8_t   memPartitionId,
401296177Sjhibbits                      bool      consecutiveMem)
402296177Sjhibbits{
403296177Sjhibbits    t_MemorySegment *p_Mem;
404296177Sjhibbits    uint32_t        i, blockSize;
405296177Sjhibbits    uint16_t        alignPad, endPad;
406296177Sjhibbits
407296177Sjhibbits    /* prepare in case of error */
408296177Sjhibbits    *p_Handle = NULL;
409296177Sjhibbits
410296177Sjhibbits    /* make sure that size is always a multiple of 4 */
411296177Sjhibbits    if (dataSize & 3)
412296177Sjhibbits    {
413296177Sjhibbits        dataSize &= ~3;
414296177Sjhibbits        dataSize += 4;
415296177Sjhibbits    }
416296177Sjhibbits
417296177Sjhibbits    /* make sure that the alignment is at least 4 and power of 2 */
418296177Sjhibbits    if (alignment < 4)
419296177Sjhibbits    {
420296177Sjhibbits        alignment = 4;
421296177Sjhibbits    }
422296177Sjhibbits    else if (!POWER_OF_2(alignment))
423296177Sjhibbits    {
424296177Sjhibbits        RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Alignment (should be power of 2)"));
425296177Sjhibbits    }
426296177Sjhibbits
427296177Sjhibbits    /* first allocate the segment descriptor */
428296177Sjhibbits    p_Mem = (t_MemorySegment *)XX_Malloc(sizeof(t_MemorySegment));
429296177Sjhibbits    if (!p_Mem)
430296177Sjhibbits    {
431296177Sjhibbits        RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Memory segment structure"));
432296177Sjhibbits    }
433296177Sjhibbits
434296177Sjhibbits    /* allocate the blocks stack */
435296177Sjhibbits    p_Mem->p_BlocksStack = (uint8_t **)XX_Malloc(num * sizeof(uint8_t*));
436296177Sjhibbits    if (!p_Mem->p_BlocksStack)
437296177Sjhibbits    {
438296177Sjhibbits        MEM_Free(p_Mem);
439296177Sjhibbits        RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Memory segment block pointers stack"));
440296177Sjhibbits    }
441296177Sjhibbits
442296177Sjhibbits    /* allocate the blocks bases array */
443296177Sjhibbits    p_Mem->p_Bases = (uint8_t **)XX_Malloc((consecutiveMem ? 1 : num) * sizeof(uint8_t*));
444296177Sjhibbits    if (!p_Mem->p_Bases)
445296177Sjhibbits    {
446296177Sjhibbits        MEM_Free(p_Mem);
447296177Sjhibbits        RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Memory segment base pointers array"));
448296177Sjhibbits    }
449296177Sjhibbits    memset(p_Mem->p_Bases, 0, (consecutiveMem ? 1 : num) * sizeof(uint8_t*));
450296177Sjhibbits
451296177Sjhibbits    /* store info about this segment */
452296177Sjhibbits    p_Mem->num = num;
453296177Sjhibbits    p_Mem->current = 0;
454296177Sjhibbits    p_Mem->dataSize = dataSize;
455296177Sjhibbits    p_Mem->getFailures = 0;
456296177Sjhibbits    p_Mem->allocOwner = e_MEM_ALLOC_OWNER_LOCAL_SMART;
457296177Sjhibbits    p_Mem->consecutiveMem = consecutiveMem;
458296177Sjhibbits    p_Mem->prefixSize = prefixSize;
459296177Sjhibbits    p_Mem->postfixSize = postfixSize;
460296177Sjhibbits    p_Mem->alignment = alignment;
461296177Sjhibbits
462296177Sjhibbits    p_Mem->h_Spinlock = XX_InitSpinlock();
463296177Sjhibbits    if (!p_Mem->h_Spinlock)
464296177Sjhibbits    {
465296177Sjhibbits        MEM_Free(p_Mem);
466296177Sjhibbits        RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Can't create spinlock!"));
467296177Sjhibbits    }
468296177Sjhibbits
469296177Sjhibbits    alignPad = (uint16_t)PAD_ALIGNMENT(4, prefixSize);
470296177Sjhibbits    /* Make sure the entire size is a multiple of alignment */
471296177Sjhibbits    endPad = (uint16_t)PAD_ALIGNMENT(alignment, alignPad + prefixSize + dataSize + postfixSize);
472296177Sjhibbits
473296177Sjhibbits    /* Calculate blockSize */
474296177Sjhibbits    blockSize = (uint32_t)(alignPad + prefixSize + dataSize + postfixSize + endPad);
475296177Sjhibbits
476296177Sjhibbits    /* Now allocate the blocks */
477296177Sjhibbits    if (p_Mem->consecutiveMem)
478296177Sjhibbits    {
479296177Sjhibbits        /* |alignment - 1| bytes at most will be discarded in the beginning of the
480296177Sjhibbits           received segment for alignment reasons, therefore the allocation is of:
481296177Sjhibbits           (alignment + (num * block size)). */
482296177Sjhibbits        uint8_t *p_Blocks = (uint8_t *)
483296177Sjhibbits            XX_MallocSmart((uint32_t)((num * blockSize) + alignment), memPartitionId, 1);
484296177Sjhibbits        if (!p_Blocks)
485296177Sjhibbits        {
486296177Sjhibbits            MEM_Free(p_Mem);
487296177Sjhibbits            RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Memory segment blocks"));
488296177Sjhibbits        }
489296177Sjhibbits
490296177Sjhibbits        /* Store the memory segment address */
491296177Sjhibbits        p_Mem->p_Bases[0] = p_Blocks;
492296177Sjhibbits
493296177Sjhibbits        /* The following manipulation places the data of block[0] in an aligned address,
494296177Sjhibbits           since block size is aligned the following block datas will all be aligned.*/
495296177Sjhibbits        ALIGN_BLOCK(p_Blocks, prefixSize, alignment);
496296177Sjhibbits
497296177Sjhibbits        /* initialize the blocks */
498296177Sjhibbits        for (i = 0; i < num; i++)
499296177Sjhibbits        {
500296177Sjhibbits            p_Mem->p_BlocksStack[i] = p_Blocks;
501296177Sjhibbits            p_Blocks += blockSize;
502296177Sjhibbits        }
503296177Sjhibbits
504296177Sjhibbits#ifdef DEBUG_MEM_LEAKS
505296177Sjhibbits        p_Mem->blockOffset = (uint32_t)(p_Mem->p_BlocksStack[0] - p_Mem->p_Bases[0]);
506296177Sjhibbits        p_Mem->blockSize = blockSize;
507296177Sjhibbits#endif /* DEBUG_MEM_LEAKS */
508296177Sjhibbits    }
509296177Sjhibbits    else
510296177Sjhibbits    {
511296177Sjhibbits        /* |alignment - 1| bytes at most will be discarded in the beginning of the
512296177Sjhibbits           received segment for alignment reasons, therefore the allocation is of:
513296177Sjhibbits           (alignment + block size). */
514296177Sjhibbits        for (i = 0; i < num; i++)
515296177Sjhibbits        {
516296177Sjhibbits            uint8_t *p_Block = (uint8_t *)
517296177Sjhibbits                XX_MallocSmart((uint32_t)(blockSize + alignment), memPartitionId, 1);
518296177Sjhibbits            if (!p_Block)
519296177Sjhibbits            {
520296177Sjhibbits                MEM_Free(p_Mem);
521296177Sjhibbits                RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Memory segment blocks"));
522296177Sjhibbits            }
523296177Sjhibbits
524296177Sjhibbits            /* Store the memory segment address */
525296177Sjhibbits            p_Mem->p_Bases[i] = p_Block;
526296177Sjhibbits
527296177Sjhibbits            /* The following places the data of each block in an aligned address */
528296177Sjhibbits            ALIGN_BLOCK(p_Block, prefixSize, alignment);
529296177Sjhibbits
530296177Sjhibbits#ifdef DEBUG_MEM_LEAKS
531296177Sjhibbits            /* Need 4 bytes before the meaningful bytes to store the block index.
532296177Sjhibbits               We know we have them because alignment is at least 4 bytes. */
533296177Sjhibbits            if (p_Block == p_Mem->p_Bases[i])
534296177Sjhibbits                p_Block += alignment;
535296177Sjhibbits
536296177Sjhibbits            *(uint32_t *)(p_Block - 4) = i;
537296177Sjhibbits#endif /* DEBUG_MEM_LEAKS */
538296177Sjhibbits
539296177Sjhibbits            p_Mem->p_BlocksStack[i] = p_Block;
540296177Sjhibbits        }
541296177Sjhibbits    }
542296177Sjhibbits
543296177Sjhibbits    /* store name */
544296177Sjhibbits    strncpy(p_Mem->name, name, MEM_MAX_NAME_LENGTH-1);
545296177Sjhibbits
546296177Sjhibbits    /* return handle to caller */
547296177Sjhibbits    *p_Handle = (t_Handle)p_Mem;
548296177Sjhibbits
549296177Sjhibbits#ifdef DEBUG_MEM_LEAKS
550296177Sjhibbits    {
551296177Sjhibbits        t_Error errCode = InitMemDebugDatabase(p_Mem);
552296177Sjhibbits
553296177Sjhibbits        if (errCode != E_OK)
554296177Sjhibbits            RETURN_ERROR(MAJOR, errCode, NO_MSG);
555296177Sjhibbits    }
556296177Sjhibbits#endif /* DEBUG_MEM_LEAKS */
557296177Sjhibbits
558296177Sjhibbits    return E_OK;
559296177Sjhibbits}
560296177Sjhibbits
561296177Sjhibbits
562296177Sjhibbits/*****************************************************************************/
563296177Sjhibbitsvoid MEM_Free(t_Handle h_Mem)
564296177Sjhibbits{
565296177Sjhibbits    t_MemorySegment *p_Mem = (t_MemorySegment*)h_Mem;
566296177Sjhibbits    uint32_t        num, i;
567296177Sjhibbits
568296177Sjhibbits    /* Check MEM leaks */
569296177Sjhibbits    MEM_CheckLeaks(h_Mem);
570296177Sjhibbits
571296177Sjhibbits    if (p_Mem)
572296177Sjhibbits    {
573296177Sjhibbits        num = p_Mem->consecutiveMem ? 1 : p_Mem->num;
574296177Sjhibbits
575296177Sjhibbits        if (p_Mem->allocOwner == e_MEM_ALLOC_OWNER_LOCAL_SMART)
576296177Sjhibbits        {
577296177Sjhibbits            for (i=0; i < num; i++)
578296177Sjhibbits            {
579296177Sjhibbits                if (p_Mem->p_Bases[i])
580296177Sjhibbits                {
581296177Sjhibbits                    XX_FreeSmart(p_Mem->p_Bases[i]);
582296177Sjhibbits                }
583296177Sjhibbits            }
584296177Sjhibbits        }
585296177Sjhibbits        else if (p_Mem->allocOwner == e_MEM_ALLOC_OWNER_LOCAL)
586296177Sjhibbits        {
587296177Sjhibbits            for (i=0; i < num; i++)
588296177Sjhibbits            {
589296177Sjhibbits                if (p_Mem->p_Bases[i])
590296177Sjhibbits                {
591296177Sjhibbits                    XX_Free(p_Mem->p_Bases[i]);
592296177Sjhibbits                }
593296177Sjhibbits            }
594296177Sjhibbits        }
595296177Sjhibbits
596296177Sjhibbits        if (p_Mem->h_Spinlock)
597296177Sjhibbits            XX_FreeSpinlock(p_Mem->h_Spinlock);
598296177Sjhibbits
599296177Sjhibbits        if (p_Mem->p_Bases)
600296177Sjhibbits            XX_Free(p_Mem->p_Bases);
601296177Sjhibbits
602296177Sjhibbits        if (p_Mem->p_BlocksStack)
603296177Sjhibbits            XX_Free(p_Mem->p_BlocksStack);
604296177Sjhibbits
605296177Sjhibbits#ifdef DEBUG_MEM_LEAKS
606296177Sjhibbits        if (p_Mem->p_MemDbg)
607296177Sjhibbits            XX_Free(p_Mem->p_MemDbg);
608296177Sjhibbits#endif /* DEBUG_MEM_LEAKS */
609296177Sjhibbits
610296177Sjhibbits       XX_Free(p_Mem);
611296177Sjhibbits    }
612296177Sjhibbits}
613296177Sjhibbits
614296177Sjhibbits
615296177Sjhibbits/*****************************************************************************/
616296177Sjhibbitsvoid * MEM_Get(t_Handle h_Mem)
617296177Sjhibbits{
618296177Sjhibbits    t_MemorySegment *p_Mem = (t_MemorySegment *)h_Mem;
619296177Sjhibbits    uint8_t         *p_Block;
620296177Sjhibbits    uint32_t        intFlags;
621296177Sjhibbits#ifdef DEBUG_MEM_LEAKS
622296177Sjhibbits    uintptr_t       callerAddr = 0;
623296177Sjhibbits
624296177Sjhibbits    GET_CALLER_ADDR;
625296177Sjhibbits#endif /* DEBUG_MEM_LEAKS */
626296177Sjhibbits
627296177Sjhibbits    ASSERT_COND(h_Mem);
628296177Sjhibbits
629296177Sjhibbits    intFlags = XX_LockIntrSpinlock(p_Mem->h_Spinlock);
630296177Sjhibbits    /* check if there is an available block */
631296177Sjhibbits    if ((p_Block = (uint8_t *)MemGet(p_Mem)) == NULL)
632296177Sjhibbits    {
633296177Sjhibbits        XX_UnlockIntrSpinlock(p_Mem->h_Spinlock, intFlags);
634296177Sjhibbits        return NULL;
635296177Sjhibbits    }
636296177Sjhibbits
637296177Sjhibbits#ifdef DEBUG_MEM_LEAKS
638296177Sjhibbits    DebugMemGet(p_Mem, p_Block, callerAddr);
639296177Sjhibbits#endif /* DEBUG_MEM_LEAKS */
640296177Sjhibbits    XX_UnlockIntrSpinlock(p_Mem->h_Spinlock, intFlags);
641296177Sjhibbits
642296177Sjhibbits    return (void *)p_Block;
643296177Sjhibbits}
644296177Sjhibbits
645296177Sjhibbits
646296177Sjhibbits/*****************************************************************************/
647296177Sjhibbitsuint16_t MEM_GetN(t_Handle h_Mem, uint32_t num, void *array[])
648296177Sjhibbits{
649296177Sjhibbits    t_MemorySegment     *p_Mem = (t_MemorySegment *)h_Mem;
650296177Sjhibbits    uint32_t            availableBlocks;
651296177Sjhibbits    register uint32_t   i;
652296177Sjhibbits    uint32_t            intFlags;
653296177Sjhibbits#ifdef DEBUG_MEM_LEAKS
654296177Sjhibbits    uintptr_t           callerAddr = 0;
655296177Sjhibbits
656296177Sjhibbits    GET_CALLER_ADDR;
657296177Sjhibbits#endif /* DEBUG_MEM_LEAKS */
658296177Sjhibbits
659296177Sjhibbits    ASSERT_COND(h_Mem);
660296177Sjhibbits
661296177Sjhibbits    intFlags = XX_LockIntrSpinlock(p_Mem->h_Spinlock);
662296177Sjhibbits    /* check how many blocks are available */
663296177Sjhibbits    availableBlocks = (uint32_t)(p_Mem->num - p_Mem->current);
664296177Sjhibbits    if (num > availableBlocks)
665296177Sjhibbits    {
666296177Sjhibbits        num = availableBlocks;
667296177Sjhibbits    }
668296177Sjhibbits
669296177Sjhibbits    for (i=0; i < num; i++)
670296177Sjhibbits    {
671296177Sjhibbits        /* get pointer to block */
672296177Sjhibbits        if ((array[i] = MemGet(p_Mem)) == NULL)
673296177Sjhibbits        {
674296177Sjhibbits            break;
675296177Sjhibbits        }
676296177Sjhibbits
677296177Sjhibbits#ifdef DEBUG_MEM_LEAKS
678296177Sjhibbits        DebugMemGet(p_Mem, array[i], callerAddr);
679296177Sjhibbits#endif /* DEBUG_MEM_LEAKS */
680296177Sjhibbits    }
681296177Sjhibbits    XX_UnlockIntrSpinlock(p_Mem->h_Spinlock, intFlags);
682296177Sjhibbits
683296177Sjhibbits    return (uint16_t)i;
684296177Sjhibbits}
685296177Sjhibbits
686296177Sjhibbits
687296177Sjhibbits/*****************************************************************************/
688296177Sjhibbitst_Error MEM_Put(t_Handle h_Mem, void *p_Block)
689296177Sjhibbits{
690296177Sjhibbits    t_MemorySegment *p_Mem = (t_MemorySegment *)h_Mem;
691296177Sjhibbits    t_Error         rc;
692296177Sjhibbits    uint32_t        intFlags;
693296177Sjhibbits
694296177Sjhibbits    ASSERT_COND(h_Mem);
695296177Sjhibbits
696296177Sjhibbits    intFlags = XX_LockIntrSpinlock(p_Mem->h_Spinlock);
697296177Sjhibbits    /* check if blocks stack is full */
698296177Sjhibbits    if ((rc = MemPut(p_Mem, p_Block)) != E_OK)
699296177Sjhibbits    {
700296177Sjhibbits        XX_UnlockIntrSpinlock(p_Mem->h_Spinlock, intFlags);
701296177Sjhibbits        RETURN_ERROR(MAJOR, rc, NO_MSG);
702296177Sjhibbits    }
703296177Sjhibbits
704296177Sjhibbits#ifdef DEBUG_MEM_LEAKS
705296177Sjhibbits    DebugMemPut(p_Mem, p_Block);
706296177Sjhibbits#endif /* DEBUG_MEM_LEAKS */
707296177Sjhibbits    XX_UnlockIntrSpinlock(p_Mem->h_Spinlock, intFlags);
708296177Sjhibbits
709296177Sjhibbits    return E_OK;
710296177Sjhibbits}
711296177Sjhibbits
712296177Sjhibbits
713296177Sjhibbits#ifdef DEBUG_MEM_LEAKS
714296177Sjhibbits
715296177Sjhibbits/*****************************************************************************/
716296177Sjhibbitsvoid MEM_CheckLeaks(t_Handle h_Mem)
717296177Sjhibbits{
718296177Sjhibbits    t_MemorySegment *p_Mem = (t_MemorySegment *)h_Mem;
719296177Sjhibbits    t_MemDbg        *p_MemDbg = (t_MemDbg *)p_Mem->p_MemDbg;
720296177Sjhibbits    uint8_t         *p_Block;
721296177Sjhibbits    int             i;
722296177Sjhibbits
723296177Sjhibbits    ASSERT_COND(h_Mem);
724296177Sjhibbits
725296177Sjhibbits    if (p_Mem->consecutiveMem)
726296177Sjhibbits    {
727296177Sjhibbits        for (i=0; i < p_Mem->num; i++)
728296177Sjhibbits        {
729296177Sjhibbits            if (p_MemDbg[i].ownerAddress != ILLEGAL_BASE)
730296177Sjhibbits            {
731296177Sjhibbits                /* Find the block address */
732296177Sjhibbits                p_Block = ((p_Mem->p_Bases[0] + p_Mem->blockOffset) +
733296177Sjhibbits                           (i * p_Mem->blockSize));
734296177Sjhibbits
735296177Sjhibbits                XX_Print("MEM leak: 0x%08x, Caller address: 0x%08x\n",
736296177Sjhibbits                         p_Block, p_MemDbg[i].ownerAddress);
737296177Sjhibbits            }
738296177Sjhibbits        }
739296177Sjhibbits    }
740296177Sjhibbits    else
741296177Sjhibbits    {
742296177Sjhibbits        for (i=0; i < p_Mem->num; i++)
743296177Sjhibbits        {
744296177Sjhibbits            if (p_MemDbg[i].ownerAddress != ILLEGAL_BASE)
745296177Sjhibbits            {
746296177Sjhibbits                /* Find the block address */
747296177Sjhibbits                p_Block = p_Mem->p_Bases[i];
748296177Sjhibbits
749296177Sjhibbits                ALIGN_BLOCK(p_Block, p_Mem->prefixSize, p_Mem->alignment);
750296177Sjhibbits
751296177Sjhibbits                if (p_Block == p_Mem->p_Bases[i])
752296177Sjhibbits                    p_Block += p_Mem->alignment;
753296177Sjhibbits
754296177Sjhibbits                XX_Print("MEM leak: 0x%08x, Caller address: 0x%08x\n",
755296177Sjhibbits                         p_Block, p_MemDbg[i].ownerAddress);
756296177Sjhibbits            }
757296177Sjhibbits        }
758296177Sjhibbits    }
759296177Sjhibbits}
760296177Sjhibbits
761296177Sjhibbits#endif /* DEBUG_MEM_LEAKS */
762296177Sjhibbits
763296177Sjhibbits
764