/** Basic setup to connect NIC to socket. * @param[in] ifname = Name of NIC device, f.e. "eth0" * @param[in] secondary = if >0 then use secondary stack instead of primary * @return >0 if succeeded */ int ecx_setupnic(ecx_portt *port, const char *ifname, int secondary) { HPESTATUS status; HPEMEDIASTATUS mstat; time_t now, t; unsigned char mac[6]; int i; int dontWaitForLink = 0; int result = 1; HPE_CONFIG_OPTIONS conf = { 0, 0, NULL}; status = hpeOpen(ifname, phy_settings, interrupt_mode, &(port->handle)); if (status != E_OK) { ECAT_PRINT_ERROR("hpeOpen failed with status %04x ", status); if(status == E_EXIST) ECAT_PRINT_ERROR("E_EXIST\n"); else if(status == E_STATE) ECAT_PRINT_ERROR("E_STATE\n"); else if(status == E_PARAM) ECAT_PRINT_ERROR("E_PARAM\n"); else if(status == E_INVALID_ADDR) ECAT_PRINT_ERROR("E_INVALID_ADDR\n"); else if(status == E_IO) ECAT_PRINT_ERROR("E_IO\n"); else if(status == E_TIME) ECAT_PRINT_ERROR("E_TIME\n"); else ECAT_PRINT_ERROR("UNKNOWN\n"); result = 0; goto end; } conf.option_flags |= OPT_PROMISC; status = hpeConfigOptions(port->handle, &conf, sizeof(conf)); if (status != E_OK) { ECAT_PRINT_ERROR("hpeConfigOptions failed with status %04x\n", status); // NOTE: HPE driver for Intel 10/100 Mbps device currently doesn't support multicast. result = 0; goto end; } time(&now); do { status = hpeGetMediaStatus(port->handle, &mstat); if (status != E_OK) { ECAT_PRINT_ERROR("hpeGetMediaStatus failed with status %04x\n", status); result = 0; goto end; } if (mstat.media_speed == SPEED_NONE) { RtSleepEx(1000); time(&t); } } while (mstat.media_speed == SPEED_NONE && t < (now+10)); if (((mstat.media_speed & phy_settings) == 0) || ((mstat.media_duplex & phy_settings) == 0)) { ECAT_PRINT_ERROR("Media not connected as requested: speed=%u, duplex=%u\n", mstat.media_speed, mstat.media_duplex); result = 0; goto end; } status= hpeGetMacAddress(port->handle, mac); if (status != E_OK) { ECAT_PRINT_ERROR("hpeGetMacAddress failed with status %04x\n", status); result = 0; goto end; } /* allocate 2 receive buffers and attach them */ status = hpeAllocateReceiveBufferSet(port->handle, &(port->rx_buffers), EC_MAXBUF, EC_BUFSIZE); if (status != E_OK) { ECAT_PRINT_ERROR("hpeAllocateReceiveBufferSet failed with status %04x\n", status); result = 0; goto end; } status = hpeAttachReceiveBufferSet(port->handle, port->rx_buffers); if (status != E_OK) { ECAT_PRINT_ERROR("hpeAttachReceiveBufferSet failed with status %04x\n", status); result = 0; goto end; } if (secondary) { /* secondary port struct available? */ if (port->redport) { /* when using secondary socket it is automatically a redundant setup */ port->redstate = ECT_RED_DOUBLE; } } else { port->redstate = ECT_RED_NONE; /* Init regions */ port->getindex_region = CreateRtRegion (PRIORITY_QUEUING); port->rx_region = CreateRtRegion (PRIORITY_QUEUING); port->tx_region = CreateRtRegion (PRIORITY_QUEUING); port->lastidx = 0; port->stack.txbuf = &(port->txbuf); port->stack.txbuflength = &(port->txbuflength); port->stack.tempbuf = &(port->tempinbuf); port->stack.rxbuf = &(port->rxbuf); port->stack.rxbufstat = &(port->rxbufstat); port->stack.rxsa = &(port->rxsa); } /* setup ethernet headers in tx buffers so we don't have to repeat it */ for (i = 0; i < EC_MAXBUF; i++) { ec_setupheader(&(port->txbuf[i])); port->rxbufstat[i] = EC_BUF_EMPTY; // allocate 1 transmit buffer of two fragments and 500 bytes and attach it port->tx_buffers[i] = (HPETXBUFFERSET *)AllocateRtMemory(sizeof(HPETXBUFFER) + sizeof(HPETXBUFFERSET)); port->tx_buffers[i]->buffer_count = 1; port->tx_buffers[i]->buffers[0].fragment_count = 1; // first fragment is the fixed header, second is dynamic data port->tx_buffers[i]->buffers[0].fragments[0].ptr = port->txbuf[i]; port->tx_buffers[i]->buffers[0].fragments[0].size = EC_BUFSIZE; port->tx_buffers[i]->buffers[0].fragments[0].paddr = 0; } ec_setupheader(&(port->txbuf2)); end: return result; }
/** Basic setup to connect NIC to socket. * @param[in] port = port context struct * @param[in] ifname = Name of NIC device, f.e. "eth0" * @param[in] secondary = if >0 then use secondary stack instead of primary * @return >0 if succeeded */ int ecx_setupnic(ecx_portt *port, const char *ifname, int secondary) { int i; int rVal; int *psock; port->getindex_mutex = mtx_create(); port->tx_mutex = mtx_create(); port->rx_mutex = mtx_create(); rVal = bfin_EMAC_init((uint8_t *)priMAC); if (rVal != 0) return 0; if (secondary) { /* secondary port struct available? */ if (port->redport) { /* when using secondary socket it is automatically a redundant setup */ psock = &(port->redport->sockhandle); *psock = -1; port->redstate = ECT_RED_DOUBLE; port->redport->stack.sock = &(port->redport->sockhandle); port->redport->stack.txbuf = &(port->txbuf); port->redport->stack.txbuflength = &(port->txbuflength); port->redport->stack.tempbuf = &(port->redport->tempinbuf); port->redport->stack.rxbuf = &(port->redport->rxbuf); port->redport->stack.rxbufstat = &(port->redport->rxbufstat); port->redport->stack.rxsa = &(port->redport->rxsa); ecx_clear_rxbufstat(&(port->redport->rxbufstat[0])); } else { /* fail */ return 0; } } else { port->getindex_mutex = mtx_create(); port->tx_mutex = mtx_create(); port->rx_mutex = mtx_create(); port->sockhandle = -1; port->lastidx = 0; port->redstate = ECT_RED_NONE; port->stack.sock = &(port->sockhandle); port->stack.txbuf = &(port->txbuf); port->stack.txbuflength = &(port->txbuflength); port->stack.tempbuf = &(port->tempinbuf); port->stack.rxbuf = &(port->rxbuf); port->stack.rxbufstat = &(port->rxbufstat); port->stack.rxsa = &(port->rxsa); ecx_clear_rxbufstat(&(port->rxbufstat[0])); psock = &(port->sockhandle); } /* setup ethernet headers in tx buffers so we don't have to repeat it */ for (i = 0; i < EC_MAXBUF; i++) { ec_setupheader(&(port->txbuf[i])); port->rxbufstat[i] = EC_BUF_EMPTY; } ec_setupheader(&(port->txbuf2)); return 1; }
/** Basic setup to connect NIC to socket. * @param[in] port = port context struct * @param[in] ifname = Name of NIC device, f.e. "eth0" * @param[in] secondary = if >0 then use secondary stack instead of primary * @return >0 if succeeded */ int ecx_setupnic(ecx_portt *port, const char *ifname, int secondary) { int i; int r, rval, ifindex; struct timeval timeout; struct ifreq ifr; struct sockaddr_ll sll; int *psock; rval = 0; if (secondary) { /* secondary port stuct available? */ if (port->redport) { /* when using secondary socket it is automatically a redundant setup */ psock = &(port->redport->sockhandle); *psock = -1; port->redstate = ECT_RED_DOUBLE; port->redport->stack.sock = &(port->redport->sockhandle); port->redport->stack.txbuf = &(port->txbuf); port->redport->stack.txbuflength = &(port->txbuflength); port->redport->stack.tempbuf = &(port->redport->tempinbuf); port->redport->stack.rxbuf = &(port->redport->rxbuf); port->redport->stack.rxbufstat = &(port->redport->rxbufstat); port->redport->stack.rxsa = &(port->redport->rxsa); } else { /* fail */ return 0; } } else { rt_mutex_create(&port->getindex_mutex, "getindex_mutex"); rt_mutex_create(&port->tx_mutex, "tx_mutex"); rt_mutex_create(&port->rx_mutex, "rx_mutex"); port->sockhandle = -1; port->lastidx = 0; port->redstate = ECT_RED_NONE; port->stack.sock = &(port->sockhandle); port->stack.txbuf = &(port->txbuf); port->stack.txbuflength = &(port->txbuflength); port->stack.tempbuf = &(port->tempinbuf); port->stack.rxbuf = &(port->rxbuf); port->stack.rxbufstat = &(port->rxbufstat); port->stack.rxsa = &(port->rxsa); psock = &(port->sockhandle); } /* we use RAW packet socket, with packet type ETH_P_ECAT */ *psock = SOCKET(PF_PACKET, SOCK_RAW, htons(ETH_P_ECAT)); timeout.tv_sec = 0; timeout.tv_usec = 1; r = SETSOCKOPT(*psock, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)); r = SETSOCKOPT(*psock, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout)); i = 1; r = SETSOCKOPT(*psock, SOL_SOCKET, SO_DONTROUTE, &i, sizeof(i)); /* connect socket to NIC by name */ strcpy(ifr.ifr_name, ifname); r = IOCTL(*psock, SIOCGIFINDEX, &ifr); ifindex = ifr.ifr_ifindex; strcpy(ifr.ifr_name, ifname); ifr.ifr_flags = 0; /* reset flags of NIC interface */ r = IOCTL(*psock, SIOCGIFFLAGS, &ifr); /* set flags of NIC interface, here promiscuous and broadcast */ ifr.ifr_flags = ifr.ifr_flags || IFF_PROMISC || IFF_BROADCAST; r = IOCTL(*psock, SIOCGIFFLAGS, &ifr); /* bind socket to protocol, in this case RAW EtherCAT */ sll.sll_family = AF_PACKET; sll.sll_ifindex = ifindex; sll.sll_protocol = htons(ETH_P_ECAT); r = BIND(*psock, (struct sockaddr *)&sll, sizeof(sll)); /* setup ethernet headers in tx buffers so we don't have to repeat it */ for (i = 0; i < EC_MAXBUF; i++) { ec_setupheader(&(port->txbuf[i])); port->rxbufstat[i] = EC_BUF_EMPTY; } ec_setupheader(&(port->txbuf2)); if (r == 0) rval = 1; return rval; }