]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - keystone-rtos/netapi.git/blob - ti/runtime/netapi/src/pktio.c
added delete/close to pktio cleanup, also pktio_control
[keystone-rtos/netapi.git] / ti / runtime / netapi / src / pktio.c
1 /*********************************\r
2  * FILE: pktio.c\r
3  * PURPOSE: pktio library for NETAPI\r
4  **************************************************************\r
5  * FILE:  pktio.c\r
6  * \r
7  * DESCRIPTION:  pktio source file for user space transport\r
8  *               library\r
9  * \r
10  * REVISION HISTORY:  rev 0.0.1 \r
11  *\r
12  *  Copyright (c) Texas Instruments Incorporated 2010-2011\r
13  * \r
14  *  Redistribution and use in source and binary forms, with or without \r
15  *  modification, are permitted provided that the following conditions \r
16  *  are met:\r
17  *\r
18  *    Redistributions of source code must retain the above copyright \r
19  *    notice, this list of conditions and the following disclaimer.\r
20  *\r
21  *    Redistributions in binary form must reproduce the above copyright\r
22  *    notice, this list of conditions and the following disclaimer in the \r
23  *    documentation and/or other materials provided with the   \r
24  *    distribution.\r
25  *\r
26  *    Neither the name of Texas Instruments Incorporated nor the names of\r
27  *    its contributors may be used to endorse or promote products derived\r
28  *    from this software without specific prior written permission.\r
29  *\r
30  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \r
31  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT \r
32  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\r
33  *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT \r
34  *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, \r
35  *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT \r
36  *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\r
37  *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\r
38  *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT \r
39  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE \r
40  *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
41 \r
42  ********************************/\r
43 #include <stdio.h>\r
44 #include <stdlib.h>\r
45 #include <unistd.h>\r
46 #include <string.h>\r
47 #include "netapi.h"\r
48 \r
49 /*--------------------Utilites-----------------*/\r
50 static PKTIO_HANDLE_T * pktiop_get_free_channel_slot(NETAPI_T n)\r
51 {\r
52         PKTIO_HANDLE_T ** pp = (PKTIO_HANDLE_T **) netapi_get_pktio_list(n);\r
53         int i;\r
54         for(i=0;i<NETAPI_MAX_PKTIO;i++)\r
55         {\r
56                 if (pp[i]->inuse != PKTIO_INUSE)\r
57                 {\r
58                         return pp[i];\r
59                 }\r
60         }\r
61         return NULL;\r
62 }\r
63 \r
64 /*-----------------------MAIN API----------------------*/\r
65 /* create a channel */\r
66 PKTIO_HANDLE_T * pktio_create(NETAPI_T n, char * name,\r
67                               PKTIO_CB cb, PKTIO_CFG_T * p_cfg, int * err)\r
68 {\r
69 int r = 0;\r
70 PKTIO_HANDLE_T *p;\r
71 uint8_t         isAllocated;\r
72 \r
73 *err=0;\r
74 \r
75 if ((!p_cfg)||(!name)) {*err=NETAPI_ERR_BAD_INPUT; return NULL;}\r
76 \r
77 /* get a free channel handle */\r
78 p=pktiop_get_free_channel_slot(n);\r
79 if (!p) {*err = PKTIO_NOMEM; return (p); }\r
80 \r
81 p->inuse= PKTIO_INUSE;\r
82 p->back = n;\r
83 p->cb = cb;\r
84 p->max_n = p_cfg->max_n;\r
85 memcpy((char *)&p->cfg, (char*) p_cfg, sizeof(PKTIO_CFG_T));\r
86 \r
87     /* create a  general queue (for now). todo: allow qnum to be passed in */\r
88      p->q  = Qmss_queueOpen(Qmss_QueueType_GENERAL_PURPOSE_QUEUE,\r
89                        QMSS_PARAM_NOT_SPECIFIED, &isAllocated);\r
90     if (p->q == (Qmss_QueueHnd) NULL)\r
91     {\r
92         printf(">pktio_create:  queueOpen failed\n");\r
93         p->inuse=0;\r
94         *err= NETAPI_ERR_QLLD;  ///queue lld error\r
95         return NULL;\r
96     }\r
97     p->qInfo = Qmss_getQueueNumber(p->q);\r
98     if (p->cfg.flags2 & PKTIO_PKT) \r
99     {\r
100         p->use_nwal =1; \r
101         p->nwalInstanceHandle = netapi_return_nwal_instance_handle(n); \r
102     }\r
103     else p->use_nwal=0;\r
104 \r
105     /* save name */ \r
106     strncpy(p->name,name,\r
107        strlen(name)<PKTIO_MAX_NAME ?\r
108                strlen(name):PKTIO_MAX_NAME);   \r
109 \r
110     /* add name, qnum to global name list */\r
111    if ((strcmp(name,NETCP_RX)) && (strcmp(name,NETCP_TX)) &&\r
112         (p_cfg->flags1 & PKTIO_GLOBAL) )\r
113    {\r
114      //todo: make sure this succeeds..\r
115      r=netapi_add_global_pktio(n, name, &p->qInfo);\r
116    }\r
117   ((NETAPI_HANDLE_T *)n )->n_pktios+=1;\r
118    return p;\r
119 }\r
120 \r
121 \r
122 /***********************************************************/\r
123 /************** open an existing channel.  *****************/\r
124 /***********************************************************/\r
125 PKTIO_HANDLE_T * pktio_open(NETAPI_T  n, char *name,\r
126                             PKTIO_CB cb,  PKTIO_CFG_T * p_cfg, int * err)\r
127 {\r
128 int r=0;\r
129 PKTIO_HANDLE_T *p, *p2;\r
130 uint8_t         isAllocated;\r
131 *err=0;\r
132 Qmss_Queue *p_qnum;\r
133 \r
134 if ((!p_cfg)||(!name)) {*err=NETAPI_ERR_BAD_INPUT; return NULL;}\r
135 \r
136 /* get a free channel handle */\r
137 p=pktiop_get_free_channel_slot(n);\r
138 if (!p) {*err = PKTIO_NOMEM; return (p); }\r
139 ((NETAPI_HANDLE_T *)n)->n_pktios+=1;\r
140 \r
141 p->inuse= PKTIO_INUSE;\r
142 p->back = n;\r
143 p->cb = cb;\r
144 p->max_n = p_cfg->max_n;\r
145 memcpy((char *)&p->cfg, (char*) p_cfg, sizeof(PKTIO_CFG_T));\r
146 \r
147 /* special handling of NETCP_RX, NETCP_TX */\r
148 if( (!strcmp(name, NETCP_RX)) || (!strcmp(name,NETCP_TX)) )\r
149 {\r
150    /* these have already been opened internally, so don't search in global list */\r
151     p->use_nwal = 2;\r
152     p->q = 0;  \r
153     p->nwalInstanceHandle = netapi_return_nwal_instance_handle(n); \r
154 }\r
155 else\r
156 {\r
157  /* find queue in global list */\r
158  p_qnum = netapi_find_global_pktio(n, name);\r
159  if (!p_qnum ) \r
160   {\r
161         printf(">pktio_open: can't find %s\n",name);\r
162         p->inuse=0;\r
163        *err= NETAPI_ERR_NOTFOUND;  ///queue lld error\r
164         return NULL;\r
165   }\r
166 \r
167  /* open a  general queue (for now). use qnum that was just found */\r
168      p->q  = Qmss_queueOpen(Qmss_QueueType_GENERAL_PURPOSE_QUEUE,\r
169                        p_qnum->qNum , &isAllocated);\r
170     if (p->q == (Qmss_QueueHnd) NULL)\r
171     {\r
172         printf(">pktio_create:  queueOpen failed\n");\r
173         p->inuse=0;\r
174         *err= NETAPI_ERR_QLLD;  ///queue lld error\r
175         return NULL;\r
176     }\r
177     p->qInfo = Qmss_getQueueNumber(p->q);\r
178     if (p_cfg->flags2 & PKTIO_PKT)\r
179     {\r
180        p->use_nwal =1; \r
181        p->nwalInstanceHandle = netapi_return_nwal_instance_handle(n); \r
182     } \r
183     else p->use_nwal=0;\r
184 }\r
185 \r
186     /* save name */\r
187     strncpy(p->name,name,\r
188        strlen(name)<PKTIO_MAX_NAME ?\r
189                strlen(name):PKTIO_MAX_NAME);\r
190 \r
191 \r
192 \r
193 return p;\r
194 }\r
195 \r
196 /***********************************************************/\r
197 /************** control the channel ****************/\r
198 /***********************************************************/\r
199 void pktio_control(PKTIO_HANDLE_T * p,\r
200                    PKTIO_CB cb,\r
201                    PKTIO_CFG_T * p_cfg,\r
202                    PKTIO_CONTROL_T * p_control,\r
203                    int *err)\r
204 {\r
205         if (!p) { *err=1; return;}\r
206         if (cb) \r
207         {\r
208                 p->cb = cb;\r
209         }\r
210         if (p_control)\r
211         {\r
212                 /* todo: implement divert */\r
213                 switch(p_control->op)\r
214                 {\r
215                         //clear the queue\r
216                         case(PKTIO_CLEAR):\r
217                                 netapi_zapQ(p->q);\r
218                                 break;\r
219                         case(PKTIO_DIVERT):\r
220                         default:\r
221                                 printf(">pktio_control: pktio_control op %d not implemented\n",p_control->op);\r
222                                 *err= NETAPI_ERR_NOT_IMPLEMENTED;\r
223                                 break;\r
224                 }\r
225         }\r
226         //all we configure is max_n.  Can't change type of queue, rx/tx, etc\r
227         if (p_cfg)\r
228         {\r
229                 p->max_n = p_cfg->max_n;\r
230         }\r
231         *err=0;\r
232         return;\r
233 }\r
234 \r
235 /***********************************************************/\r
236 /*****************close ***************************/\r
237 /***********************************************************/\r
238 void pktio_close(PKTIO_HANDLE_T * p, int * err)\r
239 {\r
240         if(!p) { *err=1; return;}\r
241         *err=0;\r
242         Qmss_queueClose(p->q); //LLD keeps reference count\r
243         p->q=-1;\r
244         p->inuse=0;\r
245         ((NETAPI_HANDLE_T *)p->back)->n_pktios-=1;\r
246         return;\r
247 }\r
248 \r
249 /***********************************************************/\r
250 /*****************Delete***************************/\r
251 /***********************************************************/\r
252 void pktio_delete(PKTIO_HANDLE_T * p, int * err)\r
253 {\r
254         if(!p) { *err=1; return;}\r
255         *err=0;\r
256         /* remove from name list */\r
257         netapi_del_global_pktio((NETAPI_HANDLE_T *)p->back, p->name);\r
258         if(p->use_nwal !=2)\r
259         {\r
260                 Qmss_queueClose(p->q);\r
261         }\r
262         p->q=-1;\r
263         p->inuse=0;\r
264         ((NETAPI_HANDLE_T *)p->back)->n_pktios-=1;\r
265         return ;\r
266 }\r
267 \r
268 \r
269 /***********************************************************/\r
270 /*****************send *************************/\r
271 /***********************************************************/\r
272 int pktio_send(PKTIO_HANDLE_T * p, Ti_Pkt *pkt, PKTIO_METADATA_T *m, int * err)\r
273 {\r
274         nwalTxPktInfo_t * pPktInfo=m->u.tx_meta;\r
275         nwal_RetValue res;\r
276         *err=0;\r
277         if(! (p->cfg.flags1&PKTIO_W)) return 0;\r
278         if (p->use_nwal)\r
279         {\r
280                 pPktInfo->pPkt = pkt;\r
281                 res=nwal_send(p->nwalInstanceHandle, nwal_HANDLE_INVALID,pPktInfo);\r
282                 if (res != nwal_OK) *err = NETAPI_ERR_NWAL_TX_ERR -res;\r
283         }\r
284         else\r
285         {\r
286                 /* tod: meta data for non netcp xfers */\r
287                 /* process meta data */\r
288                  Qmss_queuePushDesc (p->q, (void*)pkt);\r
289         }\r
290         return 1;\r
291 }\r
292 \r
293 /***********************************************************/\r
294 /*******************send multiple**************************/\r
295 /***********************************************************/\r
296 int pktio_sendMulti(PKTIO_HANDLE_T * p, Ti_Pkt * pkt[], PKTIO_METADATA_T * m[], int np, int* err)\r
297 {\r
298         int r=0;\r
299         *err=0;\r
300         if(! p->cfg.flags1&PKTIO_W) return 0;\r
301         if (p->use_nwal)\r
302         {\r
303                 for(r=0;r<np;r++)\r
304                 {\r
305                         nwalTxPktInfo_t  *pPktInfo= m[r]->u.tx_meta;\r
306                         nwal_RetValue res;\r
307                         pPktInfo->pPkt = pkt[r];\r
308                         res=nwal_send(p->nwalInstanceHandle,nwal_HANDLE_INVALID,pPktInfo);\r
309                         if (res != nwal_OK) *err = NETAPI_ERR_NWAL_TX_ERR -res;\r
310                 }\r
311         }\r
312         else\r
313         {\r
314                 for(r=0;r<np;r++)\r
315                 {\r
316                         /* process meta data */\r
317                         Qmss_queuePushDesc(p->q, (void*) pkt[r]);\r
318                 }\r
319         }       \r
320         return r;\r
321 }\r
322 \r
323 /***********************************************************/\r
324 /******************* polling **********************/\r
325 /***********************************************************/\r
326 \r
327 /* poll a particular channel */\r
328 int pktio_poll(PKTIO_HANDLE_T * p, PKTIO_POLL_T * p_poll_cfg,  int * err)\r
329 {\r
330 int r=0;\r
331 int n;\r
332 Ti_Pkt * temp;\r
333 Ti_Pkt * pkt_list[PKTIO_MAX_RECV];\r
334 PKTIO_METADATA_T meta_s[PKTIO_MAX_RECV];\r
335 uint64_t ts= netapi_getTimestamp();  //get_ts\r
336 \r
337         if(! p->cfg.flags1&PKTIO_R) return 0;\r
338 \r
339         /** poll the netcp default RX queue we squirt out below */\r
340         if (p->use_nwal==2)\r
341         {\r
342                 /* Poll for common L2/L3 packets */\r
343                 nwal_pollPkt(p->nwalInstanceHandle,\r
344                      nwal_POLL_DEFAULT_GLOB_PKT_Q,\r
345                      (uint32_t) p,\r
346                      p->max_n,\r
347                      QMSS_PARAM_NOT_SPECIFIED,\r
348                      (void*) NULL);\r
349         }\r
350         /** poll a netcp RX queue. we squirt out below */\r
351         else if (p->use_nwal==1)\r
352         {\r
353                 /* Poll an additional NETCP RX queue */\r
354                nwal_pollPkt(p->nwalInstanceHandle,\r
355                      nwal_POLL_APP_MANAGED_PKT_Q,\r
356                      (uint32_t) p,\r
357                      p->max_n,\r
358                      p->q,\r
359                      (void *)  NULL);\r
360         }\r
361         /* poll an IPC queue */\r
362         else \r
363         {\r
364                 *err=0;\r
365                 n= (p->max_n< PKTIO_MAX_RECV) ? p->max_n : PKTIO_MAX_RECV;\r
366                 for(r=0;r<n;r++)\r
367                 {\r
368                         temp=(Cppi_HostDesc*)QMSS_DESC_PTR(Qmss_queuePop(p->q));\r
369                         if(!temp) break;\r
370                          /* process meta data */\r
371                         pkt_list[r]= temp;\r
372                         meta_s[r].flags1=0x1;\r
373                 }       \r
374                 if (r) p->cb((struct PKTIO_HANDLE_tag *)p, pkt_list, &meta_s[0], r, ts);\r
375         }\r
376         return r;\r
377 }\r
378 \r
379 /***********************************************************/\r
380 /** poll all channels attached to this handle */\r
381 /***********************************************************/\r
382 int pktio_pollAll(NETAPI_T  handle, PKTIO_POLL_T * p_poll_cfg, int *err)\r
383 {\r
384 int i=0;\r
385 int r=0;\r
386 int err2;\r
387 int cnt=0;\r
388 PKTIO_HANDLE_T *pp =( PKTIO_HANDLE_T *)  netapi_get_pktio_list(handle);\r
389  \r
390 *err=0;\r
391 for(i=0;i<NETAPI_MAX_PKTIO && cnt < ((NETAPI_HANDLE_T *)handle)->n_pktios;i++,pp+=1)\r
392 {\r
393     if (pp->inuse != PKTIO_INUSE) continue;\r
394     if(!(pp->cfg.flags1&PKTIO_R)) continue;\r
395     r+=pktio_poll(pp,  p_poll_cfg,  &err2); cnt+=1;\r
396     if (err2) { *err = err2; break;}\r
397 }\r
398 return r;\r
399 \r
400 }\r
401 \r
402 /***** this is the callback we registered with NWAL for pkt reception *****/\r
403 /* appcookie -> pktio handle */\r
404 void netapi_NWALRxPktCallback     (uint32_t            appCookie,\r
405                                 uint16_t             numPkts,\r
406                                 nwalRxPktInfo_t*    pPktInfo,\r
407                                 uint64_t            timestamp,\r
408                                 nwal_Bool_t*        pFreePkt)\r
409 {\r
410 PKTIO_HANDLE_T * p = (PKTIO_HANDLE_T *) appCookie;\r
411 int r=0;\r
412 int n;\r
413 Ti_Pkt * pkt_list[PKTIO_MAX_RECV];\r
414 PKTIO_METADATA_T meta_s[PKTIO_MAX_RECV];\r
415     for(r=0;r<numPkts;r++)\r
416     {\r
417          pkt_list[r] = pPktInfo[r].pPkt;\r
418          meta_s[r].flags1 = PKTIO_META_RX;\r
419          meta_s[r].u.rx_meta = &pPktInfo[r];\r
420     }\r
421     if (r) p->cb((struct PKTIO_HANDLE_tag *)p, pkt_list, &meta_s[0], r, timestamp);\r
422 \r
423 }\r
424                                                   \r
425 \r