This is the initial commit.
[keystone-rtos/netapi.git] / ti / runtime / netapi / src / pktio.c
1 /*********************************
2  * FILE: pktio.c
3  * PURPOSE: pktio library for NETAPI
4  **************************************************************
5  * FILE:  pktio.c
6  * 
7  * DESCRIPTION:  pktio 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 "netapi.h"
45 /*--------------------Utilites-----------------*/
46 static PKTIO_HANDLE_T * pktiop_get_free_channel_slot(NETAPI_T n)
47 {
48         PKTIO_HANDLE_T * pp = (PKTIO_HANDLE_T*) netapi_get_pktio_list(n);
49         int i;
50         for(i=0;i<NETAPI_MAX_PKTIO;i++)
51         {
52                 if (pp->inuse != PKTIO_INUSE)
53                 {
54                         return pp;
55                 }
56                 pp+=1;
57         }
58         return NULL;
59 }
61 /*-----------------------MAIN API----------------------*/
62 /* create a channel */
63 PKTIO_HANDLE_T * pktio_create(NETAPI_T n, char * name,
64                               PKTIO_CB cb, PKTIO_CFG_T * p_cfg, int * err)
65 {
66 int r = 0;
67 PKTIO_HANDLE_T *p;
68 uint8_t         isAllocated;
70 *err=0;
72 if ((!p_cfg)||(!name)) {*err=NETAPI_ERR_BAD_INPUT; return NULL;}
74 /* get a free channel handle */
75 p=pktiop_get_free_channel_slot(n);
76 if (!p) {*err = PKTIO_NOMEM; return (p); }
78 p->inuse= PKTIO_INUSE;
79 p->back = n;
80 p->cb = cb;
81 p->max_n = p_cfg->max_n;
82 memcpy((char *)&p->cfg, (char*) p_cfg, sizeof(PKTIO_CFG_T));
84     /* create a  general queue (for now). TODO: allow qnum to be passed in */
85      p->q  = Qmss_queueOpen(Qmss_QueueType_GENERAL_PURPOSE_QUEUE,
86                        QMSS_PARAM_NOT_SPECIFIED, &isAllocated);
87     if (p->q == (Qmss_QueueHnd) NULL)
88     {
89         printf("pktio_create:  queueOpen failed\n");
90         p->inuse=0;
91         *err= NETAPI_ERR_QLLD;  ///queue lld error
92         return NULL;
93     }
94     p->qInfo = Qmss_getQueueNumber(p->q);
95     if (p->cfg.flags2 & PKTIO_PKT) 
96     {
97         p->use_nwal =1; 
98         p->nwalInstanceHandle = netapi_return_nwal_instance_handle(n); 
99     }
100     else p->use_nwal=0;
102     /* save name */ 
103     strncpy(p->name,name,
104        strlen(name)<PKTIO_MAX_NAME ?
105                strlen(name):PKTIO_MAX_NAME);   
107     /* add name, qnum to global name list */
108    if ((strcmp(name,NETCP_RX)) && (strcmp(name,NETCP_TX)) &&
109         (p_cfg->flags1 & PKTIO_GLOBAL) )
110    {
111      //todo: make sure this succeeds..
112      netapi_add_global_pktio(n, name, &p->qInfo);
113    }
114   ((NETAPI_HANDLE_T *)n )->n_pktios+=1;
115    return p;
119 /***********************************************************/
120 /************** open an existing channel.  *****************/
121 /***********************************************************/
122 PKTIO_HANDLE_T * pktio_open(NETAPI_T  n, char *name,
123                             PKTIO_CB cb,  PKTIO_CFG_T * p_cfg, int * err)
125 int r=0;
126 PKTIO_HANDLE_T *p, *p2;
127 uint8_t         isAllocated;
128 *err=0;
129 Qmss_Queue *p_qnum;
131 if ((!p_cfg)||(!name)) {*err=NETAPI_ERR_BAD_INPUT; return NULL;}
133 /* get a free channel handle */
134 p=pktiop_get_free_channel_slot(n);
135 if (!p) {*err = PKTIO_NOMEM; return (p); }
136 ((NETAPI_HANDLE_T *)n)->n_pktios+=1;
138 p->inuse= PKTIO_INUSE;
139 p->back = n;
140 p->cb = cb;
141 p->max_n = p_cfg->max_n;
142 memcpy((char *)&p->cfg, (char*) p_cfg, sizeof(PKTIO_CFG_T));
144 /* special handling of NETCP_RX, NETCP_TX */
145 if( (!strcmp(name, NETCP_RX)) || (!strcmp(name,NETCP_TX)) )
147    /* these have already been opened internally, so don't search in global list */
148     p->use_nwal = 2;
149     p->q = 0;  
150     p->nwalInstanceHandle = netapi_return_nwal_instance_handle(n); 
152 else
154  /* find queue in global list */
155  p_qnum = netapi_find_global_pktio(n, name);
156  if (!p_qnum ) 
157   {
158         printf("pktio_open: can't find %s\n",name);
159         p->inuse=0;
160        *err= NETAPI_ERR_NOTFOUND;  ///queue lld error
161         return NULL;
162   }
164  /* open a  general queue (for now). use qnum that was just found */
165      p->q  = Qmss_queueOpen(Qmss_QueueType_GENERAL_PURPOSE_QUEUE,
166                        p_qnum->qNum , &isAllocated);
167     if (p->q == (Qmss_QueueHnd) NULL)
168     {
169         printf("pktio_create:  queueOpen failed\n");
170         p->inuse=0;
171         *err= NETAPI_ERR_QLLD;  ///queue lld error
172         return NULL;
173     }
174     p->qInfo = Qmss_getQueueNumber(p->q);
175     if (p_cfg->flags2 & PKTIO_PKT)
176     {
177        p->use_nwal =1; 
178        p->nwalInstanceHandle = netapi_return_nwal_instance_handle(n); 
179     } 
180     else p->use_nwal=0;
183     /* save name */
184     strncpy(p->name,name,
185        strlen(name)<PKTIO_MAX_NAME ?
186                strlen(name):PKTIO_MAX_NAME);
190 return p;
193 /***********************************************************/
194 /************** control the channel ****************/
195 /***********************************************************/
196 void pktio_control(PKTIO_HANDLE_T * p,
197                    PKTIO_CB cb,
198                    PKTIO_CFG_T * p_cfg,
199                    PKTIO_CONTROL_T * p_control,
200                    int *err)
202         if (!p) { *err=1; return;}
203         if (cb) 
204         {
205                 p->cb = cb;
206         }
207         if (p_control)
208         {
209         }
210         if (p_cfg)
211         {
212                 p->max_n = p_cfg->max_n;
213                 memcpy((char *)&p->cfg, (char*) p_cfg, sizeof(PKTIO_CFG_T));
214         }
215         *err=0;
216         return;
219 /***********************************************************/
220 /*****************close ***************************/
221 /***********************************************************/
222 void pktio_close(PKTIO_HANDLE_T * p, int * err)
224         if(!p) { *err=1; return;}
225         *err=0;
226         //Qmss_queueClose(p->q);
227         p->q=-1;
228         p->inuse=0;
229         ((NETAPI_HANDLE_T *)p->back)->n_pktios-=1;
230         return;
233 /***********************************************************/
234 /*****************Delete***************************/
235 /***********************************************************/
236 void pktio_delete(PKTIO_HANDLE_T * p, int * err)
238         if(!p) { *err=1; return;}
239         *err=0;
240         /* todo remove from name list */
241         if(p->use_nwal !=2)
242         {
243                 Qmss_queueClose(p->q);
244         }
245         p->q=-1;
246         p->inuse=0;
247         ((NETAPI_HANDLE_T *)p->back)->n_pktios-=1;
248         return ;
252 /***********************************************************/
253 /*****************send *************************/
254 /***********************************************************/
255 int pktio_send(PKTIO_HANDLE_T * p, Ti_Pkt *pkt, PKTIO_METADATA_T *m, int * err)
257         nwalTxPktInfo_t * pPktInfo=m->u.tx_meta;
258         nwal_RetValue res;
259         *err=0;
260         if(! (p->cfg.flags1&PKTIO_W)) return 0;
261         if (p->use_nwal)
262         {
263                 pPktInfo->pPkt = pkt;
264                 //todo metadata
265                 res=nwal_send(p->nwalInstanceHandle, nwal_HANDLE_INVALID,pPktInfo);
266                 if (res != nwal_OK) *err = NETAPI_ERR_NWAL_TX_ERR -res;
267         }
268         else
269         {
270                 /* process meta data */
271                  Qmss_queuePushDesc (p->q, (void*)pkt);
272         }
273         return 1;
276 /***********************************************************/
277 /*******************send multiple**************************/
278 /***********************************************************/
279 int pktio_sendMulti(PKTIO_HANDLE_T * p, Ti_Pkt * pkt[], PKTIO_METADATA_T * m[], int np, int* err)
281         int r=0;
282         *err=0;
283         if(! p->cfg.flags1&PKTIO_W) return 0;
284         if (p->use_nwal)
285         {
286                 for(r=0;r<np;r++)
287                 {
288                         nwalTxPktInfo_t  *pPktInfo= m[r]->u.tx_meta;
289                         nwal_RetValue res;
290                         pPktInfo->pPkt = pkt[r];
291                         res=nwal_send(p->nwalInstanceHandle,nwal_HANDLE_INVALID,pPktInfo);
292                         if (res != nwal_OK) *err = NETAPI_ERR_NWAL_TX_ERR -res;
293                 }
294         }
295         else
296         {
297                 for(r=0;r<np;r++)
298                 {
299                         /* process meta data */
300                         Qmss_queuePushDesc(p->q, (void*) pkt[r]);
301                 }
302         }       
303         return r;
306 /***********************************************************/
307 /******************* polling **********************/
308 /***********************************************************/
310 /* poll a particular channel */
311 int pktio_poll(PKTIO_HANDLE_T * p, PKTIO_POLL_T * p_poll_cfg,  int * err)
313 int r=0;
314 int n;
315 Ti_Pkt * temp;
316 Ti_Pkt * pkt_list[PKTIO_MAX_RECV];
317 PKTIO_METADATA_T meta_s[PKTIO_MAX_RECV];
318 uint64_t ts= netapi_getTimestamp();  //get_ts
320         if(! p->cfg.flags1&PKTIO_R) return 0;
322         /** poll the netcp default RX queue we squirt out below */
323         if (p->use_nwal==2)
324         {
325                 /* Poll for common L2/L3 packets */
326                 nwal_pollPkt(p->nwalInstanceHandle,
327                      nwal_POLL_DEFAULT_GLOB_PKT_Q,
328                      (uint32_t) p,
329                      p->max_n,
330                      QMSS_PARAM_NOT_SPECIFIED,
331                      (void*) NULL);
332         }
333         /** poll a netcp RX queue. we squirt out below */
334         else if (p->use_nwal==1)
335         {
336                 /* Poll an additional NETCP RX queue */
337                nwal_pollPkt(p->nwalInstanceHandle,
338                      nwal_POLL_APP_MANAGED_PKT_Q,
339                      (uint32_t) p,
340                      p->max_n,
341                      p->q,
342                      (void *)  NULL);
343         }
344         /* poll an IPC queue */
345         else 
346         {
347                 *err=0;
348                 n= (p->max_n< PKTIO_MAX_RECV) ? p->max_n : PKTIO_MAX_RECV;
349                 for(r=0;r<n;r++)
350                 {
351                         temp=(Cppi_HostDesc*)QMSS_DESC_PTR(Qmss_queuePop(p->q));
352                         if(!temp) break;
353                          /* process meta data */
354                         pkt_list[r]= temp;
355                         meta_s[r].flags1=0x1;
356                 }       
357                 if (r) p->cb(p, pkt_list, &meta_s[0], r, ts);
358         }
359         return r;
362 /***********************************************************/
363 /** poll all channels attached to this handle */
364 /***********************************************************/
365 int pktio_pollAll(NETAPI_T  handle, PKTIO_POLL_T * p_poll_cfg, int *err)
367 int i=0;
368 int r=0;
369 int err2;
370 int cnt=0;
371 PKTIO_HANDLE_T *pp =( PKTIO_HANDLE_T *)  netapi_get_pktio_list(handle);
372  
373 *err=0;
374 for(i=0;i<NETAPI_MAX_PKTIO && cnt < ((NETAPI_HANDLE_T *)handle)->n_pktios;i++,pp+=1)
376     if (pp->inuse != PKTIO_INUSE) continue;
377     if(!(pp->cfg.flags1&PKTIO_R)) continue;
378     r+=pktio_poll(pp,  p_poll_cfg,  &err2); cnt+=1;
379     if (err2) { *err = err2; break;}
381 return r;
385 /***** this is the callback we registered with NWAL for pkt reception *****/
386 /* appcookie -> pktio handle */
387 void netapi_NWALRxPktCallback     (uint32_t            appCookie,
388                                 uint8_t             numPkts,
389                                 nwalRxPktInfo_t*    pPktInfo,
390                                 uint64_t            timestamp,
391                                 nwal_Bool_t*        pFreePkt)
393 PKTIO_HANDLE_T * p = (PKTIO_HANDLE_T *) appCookie;
394 int r=0;
395 int n;
396 Ti_Pkt * pkt_list[PKTIO_MAX_RECV];
397 PKTIO_METADATA_T meta_s[PKTIO_MAX_RECV];
398     for(r=0;r<numPkts;r++)
399     {
400          pkt_list[r] = pPktInfo[r].pPkt;
401          meta_s[r].flags1 = PKTIO_META_RX;
402          meta_s[r].u.rx_meta = &pPktInfo[r];
403     }
404     if (r) p->cb(p, pkt_list, &meta_s[0], r, timestamp);
407