/******************************* * FILE: netapi.c * Purpose: implementation of netapi startup/shutdown ************************************************************** * FILE: netapi.c * * DESCRIPTION: netapi main source file for user space transport * library * * REVISION HISTORY: rev 0.0.1 * * Copyright (c) Texas Instruments Incorporated 2010-2011 * * 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 #include #include #include #include "netapi.h" typedef struct PRESET_Tag { #define KMAXQ 10 int kqinuse[KMAXQ]; //more.. } PRESET_T; /*------------internal prototypes---------------*/ static uint8_t* netapiSharedMemoryMalloc(uint32_t size); static void netapiSharedMemoryFree(uint8_t* ptr); static int system_init(NETAPI_HANDLE_T *); static void get_presets(PRESET_T * p_preset); static void netapi_cleanup_at_start(void); /*------------globals-----------------*/ #define NUM_HOST_DESC (TUNE_NETAPI_NUM_LOCAL_DESC) #define SIZE_LOCAL_DESC (TUNE_NETAPI_DESC_SIZE) #define SIZE_SHARED_DESC (TUNE_NETAPI_DESC_SIZE) #define CONFIG_BUFSIZE_PA_INST 256 #define CONFIG_BUFSIZE_L2_TABLE 1000 #define CONFIG_BUFSIZE_L3_TABLE 4000 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 }; static Pktlib_HeapIfTable netapi_pktlib_ifTable; static 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;} //zap a queue void netapi_zapQ(int queueNum); /*------------------------------------- * initialize NETAPI instance *-------------------------------------*/ NETAPI_T netapi_init(int master, NETAPI_CFG_T * p_cfg) { int i; int err; NETAPI_HANDLE_T * p = (NETAPI_HANDLE_T *) calloc(1,sizeof(NETAPI_HANDLE_T)); if (!p) return NULL; p->master = master; /* create space for our local pktios */ for(i=0;ipktios[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)); #endif /* global stuff (if master) */ 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;iglobal = (void *) &netapi_global; /* system init */ if(master==NETAPI_SYS_MASTER) { err = system_init(p); if (err<0) { //todo: cleanup return NULL; } /* create pktio channels for tx,rx */ } else { /*todo init for non-system cores/threads */ /* qm_start, */ /* attach to heaps */ /* nwal_start */ } return (NETAPI_T) p; } /*------------------------------- * Shut down netapi instance *-------------------------------*/ void netapi_shutdown(NETAPI_T h) { int i; NETAPI_HANDLE_T * p = (NETAPI_HANDLE_T *) h; if (!p) return; printf(">netapi: WARNING shutdown may not be fully implemented\n"); if (p->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); //loop over registered heaps for(i=0;icreatedHeaps[i]) {netapi_closeHeap(h,p->createdHeaps[i]);p->createdHeaps[i]=NULL;} } netapi_cleanup_at_start(); //clear 1st 50 not-specified queues.. netapi_VM_memory_teardown(); } free(p); return; } //exception crash void netapi_err_teardown() { netapi_cleanup_at_start(); exit(-99); } /*-------------------utilities-------------------*/ static uint8_t* netapiSharedMemoryMalloc(uint32_t size) { return (uint8_t *)netapi_VM_memAlloc(size, 128); } static void netapiSharedMemoryFree(uint8_t* ptr) { /* Do Nothing. */ printf(">netapi Unexpected. need to provide a free () for some reason!! \n"); return; } // initialization static int system_init(NETAPI_HANDLE_T * handle) { int32_t result; Pktlib_HeapHandle sharedHeapHandle; Pktlib_HeapHandle controlRxHeapHandle,controlTxHeapHandle; Pktlib_HeapCfg heapCfg; int32_t errCode; /* initialize all the memory we are going to use - chunk for buffers, descriptors - memory mapped peripherals we use, such as QMSS, PA, etc */ result= netapi_VM_memory_setup(); if (result) printf(">netapi: system init - memory set up OK\n"); else {printf(">netap: system init - memory set up failed\n"); return -1;} //get timer running netapi_init_timer(); /* Initialize Queue Manager Sub System */ result = netapi_init_qm (netapi_global.cfg.def_max_descriptors); if (result != 1) { return -1; } /* Start the QMSS. */ if (netapi_start_qm() != 1) { return -1; } //clean our old junk in 1st bunch of queues that will be allocated to us netapi_cleanup_at_start(); /* Initialize the global descriptor memory region. */ result= netapi_qm_setup_mem_region( netapi_global.cfg.def_tot_descriptors_for_us, SIZE_SHARED_DESC, (unsigned int *) netapi_VM_QMemGlobalDescRam, NETAPI_GLOBAL_REGION); if(result <0) {printf(">netapi; can't setup QM shared region\n"); return -1;} #if 0 //todo setup 2nd region /* Initialize the local memory region configuration. */ result= netapi_qm_setup_mem_region( NUM_HOST_DESC, SIZE_LOCAL_DESC, netapi_VM_QMemLocalDescRam, NETAPI_LOCAL_REGION); if(result <0) {printf("can't setup local region\n"); return -1;} #endif /* Initialize CPPI CPDMA */ result = netapi_init_cppi (); if (result != 1) { printf (">netapi: Error initializing CPPI SubSystem error code : %d\n",result); return -1; } /* CPPI and Queue Manager are initialized. */ printf (">netapi: Queue Manager and CPPI are initialized.\n"); /* create main pkt heap */ /* Initialize the Shared Heaps. */ Pktlib_sharedHeapInit(); /* Populate the heap interface table. */ netapi_pktlib_ifTable.data_malloc = netapiSharedMemoryMalloc; netapi_pktlib_ifTable.data_free = netapiSharedMemoryFree; /* Initialize the heap configuration. */ memset ((void *)&heapCfg, 0, sizeof(Pktlib_HeapCfg)); /* Populate the heap configuration */ heapCfg.name = "netapi"; heapCfg.memRegion = NETAPI_GLOBAL_REGION; heapCfg.sharedHeap = 1; heapCfg.useStarvationQueue = 0; heapCfg.dataBufferSize = netapi_global.cfg.def_heap_buf_size; heapCfg.numPkts = netapi_global.cfg.def_heap_n_descriptors; heapCfg.numZeroBufferPackets= netapi_global.cfg.def_heap_n_zdescriptors; heapCfg.heapInterfaceTable.data_malloc = netapi_pktlib_ifTable.data_malloc; heapCfg.heapInterfaceTable.data_free = netapi_pktlib_ifTable.data_free; heapCfg.dataBufferPktThreshold = 0; heapCfg.zeroBufferPktThreshold = 0; /* Create Shared Heap with specified configuration. */ sharedHeapHandle = Pktlib_createHeap(&heapCfg, &errCode); //todo -> cleanup on failure if (!sharedHeapHandle) { printf(">'netapi' heap create failed, Error Code: %d\n",errCode); return -1;} handle->netcp_heap= sharedHeapHandle; /* Update for Control */ heapCfg.name = "netapi_control_rx"; heapCfg.sharedHeap = 1; heapCfg.dataBufferSize = TUNE_NETAPI_CONFIG_MAX_CTL_RXTX_BUF_SIZE; heapCfg.numPkts = TUNE_NETAPI_CONFIG_NUM_CTL_RX_BUF; heapCfg.numZeroBufferPackets= 0; controlRxHeapHandle = Pktlib_createHeap(&heapCfg, &errCode); //todo -> cleanup on failure if (!controlRxHeapHandle) { printf(">netapi -'netapi_control_rx' heap create failed, Error Code: %d\n",errCode); return -1;} handle->netcp_control_rx_heap= controlRxHeapHandle; heapCfg.name = "netapi_control_tx"; heapCfg.numPkts = TUNE_NETAPI_CONFIG_NUM_CTL_TX_BUF; controlTxHeapHandle = Pktlib_createHeap(&heapCfg, &errCode); //todo -> cleanup on failure if (!controlTxHeapHandle) { printf(">netapi -'netapi_control_tx' heap create failed, Error Code: %d\n",errCode); return -1;} handle->netcp_control_tx_heap= controlTxHeapHandle; /* now NWAL */ result = netapi_init_nwal( NETAPI_GLOBAL_REGION, &netapi_pktlib_ifTable, &netapi_global.nwal_context, &netapi_global.cfg); if (result<0) {printf(">netapi init_nwal() failed\n"); return -1; } /* start NWAL */ result = netapi_start_nwal(sharedHeapHandle, controlRxHeapHandle, controlTxHeapHandle, &handle->nwal_local, &netapi_global.cfg, &netapi_global.nwal_context); if (result<0) {printf(">netapi start_nwal() failed\n"); return -1; } //** success ** return 0; } /*--------------- * get presets() *---------------*/ static void get_presets(PRESET_T * p_preset) { /* read from kernel or overall config area */ /* for now hard code what kernel did */ } /************************************************************* ******************MISC INTERNAL****************************** **************************************************************/ /* poll the garbage queues of all registered heaps */ 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;icreatedHeaps[i]) Pktlib_garbageCollection(n->createdHeaps[i]); } } /* poll NETCP control queue for responses */ 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); } /**************************************************************** *****************Cleanup Functions****************************** *****************************************************************/ //clean up function for linux user space void netapi_zapQ(int queueNum) { char * descPtr; int i; if (!queueNum) return; for (i=0;;i+=1 ) { /* Pop descriptor from source queue */ if ((descPtr = (char *)Qmss_queuePop (queueNum)) == NULL) { break; } else {/*printf("netapi qzap in play\n");*/} } if(i) printf(">netapi: @recovery - %d descriptors cleaned from qn %d\n",i, queueNum); } //defensive: clean out stuff hanging around // // open a bunch of free queues and zap them #define NQUEUES2CLEAR 35 static Qmss_QueueHnd tempQH[NQUEUES2CLEAR]; static void netapi_cleanup_at_start(void) { int i; uint8_t isAllocated; for(i=0;i