rtk/nicdrv.c
Go to the documentation of this file.
1 /*
2  * Licensed under the GNU General Public License version 2 with exceptions. See
3  * LICENSE file in the project root for full license information
4  */
5 
33 #include <kern.h>
34 #include <ioctl.h>
35 #include <stdio.h>
36 #include <string.h>
37 
38 #include "osal.h"
39 #include "oshw.h"
40 
41 
42 #include "lw_mac/lw_emac.h"
43 
44 #ifndef MAX
45 #define MAX(a,b) (((a) > (b)) ? (a) : (b))
46 #define MIN(a,b) (((a) < (b)) ? (a) : (b))
47 #endif
48 
50 enum
51 {
56 };
57 
64 const uint16 priMAC[3] = { 0x0101, 0x0101, 0x0101 };
66 const uint16 secMAC[3] = { 0x0404, 0x0404, 0x0404 };
67 
69 #define RX_PRIM priMAC[1]
70 
71 #define RX_SEC secMAC[1]
72 
73 static void ecx_clear_rxbufstat(int *rxbufstat)
74 {
75  int i;
76  for(i = 0; i < EC_MAXBUF; i++)
77  {
78  rxbufstat[i] = EC_BUF_EMPTY;
79  }
80 }
81 
88 int ecx_setupnic(ecx_portt *port, const char *ifname, int secondary)
89 {
90  int i;
91  int rVal;
92  int *psock;
93 
94  port->getindex_mutex = mtx_create();
95  port->tx_mutex = mtx_create();
96  port->rx_mutex = mtx_create();
97 
98  rVal = bfin_EMAC_init((uint8_t *)priMAC);
99  if (rVal != 0)
100  return 0;
101 
102  if (secondary)
103  {
104  /* secondary port struct available? */
105  if (port->redport)
106  {
107  /* when using secondary socket it is automatically a redundant setup */
108  psock = &(port->redport->sockhandle);
109  *psock = -1;
110  port->redstate = ECT_RED_DOUBLE;
111  port->redport->stack.sock = &(port->redport->sockhandle);
112  port->redport->stack.txbuf = &(port->txbuf);
113  port->redport->stack.txbuflength = &(port->txbuflength);
114  port->redport->stack.tempbuf = &(port->redport->tempinbuf);
115  port->redport->stack.rxbuf = &(port->redport->rxbuf);
116  port->redport->stack.rxbufstat = &(port->redport->rxbufstat);
117  port->redport->stack.rxsa = &(port->redport->rxsa);
118  ecx_clear_rxbufstat(&(port->redport->rxbufstat[0]));
119  }
120  else
121  {
122  /* fail */
123  return 0;
124  }
125  }
126  else
127  {
128  port->getindex_mutex = mtx_create();
129  port->tx_mutex = mtx_create();
130  port->rx_mutex = mtx_create();
131  port->sockhandle = -1;
132  port->lastidx = 0;
133  port->redstate = ECT_RED_NONE;
134  port->stack.sock = &(port->sockhandle);
135  port->stack.txbuf = &(port->txbuf);
136  port->stack.txbuflength = &(port->txbuflength);
137  port->stack.tempbuf = &(port->tempinbuf);
138  port->stack.rxbuf = &(port->rxbuf);
139  port->stack.rxbufstat = &(port->rxbufstat);
140  port->stack.rxsa = &(port->rxsa);
141  ecx_clear_rxbufstat(&(port->rxbufstat[0]));
142  psock = &(port->sockhandle);
143  }
144 
145  /* setup ethernet headers in tx buffers so we don't have to repeat it */
146  for (i = 0; i < EC_MAXBUF; i++)
147  {
148  ec_setupheader(&(port->txbuf[i]));
149  port->rxbufstat[i] = EC_BUF_EMPTY;
150  }
151  ec_setupheader(&(port->txbuf2));
152 
153  return 1;
154 }
155 
161 {
162  if (port->sockhandle >= 0)
163  {
164  close(port->sockhandle);
165  }
166  if ((port->redport) && (port->redport->sockhandle >= 0))
167  {
168  close(port->redport->sockhandle);
169  }
170  return 0;
171 }
172 
178 void ec_setupheader(void *p)
179 {
180  ec_etherheadert *bp;
181  bp = p;
182  bp->da0 = oshw_htons(0xffff);
183  bp->da1 = oshw_htons(0xffff);
184  bp->da2 = oshw_htons(0xffff);
185  bp->sa0 = oshw_htons(priMAC[0]);
186  bp->sa1 = oshw_htons(priMAC[1]);
187  bp->sa2 = oshw_htons(priMAC[2]);
188  bp->etype = oshw_htons(ETH_P_ECAT);
189 }
190 
196 {
197  int idx;
198  int cnt;
199 
200  mtx_lock (port->getindex_mutex);
201 
202  idx = port->lastidx + 1;
203  /* index can't be larger than buffer array */
204  if (idx >= EC_MAXBUF)
205  {
206  idx = 0;
207  }
208  cnt = 0;
209  /* try to find unused index */
210  while ((port->rxbufstat[idx] != EC_BUF_EMPTY) && (cnt < EC_MAXBUF))
211  {
212  idx++;
213  cnt++;
214  if (idx >= EC_MAXBUF)
215  {
216  idx = 0;
217  }
218  }
219  port->rxbufstat[idx] = EC_BUF_ALLOC;
220  if (port->redstate != ECT_RED_NONE)
221  {
222  port->redport->rxbufstat[idx] = EC_BUF_ALLOC;
223  }
224  port->lastidx = idx;
225 
226  mtx_unlock (port->getindex_mutex);
227 
228  return idx;
229 }
230 
236 void ecx_setbufstat(ecx_portt *port, int idx, int bufstat)
237 {
238  port->rxbufstat[idx] = bufstat;
239  if (port->redstate != ECT_RED_NONE)
240  {
241  port->redport->rxbufstat[idx] = bufstat;
242  }
243 }
244 
251 int ecx_outframe(ecx_portt *port, int idx, int stacknumber)
252 {
253  int lp, rval;
254  ec_stackT *stack;
255 
256  if (!stacknumber)
257  {
258  stack = &(port->stack);
259  }
260  else
261  {
262  stack = &(port->redport->stack);
263  }
264  lp = (*stack->txbuflength)[idx];
265  (*stack->rxbufstat)[idx] = EC_BUF_TX;
266  rval = bfin_EMAC_send((*stack->txbuf)[idx], lp);
267 
268  return rval;
269 }
270 
276 int ecx_outframe_red(ecx_portt *port, int idx)
277 {
278  ec_comt *datagramP;
279  ec_etherheadert *ehp;
280  int rval;
281 
282  ehp = (ec_etherheadert *)&(port->txbuf[idx]);
283  /* rewrite MAC source address 1 to primary */
284  ehp->sa1 = oshw_htons(priMAC[1]);
285  /* transmit over primary socket*/
286  rval = ecx_outframe(port, idx, 0);
287  if (port->redstate != ECT_RED_NONE)
288  {
289  mtx_lock (port->tx_mutex);
290  ehp = (ec_etherheadert *)&(port->txbuf2);
291  /* use dummy frame for secondary socket transmit (BRD) */
292  datagramP = (ec_comt*)&(port->txbuf2[ETH_HEADERSIZE]);
293  /* write index to frame */
294  datagramP->index = idx;
295  /* rewrite MAC source address 1 to secondary */
296  ehp->sa1 = oshw_htons(secMAC[1]);
297  /* transmit over secondary socket */
298  //send(sockhandle2, &ec_txbuf2, ec_txbuflength2 , 0);
299  // OBS! redundant not ACTIVE for BFIN, just added to compile
300  ASSERT (0);
301  port->redport->rxbufstat[idx] = EC_BUF_TX;
302  bfin_EMAC_send(&(port->txbuf2), port->txbuflength2);
303  mtx_unlock (port->tx_mutex);
304  }
305 
306  return rval;
307 }
308 
314 static int ecx_recvpkt(ecx_portt *port, int stacknumber)
315 {
316  int lp, bytesrx;
317  ec_stackT *stack;
318 
319  if (!stacknumber)
320  {
321  stack = &(port->stack);
322  }
323  else
324  {
325  stack = &(port->redport->stack);
326  }
327  lp = sizeof(port->tempinbuf);
328  bytesrx = bfin_EMAC_recv((*stack->tempbuf), lp);
329  port->tempinbufs = bytesrx;
330 
331  return (bytesrx > 0);
332 }
333 
350 int ecx_inframe(ecx_portt *port, int idx, int stacknumber)
351 {
352  uint16 l;
353  int rval;
354  uint8 idxf;
355  ec_etherheadert *ehp;
356  ec_comt *ecp;
357  ec_stackT *stack;
358  ec_bufT *rxbuf;
359 
360  if (!stacknumber)
361  {
362  stack = &(port->stack);
363  }
364  else
365  {
366  stack = &(port->redport->stack);
367  }
368  rval = EC_NOFRAME;
369  rxbuf = &(*stack->rxbuf)[idx];
370  /* check if requested index is already in buffer ? */
371  if ((idx < EC_MAXBUF) && ( (*stack->rxbufstat)[idx] == EC_BUF_RCVD))
372  {
373  l = (*rxbuf)[0] + ((uint16)((*rxbuf)[1] & 0x0f) << 8);
374  /* return WKC */
375  rval = ((*rxbuf)[l] + ((uint16)(*rxbuf)[l + 1] << 8));
376  /* mark as completed */
377  (*stack->rxbufstat)[idx] = EC_BUF_COMPLETE;
378  }
379  else
380  {
381  mtx_lock (port->rx_mutex);
382  /* non blocking call to retrieve frame from socket */
383  if (ecx_recvpkt(port, stacknumber))
384  {
385  rval = EC_OTHERFRAME;
386  ehp =(ec_etherheadert*)(stack->tempbuf);
387  /* check if it is an EtherCAT frame */
388  if (ehp->etype == oshw_htons(ETH_P_ECAT))
389  {
390  ecp =(ec_comt*)(&(*stack->tempbuf)[ETH_HEADERSIZE]);
391  l = etohs(ecp->elength) & 0x0fff;
392  idxf = ecp->index;
393  /* found index equals requested index ? */
394  if (idxf == idx)
395  {
396  /* yes, put it in the buffer array (strip ethernet header) */
397  memcpy(rxbuf, &(*stack->tempbuf)[ETH_HEADERSIZE], (*stack->txbuflength)[idx] - ETH_HEADERSIZE);
398  /* return WKC */
399  rval = ((*rxbuf)[l] + ((uint16)((*rxbuf)[l + 1]) << 8));
400  /* mark as completed */
401  (*stack->rxbufstat)[idx] = EC_BUF_COMPLETE;
402  /* store MAC source word 1 for redundant routing info */
403  (*stack->rxsa)[idx] = oshw_ntohs(ehp->sa1);
404  }
405  else
406  {
407  /* check if index exist and someone is waiting for it */
408  if (idxf < EC_MAXBUF && (*stack->rxbufstat)[idxf] == EC_BUF_TX)
409  {
410  rxbuf = &(*stack->rxbuf)[idxf];
411  /* put it in the buffer array (strip ethernet header) */
412  memcpy(rxbuf, &(*stack->tempbuf)[ETH_HEADERSIZE], (*stack->txbuflength)[idxf] - ETH_HEADERSIZE);
413  /* mark as received */
414  (*stack->rxbufstat)[idxf] = EC_BUF_RCVD;
415  (*stack->rxsa)[idxf] = oshw_ntohs(ehp->sa1);
416  }
417  else
418  {
419  /* strange things happened */
420  }
421  }
422  }
423  }
424  mtx_unlock (port->rx_mutex);
425 
426  }
427 
428  /* WKC if matching frame found */
429  return rval;
430 }
431 
444 static int ecx_waitinframe_red(ecx_portt *port, int idx, osal_timert timer)
445 {
446  int wkc = EC_NOFRAME;
447  int wkc2 = EC_NOFRAME;
448  int primrx, secrx;
449 
450  /* if not in redundant mode then always assume secondary is OK */
451  if (port->redstate == ECT_RED_NONE)
452  {
453  wkc2 = 0;
454  }
455  do
456  {
457  /* only read frame if not already in */
458  if (wkc <= EC_NOFRAME)
459  {
460  wkc = ecx_inframe(port, idx, 0);
461  }
462  /* only try secondary if in redundant mode */
463  if (port->redstate != ECT_RED_NONE)
464  {
465  /* only read frame if not already in */
466  if (wkc2 <= EC_NOFRAME)
467  wkc2 = ecx_inframe(port, idx, 1);
468  }
469  /* wait for both frames to arrive or timeout */
470  } while (((wkc <= EC_NOFRAME) || (wkc2 <= EC_NOFRAME)) && (osal_timer_is_expired(&timer) == FALSE));
471  /* only do redundant functions when in redundant mode */
472  if (port->redstate != ECT_RED_NONE)
473  {
474  /* primrx if the received MAC source on primary socket */
475  primrx = 0;
476  if (wkc > EC_NOFRAME)
477  {
478  primrx = port->rxsa[idx];
479  }
480  /* secrx if the received MAC source on psecondary socket */
481  secrx = 0;
482  if (wkc2 > EC_NOFRAME)
483  {
484  secrx = port->redport->rxsa[idx];
485  }
486  /* primary socket got secondary frame and secondary socket got primary frame */
487  /* normal situation in redundant mode */
488  if ( ((primrx == RX_SEC) && (secrx == RX_PRIM)) )
489  {
490  /* copy secondary buffer to primary */
491  memcpy(&(port->rxbuf[idx]), &(port->redport->rxbuf[idx]), port->txbuflength[idx] - ETH_HEADERSIZE);
492  wkc = wkc2;
493  }
494  /* primary socket got nothing or primary frame, and secondary socket got secondary frame */
495  /* we need to resend TX packet */
496  if ( ((primrx == 0) && (secrx == RX_SEC)) ||
497  ((primrx == RX_PRIM) && (secrx == RX_SEC)) )
498  {
499  osal_timert read_timer;
500 
501  /* If both primary and secondary have partial connection retransmit the primary received
502  * frame over the secondary socket. The result from the secondary received frame is a combined
503  * frame that traversed all slaves in standard order. */
504  if ( (primrx == RX_PRIM) && (secrx == RX_SEC) )
505  {
506  /* copy primary rx to tx buffer */
507  memcpy(&(port->txbuf[idx][ETH_HEADERSIZE]), &(port->rxbuf[idx]), port->txbuflength[idx] - ETH_HEADERSIZE);
508  }
509  osal_timer_start(&read_timer, EC_TIMEOUTRET);
510  /* resend secondary tx */
511  ecx_outframe(port, idx, 1);
512  do
513  {
514  /* retrieve frame */
515  wkc2 = ecx_inframe(port, idx, 1);
516  } while ((wkc2 <= EC_NOFRAME) && (osal_timer_is_expired(&read_timer) == FALSE));
517  if (wkc2 > EC_NOFRAME)
518  {
519  /* copy secondary result to primary rx buffer */
520  memcpy(&(port->rxbuf[idx]), &(port->redport->rxbuf[idx]), port->txbuflength[idx] - ETH_HEADERSIZE);
521  wkc = wkc2;
522  }
523  }
524  }
525 
526  /* return WKC or EC_NOFRAME */
527  return wkc;
528 }
529 
537 int ecx_waitinframe(ecx_portt *port, int idx, int timeout)
538 {
539  int wkc;
540  osal_timert timer;
541 
542  osal_timer_start (&timer, timeout);
543  wkc = ecx_waitinframe_red(port, idx, timer);
544 
545  return wkc;
546 }
547 
560 int ecx_srconfirm(ecx_portt *port, int idx, int timeout)
561 {
562  int wkc = EC_NOFRAME;
563  osal_timert timer;
564 
565  osal_timer_start(&timer, timeout);
566  do
567  {
568  osal_timert read_timer;
569 
570  /* tx frame on primary and if in redundant mode a dummy on secondary */
571  ecx_outframe_red(port, idx);
572  osal_timer_start(&read_timer, MIN(timeout, EC_TIMEOUTRET));
573  /* get frame from primary or if in redundant mode possibly from secondary */
574  wkc = ecx_waitinframe_red(port, idx, read_timer);
575  /* wait for answer with WKC>0 or otherwise retry until timeout */
576  } while ((wkc <= EC_NOFRAME) && (osal_timer_is_expired(&timer) == FALSE));
577 
578  return wkc;
579 }
580 
581 
582 #ifdef EC_VER1
583 int ec_setupnic(const char *ifname, int secondary)
584 {
585  return ecx_setupnic(&ecx_port, ifname, secondary);
586 }
587 
588 int ec_closenic(void)
589 {
590  return ecx_closenic(&ecx_port);
591 }
592 
593 int ec_getindex(void)
594 {
595  return ecx_getindex(&ecx_port);
596 }
597 
598 void ec_setbufstat(int idx, int bufstat)
599 {
600  ecx_setbufstat(&ecx_port, idx, bufstat);
601 }
602 
603 int ec_outframe(int idx, int stacknumber)
604 {
605  return ecx_outframe(&ecx_port, idx, stacknumber);
606 }
607 
608 int ec_outframe_red(int idx)
609 {
610  return ecx_outframe_red(&ecx_port, idx);
611 }
612 
613 int ec_inframe(int idx, int stacknumber)
614 {
615  return ecx_inframe(&ecx_port, idx, stacknumber);
616 }
617 
618 int ec_waitinframe(int idx, int timeout)
619 {
620  return ecx_waitinframe(&ecx_port, idx, timeout);
621 }
622 
623 int ec_srconfirm(int idx, int timeout)
624 {
625  return ecx_srconfirm(&ecx_port, idx, timeout);
626 }
627 #endif
628 
int ec_outframe(int idx, int sock)
ec_bufT rxbuf[EC_MAXBUF]
Definition: erika/nicdrv.h:43
int rxsa[EC_MAXBUF]
Definition: erika/nicdrv.h:47
ec_bufT txbuf[EC_MAXBUF]
Definition: erika/nicdrv.h:68
boolean osal_timer_is_expired(osal_timert *self)
Definition: erika/osal.c:74
int(* rxsa)[EC_MAXBUF]
Definition: erika/nicdrv.h:34
int txbuflength[EC_MAXBUF]
Definition: erika/nicdrv.h:70
int ec_setupnic(const char *ifname, int secondary)
int ecx_outframe_red(ecx_portt *port, int idx)
Definition: rtk/nicdrv.c:276
void ecx_setbufstat(ecx_portt *port, int idx, int bufstat)
Definition: rtk/nicdrv.c:236
#define EC_MAXBUF
Definition: ethercattype.h:62
uint8_t uint8
Definition: osal.h:28
const uint16 secMAC[3]
Definition: rtk/nicdrv.c:66
ec_bufT txbuf2
Definition: erika/nicdrv.h:72
int rxsa[EC_MAXBUF]
Definition: erika/nicdrv.h:62
int(* txbuflength)[EC_MAXBUF]
Definition: erika/nicdrv.h:26
PACKED_BEGIN struct PACKED ec_etherheadert
void ec_setupheader(void *p)
Definition: rtk/nicdrv.c:178
ec_bufT * tempbuf
Definition: erika/nicdrv.h:28
uint16 oshw_ntohs(uint16 network)
Definition: erika/oshw.c:43
int txbuflength2
Definition: erika/nicdrv.h:74
uint16_t uint16
Definition: osal.h:29
static int ecx_recvpkt(ecx_portt *port, int stacknumber)
Definition: rtk/nicdrv.c:314
unsigned char uint8_t
Definition: stdint.h:78
int ecx_outframe(ecx_portt *port, int idx, int stacknumber)
Definition: rtk/nicdrv.c:251
int ecx_inframe(ecx_portt *port, int idx, int stacknumber)
Definition: rtk/nicdrv.c:350
uint16 oshw_htons(uint16 host)
Definition: erika/oshw.c:31
#define etohs(A)
Definition: ethercattype.h:536
static void ecx_clear_rxbufstat(int *rxbufstat)
Definition: rtk/nicdrv.c:73
#define ETH_HEADERSIZE
Definition: ethercattype.h:103
int rxbufstat[EC_MAXBUF]
Definition: erika/nicdrv.h:45
int bfin_EMAC_send(void *packet, int length)
Definition: lw_emac.c:354
ec_stackT stack
Definition: erika/nicdrv.h:55
ec_bufT rxbuf[EC_MAXBUF]
Definition: erika/nicdrv.h:58
pthread_mutex_t tx_mutex
Definition: linux/nicdrv.h:85
Headerfile for oshw.c.
ec_stackT stack
Definition: erika/nicdrv.h:40
ec_bufT tempinbuf
Definition: erika/nicdrv.h:64
ec_bufT(* rxbuf)[EC_MAXBUF]
Definition: erika/nicdrv.h:30
int ec_srconfirm(int idx, int timeout)
int ecx_closenic(ecx_portt *port)
Definition: rtk/nicdrv.c:160
int tempinbufs
Definition: erika/nicdrv.h:66
#define FALSE
Definition: osal.h:22
ec_bufT(* txbuf)[EC_MAXBUF]
Definition: erika/nicdrv.h:24
void ec_setbufstat(int idx, int bufstat)
ecx_redportt * redport
Definition: erika/nicdrv.h:80
int bfin_EMAC_recv(uint8_t *packet, size_t size)
Definition: lw_emac.c:384
int ecx_srconfirm(ecx_portt *port, int idx, int timeout)
Definition: rtk/nicdrv.c:560
PACKED_BEGIN struct PACKED ec_comt
int bfin_EMAC_init(uint8_t *ethAddr)
Definition: lw_emac.c:288
int ecx_getindex(ecx_portt *port)
Definition: rtk/nicdrv.c:195
int ecx_setupnic(ecx_portt *port, const char *ifname, int secondary)
Definition: rtk/nicdrv.c:88
#define EC_TIMEOUTRET
Definition: ethercattype.h:64
#define EC_OTHERFRAME
Definition: ethercattype.h:43
pthread_mutex_t getindex_mutex
Definition: linux/nicdrv.h:84
int ec_outframe_red(int idx)
int redstate
Definition: erika/nicdrv.h:78
#define ETH_P_ECAT
Definition: ethercattype.h:459
#define RX_SEC
Definition: rtk/nicdrv.c:71
int wkc
Definition: aliastool.c:47
int rxbufstat[EC_MAXBUF]
Definition: erika/nicdrv.h:60
uint8 ec_bufT[EC_BUFSIZE]
Definition: ethercattype.h:87
ec_bufT tempinbuf
Definition: erika/nicdrv.h:49
int ec_closenic(void)
int ec_getindex(void)
#define RX_PRIM
Definition: rtk/nicdrv.c:69
const uint16 priMAC[3]
Definition: rtk/nicdrv.c:64
int ec_waitinframe(int idx, int timeout)
void osal_timer_start(osal_timert *self, uint32 timeout_usec)
Definition: erika/osal.c:59
int(* rxbufstat)[EC_MAXBUF]
Definition: erika/nicdrv.h:32
int sockhandle
Definition: erika/nicdrv.h:56
#define EC_NOFRAME
Definition: ethercattype.h:41
int ecx_waitinframe(ecx_portt *port, int idx, int timeout)
Definition: rtk/nicdrv.c:537
int * sock
Definition: erika/nicdrv.h:22
static int ecx_waitinframe_red(ecx_portt *port, int idx, osal_timert timer)
Definition: rtk/nicdrv.c:444
pthread_mutex_t rx_mutex
Definition: linux/nicdrv.h:86
uint8 rxbuf[1024]
Definition: eoe_test.c:50
#define MIN(a, b)
Definition: rtk/nicdrv.c:46


soem
Author(s): Arthur Ketels and M.J.G. van den Molengraft
autogenerated on Sat Jun 27 2020 03:48:21