summaryrefslogtreecommitdiff
path: root/drivers/net/ethernet/freescale/fman/etc
diff options
context:
space:
mode:
authorMandy Lavi <mandy.lavi@freescale.com>2013-03-24 16:40:18 (GMT)
committerFleming Andrew-AFLEMING <AFLEMING@freescale.com>2013-04-08 23:07:26 (GMT)
commit3cc514986cb4e457458cc826288b6c2107c97907 (patch)
tree2985e48afc5dd20f44d51ef6aafdae917ce2698f /drivers/net/ethernet/freescale/fman/etc
parent5767d52cec831b0e2927d34e91acd738cc1cb0ef (diff)
downloadlinux-fsl-qoriq-3cc514986cb4e457458cc826288b6c2107c97907.tar.xz
fmd: fmd19 integration
Add fmd19 codebase, plus a minimal set of sources from dpaa-eth, necessary for bare compilation Change-Id: I390df8717671204e3d98a987135393bef4534e95 Signed-off-by: Mandy Lavi <mandy.lavi@freescale.com> Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com> Reviewed-on: http://git.am.freescale.net:8181/1029 Reviewed-by: Fleming Andrew-AFLEMING <AFLEMING@freescale.com> Tested-by: Fleming Andrew-AFLEMING <AFLEMING@freescale.com>
Diffstat (limited to 'drivers/net/ethernet/freescale/fman/etc')
-rw-r--r--drivers/net/ethernet/freescale/fman/etc/Makefile12
-rw-r--r--drivers/net/ethernet/freescale/fman/etc/error.c95
-rw-r--r--drivers/net/ethernet/freescale/fman/etc/list.c71
-rw-r--r--drivers/net/ethernet/freescale/fman/etc/memcpy.c601
-rw-r--r--drivers/net/ethernet/freescale/fman/etc/mm.c1142
-rw-r--r--drivers/net/ethernet/freescale/fman/etc/mm.h105
-rw-r--r--drivers/net/ethernet/freescale/fman/etc/sprint.c81
7 files changed, 2107 insertions, 0 deletions
diff --git a/drivers/net/ethernet/freescale/fman/etc/Makefile b/drivers/net/ethernet/freescale/fman/etc/Makefile
new file mode 100644
index 0000000..5e7c382
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/etc/Makefile
@@ -0,0 +1,12 @@
+#
+# Makefile for the Freescale Ethernet controllers
+#
+EXTRA_CFLAGS += -DVERSION=\"\"
+#
+#Include netcomm SW specific definitions
+
+include $(srctree)/drivers/net/ethernet/freescale/fman/ncsw_config.mk
+
+obj-y += fsl-ncsw-etc.o
+
+fsl-ncsw-etc-objs := mm.o memcpy.o sprint.o list.o error.o
diff --git a/drivers/net/ethernet/freescale/fman/etc/error.c b/drivers/net/ethernet/freescale/fman/etc/error.c
new file mode 100644
index 0000000..fead7f50
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/etc/error.c
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+/*
+
+ @File error.c
+
+ @Description General errors and events reporting utilities.
+*//***************************************************************************/
+#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0))
+#include "error_ext.h"
+
+
+const char *dbgLevelStrings[] =
+{
+ "CRITICAL"
+ ,"MAJOR"
+ ,"MINOR"
+ ,"WARNING"
+ ,"INFO"
+ ,"TRACE"
+};
+
+
+char * ErrTypeStrings (e_ErrorType err)
+{
+ switch (err)
+ {
+ case (E_OK): return "OK";
+ case (E_WRITE_FAILED): return "Write Access Failed";
+ case (E_NO_DEVICE): return "No Device";
+ case (E_NOT_AVAILABLE): return "Resource Is Unavailable";
+ case (E_NO_MEMORY): return "Memory Allocation Failed";
+ case (E_INVALID_ADDRESS): return "Invalid Address";
+ case (E_BUSY): return "Resource Is Busy";
+ case (E_ALREADY_EXISTS): return "Resource Already Exists";
+ case (E_INVALID_OPERATION): return "Invalid Operation";
+ case (E_INVALID_VALUE): return "Invalid Value";
+ case (E_NOT_IN_RANGE): return "Value Out Of Range";
+ case (E_NOT_SUPPORTED): return "Unsupported Operation";
+ case (E_INVALID_STATE): return "Invalid State";
+ case (E_INVALID_HANDLE): return "Invalid Handle";
+ case (E_INVALID_ID): return "Invalid ID";
+ case (E_NULL_POINTER): return "Unexpected NULL Pointer";
+ case (E_INVALID_SELECTION): return "Invalid Selection";
+ case (E_INVALID_COMM_MODE): return "Invalid Communication Mode";
+ case (E_INVALID_MEMORY_TYPE): return "Invalid Memory Type";
+ case (E_INVALID_CLOCK): return "Invalid Clock";
+ case (E_CONFLICT): return "Conflict In Settings";
+ case (E_NOT_ALIGNED): return "Incorrect Alignment";
+ case (E_NOT_FOUND): return "Resource Not Found";
+ case (E_FULL): return "Resource Is Full";
+ case (E_EMPTY): return "Resource Is Empty";
+ case (E_ALREADY_FREE): return "Resource Already Free";
+ case (E_READ_FAILED): return "Read Access Failed";
+ case (E_INVALID_FRAME): return "Invalid Frame";
+ case (E_SEND_FAILED): return "Send Operation Failed";
+ case (E_RECEIVE_FAILED): return "Receive Operation Failed";
+ case (E_TIMEOUT): return "Operation Timed Out";
+ default:
+ break;
+ }
+ return NULL;
+}
+#endif /* (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0)) */
diff --git a/drivers/net/ethernet/freescale/fman/etc/list.c b/drivers/net/ethernet/freescale/fman/etc/list.c
new file mode 100644
index 0000000..2d044be
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/etc/list.c
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+/**************************************************************************//**
+
+ @File list.c
+
+ @Description Implementation of list.
+*//***************************************************************************/
+#include "std_ext.h"
+#include "list_ext.h"
+
+
+void LIST_Append(t_List *p_NewList, t_List *p_Head)
+{
+ t_List *p_First = LIST_FIRST(p_NewList);
+
+ if (p_First != p_NewList)
+ {
+ t_List *p_Last = LIST_LAST(p_NewList);
+ t_List *p_Cur = LIST_NEXT(p_Head);
+
+ LIST_PREV(p_First) = p_Head;
+ LIST_FIRST(p_Head) = p_First;
+ LIST_NEXT(p_Last) = p_Cur;
+ LIST_LAST(p_Cur) = p_Last;
+ }
+}
+
+
+int LIST_NumOfObjs(t_List *p_List)
+{
+ t_List *p_Tmp;
+ int numOfObjs = 0;
+
+ if (!LIST_IsEmpty(p_List))
+ LIST_FOR_EACH(p_Tmp, p_List)
+ numOfObjs++;
+
+ return numOfObjs;
+}
diff --git a/drivers/net/ethernet/freescale/fman/etc/memcpy.c b/drivers/net/ethernet/freescale/fman/etc/memcpy.c
new file mode 100644
index 0000000..02973e5
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/etc/memcpy.c
@@ -0,0 +1,601 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+
+#include "std_ext.h"
+#include "xx_ext.h"
+#include "memcpy_ext.h"
+
+
+void * MemCpy32(void* pDst,void* pSrc, uint32_t size)
+{
+ uint32_t leftAlign;
+ uint32_t rightAlign;
+ uint32_t lastWord;
+ uint32_t currWord;
+ uint32_t *p_Src32;
+ uint32_t *p_Dst32;
+ uint8_t *p_Src8;
+ uint8_t *p_Dst8;
+
+ p_Src8 = (uint8_t*)(pSrc);
+ p_Dst8 = (uint8_t*)(pDst);
+ /* first copy byte by byte till the source first alignment
+ * this step is necessary to ensure we do not even try to access
+ * data which is before the source buffer, hence it is not ours.
+ */
+ while((PTR_TO_UINT(p_Src8) & 3) && size) /* (pSrc mod 4) > 0 and size > 0 */
+ {
+ *p_Dst8++ = *p_Src8++;
+ size--;
+ }
+
+ /* align destination (possibly disaligning source)*/
+ while((PTR_TO_UINT(p_Dst8) & 3) && size) /* (pDst mod 4) > 0 and size > 0 */
+ {
+ *p_Dst8++ = *p_Src8++;
+ size--;
+ }
+
+ /* dest is aligned and source is not necessarily aligned */
+ leftAlign = (uint32_t)((PTR_TO_UINT(p_Src8) & 3) << 3); /* leftAlign = (pSrc mod 4)*8 */
+ rightAlign = 32 - leftAlign;
+
+
+ if (leftAlign == 0)
+ {
+ /* source is also aligned */
+ p_Src32 = (uint32_t*)(p_Src8);
+ p_Dst32 = (uint32_t*)(p_Dst8);
+ while (size >> 2) /* size >= 4 */
+ {
+ *p_Dst32++ = *p_Src32++;
+ size -= 4;
+ }
+ p_Src8 = (uint8_t*)(p_Src32);
+ p_Dst8 = (uint8_t*)(p_Dst32);
+ }
+ else
+ {
+ /* source is not aligned (destination is aligned)*/
+ p_Src32 = (uint32_t*)(p_Src8 - (leftAlign >> 3));
+ p_Dst32 = (uint32_t*)(p_Dst8);
+ lastWord = *p_Src32++;
+ while(size >> 3) /* size >= 8 */
+ {
+ currWord = *p_Src32;
+ *p_Dst32 = (lastWord << leftAlign) | (currWord >> rightAlign);
+ lastWord = currWord;
+ p_Src32++;
+ p_Dst32++;
+ size -= 4;
+ }
+ p_Dst8 = (uint8_t*)(p_Dst32);
+ p_Src8 = (uint8_t*)(p_Src32) - 4 + (leftAlign >> 3);
+ }
+
+ /* complete the left overs */
+ while (size--)
+ *p_Dst8++ = *p_Src8++;
+
+ return pDst;
+}
+
+void * IO2IOCpy32(void* pDst,void* pSrc, uint32_t size)
+{
+ uint32_t leftAlign;
+ uint32_t rightAlign;
+ uint32_t lastWord;
+ uint32_t currWord;
+ uint32_t *p_Src32;
+ uint32_t *p_Dst32;
+ uint8_t *p_Src8;
+ uint8_t *p_Dst8;
+
+ p_Src8 = (uint8_t*)(pSrc);
+ p_Dst8 = (uint8_t*)(pDst);
+ /* first copy byte by byte till the source first alignment
+ * this step is necessary to ensure we do not even try to access
+ * data which is before the source buffer, hence it is not ours.
+ */
+ while((PTR_TO_UINT(p_Src8) & 3) && size) /* (pSrc mod 4) > 0 and size > 0 */
+ {
+ WRITE_UINT8(*p_Dst8, GET_UINT8(*p_Src8));
+ p_Dst8++;p_Src8++;
+ size--;
+ }
+
+ /* align destination (possibly disaligning source)*/
+ while((PTR_TO_UINT(p_Dst8) & 3) && size) /* (pDst mod 4) > 0 and size > 0 */
+ {
+ WRITE_UINT8(*p_Dst8, GET_UINT8(*p_Src8));
+ p_Dst8++;p_Src8++;
+ size--;
+ }
+
+ /* dest is aligned and source is not necessarily aligned */
+ leftAlign = (uint32_t)((PTR_TO_UINT(p_Src8) & 3) << 3); /* leftAlign = (pSrc mod 4)*8 */
+ rightAlign = 32 - leftAlign;
+
+ if (leftAlign == 0)
+ {
+ /* source is also aligned */
+ p_Src32 = (uint32_t*)(p_Src8);
+ p_Dst32 = (uint32_t*)(p_Dst8);
+ while (size >> 2) /* size >= 4 */
+ {
+ WRITE_UINT32(*p_Dst32, GET_UINT32(*p_Src32));
+ p_Dst32++;p_Src32++;
+ size -= 4;
+ }
+ p_Src8 = (uint8_t*)(p_Src32);
+ p_Dst8 = (uint8_t*)(p_Dst32);
+ }
+ else
+ {
+ /* source is not aligned (destination is aligned)*/
+ p_Src32 = (uint32_t*)(p_Src8 - (leftAlign >> 3));
+ p_Dst32 = (uint32_t*)(p_Dst8);
+ lastWord = GET_UINT32(*p_Src32);
+ p_Src32++;
+ while(size >> 3) /* size >= 8 */
+ {
+ currWord = GET_UINT32(*p_Src32);
+ WRITE_UINT32(*p_Dst32, (lastWord << leftAlign) | (currWord >> rightAlign));
+ lastWord = currWord;
+ p_Src32++;p_Dst32++;
+ size -= 4;
+ }
+ p_Dst8 = (uint8_t*)(p_Dst32);
+ p_Src8 = (uint8_t*)(p_Src32) - 4 + (leftAlign >> 3);
+ }
+
+ /* complete the left overs */
+ while (size--)
+ {
+ WRITE_UINT8(*p_Dst8, GET_UINT8(*p_Src8));
+ p_Dst8++;p_Src8++;
+ }
+
+ return pDst;
+}
+
+void * Mem2IOCpy32(void* pDst,void* pSrc, uint32_t size)
+{
+ uint32_t leftAlign;
+ uint32_t rightAlign;
+ uint32_t lastWord;
+ uint32_t currWord;
+ uint32_t *p_Src32;
+ uint32_t *p_Dst32;
+ uint8_t *p_Src8;
+ uint8_t *p_Dst8;
+
+ p_Src8 = (uint8_t*)(pSrc);
+ p_Dst8 = (uint8_t*)(pDst);
+ /* first copy byte by byte till the source first alignment
+ * this step is necessary to ensure we do not even try to access
+ * data which is before the source buffer, hence it is not ours.
+ */
+ while((PTR_TO_UINT(p_Src8) & 3) && size) /* (pSrc mod 4) > 0 and size > 0 */
+ {
+ WRITE_UINT8(*p_Dst8, *p_Src8);
+ p_Dst8++;p_Src8++;
+ size--;
+ }
+
+ /* align destination (possibly disaligning source)*/
+ while((PTR_TO_UINT(p_Dst8) & 3) && size) /* (pDst mod 4) > 0 and size > 0 */
+ {
+ WRITE_UINT8(*p_Dst8, *p_Src8);
+ p_Dst8++;p_Src8++;
+ size--;
+ }
+
+ /* dest is aligned and source is not necessarily aligned */
+ leftAlign = (uint32_t)((PTR_TO_UINT(p_Src8) & 3) << 3); /* leftAlign = (pSrc mod 4)*8 */
+ rightAlign = 32 - leftAlign;
+
+ if (leftAlign == 0)
+ {
+ /* source is also aligned */
+ p_Src32 = (uint32_t*)(p_Src8);
+ p_Dst32 = (uint32_t*)(p_Dst8);
+ while (size >> 2) /* size >= 4 */
+ {
+ WRITE_UINT32(*p_Dst32, *p_Src32);
+ p_Dst32++;p_Src32++;
+ size -= 4;
+ }
+ p_Src8 = (uint8_t*)(p_Src32);
+ p_Dst8 = (uint8_t*)(p_Dst32);
+ }
+ else
+ {
+ /* source is not aligned (destination is aligned)*/
+ p_Src32 = (uint32_t*)(p_Src8 - (leftAlign >> 3));
+ p_Dst32 = (uint32_t*)(p_Dst8);
+ lastWord = *p_Src32++;
+ while(size >> 3) /* size >= 8 */
+ {
+ currWord = *p_Src32;
+ WRITE_UINT32(*p_Dst32, (lastWord << leftAlign) | (currWord >> rightAlign));
+ lastWord = currWord;
+ p_Src32++;p_Dst32++;
+ size -= 4;
+ }
+ p_Dst8 = (uint8_t*)(p_Dst32);
+ p_Src8 = (uint8_t*)(p_Src32) - 4 + (leftAlign >> 3);
+ }
+
+ /* complete the left overs */
+ while (size--)
+ {
+ WRITE_UINT8(*p_Dst8, *p_Src8);
+ p_Dst8++;p_Src8++;
+ }
+
+ return pDst;
+}
+
+void * IO2MemCpy32(void* pDst,void* pSrc, uint32_t size)
+{
+ uint32_t leftAlign;
+ uint32_t rightAlign;
+ uint32_t lastWord;
+ uint32_t currWord;
+ uint32_t *p_Src32;
+ uint32_t *p_Dst32;
+ uint8_t *p_Src8;
+ uint8_t *p_Dst8;
+
+ p_Src8 = (uint8_t*)(pSrc);
+ p_Dst8 = (uint8_t*)(pDst);
+ /* first copy byte by byte till the source first alignment
+ * this step is necessary to ensure we do not even try to access
+ * data which is before the source buffer, hence it is not ours.
+ */
+ while((PTR_TO_UINT(p_Src8) & 3) && size) /* (pSrc mod 4) > 0 and size > 0 */
+ {
+ *p_Dst8 = GET_UINT8(*p_Src8);
+ p_Dst8++;p_Src8++;
+ size--;
+ }
+
+ /* align destination (possibly disaligning source)*/
+ while((PTR_TO_UINT(p_Dst8) & 3) && size) /* (pDst mod 4) > 0 and size > 0 */
+ {
+ *p_Dst8 = GET_UINT8(*p_Src8);
+ p_Dst8++;p_Src8++;
+ size--;
+ }
+
+ /* dest is aligned and source is not necessarily aligned */
+ leftAlign = (uint32_t)((PTR_TO_UINT(p_Src8) & 3) << 3); /* leftAlign = (pSrc mod 4)*8 */
+ rightAlign = 32 - leftAlign;
+
+ if (leftAlign == 0)
+ {
+ /* source is also aligned */
+ p_Src32 = (uint32_t*)(p_Src8);
+ p_Dst32 = (uint32_t*)(p_Dst8);
+ while (size >> 2) /* size >= 4 */
+ {
+ *p_Dst32 = GET_UINT32(*p_Src32);
+ p_Dst32++;p_Src32++;
+ size -= 4;
+ }
+ p_Src8 = (uint8_t*)(p_Src32);
+ p_Dst8 = (uint8_t*)(p_Dst32);
+ }
+ else
+ {
+ /* source is not aligned (destination is aligned)*/
+ p_Src32 = (uint32_t*)(p_Src8 - (leftAlign >> 3));
+ p_Dst32 = (uint32_t*)(p_Dst8);
+ lastWord = GET_UINT32(*p_Src32);
+ p_Src32++;
+ while(size >> 3) /* size >= 8 */
+ {
+ currWord = GET_UINT32(*p_Src32);
+ *p_Dst32 = (lastWord << leftAlign) | (currWord >> rightAlign);
+ lastWord = currWord;
+ p_Src32++;p_Dst32++;
+ size -= 4;
+ }
+ p_Dst8 = (uint8_t*)(p_Dst32);
+ p_Src8 = (uint8_t*)(p_Src32) - 4 + (leftAlign >> 3);
+ }
+
+ /* complete the left overs */
+ while (size--)
+ {
+ *p_Dst8 = GET_UINT8(*p_Src8);
+ p_Dst8++;p_Src8++;
+ }
+
+ return pDst;
+}
+
+void * MemCpy64(void* pDst,void* pSrc, uint32_t size)
+{
+ uint32_t leftAlign;
+ uint32_t rightAlign;
+ uint64_t lastWord;
+ uint64_t currWord;
+ uint64_t *pSrc64;
+ uint64_t *pDst64;
+ uint8_t *p_Src8;
+ uint8_t *p_Dst8;
+
+ p_Src8 = (uint8_t*)(pSrc);
+ p_Dst8 = (uint8_t*)(pDst);
+ /* first copy byte by byte till the source first alignment
+ * this step is necessarily to ensure we do not even try to access
+ * data which is before the source buffer, hence it is not ours.
+ */
+ while((PTR_TO_UINT(p_Src8) & 7) && size) /* (pSrc mod 8) > 0 and size > 0 */
+ {
+ *p_Dst8++ = *p_Src8++;
+ size--;
+ }
+
+ /* align destination (possibly disaligning source)*/
+ while((PTR_TO_UINT(p_Dst8) & 7) && size) /* (pDst mod 8) > 0 and size > 0 */
+ {
+ *p_Dst8++ = *p_Src8++;
+ size--;
+ }
+
+ /* dest is aligned and source is not necessarily aligned */
+ leftAlign = (uint32_t)((PTR_TO_UINT(p_Src8) & 7) << 3); /* leftAlign = (pSrc mod 8)*8 */
+ rightAlign = 64 - leftAlign;
+
+
+ if (leftAlign == 0)
+ {
+ /* source is also aligned */
+ pSrc64 = (uint64_t*)(p_Src8);
+ pDst64 = (uint64_t*)(p_Dst8);
+ while (size >> 3) /* size >= 8 */
+ {
+ *pDst64++ = *pSrc64++;
+ size -= 8;
+ }
+ p_Src8 = (uint8_t*)(pSrc64);
+ p_Dst8 = (uint8_t*)(pDst64);
+ }
+ else
+ {
+ /* source is not aligned (destination is aligned)*/
+ pSrc64 = (uint64_t*)(p_Src8 - (leftAlign >> 3));
+ pDst64 = (uint64_t*)(p_Dst8);
+ lastWord = *pSrc64++;
+ while(size >> 4) /* size >= 16 */
+ {
+ currWord = *pSrc64;
+ *pDst64 = (lastWord << leftAlign) | (currWord >> rightAlign);
+ lastWord = currWord;
+ pSrc64++;
+ pDst64++;
+ size -= 8;
+ }
+ p_Dst8 = (uint8_t*)(pDst64);
+ p_Src8 = (uint8_t*)(pSrc64) - 8 + (leftAlign >> 3);
+ }
+
+ /* complete the left overs */
+ while (size--)
+ *p_Dst8++ = *p_Src8++;
+
+ return pDst;
+}
+
+void * MemSet32(void* pDst, uint8_t val, uint32_t size)
+{
+ uint32_t val32;
+ uint32_t *p_Dst32;
+ uint8_t *p_Dst8;
+
+ p_Dst8 = (uint8_t*)(pDst);
+
+ /* generate four 8-bit val's in 32-bit container */
+ val32 = (uint32_t) val;
+ val32 |= (val32 << 8);
+ val32 |= (val32 << 16);
+
+ /* align destination to 32 */
+ while((PTR_TO_UINT(p_Dst8) & 3) && size) /* (pDst mod 4) > 0 and size > 0 */
+ {
+ *p_Dst8++ = val;
+ size--;
+ }
+
+ /* 32-bit chunks */
+ p_Dst32 = (uint32_t*)(p_Dst8);
+ while (size >> 2) /* size >= 4 */
+ {
+ *p_Dst32++ = val32;
+ size -= 4;
+ }
+
+ /* complete the leftovers */
+ p_Dst8 = (uint8_t*)(p_Dst32);
+ while (size--)
+ *p_Dst8++ = val;
+
+ return pDst;
+}
+
+void * IOMemSet32(void* pDst, uint8_t val, uint32_t size)
+{
+ uint32_t val32;
+ uint32_t *p_Dst32;
+ uint8_t *p_Dst8;
+
+ p_Dst8 = (uint8_t*)(pDst);
+
+ /* generate four 8-bit val's in 32-bit container */
+ val32 = (uint32_t) val;
+ val32 |= (val32 << 8);
+ val32 |= (val32 << 16);
+
+ /* align destination to 32 */
+ while((PTR_TO_UINT(p_Dst8) & 3) && size) /* (pDst mod 4) > 0 and size > 0 */
+ {
+ WRITE_UINT8(*p_Dst8, val);
+ p_Dst8++;
+ size--;
+ }
+
+ /* 32-bit chunks */
+ p_Dst32 = (uint32_t*)(p_Dst8);
+ while (size >> 2) /* size >= 4 */
+ {
+ WRITE_UINT32(*p_Dst32, val32);
+ p_Dst32++;
+ size -= 4;
+ }
+
+ /* complete the leftovers */
+ p_Dst8 = (uint8_t*)(p_Dst32);
+ while (size--)
+ {
+ WRITE_UINT8(*p_Dst8, val);
+ p_Dst8++;
+ }
+
+ return pDst;
+}
+
+void * MemSet64(void* pDst, uint8_t val, uint32_t size)
+{
+ uint64_t val64;
+ uint64_t *pDst64;
+ uint8_t *p_Dst8;
+
+ p_Dst8 = (uint8_t*)(pDst);
+
+ /* generate four 8-bit val's in 32-bit container */
+ val64 = (uint64_t) val;
+ val64 |= (val64 << 8);
+ val64 |= (val64 << 16);
+ val64 |= (val64 << 24);
+ val64 |= (val64 << 32);
+
+ /* align destination to 64 */
+ while((PTR_TO_UINT(p_Dst8) & 7) && size) /* (pDst mod 8) > 0 and size > 0 */
+ {
+ *p_Dst8++ = val;
+ size--;
+ }
+
+ /* 64-bit chunks */
+ pDst64 = (uint64_t*)(p_Dst8);
+ while (size >> 4) /* size >= 8 */
+ {
+ *pDst64++ = val64;
+ size -= 8;
+ }
+
+ /* complete the leftovers */
+ p_Dst8 = (uint8_t*)(pDst64);
+ while (size--)
+ *p_Dst8++ = val;
+
+ return pDst;
+}
+
+void MemDisp(uint8_t *p, int size)
+{
+ uint32_t space = (uint32_t)(PTR_TO_UINT(p) & 0x3);
+ uint8_t *p_Limit;
+
+ if (space)
+ {
+ p_Limit = (p - space + 4);
+
+ XX_Print("0x%08X: ", (p - space));
+
+ while (space--)
+ {
+ XX_Print("--");
+ }
+ while (size && (p < p_Limit))
+ {
+ XX_Print("%02x", *(uint8_t*)p);
+ size--;
+ p++;
+ }
+
+ XX_Print(" ");
+ p_Limit += 12;
+
+ while ((size > 3) && (p < p_Limit))
+ {
+ XX_Print("%08x ", *(uint32_t*)p);
+ size -= 4;
+ p += 4;
+ }
+ XX_Print("\r\n");
+ }
+
+ while (size > 15)
+ {
+ XX_Print("0x%08X: %08x %08x %08x %08x\r\n",
+ p, *(uint32_t *)p, *(uint32_t *)(p + 4),
+ *(uint32_t *)(p + 8), *(uint32_t *)(p + 12));
+ size -= 16;
+ p += 16;
+ }
+
+ if (size)
+ {
+ XX_Print("0x%08X: ", p);
+
+ while (size > 3)
+ {
+ XX_Print("%08x ", *(uint32_t *)p);
+ size -= 4;
+ p += 4;
+ }
+ while (size)
+ {
+ XX_Print("%02x", *(uint8_t *)p);
+ size--;
+ p++;
+ }
+
+ XX_Print("\r\n");
+ }
+}
diff --git a/drivers/net/ethernet/freescale/fman/etc/mm.c b/drivers/net/ethernet/freescale/fman/etc/mm.c
new file mode 100644
index 0000000..7b9d201
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/etc/mm.c
@@ -0,0 +1,1142 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#include "string_ext.h"
+#include "error_ext.h"
+#include "std_ext.h"
+#include "part_ext.h"
+#include "xx_ext.h"
+
+#include "mm.h"
+
+
+
+
+/**********************************************************************
+ * MM internal routines set *
+ **********************************************************************/
+
+/****************************************************************
+ * Routine: CreateBusyBlock
+ *
+ * Description:
+ * Initializes a new busy block of "size" bytes and started
+ * rom "base" address. Each busy block has a name that
+ * specified the purpose of the memory allocation.
+ *
+ * Arguments:
+ * base - base address of the busy block
+ * size - size of the busy block
+ * name - name that specified the busy block
+ *
+ * Return value:
+ * A pointer to new created structure returned on success;
+ * Otherwise, NULL.
+ ****************************************************************/
+static t_BusyBlock * CreateBusyBlock(uint64_t base, uint64_t size, char *name)
+{
+ t_BusyBlock *p_BusyBlock;
+ uint32_t n;
+
+ p_BusyBlock = (t_BusyBlock *)XX_Malloc(sizeof(t_BusyBlock));
+ if ( !p_BusyBlock )
+ {
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, NO_MSG);
+ return NULL;
+ }
+
+ p_BusyBlock->base = base;
+ p_BusyBlock->end = base + size;
+
+ n = strlen(name);
+ if (n >= MM_MAX_NAME_LEN)
+ n = MM_MAX_NAME_LEN - 1;
+ strncpy(p_BusyBlock->name, name, MM_MAX_NAME_LEN-1);
+ p_BusyBlock->name[n] = '\0';
+ p_BusyBlock->p_Next = 0;
+
+ return p_BusyBlock;
+}
+
+/****************************************************************
+ * Routine: CreateNewBlock
+ *
+ * Description:
+ * Initializes a new memory block of "size" bytes and started
+ * from "base" address.
+ *
+ * Arguments:
+ * base - base address of the memory block
+ * size - size of the memory block
+ *
+ * Return value:
+ * A pointer to new created structure returned on success;
+ * Otherwise, NULL.
+ ****************************************************************/
+static t_MemBlock * CreateNewBlock(uint64_t base, uint64_t size)
+{
+ t_MemBlock *p_MemBlock;
+
+ p_MemBlock = (t_MemBlock *)XX_Malloc(sizeof(t_MemBlock));
+ if ( !p_MemBlock )
+ {
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, NO_MSG);
+ return NULL;
+ }
+
+ p_MemBlock->base = base;
+ p_MemBlock->end = base+size;
+ p_MemBlock->p_Next = 0;
+
+ return p_MemBlock;
+}
+
+/****************************************************************
+ * Routine: CreateFreeBlock
+ *
+ * Description:
+ * Initializes a new free block of of "size" bytes and
+ * started from "base" address.
+ *
+ * Arguments:
+ * base - base address of the free block
+ * size - size of the free block
+ *
+ * Return value:
+ * A pointer to new created structure returned on success;
+ * Otherwise, NULL.
+ ****************************************************************/
+static t_FreeBlock * CreateFreeBlock(uint64_t base, uint64_t size)
+{
+ t_FreeBlock *p_FreeBlock;
+
+ p_FreeBlock = (t_FreeBlock *)XX_Malloc(sizeof(t_FreeBlock));
+ if ( !p_FreeBlock )
+ {
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, NO_MSG);
+ return NULL;
+ }
+
+ p_FreeBlock->base = base;
+ p_FreeBlock->end = base + size;
+ p_FreeBlock->p_Next = 0;
+
+ return p_FreeBlock;
+}
+
+/****************************************************************
+ * Routine: AddFree
+ *
+ * Description:
+ * Adds a new free block to the free lists. It updates each
+ * free list to include a new free block.
+ * Note, that all free block in each free list are ordered
+ * by their base address.
+ *
+ * Arguments:
+ * p_MM - pointer to the MM object
+ * base - base address of a given free block
+ * end - end address of a given free block
+ *
+ * Return value:
+ *
+ *
+ ****************************************************************/
+static t_Error AddFree(t_MM *p_MM, uint64_t base, uint64_t end)
+{
+ t_FreeBlock *p_PrevB, *p_CurrB, *p_NewB;
+ uint64_t alignment;
+ uint64_t alignBase;
+ int i;
+
+ /* Updates free lists to include a just released block */
+ for (i=0; i <= MM_MAX_ALIGNMENT; i++)
+ {
+ p_PrevB = p_NewB = 0;
+ p_CurrB = p_MM->freeBlocks[i];
+
+ alignment = (uint64_t)(0x1 << i);
+ alignBase = MAKE_ALIGNED(base, alignment);
+
+ /* Goes to the next free list if there is no block to free */
+ if (alignBase >= end)
+ continue;
+
+ /* Looks for a free block that should be updated */
+ while ( p_CurrB )
+ {
+ if ( alignBase <= p_CurrB->end )
+ {
+ if ( end > p_CurrB->end )
+ {
+ t_FreeBlock *p_NextB;
+ while ( p_CurrB->p_Next && end > p_CurrB->p_Next->end )
+ {
+ p_NextB = p_CurrB->p_Next;
+ p_CurrB->p_Next = p_CurrB->p_Next->p_Next;
+ XX_Free(p_NextB);
+ }
+
+ p_NextB = p_CurrB->p_Next;
+ if ( !p_NextB || (p_NextB && end < p_NextB->base) )
+ {
+ p_CurrB->end = end;
+ }
+ else
+ {
+ p_CurrB->end = p_NextB->end;
+ p_CurrB->p_Next = p_NextB->p_Next;
+ XX_Free(p_NextB);
+ }
+ }
+ else if ( (end < p_CurrB->base) && ((end-alignBase) >= alignment) )
+ {
+ if ((p_NewB = CreateFreeBlock(alignBase, end-alignBase)) == NULL)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, NO_MSG);
+
+ p_NewB->p_Next = p_CurrB;
+ if (p_PrevB)
+ p_PrevB->p_Next = p_NewB;
+ else
+ p_MM->freeBlocks[i] = p_NewB;
+ break;
+ }
+
+ if ((alignBase < p_CurrB->base) && (end >= p_CurrB->base))
+ {
+ p_CurrB->base = alignBase;
+ }
+
+ /* if size of the free block is less then alignment
+ * deletes that free block from the free list. */
+ if ( (p_CurrB->end - p_CurrB->base) < alignment)
+ {
+ if ( p_PrevB )
+ p_PrevB->p_Next = p_CurrB->p_Next;
+ else
+ p_MM->freeBlocks[i] = p_CurrB->p_Next;
+ XX_Free(p_CurrB);
+ }
+ break;
+ }
+ else
+ {
+ p_PrevB = p_CurrB;
+ p_CurrB = p_CurrB->p_Next;
+ }
+ }
+
+ /* If no free block found to be updated, insert a new free block
+ * to the end of the free list.
+ */
+ if ( !p_CurrB && ((((uint64_t)(end-base)) & ((uint64_t)(alignment-1))) == 0) )
+ {
+ if ((p_NewB = CreateFreeBlock(alignBase, end-base)) == NULL)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, NO_MSG);
+
+ if (p_PrevB)
+ p_PrevB->p_Next = p_NewB;
+ else
+ p_MM->freeBlocks[i] = p_NewB;
+ }
+
+ /* Update boundaries of the new free block */
+ if ((alignment == 1) && !p_NewB)
+ {
+ if ( p_CurrB && base > p_CurrB->base )
+ base = p_CurrB->base;
+ if ( p_CurrB && end < p_CurrB->end )
+ end = p_CurrB->end;
+ }
+ }
+
+ return (E_OK);
+}
+
+/****************************************************************
+ * Routine: CutFree
+ *
+ * Description:
+ * Cuts a free block from holdBase to holdEnd from the free lists.
+ * That is, it updates all free lists of the MM object do
+ * not include a block of memory from holdBase to holdEnd.
+ * For each free lists it seek for a free block that holds
+ * either holdBase or holdEnd. If such block is found it updates it.
+ *
+ * Arguments:
+ * p_MM - pointer to the MM object
+ * holdBase - base address of the allocated block
+ * holdEnd - end address of the allocated block
+ *
+ * Return value:
+ * E_OK is returned on success,
+ * otherwise returns an error code.
+ *
+ ****************************************************************/
+static t_Error CutFree(t_MM *p_MM, uint64_t holdBase, uint64_t holdEnd)
+{
+ t_FreeBlock *p_PrevB, *p_CurrB, *p_NewB;
+ uint64_t alignBase, base, end;
+ uint64_t alignment;
+ int i;
+
+ for (i=0; i <= MM_MAX_ALIGNMENT; i++)
+ {
+ p_PrevB = p_NewB = 0;
+ p_CurrB = p_MM->freeBlocks[i];
+
+ alignment = (uint64_t)(0x1 << i);
+ alignBase = MAKE_ALIGNED(holdEnd, alignment);
+
+ while ( p_CurrB )
+ {
+ base = p_CurrB->base;
+ end = p_CurrB->end;
+
+ if ( (holdBase <= base) && (holdEnd <= end) && (holdEnd > base) )
+ {
+ if ( alignBase >= end ||
+ (alignBase < end && ((end-alignBase) < alignment)) )
+ {
+ if (p_PrevB)
+ p_PrevB->p_Next = p_CurrB->p_Next;
+ else
+ p_MM->freeBlocks[i] = p_CurrB->p_Next;
+ XX_Free(p_CurrB);
+ }
+ else
+ {
+ p_CurrB->base = alignBase;
+ }
+ break;
+ }
+ else if ( (holdBase > base) && (holdEnd <= end) )
+ {
+ if ( (holdBase-base) >= alignment )
+ {
+ if ( (alignBase < end) && ((end-alignBase) >= alignment) )
+ {
+ if ((p_NewB = CreateFreeBlock(alignBase, end-alignBase)) == NULL)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, NO_MSG);
+ p_NewB->p_Next = p_CurrB->p_Next;
+ p_CurrB->p_Next = p_NewB;
+ }
+ p_CurrB->end = holdBase;
+ }
+ else if ( (alignBase < end) && ((end-alignBase) >= alignment) )
+ {
+ p_CurrB->base = alignBase;
+ }
+ else
+ {
+ if (p_PrevB)
+ p_PrevB->p_Next = p_CurrB->p_Next;
+ else
+ p_MM->freeBlocks[i] = p_CurrB->p_Next;
+ XX_Free(p_CurrB);
+ }
+ break;
+ }
+ else
+ {
+ p_PrevB = p_CurrB;
+ p_CurrB = p_CurrB->p_Next;
+ }
+ }
+ }
+
+ return (E_OK);
+}
+
+/****************************************************************
+ * Routine: AddBusy
+ *
+ * Description:
+ * Adds a new busy block to the list of busy blocks. Note,
+ * that all busy blocks are ordered by their base address in
+ * the busy list.
+ *
+ * Arguments:
+ * MM - handler to the MM object
+ * p_NewBusyB - pointer to the a busy block
+ *
+ * Return value:
+ * None.
+ *
+ ****************************************************************/
+static void AddBusy(t_MM *p_MM, t_BusyBlock *p_NewBusyB)
+{
+ t_BusyBlock *p_CurrBusyB, *p_PrevBusyB;
+
+ /* finds a place of a new busy block in the list of busy blocks */
+ p_PrevBusyB = 0;
+ p_CurrBusyB = p_MM->busyBlocks;
+
+ while ( p_CurrBusyB && p_NewBusyB->base > p_CurrBusyB->base )
+ {
+ p_PrevBusyB = p_CurrBusyB;
+ p_CurrBusyB = p_CurrBusyB->p_Next;
+ }
+
+ /* insert the new busy block into the list of busy blocks */
+ if ( p_CurrBusyB )
+ p_NewBusyB->p_Next = p_CurrBusyB;
+ if ( p_PrevBusyB )
+ p_PrevBusyB->p_Next = p_NewBusyB;
+ else
+ p_MM->busyBlocks = p_NewBusyB;
+}
+
+/****************************************************************
+ * Routine: CutBusy
+ *
+ * Description:
+ * Cuts a block from base to end from the list of busy blocks.
+ * This is done by updating the list of busy blocks do not
+ * include a given block, that block is going to be free. If a
+ * given block is a part of some other busy block, so that
+ * busy block is updated. If there are number of busy blocks
+ * included in the given block, so all that blocks are removed
+ * from the busy list and the end blocks are updated.
+ * If the given block devides some block into two parts, a new
+ * busy block is added to the busy list.
+ *
+ * Arguments:
+ * p_MM - pointer to the MM object
+ * base - base address of a given busy block
+ * end - end address of a given busy block
+ *
+ * Return value:
+ * E_OK on success, E_NOMEMORY otherwise.
+ *
+ ****************************************************************/
+static t_Error CutBusy(t_MM *p_MM, uint64_t base, uint64_t end)
+{
+ t_BusyBlock *p_CurrB, *p_PrevB, *p_NewB;
+
+ p_CurrB = p_MM->busyBlocks;
+ p_PrevB = p_NewB = 0;
+
+ while ( p_CurrB )
+ {
+ if ( base < p_CurrB->end )
+ {
+ if ( end > p_CurrB->end )
+ {
+ t_BusyBlock *p_NextB;
+ while ( p_CurrB->p_Next && end >= p_CurrB->p_Next->end )
+ {
+ p_NextB = p_CurrB->p_Next;
+ p_CurrB->p_Next = p_CurrB->p_Next->p_Next;
+ XX_Free(p_NextB);
+ }
+
+ p_NextB = p_CurrB->p_Next;
+ if ( p_NextB && end > p_NextB->base )
+ {
+ p_NextB->base = end;
+ }
+ }
+
+ if ( base <= p_CurrB->base )
+ {
+ if ( end < p_CurrB->end && end > p_CurrB->base )
+ {
+ p_CurrB->base = end;
+ }
+ else if ( end >= p_CurrB->end )
+ {
+ if ( p_PrevB )
+ p_PrevB->p_Next = p_CurrB->p_Next;
+ else
+ p_MM->busyBlocks = p_CurrB->p_Next;
+ XX_Free(p_CurrB);
+ }
+ }
+ else
+ {
+ if ( end < p_CurrB->end && end > p_CurrB->base )
+ {
+ if ((p_NewB = CreateBusyBlock(end,
+ p_CurrB->end-end,
+ p_CurrB->name)) == NULL)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, NO_MSG);
+ p_NewB->p_Next = p_CurrB->p_Next;
+ p_CurrB->p_Next = p_NewB;
+ }
+ p_CurrB->end = base;
+ }
+ break;
+ }
+ else
+ {
+ p_PrevB = p_CurrB;
+ p_CurrB = p_CurrB->p_Next;
+ }
+ }
+
+ return (E_OK);
+}
+
+/****************************************************************
+ * Routine: MmGetGreaterAlignment
+ *
+ * Description:
+ * Allocates a block of memory according to the given size
+ * and the alignment. That routine is called from the MM_Get
+ * routine if the required alignment is greater then MM_MAX_ALIGNMENT.
+ * In that case, it goes over free blocks of 64 byte align list
+ * and checks if it has the required size of bytes of the required
+ * alignment. If no blocks found returns ILLEGAL_BASE.
+ * After the block is found and data is allocated, it calls
+ * the internal CutFree routine to update all free lists
+ * do not include a just allocated block. Of course, each
+ * free list contains a free blocks with the same alignment.
+ * It is also creates a busy block that holds
+ * information about an allocated block.
+ *
+ * Arguments:
+ * MM - handle to the MM object
+ * size - size of the MM
+ * alignment - index as a power of two defines
+ * a required alignment that is greater then 64.
+ * name - the name that specifies an allocated block.
+ *
+ * Return value:
+ * base address of an allocated block.
+ * ILLEGAL_BASE if can't allocate a block
+ *
+ ****************************************************************/
+static uint64_t MmGetGreaterAlignment(t_MM *p_MM, uint64_t size, uint64_t alignment, char* name)
+{
+ t_FreeBlock *p_FreeB;
+ t_BusyBlock *p_NewBusyB;
+ uint64_t holdBase, holdEnd, alignBase = 0;
+
+ /* goes over free blocks of the 64 byte alignment list
+ and look for a block of the suitable size and
+ base address according to the alignment. */
+ p_FreeB = p_MM->freeBlocks[MM_MAX_ALIGNMENT];
+
+ while ( p_FreeB )
+ {
+ alignBase = MAKE_ALIGNED(p_FreeB->base, alignment);
+
+ /* the block is found if the aligned base inside the block
+ * and has the anough size. */
+ if ( alignBase >= p_FreeB->base &&
+ alignBase < p_FreeB->end &&
+ size <= (p_FreeB->end - alignBase) )
+ break;
+ else
+ p_FreeB = p_FreeB->p_Next;
+ }
+
+ /* If such block isn't found */
+ if ( !p_FreeB )
+ return (uint64_t)(ILLEGAL_BASE);
+
+ holdBase = alignBase;
+ holdEnd = alignBase + size;
+
+ /* init a new busy block */
+ if ((p_NewBusyB = CreateBusyBlock(holdBase, size, name)) == NULL)
+ return (uint64_t)(ILLEGAL_BASE);
+
+ /* calls Update routine to update a lists of free blocks */
+ if ( CutFree ( p_MM, holdBase, holdEnd ) != E_OK )
+ return (uint64_t)(ILLEGAL_BASE);
+
+ /* insert the new busy block into the list of busy blocks */
+ AddBusy ( p_MM, p_NewBusyB );
+
+ return (holdBase);
+}
+
+
+/**********************************************************************
+ * MM API routines set *
+ **********************************************************************/
+
+/*****************************************************************************/
+t_Error MM_Init(t_Handle *h_MM, uint64_t base, uint64_t size)
+{
+ t_MM *p_MM;
+ uint64_t newBase, newSize;
+ int i;
+
+ if (!size)
+ {
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Size (should be positive)"));
+ }
+
+ /* Initializes a new MM object */
+ p_MM = (t_MM *)XX_Malloc(sizeof(t_MM));
+ if (!p_MM)
+ {
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, NO_MSG);
+ }
+
+ p_MM->h_Spinlock = XX_InitSpinlock();
+ if (!p_MM->h_Spinlock)
+ {
+ XX_Free(p_MM);
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MM spinlock!"));
+ }
+
+ /* Initializes counter of free memory to total size */
+ p_MM->freeMemSize = size;
+
+ /* Initializes a new memory block */
+ if ((p_MM->memBlocks = CreateNewBlock(base, size)) == NULL)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, NO_MSG);
+
+ /* A busy list is empty */
+ p_MM->busyBlocks = 0;
+
+ /* Initializes a new free block for each free list*/
+ for (i=0; i <= MM_MAX_ALIGNMENT; i++)
+ {
+ newBase = MAKE_ALIGNED( base, (0x1 << i) );
+ newSize = size - (newBase - base);
+
+ if ((p_MM->freeBlocks[i] = CreateFreeBlock(newBase, newSize)) == NULL)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, NO_MSG);
+ }
+
+ *h_MM = p_MM;
+
+ return (E_OK);
+}
+
+/*****************************************************************************/
+void MM_Free(t_Handle h_MM)
+{
+ t_MM *p_MM = (t_MM *)h_MM;
+ t_MemBlock *p_MemBlock;
+ t_BusyBlock *p_BusyBlock;
+ t_FreeBlock *p_FreeBlock;
+ void *p_Block;
+ int i;
+
+ ASSERT_COND(p_MM);
+
+ /* release memory allocated for busy blocks */
+ p_BusyBlock = p_MM->busyBlocks;
+ while ( p_BusyBlock )
+ {
+ p_Block = p_BusyBlock;
+ p_BusyBlock = p_BusyBlock->p_Next;
+ XX_Free(p_Block);
+ }
+
+ /* release memory allocated for free blocks */
+ for (i=0; i <= MM_MAX_ALIGNMENT; i++)
+ {
+ p_FreeBlock = p_MM->freeBlocks[i];
+ while ( p_FreeBlock )
+ {
+ p_Block = p_FreeBlock;
+ p_FreeBlock = p_FreeBlock->p_Next;
+ XX_Free(p_Block);
+ }
+ }
+
+ /* release memory allocated for memory blocks */
+ p_MemBlock = p_MM->memBlocks;
+ while ( p_MemBlock )
+ {
+ p_Block = p_MemBlock;
+ p_MemBlock = p_MemBlock->p_Next;
+ XX_Free(p_Block);
+ }
+
+ if (p_MM->h_Spinlock)
+ XX_FreeSpinlock(p_MM->h_Spinlock);
+
+ /* release memory allocated for MM object itself */
+ XX_Free(p_MM);
+}
+
+/*****************************************************************************/
+uint64_t MM_Get(t_Handle h_MM, uint64_t size, uint64_t alignment, char* name)
+{
+ t_MM *p_MM = (t_MM *)h_MM;
+ t_FreeBlock *p_FreeB;
+ t_BusyBlock *p_NewBusyB;
+ uint64_t holdBase, holdEnd, j, i = 0;
+ uint32_t intFlags;
+
+ SANITY_CHECK_RETURN_VALUE(p_MM, E_INVALID_HANDLE, (uint64_t)ILLEGAL_BASE);
+
+ /* checks that alignment value is greater then zero */
+ if (alignment == 0)
+ {
+ alignment = 1;
+ }
+
+ j = alignment;
+
+ /* checks if alignment is a power of two, if it correct and if the
+ required size is multiple of the given alignment. */
+ while ((j & 0x1) == 0)
+ {
+ i++;
+ j = j >> 1;
+ }
+
+ /* if the given alignment isn't power of two, returns an error */
+ if (j != 1)
+ {
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("alignment (should be power of 2)"));
+ return (uint64_t)ILLEGAL_BASE;
+ }
+
+ if (i > MM_MAX_ALIGNMENT)
+ {
+ return (MmGetGreaterAlignment(p_MM, size, alignment, name));
+ }
+
+ intFlags = XX_LockIntrSpinlock(p_MM->h_Spinlock);
+ /* look for a block of the size greater or equal to the required size. */
+ p_FreeB = p_MM->freeBlocks[i];
+ while ( p_FreeB && (p_FreeB->end - p_FreeB->base) < size )
+ p_FreeB = p_FreeB->p_Next;
+
+ /* If such block is found */
+ if ( !p_FreeB )
+ {
+ XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags);
+ return (uint64_t)(ILLEGAL_BASE);
+ }
+
+ holdBase = p_FreeB->base;
+ holdEnd = holdBase + size;
+
+ /* init a new busy block */
+ if ((p_NewBusyB = CreateBusyBlock(holdBase, size, name)) == NULL)
+ {
+ XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags);
+ return (uint64_t)(ILLEGAL_BASE);
+ }
+
+ /* calls Update routine to update a lists of free blocks */
+ if ( CutFree ( p_MM, holdBase, holdEnd ) != E_OK )
+ {
+ XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags);
+ return (uint64_t)(ILLEGAL_BASE);
+ }
+
+ /* Decreasing the allocated memory size from free memory size */
+ p_MM->freeMemSize -= size;
+
+ /* insert the new busy block into the list of busy blocks */
+ AddBusy ( p_MM, p_NewBusyB );
+ XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags);
+
+ return (holdBase);
+}
+
+/*****************************************************************************/
+uint64_t MM_GetForce(t_Handle h_MM, uint64_t base, uint64_t size, char* name)
+{
+ t_MM *p_MM = (t_MM *)h_MM;
+ t_FreeBlock *p_FreeB;
+ t_BusyBlock *p_NewBusyB;
+ uint32_t intFlags;
+ bool blockIsFree = FALSE;
+
+ ASSERT_COND(p_MM);
+
+ intFlags = XX_LockIntrSpinlock(p_MM->h_Spinlock);
+ p_FreeB = p_MM->freeBlocks[0]; /* The biggest free blocks are in the
+ free list with alignment 1 */
+
+ while ( p_FreeB )
+ {
+ if ( base >= p_FreeB->base && (base+size) <= p_FreeB->end )
+ {
+ blockIsFree = TRUE;
+ break;
+ }
+ else
+ p_FreeB = p_FreeB->p_Next;
+ }
+
+ if ( !blockIsFree )
+ {
+ XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags);
+ return (uint64_t)(ILLEGAL_BASE);
+ }
+
+ /* init a new busy block */
+ if ((p_NewBusyB = CreateBusyBlock(base, size, name)) == NULL)
+ {
+ XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags);
+ return (uint64_t)(ILLEGAL_BASE);
+ }
+
+ /* calls Update routine to update a lists of free blocks */
+ if ( CutFree ( p_MM, base, base+size ) != E_OK )
+ {
+ XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags);
+ return (uint64_t)(ILLEGAL_BASE);
+ }
+
+ /* Decreasing the allocated memory size from free memory size */
+ p_MM->freeMemSize -= size;
+
+ /* insert the new busy block into the list of busy blocks */
+ AddBusy ( p_MM, p_NewBusyB );
+ XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags);
+
+ return (base);
+}
+
+/*****************************************************************************/
+uint64_t MM_GetForceMin(t_Handle h_MM, uint64_t size, uint64_t alignment, uint64_t min, char* name)
+{
+ t_MM *p_MM = (t_MM *)h_MM;
+ t_FreeBlock *p_FreeB;
+ t_BusyBlock *p_NewBusyB;
+ uint64_t holdBase, holdEnd, j = alignment, i=0;
+ uint32_t intFlags;
+
+ ASSERT_COND(p_MM);
+
+ /* checks if alignment is a power of two, if it correct and if the
+ required size is multiple of the given alignment. */
+ while ((j & 0x1) == 0)
+ {
+ i++;
+ j = j >> 1;
+ }
+
+ if ( (j != 1) || (i > MM_MAX_ALIGNMENT) )
+ {
+ return (uint64_t)(ILLEGAL_BASE);
+ }
+
+ intFlags = XX_LockIntrSpinlock(p_MM->h_Spinlock);
+ p_FreeB = p_MM->freeBlocks[i];
+
+ /* look for the first block that contains the minimum
+ base address. If the whole required size may be fit
+ into it, use that block, otherwise look for the next
+ block of size greater or equal to the required size. */
+ while ( p_FreeB && (min >= p_FreeB->end))
+ p_FreeB = p_FreeB->p_Next;
+
+ /* If such block is found */
+ if ( !p_FreeB )
+ {
+ XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags);
+ return (uint64_t)(ILLEGAL_BASE);
+ }
+
+ /* if this block is large enough, use this block */
+ holdBase = ( min <= p_FreeB->base ) ? p_FreeB->base : min;
+ if ((holdBase + size) <= p_FreeB->end )
+ {
+ holdEnd = holdBase + size;
+ }
+ else
+ {
+ p_FreeB = p_FreeB->p_Next;
+ while ( p_FreeB && ((p_FreeB->end - p_FreeB->base) < size) )
+ p_FreeB = p_FreeB->p_Next;
+
+ /* If such block is found */
+ if ( !p_FreeB )
+ {
+ XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags);
+ return (uint64_t)(ILLEGAL_BASE);
+ }
+
+ holdBase = p_FreeB->base;
+ holdEnd = holdBase + size;
+ }
+
+ /* init a new busy block */
+ if ((p_NewBusyB = CreateBusyBlock(holdBase, size, name)) == NULL)
+ {
+ XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags);
+ return (uint64_t)(ILLEGAL_BASE);
+ }
+
+ /* calls Update routine to update a lists of free blocks */
+ if ( CutFree( p_MM, holdBase, holdEnd ) != E_OK )
+ {
+ XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags);
+ return (uint64_t)(ILLEGAL_BASE);
+ }
+
+ /* Decreasing the allocated memory size from free memory size */
+ p_MM->freeMemSize -= size;
+
+ /* insert the new busy block into the list of busy blocks */
+ AddBusy( p_MM, p_NewBusyB );
+ XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags);
+
+ return (holdBase);
+}
+
+/*****************************************************************************/
+uint64_t MM_Put(t_Handle h_MM, uint64_t base)
+{
+ t_MM *p_MM = (t_MM *)h_MM;
+ t_BusyBlock *p_BusyB, *p_PrevBusyB;
+ uint64_t size;
+ uint32_t intFlags;
+
+ ASSERT_COND(p_MM);
+
+ /* Look for a busy block that have the given base value.
+ * That block will be returned back to the memory.
+ */
+ p_PrevBusyB = 0;
+
+ intFlags = XX_LockIntrSpinlock(p_MM->h_Spinlock);
+ p_BusyB = p_MM->busyBlocks;
+ while ( p_BusyB && base != p_BusyB->base )
+ {
+ p_PrevBusyB = p_BusyB;
+ p_BusyB = p_BusyB->p_Next;
+ }
+
+ if ( !p_BusyB )
+ {
+ XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags);
+ return (uint64_t)(0);
+ }
+
+ if ( AddFree( p_MM, p_BusyB->base, p_BusyB->end ) != E_OK )
+ {
+ XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags);
+ return (uint64_t)(0);
+ }
+
+ /* removes a busy block form the list of busy blocks */
+ if ( p_PrevBusyB )
+ p_PrevBusyB->p_Next = p_BusyB->p_Next;
+ else
+ p_MM->busyBlocks = p_BusyB->p_Next;
+
+ size = p_BusyB->end - p_BusyB->base;
+
+ /* Adding the deallocated memory size to free memory size */
+ p_MM->freeMemSize += size;
+
+ XX_Free(p_BusyB);
+ XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags);
+
+ return (size);
+}
+
+/*****************************************************************************/
+uint64_t MM_PutForce(t_Handle h_MM, uint64_t base, uint64_t size)
+{
+ t_MM *p_MM = (t_MM *)h_MM;
+ uint64_t end = base + size;
+ uint32_t intFlags;
+
+ ASSERT_COND(p_MM);
+
+ intFlags = XX_LockIntrSpinlock(p_MM->h_Spinlock);
+
+ if ( CutBusy( p_MM, base, end ) != E_OK )
+ {
+ XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags);
+ return (uint64_t)(0);
+ }
+
+ if ( AddFree ( p_MM, base, end ) != E_OK )
+ {
+ XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags);
+ return (uint64_t)(0);
+ }
+
+ /* Adding the deallocated memory size to free memory size */
+ p_MM->freeMemSize += size;
+
+ XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags);
+
+ return (size);
+}
+
+/*****************************************************************************/
+t_Error MM_Add(t_Handle h_MM, uint64_t base, uint64_t size)
+{
+ t_MM *p_MM = (t_MM *)h_MM;
+ t_MemBlock *p_MemB, *p_NewMemB;
+ t_Error errCode;
+ uint32_t intFlags;
+
+ ASSERT_COND(p_MM);
+
+ /* find a last block in the list of memory blocks to insert a new
+ * memory block
+ */
+ intFlags = XX_LockIntrSpinlock(p_MM->h_Spinlock);
+
+ p_MemB = p_MM->memBlocks;
+ while ( p_MemB->p_Next )
+ {
+ if ( base >= p_MemB->base && base < p_MemB->end )
+ {
+ XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags);
+ RETURN_ERROR(MAJOR, E_ALREADY_EXISTS, NO_MSG);
+ }
+ p_MemB = p_MemB->p_Next;
+ }
+ /* check for a last memory block */
+ if ( base >= p_MemB->base && base < p_MemB->end )
+ {
+ XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags);
+ RETURN_ERROR(MAJOR, E_ALREADY_EXISTS, NO_MSG);
+ }
+
+ /* create a new memory block */
+ if ((p_NewMemB = CreateNewBlock(base, size)) == NULL)
+ {
+ XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags);
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, NO_MSG);
+ }
+
+ /* append a new memory block to the end of the list of memory blocks */
+ p_MemB->p_Next = p_NewMemB;
+
+ /* add a new free block to the free lists */
+ errCode = AddFree(p_MM, base, base+size);
+ if (errCode)
+ {
+ XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags);
+ p_MemB->p_Next = 0;
+ XX_Free(p_NewMemB);
+ return ((t_Error)errCode);
+ }
+
+ /* Adding the new block size to free memory size */
+ p_MM->freeMemSize += size;
+
+ XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags);
+
+ return (E_OK);
+}
+
+/*****************************************************************************/
+uint64_t MM_GetMemBlock(t_Handle h_MM, int index)
+{
+ t_MM *p_MM = (t_MM*)h_MM;
+ t_MemBlock *p_MemBlock;
+ int i;
+
+ ASSERT_COND(p_MM);
+
+ p_MemBlock = p_MM->memBlocks;
+ for (i=0; i < index; i++)
+ p_MemBlock = p_MemBlock->p_Next;
+
+ if ( p_MemBlock )
+ return (p_MemBlock->base);
+ else
+ return (uint64_t)ILLEGAL_BASE;
+}
+
+/*****************************************************************************/
+uint64_t MM_GetBase(t_Handle h_MM)
+{
+ t_MM *p_MM = (t_MM*)h_MM;
+ t_MemBlock *p_MemBlock;
+
+ ASSERT_COND(p_MM);
+
+ p_MemBlock = p_MM->memBlocks;
+ return p_MemBlock->base;
+}
+
+/*****************************************************************************/
+bool MM_InRange(t_Handle h_MM, uint64_t addr)
+{
+ t_MM *p_MM = (t_MM*)h_MM;
+ t_MemBlock *p_MemBlock;
+
+ ASSERT_COND(p_MM);
+
+ p_MemBlock = p_MM->memBlocks;
+
+ if ((addr >= p_MemBlock->base) && (addr < p_MemBlock->end))
+ return TRUE;
+ else
+ return FALSE;
+}
+
+/*****************************************************************************/
+uint64_t MM_GetFreeMemSize(t_Handle h_MM)
+{
+ t_MM *p_MM = (t_MM*)h_MM;
+
+ ASSERT_COND(p_MM);
+
+ return p_MM->freeMemSize;
+}
+
+/*****************************************************************************/
+void MM_Dump(t_Handle h_MM)
+{
+ t_MM *p_MM = (t_MM *)h_MM;
+ t_FreeBlock *p_FreeB;
+ t_BusyBlock *p_BusyB;
+ int i;
+
+ p_BusyB = p_MM->busyBlocks;
+ XX_Print("List of busy blocks:\n");
+ while (p_BusyB)
+ {
+ XX_Print("\t0x%p: (%s: b=0x%llx, e=0x%llx)\n", p_BusyB, p_BusyB->name, p_BusyB->base, p_BusyB->end );
+ p_BusyB = p_BusyB->p_Next;
+ }
+
+ XX_Print("\nLists of free blocks according to alignment:\n");
+ for (i=0; i <= MM_MAX_ALIGNMENT; i++)
+ {
+ XX_Print("%d alignment:\n", (0x1 << i));
+ p_FreeB = p_MM->freeBlocks[i];
+ while (p_FreeB)
+ {
+ XX_Print("\t0x%p: (b=0x%llx, e=0x%llx)\n", p_FreeB, p_FreeB->base, p_FreeB->end);
+ p_FreeB = p_FreeB->p_Next;
+ }
+ XX_Print("\n");
+ }
+}
diff --git a/drivers/net/ethernet/freescale/fman/etc/mm.h b/drivers/net/ethernet/freescale/fman/etc/mm.h
new file mode 100644
index 0000000..43b2298
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/etc/mm.h
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+/****************************************************************
+ *
+ * File: mm.h
+ *
+ *
+ * Description:
+ * MM (Memory Management) object definitions.
+ * It also includes definitions of the Free Block, Busy Block
+ * and Memory Block structures used by the MM object.
+ *
+ ****************************************************************/
+
+#ifndef __MM_H
+#define __MM_H
+
+
+#include "mm_ext.h"
+
+#define __ERR_MODULE__ MODULE_MM
+
+
+#define MAKE_ALIGNED(addr, align) \
+ (((uint64_t)(addr) + ((align) - 1)) & (~(((uint64_t)align) - 1)))
+
+
+/* t_MemBlock data structure defines parameters of the Memory Block */
+typedef struct t_MemBlock
+{
+ struct t_MemBlock *p_Next; /* Pointer to the next memory block */
+
+ uint64_t base; /* Base address of the memory block */
+ uint64_t end; /* End address of the memory block */
+} t_MemBlock;
+
+
+/* t_FreeBlock data structure defines parameters of the Free Block */
+typedef struct t_FreeBlock
+{
+ struct t_FreeBlock *p_Next; /* Pointer to the next free block */
+
+ uint64_t base; /* Base address of the block */
+ uint64_t end; /* End address of the block */
+} t_FreeBlock;
+
+
+/* t_BusyBlock data structure defines parameters of the Busy Block */
+typedef struct t_BusyBlock
+{
+ struct t_BusyBlock *p_Next; /* Pointer to the next free block */
+
+ uint64_t base; /* Base address of the block */
+ uint64_t end; /* End address of the block */
+ char name[MM_MAX_NAME_LEN]; /* That block of memory was allocated for
+ something specified by the Name */
+} t_BusyBlock;
+
+
+/* t_MM data structure defines parameters of the MM object */
+typedef struct t_MM
+{
+ t_Handle h_Spinlock;
+
+ t_MemBlock *memBlocks; /* List of memory blocks (Memory list) */
+ t_BusyBlock *busyBlocks; /* List of busy blocks (Busy list) */
+ t_FreeBlock *freeBlocks[MM_MAX_ALIGNMENT + 1];
+ /* Alignment lists of free blocks (Free lists) */
+
+ uint64_t freeMemSize; /* Total size of free memory (in bytes) */
+} t_MM;
+
+
+#endif /* __MM_H */
diff --git a/drivers/net/ethernet/freescale/fman/etc/sprint.c b/drivers/net/ethernet/freescale/fman/etc/sprint.c
new file mode 100644
index 0000000..46d2956
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/etc/sprint.c
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+/*------------------------------------------------------*/
+/* File: sprint.c */
+/* */
+/* Description: */
+/* Debug routines (externals) */
+/*------------------------------------------------------*/
+#include "string_ext.h"
+#include "stdlib_ext.h"
+#include "stdarg_ext.h"
+#include "sprint_ext.h"
+#include "std_ext.h"
+#include "xx_ext.h"
+
+
+int Sprint(char * buf, const char *fmt, ...)
+{
+ va_list args;
+ int i;
+
+ va_start(args, fmt);
+ i=vsprintf(buf,fmt,args);
+ va_end(args);
+ return i;
+}
+
+int Snprint(char * buf, uint32_t size, const char *fmt, ...)
+{
+ va_list args;
+ int i;
+
+ va_start(args, fmt);
+ i=vsnprintf(buf,size,fmt,args);
+ va_end(args);
+ return i;
+}
+
+#ifndef NCSW_VXWORKS
+int Sscan(const char * buf, const char * fmt, ...)
+{
+ va_list args;
+ int i;
+
+ va_start(args,fmt);
+ i = vsscanf(buf,fmt,args);
+ va_end(args);
+ return i;
+}
+#endif /* NCSW_VXWORKS */