1296177Sjhibbits/* Copyright (c) 2008-2011 Freescale Semiconductor, Inc.
2296177Sjhibbits * All rights reserved.
3296177Sjhibbits *
4296177Sjhibbits * Redistribution and use in source and binary forms, with or without
5296177Sjhibbits * modification, are permitted provided that the following conditions are met:
6296177Sjhibbits *     * Redistributions of source code must retain the above copyright
7296177Sjhibbits *       notice, this list of conditions and the following disclaimer.
8296177Sjhibbits *     * Redistributions in binary form must reproduce the above copyright
9296177Sjhibbits *       notice, this list of conditions and the following disclaimer in the
10296177Sjhibbits *       documentation and/or other materials provided with the distribution.
11296177Sjhibbits *     * Neither the name of Freescale Semiconductor nor the
12296177Sjhibbits *       names of its contributors may be used to endorse or promote products
13296177Sjhibbits *       derived from this software without specific prior written permission.
14296177Sjhibbits *
15296177Sjhibbits *
16296177Sjhibbits * ALTERNATIVELY, this software may be distributed under the terms of the
17296177Sjhibbits * GNU General Public License ("GPL") as published by the Free Software
18296177Sjhibbits * Foundation, either version 2 of that License or (at your option) any
19296177Sjhibbits * later version.
20296177Sjhibbits *
21296177Sjhibbits * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
22296177Sjhibbits * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23296177Sjhibbits * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24296177Sjhibbits * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
25296177Sjhibbits * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26296177Sjhibbits * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27296177Sjhibbits * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
28296177Sjhibbits * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29296177Sjhibbits * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30296177Sjhibbits * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31296177Sjhibbits */
32296177Sjhibbits
33296177Sjhibbits#include "string_ext.h"
34296177Sjhibbits#include "error_ext.h"
35296177Sjhibbits#include "std_ext.h"
36296177Sjhibbits#include "sprint_ext.h"
37296177Sjhibbits#include "part_ext.h"
38296177Sjhibbits#include "xx_ext.h"
39296177Sjhibbits
40296177Sjhibbits#include "mm.h"
41296177Sjhibbits
42296177Sjhibbits
43296177Sjhibbits
44296177Sjhibbits
45296177Sjhibbits/**********************************************************************
46296177Sjhibbits *                     MM internal routines set                       *
47296177Sjhibbits **********************************************************************/
48296177Sjhibbits
49296177Sjhibbits/****************************************************************
50296177Sjhibbits *  Routine:   CreateBusyBlock
51296177Sjhibbits *
52296177Sjhibbits *  Description:
53296177Sjhibbits *      Initializes a new busy block of "size" bytes and started
54296177Sjhibbits *      rom "base" address. Each busy block has a name that
55296177Sjhibbits *      specified the purpose of the memory allocation.
56296177Sjhibbits *
57296177Sjhibbits *  Arguments:
58296177Sjhibbits *      base      - base address of the busy block
59296177Sjhibbits *      size      - size of the busy block
60296177Sjhibbits *      name      - name that specified the busy block
61296177Sjhibbits *
62296177Sjhibbits *  Return value:
63296177Sjhibbits *      A pointer to new created structure returned on success;
64296177Sjhibbits *      Otherwise, NULL.
65296177Sjhibbits ****************************************************************/
66296177Sjhibbitsstatic t_BusyBlock * CreateBusyBlock(uint64_t base, uint64_t size, char *name)
67296177Sjhibbits{
68296177Sjhibbits    t_BusyBlock *p_BusyBlock;
69296177Sjhibbits    uint32_t    n;
70296177Sjhibbits
71296177Sjhibbits    p_BusyBlock = (t_BusyBlock *)XX_Malloc(sizeof(t_BusyBlock));
72296177Sjhibbits    if ( !p_BusyBlock )
73296177Sjhibbits    {
74296177Sjhibbits        REPORT_ERROR(MAJOR, E_NO_MEMORY, NO_MSG);
75296177Sjhibbits        return NULL;
76296177Sjhibbits    }
77296177Sjhibbits
78296177Sjhibbits    p_BusyBlock->base = base;
79296177Sjhibbits    p_BusyBlock->end = base + size;
80296177Sjhibbits
81296177Sjhibbits    n = strlen(name);
82296177Sjhibbits    if (n >= MM_MAX_NAME_LEN)
83296177Sjhibbits        n = MM_MAX_NAME_LEN - 1;
84296177Sjhibbits    strncpy(p_BusyBlock->name, name, MM_MAX_NAME_LEN-1);
85296177Sjhibbits    p_BusyBlock->name[n] = '\0';
86296177Sjhibbits    p_BusyBlock->p_Next = 0;
87296177Sjhibbits
88296177Sjhibbits    return p_BusyBlock;
89296177Sjhibbits}
90296177Sjhibbits
91296177Sjhibbits/****************************************************************
92296177Sjhibbits *  Routine:   CreateNewBlock
93296177Sjhibbits *
94296177Sjhibbits *  Description:
95296177Sjhibbits *      Initializes a new memory block of "size" bytes and started
96296177Sjhibbits *      from "base" address.
97296177Sjhibbits *
98296177Sjhibbits *  Arguments:
99296177Sjhibbits *      base    - base address of the memory block
100296177Sjhibbits *      size    - size of the memory block
101296177Sjhibbits *
102296177Sjhibbits *  Return value:
103296177Sjhibbits *      A pointer to new created structure returned on success;
104296177Sjhibbits *      Otherwise, NULL.
105296177Sjhibbits ****************************************************************/
106296177Sjhibbitsstatic t_MemBlock * CreateNewBlock(uint64_t base, uint64_t size)
107296177Sjhibbits{
108296177Sjhibbits    t_MemBlock *p_MemBlock;
109296177Sjhibbits
110296177Sjhibbits    p_MemBlock = (t_MemBlock *)XX_Malloc(sizeof(t_MemBlock));
111296177Sjhibbits    if ( !p_MemBlock )
112296177Sjhibbits    {
113296177Sjhibbits        REPORT_ERROR(MAJOR, E_NO_MEMORY, NO_MSG);
114296177Sjhibbits        return NULL;
115296177Sjhibbits    }
116296177Sjhibbits
117296177Sjhibbits    p_MemBlock->base = base;
118296177Sjhibbits    p_MemBlock->end = base+size;
119296177Sjhibbits    p_MemBlock->p_Next = 0;
120296177Sjhibbits
121296177Sjhibbits    return p_MemBlock;
122296177Sjhibbits}
123296177Sjhibbits
124296177Sjhibbits/****************************************************************
125296177Sjhibbits *  Routine:   CreateFreeBlock
126296177Sjhibbits *
127296177Sjhibbits *  Description:
128296177Sjhibbits *      Initializes a new free block of of "size" bytes and
129296177Sjhibbits *      started from "base" address.
130296177Sjhibbits *
131296177Sjhibbits *  Arguments:
132296177Sjhibbits *      base      - base address of the free block
133296177Sjhibbits *      size      - size of the free block
134296177Sjhibbits *
135296177Sjhibbits *  Return value:
136296177Sjhibbits *      A pointer to new created structure returned on success;
137296177Sjhibbits *      Otherwise, NULL.
138296177Sjhibbits ****************************************************************/
139296177Sjhibbitsstatic t_FreeBlock * CreateFreeBlock(uint64_t base, uint64_t size)
140296177Sjhibbits{
141296177Sjhibbits    t_FreeBlock *p_FreeBlock;
142296177Sjhibbits
143296177Sjhibbits    p_FreeBlock = (t_FreeBlock *)XX_Malloc(sizeof(t_FreeBlock));
144296177Sjhibbits    if ( !p_FreeBlock )
145296177Sjhibbits    {
146296177Sjhibbits        REPORT_ERROR(MAJOR, E_NO_MEMORY, NO_MSG);
147296177Sjhibbits        return NULL;
148296177Sjhibbits    }
149296177Sjhibbits
150296177Sjhibbits    p_FreeBlock->base = base;
151296177Sjhibbits    p_FreeBlock->end = base + size;
152296177Sjhibbits    p_FreeBlock->p_Next = 0;
153296177Sjhibbits
154296177Sjhibbits    return p_FreeBlock;
155296177Sjhibbits}
156296177Sjhibbits
157296177Sjhibbits/****************************************************************
158296177Sjhibbits *  Routine:    AddFree
159296177Sjhibbits *
160296177Sjhibbits *  Description:
161296177Sjhibbits *      Adds a new free block to the free lists. It updates each
162296177Sjhibbits *      free list to include a new free block.
163296177Sjhibbits *      Note, that all free block in each free list are ordered
164296177Sjhibbits *      by their base address.
165296177Sjhibbits *
166296177Sjhibbits *  Arguments:
167296177Sjhibbits *      p_MM  - pointer to the MM object
168296177Sjhibbits *      base  - base address of a given free block
169296177Sjhibbits *      end   - end address of a given free block
170296177Sjhibbits *
171296177Sjhibbits *  Return value:
172296177Sjhibbits *
173296177Sjhibbits *
174296177Sjhibbits ****************************************************************/
175296177Sjhibbitsstatic t_Error AddFree(t_MM *p_MM, uint64_t base, uint64_t end)
176296177Sjhibbits{
177296177Sjhibbits    t_FreeBlock *p_PrevB, *p_CurrB, *p_NewB;
178296177Sjhibbits    uint64_t    alignment;
179296177Sjhibbits    uint64_t    alignBase;
180296177Sjhibbits    int         i;
181296177Sjhibbits
182296177Sjhibbits    /* Updates free lists to include  a just released block */
183296177Sjhibbits    for (i=0; i <= MM_MAX_ALIGNMENT; i++)
184296177Sjhibbits    {
185296177Sjhibbits        p_PrevB = p_NewB = 0;
186296177Sjhibbits        p_CurrB = p_MM->freeBlocks[i];
187296177Sjhibbits
188296177Sjhibbits        alignment = (uint64_t)(0x1 << i);
189296177Sjhibbits        alignBase = MAKE_ALIGNED(base, alignment);
190296177Sjhibbits
191296177Sjhibbits        /* Goes to the next free list if there is no block to free */
192296177Sjhibbits        if (alignBase >= end)
193296177Sjhibbits            continue;
194296177Sjhibbits
195296177Sjhibbits        /* Looks for a free block that should be updated */
196296177Sjhibbits        while ( p_CurrB )
197296177Sjhibbits        {
198296177Sjhibbits            if ( alignBase <= p_CurrB->end )
199296177Sjhibbits            {
200296177Sjhibbits                if ( end > p_CurrB->end )
201296177Sjhibbits                {
202296177Sjhibbits                    t_FreeBlock *p_NextB;
203296177Sjhibbits                    while ( p_CurrB->p_Next && end > p_CurrB->p_Next->end )
204296177Sjhibbits                    {
205296177Sjhibbits                        p_NextB = p_CurrB->p_Next;
206296177Sjhibbits                        p_CurrB->p_Next = p_CurrB->p_Next->p_Next;
207296177Sjhibbits                        XX_Free(p_NextB);
208296177Sjhibbits                    }
209296177Sjhibbits
210296177Sjhibbits                    p_NextB = p_CurrB->p_Next;
211296177Sjhibbits                    if ( !p_NextB || (p_NextB && end < p_NextB->base) )
212296177Sjhibbits                    {
213296177Sjhibbits                        p_CurrB->end = end;
214296177Sjhibbits                    }
215296177Sjhibbits                    else
216296177Sjhibbits                    {
217296177Sjhibbits                        p_CurrB->end = p_NextB->end;
218296177Sjhibbits                        p_CurrB->p_Next = p_NextB->p_Next;
219296177Sjhibbits                        XX_Free(p_NextB);
220296177Sjhibbits                    }
221296177Sjhibbits                }
222296177Sjhibbits                else if ( (end < p_CurrB->base) && ((end-alignBase) >= alignment) )
223296177Sjhibbits                {
224296177Sjhibbits                    if ((p_NewB = CreateFreeBlock(alignBase, end-alignBase)) == NULL)
225296177Sjhibbits                        RETURN_ERROR(MAJOR, E_NO_MEMORY, NO_MSG);
226296177Sjhibbits
227296177Sjhibbits                    p_NewB->p_Next = p_CurrB;
228296177Sjhibbits                    if (p_PrevB)
229296177Sjhibbits                        p_PrevB->p_Next = p_NewB;
230296177Sjhibbits                    else
231296177Sjhibbits                        p_MM->freeBlocks[i] = p_NewB;
232296177Sjhibbits                    break;
233296177Sjhibbits                }
234296177Sjhibbits
235296177Sjhibbits                if ((alignBase < p_CurrB->base) && (end >= p_CurrB->base))
236296177Sjhibbits                {
237296177Sjhibbits                    p_CurrB->base = alignBase;
238296177Sjhibbits                }
239296177Sjhibbits
240296177Sjhibbits                /* if size of the free block is less then alignment
241296177Sjhibbits                 * deletes that free block from the free list. */
242296177Sjhibbits                if ( (p_CurrB->end - p_CurrB->base) < alignment)
243296177Sjhibbits                {
244296177Sjhibbits                    if ( p_PrevB )
245296177Sjhibbits                        p_PrevB->p_Next = p_CurrB->p_Next;
246296177Sjhibbits                    else
247296177Sjhibbits                        p_MM->freeBlocks[i] = p_CurrB->p_Next;
248296177Sjhibbits                    XX_Free(p_CurrB);
249296177Sjhibbits                }
250296177Sjhibbits                break;
251296177Sjhibbits            }
252296177Sjhibbits            else
253296177Sjhibbits            {
254296177Sjhibbits                p_PrevB = p_CurrB;
255296177Sjhibbits                p_CurrB = p_CurrB->p_Next;
256296177Sjhibbits            }
257296177Sjhibbits        }
258296177Sjhibbits
259296177Sjhibbits        /* If no free block found to be updated, insert a new free block
260296177Sjhibbits         * to the end of the free list.
261296177Sjhibbits         */
262296177Sjhibbits        if ( !p_CurrB && ((((uint64_t)(end-base)) & ((uint64_t)(alignment-1))) == 0) )
263296177Sjhibbits        {
264296177Sjhibbits            if ((p_NewB = CreateFreeBlock(alignBase, end-base)) == NULL)
265296177Sjhibbits                RETURN_ERROR(MAJOR, E_NO_MEMORY, NO_MSG);
266296177Sjhibbits
267296177Sjhibbits            if (p_PrevB)
268296177Sjhibbits                p_PrevB->p_Next = p_NewB;
269296177Sjhibbits            else
270296177Sjhibbits                p_MM->freeBlocks[i] = p_NewB;
271296177Sjhibbits        }
272296177Sjhibbits
273296177Sjhibbits        /* Update boundaries of the new free block */
274296177Sjhibbits        if ((alignment == 1) && !p_NewB)
275296177Sjhibbits        {
276296177Sjhibbits            if ( p_CurrB && base > p_CurrB->base )
277296177Sjhibbits                base = p_CurrB->base;
278296177Sjhibbits            if ( p_CurrB && end < p_CurrB->end )
279296177Sjhibbits                end = p_CurrB->end;
280296177Sjhibbits        }
281296177Sjhibbits    }
282296177Sjhibbits
283296177Sjhibbits    return (E_OK);
284296177Sjhibbits}
285296177Sjhibbits
286296177Sjhibbits/****************************************************************
287296177Sjhibbits *  Routine:      CutFree
288296177Sjhibbits *
289296177Sjhibbits *  Description:
290296177Sjhibbits *      Cuts a free block from holdBase to holdEnd from the free lists.
291296177Sjhibbits *      That is, it updates all free lists of the MM object do
292296177Sjhibbits *      not include a block of memory from holdBase to holdEnd.
293296177Sjhibbits *      For each free lists it seek for a free block that holds
294296177Sjhibbits *      either holdBase or holdEnd. If such block is found it updates it.
295296177Sjhibbits *
296296177Sjhibbits *  Arguments:
297296177Sjhibbits *      p_MM            - pointer to the MM object
298296177Sjhibbits *      holdBase        - base address of the allocated block
299296177Sjhibbits *      holdEnd         - end address of the allocated block
300296177Sjhibbits *
301296177Sjhibbits *  Return value:
302296177Sjhibbits *      E_OK is returned on success,
303296177Sjhibbits *      otherwise returns an error code.
304296177Sjhibbits *
305296177Sjhibbits ****************************************************************/
306296177Sjhibbitsstatic t_Error CutFree(t_MM *p_MM, uint64_t holdBase, uint64_t holdEnd)
307296177Sjhibbits{
308296177Sjhibbits    t_FreeBlock *p_PrevB, *p_CurrB, *p_NewB;
309296177Sjhibbits    uint64_t    alignBase, base, end;
310296177Sjhibbits    uint64_t    alignment;
311296177Sjhibbits    int         i;
312296177Sjhibbits
313296177Sjhibbits    for (i=0; i <= MM_MAX_ALIGNMENT; i++)
314296177Sjhibbits    {
315296177Sjhibbits        p_PrevB = p_NewB = 0;
316296177Sjhibbits        p_CurrB = p_MM->freeBlocks[i];
317296177Sjhibbits
318296177Sjhibbits        alignment = (uint64_t)(0x1 << i);
319296177Sjhibbits        alignBase = MAKE_ALIGNED(holdEnd, alignment);
320296177Sjhibbits
321296177Sjhibbits        while ( p_CurrB )
322296177Sjhibbits        {
323296177Sjhibbits            base = p_CurrB->base;
324296177Sjhibbits            end = p_CurrB->end;
325296177Sjhibbits
326296177Sjhibbits            if ( (holdBase <= base) && (holdEnd <= end) && (holdEnd > base) )
327296177Sjhibbits            {
328296177Sjhibbits                if ( alignBase >= end ||
329296177Sjhibbits                     (alignBase < end && ((end-alignBase) < alignment)) )
330296177Sjhibbits                {
331296177Sjhibbits                    if (p_PrevB)
332296177Sjhibbits                        p_PrevB->p_Next = p_CurrB->p_Next;
333296177Sjhibbits                    else
334296177Sjhibbits                        p_MM->freeBlocks[i] = p_CurrB->p_Next;
335296177Sjhibbits                    XX_Free(p_CurrB);
336296177Sjhibbits                }
337296177Sjhibbits                else
338296177Sjhibbits                {
339296177Sjhibbits                    p_CurrB->base = alignBase;
340296177Sjhibbits                }
341296177Sjhibbits                break;
342296177Sjhibbits            }
343296177Sjhibbits            else if ( (holdBase > base) && (holdEnd <= end) )
344296177Sjhibbits            {
345296177Sjhibbits                if ( (holdBase-base) >= alignment )
346296177Sjhibbits                {
347296177Sjhibbits                    if ( (alignBase < end) && ((end-alignBase) >= alignment) )
348296177Sjhibbits                    {
349296177Sjhibbits                        if ((p_NewB = CreateFreeBlock(alignBase, end-alignBase)) == NULL)
350296177Sjhibbits                            RETURN_ERROR(MAJOR, E_NO_MEMORY, NO_MSG);
351296177Sjhibbits                        p_NewB->p_Next = p_CurrB->p_Next;
352296177Sjhibbits                        p_CurrB->p_Next = p_NewB;
353296177Sjhibbits                    }
354296177Sjhibbits                    p_CurrB->end = holdBase;
355296177Sjhibbits                }
356296177Sjhibbits                else if ( (alignBase < end) && ((end-alignBase) >= alignment) )
357296177Sjhibbits                {
358296177Sjhibbits                    p_CurrB->base = alignBase;
359296177Sjhibbits                }
360296177Sjhibbits                else
361296177Sjhibbits                {
362296177Sjhibbits                    if (p_PrevB)
363296177Sjhibbits                        p_PrevB->p_Next = p_CurrB->p_Next;
364296177Sjhibbits                    else
365296177Sjhibbits                        p_MM->freeBlocks[i] = p_CurrB->p_Next;
366296177Sjhibbits                    XX_Free(p_CurrB);
367296177Sjhibbits                }
368296177Sjhibbits                break;
369296177Sjhibbits            }
370296177Sjhibbits            else
371296177Sjhibbits            {
372296177Sjhibbits                p_PrevB = p_CurrB;
373296177Sjhibbits                p_CurrB = p_CurrB->p_Next;
374296177Sjhibbits            }
375296177Sjhibbits        }
376296177Sjhibbits    }
377296177Sjhibbits
378296177Sjhibbits    return (E_OK);
379296177Sjhibbits}
380296177Sjhibbits
381296177Sjhibbits/****************************************************************
382296177Sjhibbits *  Routine:     AddBusy
383296177Sjhibbits *
384296177Sjhibbits *  Description:
385296177Sjhibbits *      Adds a new busy block to the list of busy blocks. Note,
386296177Sjhibbits *      that all busy blocks are ordered by their base address in
387296177Sjhibbits *      the busy list.
388296177Sjhibbits *
389296177Sjhibbits *  Arguments:
390296177Sjhibbits *      MM              - handler to the MM object
391296177Sjhibbits *      p_NewBusyB      - pointer to the a busy block
392296177Sjhibbits *
393296177Sjhibbits *  Return value:
394296177Sjhibbits *      None.
395296177Sjhibbits *
396296177Sjhibbits ****************************************************************/
397296177Sjhibbitsstatic void AddBusy(t_MM *p_MM, t_BusyBlock *p_NewBusyB)
398296177Sjhibbits{
399296177Sjhibbits    t_BusyBlock *p_CurrBusyB, *p_PrevBusyB;
400296177Sjhibbits
401296177Sjhibbits    /* finds a place of a new busy block in the list of busy blocks */
402296177Sjhibbits    p_PrevBusyB = 0;
403296177Sjhibbits    p_CurrBusyB = p_MM->busyBlocks;
404296177Sjhibbits
405296177Sjhibbits    while ( p_CurrBusyB && p_NewBusyB->base > p_CurrBusyB->base )
406296177Sjhibbits    {
407296177Sjhibbits        p_PrevBusyB = p_CurrBusyB;
408296177Sjhibbits        p_CurrBusyB = p_CurrBusyB->p_Next;
409296177Sjhibbits    }
410296177Sjhibbits
411296177Sjhibbits    /* insert the new busy block into the list of busy blocks */
412296177Sjhibbits    if ( p_CurrBusyB )
413296177Sjhibbits        p_NewBusyB->p_Next = p_CurrBusyB;
414296177Sjhibbits    if ( p_PrevBusyB )
415296177Sjhibbits        p_PrevBusyB->p_Next = p_NewBusyB;
416296177Sjhibbits    else
417296177Sjhibbits        p_MM->busyBlocks = p_NewBusyB;
418296177Sjhibbits}
419296177Sjhibbits
420296177Sjhibbits/****************************************************************
421296177Sjhibbits *  Routine:    CutBusy
422296177Sjhibbits *
423296177Sjhibbits *  Description:
424296177Sjhibbits *      Cuts a block from base to end from the list of busy blocks.
425296177Sjhibbits *      This is done by updating the list of busy blocks do not
426296177Sjhibbits *      include a given block, that block is going to be free. If a
427296177Sjhibbits *      given block is a part of some other busy block, so that
428296177Sjhibbits *      busy block is updated. If there are number of busy blocks
429296177Sjhibbits *      included in the given block, so all that blocks are removed
430296177Sjhibbits *      from the busy list and the end blocks are updated.
431296177Sjhibbits *      If the given block devides some block into two parts, a new
432296177Sjhibbits *      busy block is added to the busy list.
433296177Sjhibbits *
434296177Sjhibbits *  Arguments:
435296177Sjhibbits *      p_MM  - pointer to the MM object
436296177Sjhibbits *      base  - base address of a given busy block
437296177Sjhibbits *      end   - end address of a given busy block
438296177Sjhibbits *
439296177Sjhibbits *  Return value:
440296177Sjhibbits *      E_OK on success, E_NOMEMORY otherwise.
441296177Sjhibbits *
442296177Sjhibbits ****************************************************************/
443296177Sjhibbitsstatic t_Error CutBusy(t_MM *p_MM, uint64_t base, uint64_t end)
444296177Sjhibbits{
445296177Sjhibbits    t_BusyBlock  *p_CurrB, *p_PrevB, *p_NewB;
446296177Sjhibbits
447296177Sjhibbits    p_CurrB = p_MM->busyBlocks;
448296177Sjhibbits    p_PrevB = p_NewB = 0;
449296177Sjhibbits
450296177Sjhibbits    while ( p_CurrB )
451296177Sjhibbits    {
452296177Sjhibbits        if ( base < p_CurrB->end )
453296177Sjhibbits        {
454296177Sjhibbits            if ( end > p_CurrB->end )
455296177Sjhibbits            {
456296177Sjhibbits                t_BusyBlock *p_NextB;
457296177Sjhibbits                while ( p_CurrB->p_Next && end >= p_CurrB->p_Next->end )
458296177Sjhibbits                {
459296177Sjhibbits                    p_NextB = p_CurrB->p_Next;
460296177Sjhibbits                    p_CurrB->p_Next = p_CurrB->p_Next->p_Next;
461296177Sjhibbits                    XX_Free(p_NextB);
462296177Sjhibbits                }
463296177Sjhibbits
464296177Sjhibbits                p_NextB = p_CurrB->p_Next;
465296177Sjhibbits                if ( p_NextB && end > p_NextB->base )
466296177Sjhibbits                {
467296177Sjhibbits                    p_NextB->base = end;
468296177Sjhibbits                }
469296177Sjhibbits            }
470296177Sjhibbits
471296177Sjhibbits            if ( base <= p_CurrB->base )
472296177Sjhibbits            {
473296177Sjhibbits                if ( end < p_CurrB->end && end > p_CurrB->base )
474296177Sjhibbits                {
475296177Sjhibbits                    p_CurrB->base = end;
476296177Sjhibbits                }
477296177Sjhibbits                else if ( end >= p_CurrB->end )
478296177Sjhibbits                {
479296177Sjhibbits                    if ( p_PrevB )
480296177Sjhibbits                        p_PrevB->p_Next = p_CurrB->p_Next;
481296177Sjhibbits                    else
482296177Sjhibbits                        p_MM->busyBlocks = p_CurrB->p_Next;
483296177Sjhibbits                    XX_Free(p_CurrB);
484296177Sjhibbits                }
485296177Sjhibbits            }
486296177Sjhibbits            else
487296177Sjhibbits            {
488296177Sjhibbits                if ( end < p_CurrB->end && end > p_CurrB->base )
489296177Sjhibbits                {
490296177Sjhibbits                    if ((p_NewB = CreateBusyBlock(end,
491296177Sjhibbits                                                  p_CurrB->end-end,
492296177Sjhibbits                                                  p_CurrB->name)) == NULL)
493296177Sjhibbits                        RETURN_ERROR(MAJOR, E_NO_MEMORY, NO_MSG);
494296177Sjhibbits                    p_NewB->p_Next = p_CurrB->p_Next;
495296177Sjhibbits                    p_CurrB->p_Next = p_NewB;
496296177Sjhibbits                }
497296177Sjhibbits                p_CurrB->end = base;
498296177Sjhibbits            }
499296177Sjhibbits            break;
500296177Sjhibbits        }
501296177Sjhibbits        else
502296177Sjhibbits        {
503296177Sjhibbits            p_PrevB = p_CurrB;
504296177Sjhibbits            p_CurrB = p_CurrB->p_Next;
505296177Sjhibbits        }
506296177Sjhibbits    }
507296177Sjhibbits
508296177Sjhibbits    return (E_OK);
509296177Sjhibbits}
510296177Sjhibbits
511296177Sjhibbits/****************************************************************
512296177Sjhibbits *  Routine:     MmGetGreaterAlignment
513296177Sjhibbits *
514296177Sjhibbits *  Description:
515296177Sjhibbits *      Allocates a block of memory according to the given size
516296177Sjhibbits *      and the alignment. That routine is called from the MM_Get
517296177Sjhibbits *      routine if the required alignment is greater then MM_MAX_ALIGNMENT.
518296177Sjhibbits *      In that case, it goes over free blocks of 64 byte align list
519296177Sjhibbits *      and checks if it has the required size of bytes of the required
520296177Sjhibbits *      alignment. If no blocks found returns ILLEGAL_BASE.
521296177Sjhibbits *      After the block is found and data is allocated, it calls
522296177Sjhibbits *      the internal CutFree routine to update all free lists
523296177Sjhibbits *      do not include a just allocated block. Of course, each
524296177Sjhibbits *      free list contains a free blocks with the same alignment.
525296177Sjhibbits *      It is also creates a busy block that holds
526296177Sjhibbits *      information about an allocated block.
527296177Sjhibbits *
528296177Sjhibbits *  Arguments:
529296177Sjhibbits *      MM              - handle to the MM object
530296177Sjhibbits *      size            - size of the MM
531296177Sjhibbits *      alignment       - index as a power of two defines
532296177Sjhibbits *                        a required alignment that is greater then 64.
533296177Sjhibbits *      name            - the name that specifies an allocated block.
534296177Sjhibbits *
535296177Sjhibbits *  Return value:
536296177Sjhibbits *      base address of an allocated block.
537296177Sjhibbits *      ILLEGAL_BASE if can't allocate a block
538296177Sjhibbits *
539296177Sjhibbits ****************************************************************/
540296177Sjhibbitsstatic uint64_t MmGetGreaterAlignment(t_MM *p_MM, uint64_t size, uint64_t alignment, char* name)
541296177Sjhibbits{
542296177Sjhibbits    t_FreeBlock *p_FreeB;
543296177Sjhibbits    t_BusyBlock *p_NewBusyB;
544296177Sjhibbits    uint64_t    holdBase, holdEnd, alignBase = 0;
545296177Sjhibbits
546296177Sjhibbits    /* goes over free blocks of the 64 byte alignment list
547296177Sjhibbits       and look for a block of the suitable size and
548296177Sjhibbits       base address according to the alignment. */
549296177Sjhibbits    p_FreeB = p_MM->freeBlocks[MM_MAX_ALIGNMENT];
550296177Sjhibbits
551296177Sjhibbits    while ( p_FreeB )
552296177Sjhibbits    {
553296177Sjhibbits        alignBase = MAKE_ALIGNED(p_FreeB->base, alignment);
554296177Sjhibbits
555296177Sjhibbits        /* the block is found if the aligned base inside the block
556296177Sjhibbits         * and has the anough size. */
557296177Sjhibbits        if ( alignBase >= p_FreeB->base &&
558296177Sjhibbits             alignBase < p_FreeB->end &&
559296177Sjhibbits             size <= (p_FreeB->end - alignBase) )
560296177Sjhibbits            break;
561296177Sjhibbits        else
562296177Sjhibbits            p_FreeB = p_FreeB->p_Next;
563296177Sjhibbits    }
564296177Sjhibbits
565296177Sjhibbits    /* If such block isn't found */
566296177Sjhibbits    if ( !p_FreeB )
567296177Sjhibbits        return (uint64_t)(ILLEGAL_BASE);
568296177Sjhibbits
569296177Sjhibbits    holdBase = alignBase;
570296177Sjhibbits    holdEnd = alignBase + size;
571296177Sjhibbits
572296177Sjhibbits    /* init a new busy block */
573296177Sjhibbits    if ((p_NewBusyB = CreateBusyBlock(holdBase, size, name)) == NULL)
574296177Sjhibbits        return (uint64_t)(ILLEGAL_BASE);
575296177Sjhibbits
576296177Sjhibbits    /* calls Update routine to update a lists of free blocks */
577296177Sjhibbits    if ( CutFree ( p_MM, holdBase, holdEnd ) != E_OK )
578296177Sjhibbits        return (uint64_t)(ILLEGAL_BASE);
579296177Sjhibbits
580296177Sjhibbits    /* insert the new busy block into the list of busy blocks */
581296177Sjhibbits    AddBusy ( p_MM, p_NewBusyB );
582296177Sjhibbits
583296177Sjhibbits    return (holdBase);
584296177Sjhibbits}
585296177Sjhibbits
586296177Sjhibbits
587296177Sjhibbits/**********************************************************************
588296177Sjhibbits *                     MM API routines set                            *
589296177Sjhibbits **********************************************************************/
590296177Sjhibbits
591296177Sjhibbits/*****************************************************************************/
592296177Sjhibbitst_Error MM_Init(t_Handle *h_MM, uint64_t base, uint64_t size)
593296177Sjhibbits{
594296177Sjhibbits    t_MM        *p_MM;
595296177Sjhibbits    uint64_t    newBase, newSize;
596296177Sjhibbits    int         i;
597296177Sjhibbits
598296177Sjhibbits    if (!size)
599296177Sjhibbits    {
600296177Sjhibbits        RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Size (should be positive)"));
601296177Sjhibbits    }
602296177Sjhibbits
603296177Sjhibbits    /* Initializes a new MM object */
604296177Sjhibbits    p_MM = (t_MM *)XX_Malloc(sizeof(t_MM));
605296177Sjhibbits    if (!p_MM)
606296177Sjhibbits    {
607296177Sjhibbits        RETURN_ERROR(MAJOR, E_NO_MEMORY, NO_MSG);
608296177Sjhibbits    }
609296177Sjhibbits
610296177Sjhibbits    p_MM->h_Spinlock = XX_InitSpinlock();
611296177Sjhibbits    if (!p_MM->h_Spinlock)
612296177Sjhibbits    {
613296177Sjhibbits        XX_Free(p_MM);
614296177Sjhibbits        RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MM spinlock!"));
615296177Sjhibbits    }
616296177Sjhibbits
617296177Sjhibbits    /* initializes a new memory block */
618296177Sjhibbits    if ((p_MM->memBlocks = CreateNewBlock(base, size)) == NULL)
619296177Sjhibbits        RETURN_ERROR(MAJOR, E_NO_MEMORY, NO_MSG);
620296177Sjhibbits
621296177Sjhibbits    /* A busy list is empty */
622296177Sjhibbits    p_MM->busyBlocks = 0;
623296177Sjhibbits
624296177Sjhibbits    /*Initializes a new free block for each free list*/
625296177Sjhibbits    for (i=0; i <= MM_MAX_ALIGNMENT; i++)
626296177Sjhibbits    {
627296177Sjhibbits        newBase = MAKE_ALIGNED( base, (0x1 << i) );
628296177Sjhibbits        newSize = size - (newBase - base);
629296177Sjhibbits
630296177Sjhibbits        if ((p_MM->freeBlocks[i] = CreateFreeBlock(newBase, newSize)) == NULL)
631296177Sjhibbits            RETURN_ERROR(MAJOR, E_NO_MEMORY, NO_MSG);
632296177Sjhibbits    }
633296177Sjhibbits
634296177Sjhibbits    *h_MM = p_MM;
635296177Sjhibbits
636296177Sjhibbits    return (E_OK);
637296177Sjhibbits}
638296177Sjhibbits
639296177Sjhibbits/*****************************************************************************/
640296177Sjhibbitsvoid MM_Free(t_Handle h_MM)
641296177Sjhibbits{
642296177Sjhibbits    t_MM        *p_MM = (t_MM *)h_MM;
643296177Sjhibbits    t_MemBlock  *p_MemBlock;
644296177Sjhibbits    t_BusyBlock *p_BusyBlock;
645296177Sjhibbits    t_FreeBlock *p_FreeBlock;
646296177Sjhibbits    void        *p_Block;
647296177Sjhibbits    int         i;
648296177Sjhibbits
649296177Sjhibbits    ASSERT_COND(p_MM);
650296177Sjhibbits
651296177Sjhibbits    /* release memory allocated for busy blocks */
652296177Sjhibbits    p_BusyBlock = p_MM->busyBlocks;
653296177Sjhibbits    while ( p_BusyBlock )
654296177Sjhibbits    {
655296177Sjhibbits        p_Block = p_BusyBlock;
656296177Sjhibbits        p_BusyBlock = p_BusyBlock->p_Next;
657296177Sjhibbits        XX_Free(p_Block);
658296177Sjhibbits    }
659296177Sjhibbits
660296177Sjhibbits    /* release memory allocated for free blocks */
661296177Sjhibbits    for (i=0; i <= MM_MAX_ALIGNMENT; i++)
662296177Sjhibbits    {
663296177Sjhibbits        p_FreeBlock = p_MM->freeBlocks[i];
664296177Sjhibbits        while ( p_FreeBlock )
665296177Sjhibbits        {
666296177Sjhibbits            p_Block = p_FreeBlock;
667296177Sjhibbits            p_FreeBlock = p_FreeBlock->p_Next;
668296177Sjhibbits            XX_Free(p_Block);
669296177Sjhibbits        }
670296177Sjhibbits    }
671296177Sjhibbits
672296177Sjhibbits    /* release memory allocated for memory blocks */
673296177Sjhibbits    p_MemBlock = p_MM->memBlocks;
674296177Sjhibbits    while ( p_MemBlock )
675296177Sjhibbits    {
676296177Sjhibbits        p_Block = p_MemBlock;
677296177Sjhibbits        p_MemBlock = p_MemBlock->p_Next;
678296177Sjhibbits        XX_Free(p_Block);
679296177Sjhibbits    }
680296177Sjhibbits
681296177Sjhibbits    if (p_MM->h_Spinlock)
682296177Sjhibbits        XX_FreeSpinlock(p_MM->h_Spinlock);
683296177Sjhibbits
684296177Sjhibbits    /* release memory allocated for MM object itself */
685296177Sjhibbits    XX_Free(p_MM);
686296177Sjhibbits}
687296177Sjhibbits
688296177Sjhibbits/*****************************************************************************/
689296177Sjhibbitsuint64_t MM_Get(t_Handle h_MM, uint64_t size, uint64_t alignment, char* name)
690296177Sjhibbits{
691296177Sjhibbits    t_MM        *p_MM = (t_MM *)h_MM;
692296177Sjhibbits    t_FreeBlock *p_FreeB;
693296177Sjhibbits    t_BusyBlock *p_NewBusyB;
694296177Sjhibbits    uint64_t    holdBase, holdEnd, j, i = 0;
695296177Sjhibbits    uint32_t    intFlags;
696296177Sjhibbits
697296177Sjhibbits    SANITY_CHECK_RETURN_VALUE(p_MM, E_INVALID_HANDLE, (uint64_t)ILLEGAL_BASE);
698296177Sjhibbits
699296177Sjhibbits    /* checks that alignment value is greater then zero */
700296177Sjhibbits    if (alignment == 0)
701296177Sjhibbits    {
702296177Sjhibbits        alignment = 1;
703296177Sjhibbits    }
704296177Sjhibbits
705296177Sjhibbits    j = alignment;
706296177Sjhibbits
707296177Sjhibbits    /* checks if alignment is a power of two, if it correct and if the
708296177Sjhibbits       required size is multiple of the given alignment. */
709296177Sjhibbits    while ((j & 0x1) == 0)
710296177Sjhibbits    {
711296177Sjhibbits        i++;
712296177Sjhibbits        j = j >> 1;
713296177Sjhibbits    }
714296177Sjhibbits
715296177Sjhibbits    /* if the given alignment isn't power of two, returns an error */
716296177Sjhibbits    if (j != 1)
717296177Sjhibbits    {
718296177Sjhibbits        REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("alignment (should be power of 2)"));
719296177Sjhibbits        return (uint64_t)ILLEGAL_BASE;
720296177Sjhibbits    }
721296177Sjhibbits
722296177Sjhibbits    if (i > MM_MAX_ALIGNMENT)
723296177Sjhibbits    {
724296177Sjhibbits        return (MmGetGreaterAlignment(p_MM, size, alignment, name));
725296177Sjhibbits    }
726296177Sjhibbits
727296177Sjhibbits    intFlags = XX_LockIntrSpinlock(p_MM->h_Spinlock);
728296177Sjhibbits    /* look for a block of the size greater or equal to the required size. */
729296177Sjhibbits    p_FreeB = p_MM->freeBlocks[i];
730296177Sjhibbits    while ( p_FreeB && (p_FreeB->end - p_FreeB->base) < size )
731296177Sjhibbits        p_FreeB = p_FreeB->p_Next;
732296177Sjhibbits
733296177Sjhibbits    /* If such block is found */
734296177Sjhibbits    if ( !p_FreeB )
735296177Sjhibbits    {
736296177Sjhibbits        XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags);
737296177Sjhibbits        return (uint64_t)(ILLEGAL_BASE);
738296177Sjhibbits    }
739296177Sjhibbits
740296177Sjhibbits    holdBase = p_FreeB->base;
741296177Sjhibbits    holdEnd = holdBase + size;
742296177Sjhibbits
743296177Sjhibbits    /* init a new busy block */
744296177Sjhibbits    if ((p_NewBusyB = CreateBusyBlock(holdBase, size, name)) == NULL)
745296177Sjhibbits    {
746296177Sjhibbits        XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags);
747296177Sjhibbits        return (uint64_t)(ILLEGAL_BASE);
748296177Sjhibbits    }
749296177Sjhibbits
750296177Sjhibbits    /* calls Update routine to update a lists of free blocks */
751296177Sjhibbits    if ( CutFree ( p_MM, holdBase, holdEnd ) != E_OK )
752296177Sjhibbits    {
753296177Sjhibbits        XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags);
754296177Sjhibbits        return (uint64_t)(ILLEGAL_BASE);
755296177Sjhibbits    }
756296177Sjhibbits
757296177Sjhibbits    /* insert the new busy block into the list of busy blocks */
758296177Sjhibbits    AddBusy ( p_MM, p_NewBusyB );
759296177Sjhibbits    XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags);
760296177Sjhibbits
761296177Sjhibbits    return (holdBase);
762296177Sjhibbits}
763296177Sjhibbits
764296177Sjhibbits/*****************************************************************************/
765296177Sjhibbitsuint64_t MM_GetForce(t_Handle h_MM, uint64_t base, uint64_t size, char* name)
766296177Sjhibbits{
767296177Sjhibbits    t_MM        *p_MM = (t_MM *)h_MM;
768296177Sjhibbits    t_FreeBlock *p_FreeB;
769296177Sjhibbits    t_BusyBlock *p_NewBusyB;
770296177Sjhibbits    uint32_t    intFlags;
771296177Sjhibbits    bool        blockIsFree = FALSE;
772296177Sjhibbits
773296177Sjhibbits    ASSERT_COND(p_MM);
774296177Sjhibbits
775296177Sjhibbits    intFlags = XX_LockIntrSpinlock(p_MM->h_Spinlock);
776296177Sjhibbits    p_FreeB = p_MM->freeBlocks[0]; /* The biggest free blocks are in the
777296177Sjhibbits                                      free list with alignment 1 */
778296177Sjhibbits
779296177Sjhibbits    while ( p_FreeB )
780296177Sjhibbits    {
781296177Sjhibbits        if ( base >= p_FreeB->base && (base+size) <= p_FreeB->end )
782296177Sjhibbits        {
783296177Sjhibbits            blockIsFree = TRUE;
784296177Sjhibbits            break;
785296177Sjhibbits        }
786296177Sjhibbits        else
787296177Sjhibbits            p_FreeB = p_FreeB->p_Next;
788296177Sjhibbits    }
789296177Sjhibbits
790296177Sjhibbits    if ( !blockIsFree )
791296177Sjhibbits    {
792296177Sjhibbits        XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags);
793296177Sjhibbits        return (uint64_t)(ILLEGAL_BASE);
794296177Sjhibbits    }
795296177Sjhibbits
796296177Sjhibbits    /* init a new busy block */
797296177Sjhibbits    if ((p_NewBusyB = CreateBusyBlock(base, size, name)) == NULL)
798296177Sjhibbits    {
799296177Sjhibbits        XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags);
800296177Sjhibbits        return (uint64_t)(ILLEGAL_BASE);
801296177Sjhibbits    }
802296177Sjhibbits
803296177Sjhibbits    /* calls Update routine to update a lists of free blocks */
804296177Sjhibbits    if ( CutFree ( p_MM, base, base+size ) != E_OK )
805296177Sjhibbits    {
806296177Sjhibbits        XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags);
807296177Sjhibbits        return (uint64_t)(ILLEGAL_BASE);
808296177Sjhibbits    }
809296177Sjhibbits
810296177Sjhibbits    /* insert the new busy block into the list of busy blocks */
811296177Sjhibbits    AddBusy ( p_MM, p_NewBusyB );
812296177Sjhibbits    XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags);
813296177Sjhibbits
814296177Sjhibbits    return (base);
815296177Sjhibbits}
816296177Sjhibbits
817296177Sjhibbits/*****************************************************************************/
818296177Sjhibbitsuint64_t MM_GetForceMin(t_Handle h_MM, uint64_t size, uint64_t alignment, uint64_t min, char* name)
819296177Sjhibbits{
820296177Sjhibbits    t_MM        *p_MM = (t_MM *)h_MM;
821296177Sjhibbits    t_FreeBlock *p_FreeB;
822296177Sjhibbits    t_BusyBlock *p_NewBusyB;
823296177Sjhibbits    uint64_t    holdBase, holdEnd, j = alignment, i=0;
824296177Sjhibbits    uint32_t    intFlags;
825296177Sjhibbits
826296177Sjhibbits    ASSERT_COND(p_MM);
827296177Sjhibbits
828296177Sjhibbits    /* checks if alignment is a power of two, if it correct and if the
829296177Sjhibbits       required size is multiple of the given alignment. */
830296177Sjhibbits    while ((j & 0x1) == 0)
831296177Sjhibbits    {
832296177Sjhibbits        i++;
833296177Sjhibbits        j = j >> 1;
834296177Sjhibbits    }
835296177Sjhibbits
836296177Sjhibbits    if ( (j != 1) || (i > MM_MAX_ALIGNMENT) )
837296177Sjhibbits    {
838296177Sjhibbits        return (uint64_t)(ILLEGAL_BASE);
839296177Sjhibbits    }
840296177Sjhibbits
841296177Sjhibbits    intFlags = XX_LockIntrSpinlock(p_MM->h_Spinlock);
842296177Sjhibbits    p_FreeB = p_MM->freeBlocks[i];
843296177Sjhibbits
844296177Sjhibbits    /* look for the first block that contains the minimum
845296177Sjhibbits       base address. If the whole required size may be fit
846296177Sjhibbits       into it, use that block, otherwise look for the next
847296177Sjhibbits       block of size greater or equal to the required size. */
848296177Sjhibbits    while ( p_FreeB && (min >= p_FreeB->end))
849296177Sjhibbits            p_FreeB = p_FreeB->p_Next;
850296177Sjhibbits
851296177Sjhibbits    /* If such block is found */
852296177Sjhibbits    if ( !p_FreeB )
853296177Sjhibbits    {
854296177Sjhibbits        XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags);
855296177Sjhibbits        return (uint64_t)(ILLEGAL_BASE);
856296177Sjhibbits    }
857296177Sjhibbits
858296177Sjhibbits    /* if this block is large enough, use this block */
859296177Sjhibbits    holdBase = ( min <= p_FreeB->base ) ? p_FreeB->base : min;
860296177Sjhibbits    if ((holdBase + size) <= p_FreeB->end )
861296177Sjhibbits    {
862296177Sjhibbits        holdEnd = holdBase + size;
863296177Sjhibbits    }
864296177Sjhibbits    else
865296177Sjhibbits    {
866296177Sjhibbits        p_FreeB = p_FreeB->p_Next;
867296177Sjhibbits        while ( p_FreeB && ((p_FreeB->end - p_FreeB->base) < size) )
868296177Sjhibbits            p_FreeB = p_FreeB->p_Next;
869296177Sjhibbits
870296177Sjhibbits        /* If such block is found */
871296177Sjhibbits        if ( !p_FreeB )
872296177Sjhibbits        {
873296177Sjhibbits            XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags);
874296177Sjhibbits            return (uint64_t)(ILLEGAL_BASE);
875296177Sjhibbits        }
876296177Sjhibbits
877296177Sjhibbits        holdBase = p_FreeB->base;
878296177Sjhibbits        holdEnd = holdBase + size;
879296177Sjhibbits    }
880296177Sjhibbits
881296177Sjhibbits    /* init a new busy block */
882296177Sjhibbits    if ((p_NewBusyB = CreateBusyBlock(holdBase, size, name)) == NULL)
883296177Sjhibbits    {
884296177Sjhibbits        XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags);
885296177Sjhibbits        return (uint64_t)(ILLEGAL_BASE);
886296177Sjhibbits    }
887296177Sjhibbits
888296177Sjhibbits    /* calls Update routine to update a lists of free blocks */
889296177Sjhibbits    if ( CutFree( p_MM, holdBase, holdEnd ) != E_OK )
890296177Sjhibbits    {
891296177Sjhibbits        XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags);
892296177Sjhibbits        return (uint64_t)(ILLEGAL_BASE);
893296177Sjhibbits    }
894296177Sjhibbits
895296177Sjhibbits    /* insert the new busy block into the list of busy blocks */
896296177Sjhibbits    AddBusy( p_MM, p_NewBusyB );
897296177Sjhibbits    XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags);
898296177Sjhibbits
899296177Sjhibbits    return (holdBase);
900296177Sjhibbits}
901296177Sjhibbits
902296177Sjhibbits/*****************************************************************************/
903296177Sjhibbitsuint64_t MM_Put(t_Handle h_MM, uint64_t base)
904296177Sjhibbits{
905296177Sjhibbits    t_MM        *p_MM = (t_MM *)h_MM;
906296177Sjhibbits    t_BusyBlock *p_BusyB, *p_PrevBusyB;
907296177Sjhibbits    uint64_t    size;
908296177Sjhibbits    uint32_t    intFlags;
909296177Sjhibbits
910296177Sjhibbits    ASSERT_COND(p_MM);
911296177Sjhibbits
912296177Sjhibbits    /* Look for a busy block that have the given base value.
913296177Sjhibbits     * That block will be returned back to the memory.
914296177Sjhibbits     */
915296177Sjhibbits    p_PrevBusyB = 0;
916296177Sjhibbits
917296177Sjhibbits    intFlags = XX_LockIntrSpinlock(p_MM->h_Spinlock);
918296177Sjhibbits    p_BusyB = p_MM->busyBlocks;
919296177Sjhibbits    while ( p_BusyB && base != p_BusyB->base )
920296177Sjhibbits    {
921296177Sjhibbits        p_PrevBusyB = p_BusyB;
922296177Sjhibbits        p_BusyB = p_BusyB->p_Next;
923296177Sjhibbits    }
924296177Sjhibbits
925296177Sjhibbits    if ( !p_BusyB )
926296177Sjhibbits    {
927296177Sjhibbits        XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags);
928296177Sjhibbits        return (uint64_t)(0);
929296177Sjhibbits    }
930296177Sjhibbits
931296177Sjhibbits    if ( AddFree( p_MM, p_BusyB->base, p_BusyB->end ) != E_OK )
932296177Sjhibbits    {
933296177Sjhibbits        XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags);
934296177Sjhibbits        return (uint64_t)(0);
935296177Sjhibbits    }
936296177Sjhibbits
937296177Sjhibbits    /* removes a busy block form the list of busy blocks */
938296177Sjhibbits    if ( p_PrevBusyB )
939296177Sjhibbits        p_PrevBusyB->p_Next = p_BusyB->p_Next;
940296177Sjhibbits    else
941296177Sjhibbits        p_MM->busyBlocks = p_BusyB->p_Next;
942296177Sjhibbits
943296177Sjhibbits    size = p_BusyB->end - p_BusyB->base;
944296177Sjhibbits
945296177Sjhibbits    XX_Free(p_BusyB);
946296177Sjhibbits    XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags);
947296177Sjhibbits
948296177Sjhibbits    return (size);
949296177Sjhibbits}
950296177Sjhibbits
951296177Sjhibbits/*****************************************************************************/
952296177Sjhibbitsuint64_t MM_PutForce(t_Handle h_MM, uint64_t base, uint64_t size)
953296177Sjhibbits{
954296177Sjhibbits    t_MM        *p_MM = (t_MM *)h_MM;
955296177Sjhibbits    uint64_t    end = base + size;
956296177Sjhibbits    uint32_t    intFlags;
957296177Sjhibbits
958296177Sjhibbits    ASSERT_COND(p_MM);
959296177Sjhibbits
960296177Sjhibbits    intFlags = XX_LockIntrSpinlock(p_MM->h_Spinlock);
961296177Sjhibbits    if ( CutBusy( p_MM, base, end ) != E_OK )
962296177Sjhibbits    {
963296177Sjhibbits        XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags);
964296177Sjhibbits        return (uint64_t)(0);
965296177Sjhibbits    }
966296177Sjhibbits
967296177Sjhibbits    if ( AddFree ( p_MM, base, end ) != E_OK )
968296177Sjhibbits    {
969296177Sjhibbits        XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags);
970296177Sjhibbits        return (uint64_t)(0);
971296177Sjhibbits    }
972296177Sjhibbits    XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags);
973296177Sjhibbits
974296177Sjhibbits    return (size);
975296177Sjhibbits}
976296177Sjhibbits
977296177Sjhibbits/*****************************************************************************/
978296177Sjhibbitst_Error MM_Add(t_Handle h_MM, uint64_t base, uint64_t size)
979296177Sjhibbits{
980296177Sjhibbits    t_MM        *p_MM = (t_MM *)h_MM;
981296177Sjhibbits    t_MemBlock  *p_MemB, *p_NewMemB;
982296177Sjhibbits    t_Error     errCode;
983296177Sjhibbits    uint32_t    intFlags;
984296177Sjhibbits
985296177Sjhibbits    ASSERT_COND(p_MM);
986296177Sjhibbits
987296177Sjhibbits    /* find a last block in the list of memory blocks to insert a new
988296177Sjhibbits     * memory block
989296177Sjhibbits     */
990296177Sjhibbits    intFlags = XX_LockIntrSpinlock(p_MM->h_Spinlock);
991296177Sjhibbits    p_MemB = p_MM->memBlocks;
992296177Sjhibbits    while ( p_MemB->p_Next )
993296177Sjhibbits    {
994296177Sjhibbits        if ( base >= p_MemB->base && base < p_MemB->end )
995296177Sjhibbits        {
996296177Sjhibbits        XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags);
997296177Sjhibbits            RETURN_ERROR(MAJOR, E_ALREADY_EXISTS, NO_MSG);
998296177Sjhibbits        }
999296177Sjhibbits        p_MemB = p_MemB->p_Next;
1000296177Sjhibbits    }
1001296177Sjhibbits    /* check for a last memory block */
1002296177Sjhibbits    if ( base >= p_MemB->base && base < p_MemB->end )
1003296177Sjhibbits    {
1004296177Sjhibbits        XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags);
1005296177Sjhibbits        RETURN_ERROR(MAJOR, E_ALREADY_EXISTS, NO_MSG);
1006296177Sjhibbits    }
1007296177Sjhibbits
1008296177Sjhibbits    /* create a new memory block */
1009296177Sjhibbits    if ((p_NewMemB = CreateNewBlock(base, size)) == NULL)
1010296177Sjhibbits    {
1011296177Sjhibbits        XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags);
1012296177Sjhibbits        RETURN_ERROR(MAJOR, E_NO_MEMORY, NO_MSG);
1013296177Sjhibbits    }
1014296177Sjhibbits
1015296177Sjhibbits    /* append a new memory block to the end of the list of memory blocks */
1016296177Sjhibbits    p_MemB->p_Next = p_NewMemB;
1017296177Sjhibbits
1018296177Sjhibbits    /* add a new free block to the free lists */
1019296177Sjhibbits    errCode = AddFree(p_MM, base, base+size);
1020296177Sjhibbits    if (errCode)
1021296177Sjhibbits    {
1022296177Sjhibbits        XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags);
1023296177Sjhibbits        p_MemB->p_Next = 0;
1024296177Sjhibbits        XX_Free(p_NewMemB);
1025296177Sjhibbits        return ((t_Error)errCode);
1026296177Sjhibbits    }
1027296177Sjhibbits    XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags);
1028296177Sjhibbits
1029296177Sjhibbits    return (E_OK);
1030296177Sjhibbits}
1031296177Sjhibbits
1032296177Sjhibbits/*****************************************************************************/
1033296177Sjhibbitsuint64_t MM_GetMemBlock(t_Handle h_MM, int index)
1034296177Sjhibbits{
1035296177Sjhibbits    t_MM       *p_MM = (t_MM*)h_MM;
1036296177Sjhibbits    t_MemBlock *p_MemBlock;
1037296177Sjhibbits    int         i;
1038296177Sjhibbits
1039296177Sjhibbits    ASSERT_COND(p_MM);
1040296177Sjhibbits
1041296177Sjhibbits    p_MemBlock = p_MM->memBlocks;
1042296177Sjhibbits    for (i=0; i < index; i++)
1043296177Sjhibbits        p_MemBlock = p_MemBlock->p_Next;
1044296177Sjhibbits
1045296177Sjhibbits    if ( p_MemBlock )
1046296177Sjhibbits        return (p_MemBlock->base);
1047296177Sjhibbits    else
1048296177Sjhibbits        return (uint64_t)ILLEGAL_BASE;
1049296177Sjhibbits}
1050296177Sjhibbits
1051296177Sjhibbits/*****************************************************************************/
1052296177Sjhibbitsuint64_t MM_GetBase(t_Handle h_MM)
1053296177Sjhibbits{
1054296177Sjhibbits    t_MM       *p_MM = (t_MM*)h_MM;
1055296177Sjhibbits    t_MemBlock *p_MemBlock;
1056296177Sjhibbits
1057296177Sjhibbits    ASSERT_COND(p_MM);
1058296177Sjhibbits
1059296177Sjhibbits    p_MemBlock = p_MM->memBlocks;
1060296177Sjhibbits    return  p_MemBlock->base;
1061296177Sjhibbits}
1062296177Sjhibbits
1063296177Sjhibbits/*****************************************************************************/
1064296177Sjhibbitsbool MM_InRange(t_Handle h_MM, uint64_t addr)
1065296177Sjhibbits{
1066296177Sjhibbits    t_MM       *p_MM = (t_MM*)h_MM;
1067296177Sjhibbits    t_MemBlock *p_MemBlock;
1068296177Sjhibbits
1069296177Sjhibbits    ASSERT_COND(p_MM);
1070296177Sjhibbits
1071296177Sjhibbits    p_MemBlock = p_MM->memBlocks;
1072296177Sjhibbits
1073296177Sjhibbits    if ((addr >= p_MemBlock->base) && (addr < p_MemBlock->end))
1074296177Sjhibbits        return TRUE;
1075296177Sjhibbits    else
1076296177Sjhibbits        return FALSE;
1077296177Sjhibbits}
1078296177Sjhibbits
1079296177Sjhibbits/*****************************************************************************/
1080296177Sjhibbitsvoid MM_Dump(t_Handle h_MM, void *buff)
1081296177Sjhibbits{
1082296177Sjhibbits    t_MM        *p_MM = (t_MM *)h_MM;
1083296177Sjhibbits    t_FreeBlock *p_FreeB;
1084296177Sjhibbits    t_BusyBlock *p_BusyB;
1085296177Sjhibbits    int          i;
1086296177Sjhibbits
1087296177Sjhibbits    p_BusyB = p_MM->busyBlocks;
1088296177Sjhibbits    Sprint(buff, "List of busy blocks:\n");
1089296177Sjhibbits    while (p_BusyB)
1090296177Sjhibbits    {
1091296177Sjhibbits        Sprint(buff, "\t0x%p: (%s: b=0x%lx, e=0x%lx)\n",
1092296177Sjhibbits               p_BusyB, p_BusyB->name, p_BusyB->base, p_BusyB->end );
1093296177Sjhibbits        p_BusyB = p_BusyB->p_Next;
1094296177Sjhibbits    }
1095296177Sjhibbits
1096296177Sjhibbits    Sprint(buff, "\nLists of free blocks according to alignment:\n");
1097296177Sjhibbits    for (i=0; i <= MM_MAX_ALIGNMENT; i++)
1098296177Sjhibbits    {
1099296177Sjhibbits        Sprint(buff, "%d alignment:\n", (0x1 << i));
1100296177Sjhibbits        p_FreeB = p_MM->freeBlocks[i];
1101296177Sjhibbits        while (p_FreeB)
1102296177Sjhibbits        {
1103296177Sjhibbits            Sprint(buff, "\t0x%p: (b=0x%lx, e=0x%lx)\n",
1104296177Sjhibbits                   p_FreeB, p_FreeB->base, p_FreeB->end);
1105296177Sjhibbits            p_FreeB = p_FreeB->p_Next;
1106296177Sjhibbits        }
1107296177Sjhibbits        Sprint(buff, "\n");
1108296177Sjhibbits    }
1109296177Sjhibbits}
1110