1 /*******************************
2 * FILE: netapi.c
3 * Purpose: implementation of netapi startup/shutdown
4 **************************************************************
5 * FILE: netapi.c
6 *
7 * DESCRIPTION: netapi main source file for user space transport
8 * library
9 *
10 * REVISION HISTORY: rev 0.0.1
11 *
12 * Copyright (c) Texas Instruments Incorporated 2010-2011
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions
16 * are met:
17 *
18 * Redistributions of source code must retain the above copyright
19 * notice, this list of conditions and the following disclaimer.
20 *
21 * Redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the
24 * distribution.
25 *
26 * Neither the name of Texas Instruments Incorporated nor the names of
27 * its contributors may be used to endorse or promote products derived
28 * from this software without specific prior written permission.
29 *
30 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
31 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
32 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
33 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
34 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
35 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
36 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
37 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
38 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
39 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
40 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
42 * *****************************/
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include <unistd.h>
46 #include <string.h>
47 #include "netapi.h"
49 typedef struct PRESET_Tag
50 {
51 #define KMAXQ 10
52 int kqinuse[KMAXQ];
53 //more..
54 } PRESET_T;
56 /*------------internal prototypes---------------*/
57 static uint8_t* netapiSharedMemoryMalloc(uint32_t size);
58 static void netapiSharedMemoryFree(uint8_t* ptr);
59 static int system_init(NETAPI_HANDLE_T *);
60 static void get_presets(PRESET_T * p_preset);
61 static void netapi_cleanup_at_start(void);
64 /*------------globals-----------------*/
65 #define NUM_HOST_DESC (TUNE_NETAPI_NUM_LOCAL_DESC)
66 #define SIZE_LOCAL_DESC (TUNE_NETAPI_DESC_SIZE)
67 #define SIZE_SHARED_DESC (TUNE_NETAPI_DESC_SIZE)
69 #define CONFIG_BUFSIZE_PA_INST 256
70 #define CONFIG_BUFSIZE_L2_TABLE 1000
71 #define CONFIG_BUFSIZE_L3_TABLE 4000
73 static NETAPI_CFG_T netapi_default_cfg=
74 {
75 TUNE_NETAPI_PERM_MEM_SZ,
76 0, //start of packet offset for hw to place data on rx for default flow
77 TUNE_NETAPI_QM_CONFIG_MAX_DESC_NUM, //max number of descriptors in system
78 TUNE_NETAPI_NUM_GLOBAL_DESC, //total we will use
79 TUNE_NETAPI_DEFAULT_NUM_BUFFERS, //#descriptors+buffers in default heap
80 TUNE_NETAPI_DEFAULT_NUM_SOLO_DESCRIPTORS, //#descriptors w/o buffers in default heap
81 TUNE_NETAPI_DEFAULT_BUFFER_SIZE //size of buffers in default heap
83 };
85 static Pktlib_HeapIfTable netapi_pktlib_ifTable;
86 static NETAPI_GLOBAL_T netapi_global;
87 NETAPI_GLOBAL_T * netapi_get_global(){ return &netapi_global;}
89 /* utility API for NETAPI user to get pktlib if table to use if he creates his own heap */
90 Pktlib_HeapIfTable *netapi_getPktlibIfTable(void) {return &netapi_pktlib_ifTable;}
92 //zap a queue
93 void netapi_zapQ(int queueNum);
94 /*-------------------------------------
95 * initialize NETAPI instance
96 *-------------------------------------*/
97 NETAPI_T netapi_init(int master, NETAPI_CFG_T * p_cfg)
98 {
99 int i;
100 int err;
101 NETAPI_HANDLE_T * p = (NETAPI_HANDLE_T *) calloc(1,sizeof(NETAPI_HANDLE_T));
102 if (!p) return NULL;
103 p->master = master;
105 /* create space for our local pktios */
106 for(i=0;i<NETAPI_MAX_PKTIO; i++)
107 {
108 p->pktios[i] = calloc(1,sizeof(PKTIO_HANDLE_T));
109 if (!p->pktios[i]) return NULL;
110 }
112 #ifdef NETAPI_INCLUDE_SCHED
113 /* create space for scheduler */
114 p->p_sched = calloc(1,sizeof(NETAPI_SCHED_HANDLE_T));
115 #endif
118 /* global stuff (if master) */
119 if (master==NETAPI_SYS_MASTER)
120 {
121 if (p_cfg) memcpy(&netapi_global.cfg,p_cfg, sizeof(NETAPI_CFG_T));
122 else memcpy(&netapi_global.cfg,&netapi_default_cfg, sizeof(NETAPI_CFG_T));
123 for(i=0;i<NETAPI_MAX_PKTIO;i++)
124 {
125 netapi_global.pktios[i].qn.qNum=-1;
126 netapi_global.pktios[i].name[0]='\0';
127 }
128 }
129 //this goes to shared memory eventually
130 p->global = (void *) &netapi_global;
133 /* system init */
134 if(master==NETAPI_SYS_MASTER)
135 {
136 err = system_init(p);
137 if (err<0)
138 {
139 //todo: cleanup
140 return NULL;
141 }
142 /* create pktio channels for tx,rx */
143 }
144 else
145 {
146 /*todo init for non-system cores/threads */
147 /* qm_start, */
148 /* attach to heaps */
149 /* nwal_start */
150 }
152 return (NETAPI_T) p;
153 }
155 /*-------------------------------
156 * Shut down netapi instance
157 *-------------------------------*/
158 void netapi_shutdown(NETAPI_T h)
159 {
160 int i;
161 NETAPI_HANDLE_T * p = (NETAPI_HANDLE_T *) h;
162 if (!p) return;
164 printf(">netapi: WARNING shutdown may not be fully implemented\n");
165 if (p->master)
166 {
167 /* close nwal */
168 nwal_delete(netapi_global.nwal_context.nwalInstHandle);
170 /* close heaps */
171 netapi_closeHeap(h, p->netcp_heap);
172 netapi_closeHeap(h, p->netcp_control_rx_heap);
173 netapi_closeHeap(h, p->netcp_control_tx_heap);
174 netapi_closeHeap(h, netapi_get_global()->nwal_context.pa2sa_heap);
175 netapi_closeHeap(h, netapi_get_global()->nwal_context.sa2pa_heap);
177 //loop over registered heaps
178 for(i=0;i<TUNE_NETAPI_MAX_HEAPS;i++)
179 {
180 if (p->createdHeaps[i]) {netapi_closeHeap(h,p->createdHeaps[i]);p->createdHeaps[i]=NULL;}
181 }
182 netapi_cleanup_at_start(); //clear 1st 50 not-specified queues..
183 netapi_VM_memory_teardown();
184 }
185 free(p);
186 return;
187 }
189 //exception crash
190 void netapi_err_teardown() { netapi_cleanup_at_start(); exit(-99); }
192 /*-------------------utilities-------------------*/
193 static uint8_t* netapiSharedMemoryMalloc(uint32_t size)
194 {
195 return (uint8_t *)netapi_VM_memAlloc(size, 128);
196 }
198 static void netapiSharedMemoryFree(uint8_t* ptr)
199 {
200 /* Do Nothing. */
201 printf(">netapi Unexpected. need to provide a free () for some reason!! \n");
202 return;
203 }
205 // initialization
206 static int system_init(NETAPI_HANDLE_T * handle)
207 {
208 int32_t result;
209 Pktlib_HeapHandle sharedHeapHandle;
210 Pktlib_HeapHandle controlRxHeapHandle,controlTxHeapHandle;
211 Pktlib_HeapCfg heapCfg;
212 int32_t errCode;
214 /* initialize all the memory we are going to use
215 - chunk for buffers, descriptors
216 - memory mapped peripherals we use, such as QMSS, PA, etc */
217 result= netapi_VM_memory_setup();
218 if (result) printf(">netapi: system init - memory set up OK\n");
219 else {printf(">netap: system init - memory set up failed\n"); return -1;}
221 //get timer running
222 netapi_init_timer();
224 /* Initialize Queue Manager Sub System */
225 result = netapi_init_qm (netapi_global.cfg.def_max_descriptors);
226 if (result != 1)
227 {
228 return -1;
229 }
231 /* Start the QMSS. */
232 if (netapi_start_qm() != 1)
233 {
234 return -1;
235 }
237 //clean our old junk in 1st bunch of queues that will be allocated to us
238 netapi_cleanup_at_start();
240 /* Initialize the global descriptor memory region. */
241 result= netapi_qm_setup_mem_region(
242 netapi_global.cfg.def_tot_descriptors_for_us,
243 SIZE_SHARED_DESC,
244 (unsigned int *) netapi_VM_QMemGlobalDescRam,
245 NETAPI_GLOBAL_REGION);
246 if(result <0) {printf(">netapi; can't setup QM shared region\n"); return -1;}
248 #if 0 //todo setup 2nd region
249 /* Initialize the local memory region configuration. */
250 result= netapi_qm_setup_mem_region(
251 NUM_HOST_DESC,
252 SIZE_LOCAL_DESC,
253 netapi_VM_QMemLocalDescRam,
254 NETAPI_LOCAL_REGION);
255 if(result <0) {printf("can't setup local region\n"); return -1;}
256 #endif
257 /* Initialize CPPI CPDMA */
259 result = netapi_init_cppi ();
260 if (result != 1)
261 {
262 printf (">netapi: Error initializing CPPI SubSystem error code : %d\n",result);
263 return -1;
264 }
266 /* CPPI and Queue Manager are initialized. */
267 printf (">netapi: Queue Manager and CPPI are initialized.\n");
269 /* create main pkt heap */
270 /* Initialize the Shared Heaps. */
271 Pktlib_sharedHeapInit();
273 /* Populate the heap interface table. */
274 netapi_pktlib_ifTable.data_malloc = netapiSharedMemoryMalloc;
275 netapi_pktlib_ifTable.data_free = netapiSharedMemoryFree;
277 /* Initialize the heap configuration. */
278 memset ((void *)&heapCfg, 0, sizeof(Pktlib_HeapCfg));
279 /* Populate the heap configuration */
280 heapCfg.name = "netapi";
281 heapCfg.memRegion = NETAPI_GLOBAL_REGION;
282 heapCfg.sharedHeap = 1;
283 heapCfg.useStarvationQueue = 0;
284 heapCfg.dataBufferSize = netapi_global.cfg.def_heap_buf_size;
285 heapCfg.numPkts = netapi_global.cfg.def_heap_n_descriptors;
286 heapCfg.numZeroBufferPackets= netapi_global.cfg.def_heap_n_zdescriptors;
287 heapCfg.heapInterfaceTable.data_malloc = netapi_pktlib_ifTable.data_malloc;
288 heapCfg.heapInterfaceTable.data_free = netapi_pktlib_ifTable.data_free;
289 heapCfg.dataBufferPktThreshold = 0;
290 heapCfg.zeroBufferPktThreshold = 0;
292 /* Create Shared Heap with specified configuration. */
293 sharedHeapHandle = Pktlib_createHeap(&heapCfg, &errCode);
294 //todo -> cleanup on failure
295 if (!sharedHeapHandle) { printf(">'netapi' heap create failed, Error Code: %d\n",errCode); return -1;}
296 handle->netcp_heap= sharedHeapHandle;
299 /* Update for Control */
300 heapCfg.name = "netapi_control_rx";
301 heapCfg.sharedHeap = 1;
302 heapCfg.dataBufferSize = TUNE_NETAPI_CONFIG_MAX_CTL_RXTX_BUF_SIZE;
303 heapCfg.numPkts = TUNE_NETAPI_CONFIG_NUM_CTL_RX_BUF;
304 heapCfg.numZeroBufferPackets= 0;
306 controlRxHeapHandle = Pktlib_createHeap(&heapCfg, &errCode);
307 //todo -> cleanup on failure
308 if (!controlRxHeapHandle) { printf(">netapi -'netapi_control_rx' heap create failed, Error Code: %d\n",errCode); return -1;}
309 handle->netcp_control_rx_heap= controlRxHeapHandle;
312 heapCfg.name = "netapi_control_tx";
313 heapCfg.numPkts = TUNE_NETAPI_CONFIG_NUM_CTL_TX_BUF;
315 controlTxHeapHandle = Pktlib_createHeap(&heapCfg, &errCode);
316 //todo -> cleanup on failure
317 if (!controlTxHeapHandle) { printf(">netapi -'netapi_control_tx' heap create failed, Error Code: %d\n",errCode); return -1;}
318 handle->netcp_control_tx_heap= controlTxHeapHandle;
320 /* now NWAL */
321 result = netapi_init_nwal(
322 NETAPI_GLOBAL_REGION,
323 &netapi_pktlib_ifTable,
324 &netapi_global.nwal_context,
325 &netapi_global.cfg);
326 if (result<0) {printf(">netapi init_nwal() failed\n"); return -1; }
328 /* start NWAL */
329 result = netapi_start_nwal(sharedHeapHandle,
330 controlRxHeapHandle,
331 controlTxHeapHandle,
332 &handle->nwal_local,
333 &netapi_global.cfg,
334 &netapi_global.nwal_context);
335 if (result<0) {printf(">netapi start_nwal() failed\n"); return -1; }
336 //** success **
339 return 0;
341 }
344 /*---------------
345 * get presets()
346 *---------------*/
347 static void get_presets(PRESET_T * p_preset)
348 {
349 /* read from kernel or overall config area */
350 /* for now hard code what kernel did */
351 }
354 /*************************************************************
355 ******************MISC INTERNAL******************************
356 **************************************************************/
357 /* poll the garbage queues of all registered heaps */
358 void netapi_pollHeapGarbage(NETAPI_T h)
359 {
360 int i;
361 NETAPI_HANDLE_T * n = (NETAPI_HANDLE_T *) h;
362 Pktlib_garbageCollection(n->netcp_heap);
363 //no need to do garbage collection on other internal heaps
364 for(i=0;i<TUNE_NETAPI_MAX_HEAPS;i++)
365 {
366 if (n->createdHeaps[i]) Pktlib_garbageCollection(n->createdHeaps[i]);
367 }
368 }
370 /* poll NETCP control queue for responses */
371 void netapi_netcpPoll(NETAPI_T p)
372 {
373 NETAPI_HANDLE_T * n = (NETAPI_HANDLE_T *) p;
374 nwal_pollCtl( ((NETAPI_GLOBAL_T *) (n->global))->nwal_context.nwalInstHandle,NULL,NULL);
375 }
377 /****************************************************************
378 *****************Cleanup Functions******************************
379 *****************************************************************/
381 //clean up function for linux user space
382 void netapi_zapQ(int queueNum)
383 {
384 char * descPtr;
385 int i;
386 if (!queueNum) return;
387 for (i=0;;i+=1 )
388 {
389 /* Pop descriptor from source queue */
390 if ((descPtr = (char *)Qmss_queuePop (queueNum)) == NULL)
391 {
392 break;
393 }
394 else {/*printf("netapi qzap in play\n");*/}
395 }
396 if(i) printf(">netapi: @recovery - %d descriptors cleaned from qn %d\n",i, queueNum);
397 }
399 //defensive: clean out stuff hanging around
400 //
401 // open a bunch of free queues and zap them
402 #define NQUEUES2CLEAR 35
403 static Qmss_QueueHnd tempQH[NQUEUES2CLEAR];
404 static void netapi_cleanup_at_start(void)
405 {
406 int i;
407 uint8_t isAllocated;
409 for(i=0;i<NQUEUES2CLEAR;i++)
410 {
411 tempQH[i] = Qmss_queueOpen(Qmss_QueueType_GENERAL_PURPOSE_QUEUE,
412 QMSS_PARAM_NOT_SPECIFIED, &isAllocated);
413 netapi_zapQ(tempQH[i]);
414 }
416 for(i=0;i<NQUEUES2CLEAR;i++)
417 {
418 Qmss_queueClose(tempQH[i]);
419 }
421 }
423 /********************************
424 * clean up a pktlib heap
425 ***********************************/
426 int netapi_closeHeap(NETAPI_T h, Pktlib_HeapHandle p)
427 {
428 Qmss_QueueHnd q;
429 Pktlib_garbageCollection(p);
430 q = Pktlib_getZeroHeapQueue(p);
431 netapi_zapQ(q);
432 q= Pktlib_getInternalHeapQueue(p);
433 netapi_zapQ(q);
434 }