]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - keystone-rtos/netapi.git/blobdiff - ti/runtime/netapi/src/netapi.c
Fix for SDOCM00101269: call netapi_netcpCfgException with action to discard packets...
[keystone-rtos/netapi.git] / ti / runtime / netapi / src / netapi.c
index e33585d3bdd4501ed0d9ec1a95318e08d86872de..21cd90c2309902b9c3b15e9d1ca9d2ca53ff6c3c 100755 (executable)
-/*******************************\r
- * FILE: netapi.c\r
- * Purpose:  implementation of netapi startup/shutdown\r
- **************************************************************\r
- * FILE: netapi.c\r
- * \r
- * DESCRIPTION:  netapi main source file for user space transport\r
- *               library\r
- * \r
- * REVISION HISTORY:  rev 0.0.1 \r
- *\r
- *  Copyright (c) Texas Instruments Incorporated 2010-2011\r
- * \r
- *  Redistribution and use in source and binary forms, with or without \r
- *  modification, are permitted provided that the following conditions \r
- *  are met:\r
- *\r
- *    Redistributions of source code must retain the above copyright \r
- *    notice, this list of conditions and the following disclaimer.\r
- *\r
- *    Redistributions in binary form must reproduce the above copyright\r
- *    notice, this list of conditions and the following disclaimer in the \r
- *    documentation and/or other materials provided with the   \r
- *    distribution.\r
- *\r
- *    Neither the name of Texas Instruments Incorporated nor the names of\r
- *    its contributors may be used to endorse or promote products derived\r
- *    from this software without specific prior written permission.\r
- *\r
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \r
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT \r
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\r
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT \r
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, \r
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT \r
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\r
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\r
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT \r
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE \r
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
-\r
- * *****************************/\r
-#include <stdio.h>\r
-#include <stdlib.h>\r
-#include <unistd.h>\r
-#include <string.h>\r
-#include "netapi.h"\r
-\r
-typedef struct PRESET_Tag\r
-{\r
-#define KMAXQ 10\r
-       int kqinuse[KMAXQ];\r
-        //more..\r
-} PRESET_T;\r
-\r
-/*------------internal prototypes---------------*/\r
-static uint8_t* netapiSharedMemoryMalloc(uint32_t size);\r
-static void netapiSharedMemoryFree(uint8_t* ptr);\r
-static int system_init(NETAPI_HANDLE_T *);\r
-static void get_presets(PRESET_T * p_preset);\r
-static void netapi_cleanup_at_start(void);\r
-\r
-\r
-/*------------globals-----------------*/\r
-#define NUM_HOST_DESC  (TUNE_NETAPI_NUM_LOCAL_DESC)\r
-#define SIZE_LOCAL_DESC  (TUNE_NETAPI_DESC_SIZE) \r
-#define SIZE_SHARED_DESC (TUNE_NETAPI_DESC_SIZE)\r
-\r
-#define CONFIG_BUFSIZE_PA_INST      256\r
-#define CONFIG_BUFSIZE_L2_TABLE     1000\r
-#define CONFIG_BUFSIZE_L3_TABLE     4000\r
-\r
-static NETAPI_CFG_T netapi_default_cfg=\r
-{\r
-TUNE_NETAPI_PERM_MEM_SZ,\r
-0,  //start of packet offset for hw to place data on rx for default flow\r
-TUNE_NETAPI_QM_CONFIG_MAX_DESC_NUM, //max number of descriptors in system\r
-TUNE_NETAPI_NUM_GLOBAL_DESC,        //total we will use\r
-TUNE_NETAPI_DEFAULT_NUM_BUFFERS,   //#descriptors+buffers in default heap\r
-TUNE_NETAPI_DEFAULT_NUM_SOLO_DESCRIPTORS, //#descriptors w/o buffers in default heap\r
-TUNE_NETAPI_DEFAULT_BUFFER_SIZE,   //size of buffers in default heap\r
-0,0\r
-\r
-};\r
-\r
-static Pktlib_HeapIfTable  netapi_pktlib_ifTable;\r
-static NETAPI_GLOBAL_T netapi_global;\r
-NETAPI_GLOBAL_T * netapi_get_global(){ return &netapi_global;}\r
-\r
-/* utility API for NETAPI user to get pktlib if table to use if he creates his own heap */\r
-Pktlib_HeapIfTable *netapi_getPktlibIfTable(void) {return &netapi_pktlib_ifTable;}\r
-\r
-//zap a queue\r
-void netapi_zapQ(int queueNum);\r
-/*-------------------------------------\r
- *  initialize NETAPI instance \r
- *-------------------------------------*/\r
-NETAPI_T netapi_init(int master, NETAPI_CFG_T * p_cfg)\r
-{\r
- int i;\r
- int err;\r
- NETAPI_HANDLE_T * p = (NETAPI_HANDLE_T *) calloc(1,sizeof(NETAPI_HANDLE_T));\r
- if (!p) return NULL;\r
- p->master = master;\r
-\r
- /* create space for our local pktios */\r
- for(i=0;i<NETAPI_MAX_PKTIO; i++)\r
- {\r
-   p->pktios[i] = calloc(1,sizeof(PKTIO_HANDLE_T));\r
-  if (!p->pktios[i]) return NULL;\r
- }\r
-\r
-#ifdef NETAPI_INCLUDE_SCHED\r
- /* create space for scheduler */\r
- p->p_sched = calloc(1,sizeof(NETAPI_SCHED_HANDLE_T));\r
-#endif \r
-\r
-\r
- /* global stuff (if master) */\r
- if (master==NETAPI_SYS_MASTER)\r
- {\r
-   if (p_cfg) memcpy(&netapi_global.cfg,p_cfg, sizeof(NETAPI_CFG_T));\r
-   else      memcpy(&netapi_global.cfg,&netapi_default_cfg, sizeof(NETAPI_CFG_T));\r
-   for(i=0;i<NETAPI_MAX_PKTIO;i++) \r
-   { \r
-       netapi_global.pktios[i].qn.qNum=-1;\r
-        netapi_global.pktios[i].name[0]='\0';\r
-   }\r
- }   \r
- //this goes to shared memory eventually\r
- p->global = (void *) &netapi_global;\r
-\r
-\r
-   /* system init */\r
-   if(master==NETAPI_SYS_MASTER)\r
-   {\r
-      err = system_init(p);\r
-      if (err<0) \r
-      {\r
-       //todo: cleanup\r
-       return NULL;\r
-      }\r
-      /* create pktio channels for tx,rx */\r
-   }\r
-   else\r
-   {\r
-       /*todo init for non-system cores/threads */\r
-       /* qm_start, */\r
-       /* attach to heaps */\r
-       /* nwal_start */\r
-   }\r
-  \r
-   return (NETAPI_T) p;\r
-}\r
-\r
-/*-------------------------------\r
- * Shut down netapi instance\r
- *-------------------------------*/\r
-void netapi_shutdown(NETAPI_T h)\r
-{\r
-       int i;\r
-       NETAPI_HANDLE_T * p = (NETAPI_HANDLE_T *) h;\r
-       if (!p) return;\r
-\r
-        printf(">netapi: WARNING shutdown may not be fully implemented\n");\r
-       if (p->master)\r
-        {\r
-           /* close nwal */\r
-           nwal_delete(netapi_global.nwal_context.nwalInstHandle);\r
-\r
-           /* close heaps */\r
-           netapi_closeHeap(h, p->netcp_heap);\r
-           netapi_closeHeap(h, p->netcp_control_heap);\r
-           netapi_closeHeap(h, netapi_get_global()->nwal_context.pa2sa_heap); \r
-           netapi_closeHeap(h, netapi_get_global()->nwal_context.sa2pa_heap); \r
\r
-           //loop over registered heaps\r
-           for(i=0;i<TUNE_NETAPI_MAX_HEAPS;i++)\r
-           {\r
-                if (p->createdHeaps[i])  {netapi_closeHeap(h,p->createdHeaps[i]);p->createdHeaps[i]=NULL;}\r
-           }\r
-           netapi_cleanup_at_start();  //clear 1st 50 not-specified queues..\r
-           netapi_VM_memory_teardown();\r
-        } \r
-       free(p);\r
-        return;\r
-}\r
-\r
-//exception crash\r
-void netapi_err_teardown() { netapi_cleanup_at_start(); exit(-99); }\r
-\r
-/*-------------------utilities-------------------*/\r
-static uint8_t* netapiSharedMemoryMalloc(uint32_t size)\r
-{\r
-return  (uint8_t *)netapi_VM_memAlloc(size +netapi_global.cfg.def_heap_extra_size , 128); \r
-}\r
-\r
-static void netapiSharedMemoryFree(uint8_t* ptr)\r
-{\r
-    /* Do Nothing. */\r
-    printf(">netapi Unexpected.  need to provide a free () for some reason!! \n");\r
-    return;\r
-}\r
-\r
-// initialization\r
-static int system_init(NETAPI_HANDLE_T * handle) \r
-{\r
-    int32_t             result;\r
-    Pktlib_HeapHandle   sharedHeapHandle;\r
-    Pktlib_HeapHandle   controlHeapHandle;    \r
-    Pktlib_HeapCfg      heapCfg;\r
-    int32_t             errCode;\r
-\r
-    /* initialize all the memory we are going to use\r
-       - chunk for buffers, descriptors\r
-       - memory mapped peripherals we use, such as QMSS, PA, etc */\r
-    result= netapi_VM_memory_setup();\r
-    if (result) printf(">netapi: system init - memory set  up OK\n");\r
-    else {printf(">netap: system init - memory set up failed\n"); return -1;}\r
-\r
-    //get timer running\r
-    netapi_init_timer();\r
-\r
-    /* Initialize Queue Manager Sub System */\r
-    result = netapi_init_qm (netapi_global.cfg.def_max_descriptors); \r
-    if (result != 1)\r
-    {\r
-        return -1;\r
-    }\r
-\r
-    /* Start the QMSS. */\r
-    if (netapi_start_qm() != 1)\r
-    {\r
-        return -1;\r
-    }\r
-\r
-    //clean our old junk in 1st bunch of queues that will be allocated to us\r
-    netapi_cleanup_at_start();\r
-\r
-    /* Initialize the global descriptor memory region. */\r
-    result= netapi_qm_setup_mem_region( \r
-                      netapi_global.cfg.def_tot_descriptors_for_us,\r
-                      SIZE_SHARED_DESC,\r
-                      (unsigned int *) netapi_VM_QMemGlobalDescRam,\r
-                      NETAPI_GLOBAL_REGION);\r
-    if(result <0) {printf(">netapi; can't setup QM shared region\n"); return -1;}\r
-\r
-#if 0 //todo setup 2nd region\r
-/* Initialize the local memory region configuration. */\r
-    result= netapi_qm_setup_mem_region( \r
-                      NUM_HOST_DESC,\r
-                      SIZE_LOCAL_DESC,\r
-                      netapi_VM_QMemLocalDescRam,\r
-                      NETAPI_LOCAL_REGION);\r
-    if(result <0) {printf("can't setup local region\n"); return -1;}\r
-#endif\r
-    /* Initialize CPPI CPDMA */\r
-\r
-    result = netapi_init_cppi ();\r
-    if (result != 1)\r
-    {\r
-        printf (">netapi: Error initializing CPPI SubSystem error code : %d\n",result);\r
-        return -1;\r
-    }\r
-\r
-    /* CPPI and Queue Manager are initialized. */\r
-    printf (">netapi: Queue Manager and CPPI are initialized.\n");\r
-\r
-    /* create main pkt heap */\r
-    /* Initialize the Shared Heaps. */\r
-    Pktlib_sharedHeapInit();\r
-\r
-    /* Populate the heap interface table. */\r
-    netapi_pktlib_ifTable.data_malloc             = netapiSharedMemoryMalloc;\r
-    netapi_pktlib_ifTable.data_free               = netapiSharedMemoryFree;\r
-\r
-    /* Initialize the heap configuration. */\r
-    memset ((void *)&heapCfg, 0, sizeof(Pktlib_HeapCfg));\r
-    /* Populate the heap configuration */\r
-    heapCfg.name                = "netapi";\r
-    heapCfg.memRegion           = NETAPI_GLOBAL_REGION;\r
-    heapCfg.sharedHeap          = 1;\r
-    heapCfg.useStarvationQueue  = 0;\r
-    heapCfg.dataBufferSize      = netapi_global.cfg.def_heap_buf_size;\r
-    heapCfg.numPkts             = netapi_global.cfg.def_heap_n_descriptors;\r
-    heapCfg.numZeroBufferPackets= netapi_global.cfg.def_heap_n_zdescriptors;\r
-    heapCfg.heapInterfaceTable.data_malloc  = netapi_pktlib_ifTable.data_malloc;\r
-    heapCfg.heapInterfaceTable.data_free    = netapi_pktlib_ifTable.data_free;\r
-    heapCfg.dataBufferPktThreshold   = 0;\r
-    heapCfg.zeroBufferPktThreshold   = 0;\r
-\r
-    /* Create Shared Heap with specified configuration. */\r
-    sharedHeapHandle = Pktlib_createHeap(&heapCfg, &errCode);\r
-    //todo -> cleanup on failure\r
-    if (!sharedHeapHandle) { printf(">'netapi' heap create failed, Error Code: %d\n",errCode); return -1;}\r
-    handle->netcp_heap= sharedHeapHandle;\r
-\r
-\r
-    /* Update for Control */\r
-    heapCfg.name                = "netapi_control";\r
-    heapCfg.sharedHeap          = 1;\r
-    heapCfg.dataBufferSize      = TUNE_NETAPI_CONFIG_MAX_CTL_RXTX_BUF_SIZE;\r
-    heapCfg.numPkts             = TUNE_NETAPI_CONFIG_NUM_CTL_BUF;\r
-    heapCfg.numZeroBufferPackets= 0;\r
-\r
-    controlHeapHandle = Pktlib_createHeap(&heapCfg, &errCode);;\r
-   //todo -> cleanup on failure\r
-   if (!controlHeapHandle) { printf(">netapi -'netapicontrol' heap create failed, Error Code: %d\n",errCode); return -1;}\r
-   handle->netcp_control_heap= controlHeapHandle;\r
-\r
-\r
-    /* now NWAL */\r
-    result = netapi_init_nwal(\r
-                              NETAPI_GLOBAL_REGION,\r
-                              &netapi_pktlib_ifTable, \r
-                              &netapi_global.nwal_context,\r
-                              &netapi_global.cfg);\r
-    if (result<0) {printf(">netapi  init_nwal() failed\n"); return -1; }\r
-\r
-    /* start NWAL */\r
-    result = netapi_start_nwal(sharedHeapHandle, \r
-                               controlHeapHandle,\r
-                               &handle->nwal_local,\r
-                               &netapi_global.cfg,\r
-                               &netapi_global.nwal_context);\r
-    if (result<0) {printf(">netapi start_nwal() failed\n"); return -1; }\r
-    //** success **\r
-\r
-\r
-    return 0;\r
-\r
-}\r
-\r
-\r
-/*---------------\r
- * get presets()\r
- *---------------*/\r
-static void get_presets(PRESET_T * p_preset)\r
-{\r
- /* read from kernel or overall config area */\r
- /* for now hard code what kernel did */\r
-}\r
-\r
-\r
-/*************************************************************\r
- ******************MISC INTERNAL******************************\r
-**************************************************************/\r
-/* poll the garbage queues of all registered heaps */\r
-void netapi_pollHeapGarbage(NETAPI_T h)\r
-{\r
-int i;\r
-       NETAPI_HANDLE_T * n = (NETAPI_HANDLE_T *) h;\r
-        Pktlib_garbageCollection(n->netcp_heap);\r
-        //no need to do garbage collection on other internal heaps\r
-       for(i=0;i<TUNE_NETAPI_MAX_HEAPS;i++)\r
-       {\r
-               if (n->createdHeaps[i]) Pktlib_garbageCollection(n->createdHeaps[i]);\r
-       }\r
-}\r
-\r
-/* poll NETCP control queue for responses */\r
-void netapi_netcpPoll(NETAPI_T  p)\r
-{\r
-       NETAPI_HANDLE_T * n = (NETAPI_HANDLE_T *) p;\r
-        nwal_pollCtl( ((NETAPI_GLOBAL_T *) (n->global))->nwal_context.nwalInstHandle,NULL,NULL);\r
-}\r
-\r
-/****************************************************************\r
- *****************Cleanup Functions******************************\r
-*****************************************************************/\r
-\r
-//clean up function for linux user space\r
-void netapi_zapQ(int queueNum)\r
-{\r
-char * descPtr;\r
-int i;\r
-if (!queueNum) return;\r
-for (i=0;;i+=1 )\r
-        {\r
-                /* Pop descriptor from source queue */\r
-                if ((descPtr = (char *)Qmss_queuePop (queueNum)) == NULL)\r
-                {\r
-                        break;\r
-                }\r
-                else {/*printf("netapi qzap in play\n");*/}\r
-        }\r
-        if(i) printf(">netapi: @recovery -  %d descriptors cleaned from qn %d\n",i, queueNum);\r
-}\r
-\r
-//defensive: clean out stuff hanging around\r
-//\r
-//  open a bunch of free queues and zap them\r
-#define NQUEUES2CLEAR 15\r
-static Qmss_QueueHnd tempQH[NQUEUES2CLEAR];\r
-static void netapi_cleanup_at_start(void)\r
-{\r
-int i;\r
-uint8_t         isAllocated;\r
-\r
-for(i=0;i<NQUEUES2CLEAR;i++) \r
-{\r
-       tempQH[i] = Qmss_queueOpen(Qmss_QueueType_GENERAL_PURPOSE_QUEUE,\r
-                                                  QMSS_PARAM_NOT_SPECIFIED, &isAllocated);\r
-       netapi_zapQ(tempQH[i]);\r
-}\r
-\r
-for(i=0;i<NQUEUES2CLEAR;i++)\r
-{\r
-        Qmss_queueClose(tempQH[i]);\r
-}\r
-\r
-}\r
-\r
-/********************************\r
- *  clean up a  pktlib heap\r
- ***********************************/\r
-int netapi_closeHeap(NETAPI_T h, Pktlib_HeapHandle p)\r
-{\r
-Qmss_QueueHnd q;\r
-Pktlib_garbageCollection(p);  \r
-q = Pktlib_getZeroHeapQueue(p);\r
-netapi_zapQ(q);\r
-q= Pktlib_getInternalHeapQueue(p);\r
-netapi_zapQ(q);\r
-}\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
+/***********************************************************************
+ * FILE: netapi.c
+ * Purpose:  Main initialization and shutdown routines of NETAPI 
+ *           user space transport library.
+ ***********************************************************************
+ * FILE: netapi.c
+ * 
+ * DESCRIPTION:  netapi main source file for user space transport
+ *               library
+ * 
+ * REVISION HISTORY:
+ *
+ *  Copyright (c) Texas Instruments Incorporated 2013
+ * 
+ *  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 Texas Instruments Incorporated nor the names of
+ *    its contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+ *  "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 THE COPYRIGHT 
+ *  OWNER OR CONTRIBUTORS 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 <unistd.h>
+#include "ti/runtime/netapi/netapi.h"
+#include "netapi_loc.h"
+
+static NETAPI_CFG_T netapi_default_cfg=
+{
+    TUNE_NETAPI_PERM_MEM_SZ,
+    0,  //start of packet offset for hw to place data on rx for default flow
+    TUNE_NETAPI_QM_CONFIG_MAX_DESC_NUM, //max number of descriptors in system
+    TUNE_NETAPI_NUM_GLOBAL_DESC,        //total we will use
+    TUNE_NETAPI_DEFAULT_NUM_BUFFERS,   //#descriptors+buffers in default heap
+    TUNE_NETAPI_DEFAULT_NUM_SOLO_DESCRIPTORS, //#descriptors w/o buffers in default heap
+    TUNE_NETAPI_DEFAULT_BUFFER_SIZE,   //size of buffers in default heap
+    0,0
+};
+
+/* Global variablesto hold virtual address of various subsystems */
+hplib_virtualAddrInfo_T netapi_VM_VirtAddr[HPLIB_MAX_MEM_POOLS];
+
+/* Global variables which needs to be populated with memory pool attributes
+   which is passed to HPLIB for memory pool initialization*/
+hplib_memPoolAttr_T netapi_VM_MempoolAttr[HPLIB_MAX_MEM_POOLS];
+unsigned char *netapi_VM_QMemLocalDescRam;
+unsigned char *netapi_VM_QMemGlobalDescRam;
+unsigned char *netapi_VM_SaContextVaddr;
+
+Pktlib_HeapIfTable  netapi_pktlib_ifTable;
+NETAPI_GLOBAL_T netapi_global;
+NETAPI_GLOBAL_T * netapi_get_global(){ return &netapi_global;}
+
+/* utility API for NETAPI user to get pktlib if table to use if he creates his own heap */
+Pktlib_HeapIfTable *netapi_getPktlibIfTable(void) {return &netapi_pktlib_ifTable;}
+
+
+/********************************************************************
+* FUNCTION PURPOSE:  API instantiates the NETAPI and allocated global resources.
+ ********************************************************************
+ * DESCRIPTION:  API instantiates the NETAPI and allocated global resources.
+ ********************************************************************/
+NETAPI_T netapi_init(int master, NETAPI_CFG_T * p_cfg)
+{
+    int i;
+    int err;
+    int exception_id = 7;
+    NETAPI_HANDLE_T * p = (NETAPI_HANDLE_T *) calloc(1,sizeof(NETAPI_HANDLE_T));
+    NETAPI_HANDLE_T * p_master;
+    if (!p) return NULL;
+    p->master = master;
+
+    /* create space for our local pktios */
+    for(i=0;i<TUNE_NETAPI_MAX_PKTIO; i++)
+    {
+        p->pktios[i] = calloc(1,sizeof(PKTIO_HANDLE_T));
+        if (!p->pktios[i])
+        {
+            return NULL;
+        }
+    }
+
+#ifdef NETAPI_INCLUDE_SCHED
+    /* create space for scheduler */
+    p->p_sched = calloc(1,sizeof(NETAPI_SCHED_HANDLE_T));
+    if (!p->p_sched)
+    {
+        goto ERR_netapi_init;
+    }
+#endif
+
+    /* Global init for SYS_MATER */
+    if (master==NETAPI_SYS_MASTER)
+    {
+        if (p_cfg)
+        {
+            memcpy(&netapi_global.cfg,p_cfg, sizeof(NETAPI_CFG_T));
+        }
+        else
+        {
+            memcpy(&netapi_global.cfg,&netapi_default_cfg, sizeof(NETAPI_CFG_T));
+        }
+        for(i=0;i<TUNE_NETAPI_MAX_PKTIO;i++) 
+        {
+            netapi_global.pktios[i].qn.qNum=-1;
+            netapi_global.pktios[i].name[0]='\0';
+        }
+    }
+    //this goes to shared memory eventually
+    p->global = (void *) &netapi_global;
+
+    //save master's handle back in global; else for slave retrieve p_master
+    if (master==NETAPI_SYS_MASTER)
+    {
+        netapi_global.p_master = p;
+    }
+    else
+    {
+        /* get system master reqquired for core and no master */
+        p_master=(NETAPI_HANDLE_T *)netapi_global.p_master;
+    }
+
+    /* system init */
+    if(master==NETAPI_SYS_MASTER)
+    {
+        err = netapip_systemInit(p);
+        netapi_netcpCfgExceptions(p, NETCP_CFG_ALL_EXCEPTIONS, NETCP_CFG_ACTION_TO_SW, (NETCP_CFG_ROUTE_HANDLE_T) NULL);
+        if (err<0) 
+        {
+            goto ERR_netapi_init;
+        }
+    /* create pktio channels for tx,rx */
+    }
+    else if (master==NETAPI_NO_MASTER)
+    {
+        //dalmt ->simple trial.  Just copy master's packetio list for now
+        p->n_pktios = p_master->n_pktios;
+        memcpy(&p->pktios[0],&p_master->pktios[0],TUNE_NETAPI_MAX_PKTIO*sizeof(PKTIO_HANDLE_T));
+        p->nwal_local=p_master->nwal_local;
+    }
+    /* this is the NETAPI_CORE_MASTER case */
+     else if (master==NETAPI_CORE_MASTER)
+    {
+
+        /* Start the QMSS. */
+        if (netapip_startQm() != 1)
+        {
+            goto ERR_netapi_init;
+        }
+        netapip_startNwal(p_master->netcp_heap, 
+                                       p_master->netcp_control_rx_heap,
+                                       p_master->netcp_control_tx_heap, 
+                                       &p->nwal_local,
+                                       &netapi_global.cfg,
+                                       &netapi_global.nwal_context);
+    }
+    else
+    {
+        netapi_Log("netapi_init: no master specified\n");
+        goto ERR_netapi_init;
+    }
+
+    return (NETAPI_T) p;
+
+ERR_netapi_init:
+    for(i=0;i<TUNE_NETAPI_MAX_PKTIO; i++)
+    {
+        if (p->pktios[i])
+        {
+            free(p->pktios[i]);
+        }
+    }
+#ifdef NETAPI_INCLUDE_SCHED
+    if (p->p_sched)
+    {
+        free(p->p_sched);
+    }
+#endif
+    return NULL;
+}
+
+/********************************************************************
+* FUNCTION PURPOSE:  API de-allocates all global resources allocated as part 
+*                                   of ref netapi_init
+ ********************************************************************
+ * DESCRIPTION:   API de-allocates all global resources allocated as part 
+*                                   of ref netapi_init
+ ********************************************************************/
+void netapi_shutdown(NETAPI_T h)
+{
+    int i;
+    NETAPI_HANDLE_T * p = (NETAPI_HANDLE_T *) h;
+    if (!p) return;
+
+    netapi_Log("netapi: WARNING shutdown may not be fully implemented\n");
+    if (p->master ==NETAPI_SYS_MASTER)
+    {
+        /* close nwal */
+        nwal_delete(netapi_global.nwal_context.nwalInstHandle);
+
+        /* close heaps */
+        netapi_closeHeap(h, p->netcp_heap);
+        netapi_closeHeap(h, p->netcp_control_rx_heap);
+        netapi_closeHeap(h, p->netcp_control_tx_heap);
+        netapi_closeHeap(h, netapi_get_global()->nwal_context.pa2sa_heap); 
+        netapi_closeHeap(h, netapi_get_global()->nwal_context.sa2pa_heap); 
+
+    /* Un-configure rules for execption packet handling */
+    netapi_netcpCfgExceptions(p,
+                              NETCP_CFG_ALL_EXCEPTIONS,
+                              NETCP_CFG_ACTION_DISCARD,
+                              (NETCP_CFG_ROUTE_HANDLE_T) NULL);
+        //loop over registered heaps
+        for(i=0;i<TUNE_NETAPI_MAX_HEAPS;i++)
+        {
+            if (p->createdHeaps[i])  {netapi_closeHeap(h,p->createdHeaps[i]);p->createdHeaps[i]=NULL;}
+        }
+        netapip_cleanupAtStart();  //clear 1st 50 not-specified queues..
+        hplib_vmTeardown();
+    }
+    free(p);
+    return;
+}
+
+/***********************************************************************
+* FUNCTION PURPOSE:  API is used to poll for NETCP configuration response messages.
+************************************************************************
+* DESCRIPTION:  This API is used to poll the netapi internal heaps and any 
+ *              application-created heaps that have been registered with 
+ *              the netapi instance. The poll function checks the garbage collection 
+ *              queue associated with the heap and returns descriptors and buffers 
+ *              when appropriate to the main free queue.
+***********************************************************************/
+void netapi_pollHeapGarbage(NETAPI_T h)
+{
+    int i;
+    NETAPI_HANDLE_T * n = (NETAPI_HANDLE_T *) h;
+    Pktlib_garbageCollection(n->netcp_heap);
+    //no need to do garbage collection on other internal heaps
+    for(i=0;i<TUNE_NETAPI_MAX_HEAPS;i++)
+    {
+        if (n->createdHeaps[i])
+        {
+            Pktlib_garbageCollection(n->createdHeaps[i]);
+        }
+    }
+}
+
+/****************************************************************************
+* FUNCTION PURPOSE:  API is used to poll for NETCP configuration response messages.
+****************************************************************************
+* DESCRIPTION:  This API is used to poll the netapi internal heaps and any 
+ *              application-created heaps    that have been registered with the 
+ *              netapi instance. The poll function checks the garbage collection 
+ *              queue associated with the heap and returns descriptors and buffers
+ *              when appropriate to the main free queue.
+***************************************************************************/
+void netapi_netcpPoll(NETAPI_T  p)
+{
+    NETAPI_HANDLE_T * n = (NETAPI_HANDLE_T *) p;
+    nwal_pollCtl( ((NETAPI_GLOBAL_T *) (n->global))->nwal_context.nwalInstHandle,NULL,NULL);
+}
+