37 #include <linux/version.h> 38 #include <linux/netdevice.h> 39 #include <linux/etherdevice.h> 56 #define EOE_DEBUG_LEVEL 1 60 #define EC_EOE_TX_RING_SIZE 100 64 #define EC_EOE_TRIES 100 88 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29) 112 struct sockaddr *addr = p;
114 if (!is_valid_ether_addr(addr->sa_data)) {
115 return -EADDRNOTAVAIL;
118 memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
133 uint16_t *alias, uint16_t *posn)
136 const char *orig = eoe;
140 EC_ERR(
"EOE interface may not be empty.\n");
145 if (strncmp(eoe,
"eoe", 3) != 0) {
146 EC_ERR(
"Invalid EOE interface \"%s\".\n", orig);
153 value = simple_strtoul(eoe, &rem, 10);
155 EC_ERR(
"Invalid EOE interface \"%s\", master index: %d\n", orig, value);
164 value = simple_strtoul(eoe, &rem, 10);
165 if ((value <= 0) || (value >= 0xFFFF)) {
166 EC_ERR(
"Invalid EOE interface \"%s\", invalid alias: %d\n",
172 }
else if (eoe[0] ==
's') {
174 value = simple_strtoul(eoe, &rem, 10);
175 if ((value < 0) || (value >= 0xFFFF)) {
176 EC_ERR(
"Invalid EOE interface \"%s\", invalid ring position: %d\n",
183 EC_ERR(
"Invalid EOE interface \"%s\", invalid alias/position specifier: %c\n",
189 if (rem[0] !=
'\0') {
190 EC_ERR(
"Invalid EOE interface \"%s\", unexpected end characters: %s\n",
211 uint16_t ring_position
218 struct net_device *dev;
219 unsigned char lo_mac[ETH_ALEN] = {0};
220 unsigned int use_master_mac = 0;
244 memset(&eoe->
stats, 0,
sizeof(
struct net_device_stats));
264 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0) 265 eoe->
dev = alloc_netdev(
sizeof(
ec_eoe_t *), name, NET_NAME_UNKNOWN,
268 eoe->
dev = alloc_netdev(
sizeof(
ec_eoe_t *), name, ether_setup);
272 " for EoE handler!\n", name);
278 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29) 298 dev = first_net_device(&init_net);
301 if (dev->addr_len == ETH_ALEN) {
302 if (memcmp(dev->dev_addr, lo_mac, ETH_ALEN) != 0) {
303 if ((dev->dev_addr[0] & 0x02) != 0x02) {
310 dev = next_net_device(dev);
312 if (eoe->
dev->addr_len == ETH_ALEN) {
318 " NIC part of %s MAC address\n",
319 eoe->
dev->name, dev->name);
320 eoe->
dev->dev_addr[1] = dev->dev_addr[3];
321 eoe->
dev->dev_addr[2] = dev->dev_addr[4];
322 eoe->
dev->dev_addr[3] = dev->dev_addr[5];
329 if (eoe->
dev->addr_len == ETH_ALEN) {
330 if (use_master_mac) {
332 " from NIC part of %s MAC address\n",
335 eoe->
dev->dev_addr[1] =
337 eoe->
dev->dev_addr[2] =
339 eoe->
dev->dev_addr[3] =
342 eoe->
dev->dev_addr[0] = 0x02;
344 eoe->
dev->dev_addr[4] = (uint8_t)(alias >> 8);
345 eoe->
dev->dev_addr[5] = (uint8_t)(alias);
347 eoe->
dev->dev_addr[4] = (uint8_t)(ring_position >> 8);
348 eoe->
dev->dev_addr[5] = (uint8_t)(ring_position);
353 priv = netdev_priv(eoe->
dev);
357 ret = register_netdev(eoe->
dev);
359 EC_MASTER_ERR(master,
"Unable to register net_device for %s:" 360 " error %i\n", eoe->
dev->name, ret);
366 netif_carrier_off(eoe->
dev);
371 free_netdev(eoe->
dev);
432 netif_carrier_on(eoe->
dev);
437 netif_carrier_off(eoe->
dev);
450 #if EOE_DEBUG_LEVEL >= 1 455 netif_carrier_off(eoe->
dev);
461 dev_kfree_skb(eoe->
tx_skb);
463 eoe->
stats.tx_errors++;
467 dev_kfree_skb(eoe->
rx_skb);
469 eoe->
stats.rx_errors++;
476 #if EOE_DEBUG_LEVEL >= 1 491 unregister_netdev(eoe->
dev);
497 dev_kfree_skb(eoe->
tx_skb);
500 dev_kfree_skb(eoe->
rx_skb);
504 free_netdev(eoe->
dev);
527 eoe->
stats.tx_dropped++;
545 if (next_to_use >= next_to_clean) {
546 return next_to_use - next_to_clean;
560 if (next_to_clean > next_to_use) {
561 return next_to_clean - next_to_use - 1;
575 size_t remaining_size, current_size, complete_offset;
576 unsigned int last_fragment;
578 #if EOE_DEBUG_LEVEL >= 3 588 if (remaining_size <= eoe->slave->configured_tx_mailbox_size - 10) {
589 current_size = remaining_size;
602 complete_offset = remaining_size / 32 + 1;
605 #if EOE_DEBUG_LEVEL >= 2 607 " with %zu octets (%zu). %u frames queued.\n",
609 last_fragment ?
"" :
"+", current_size, complete_offset,
613 #if EOE_DEBUG_LEVEL >= 3 615 for (i = 0; i < current_size; i++) {
617 if ((i + 1) % 16 == 0) {
618 printk(KERN_CONT
"\n");
622 printk(KERN_CONT
"\n");
626 EC_MBOX_TYPE_EOE, current_size + 4);
628 return PTR_ERR(data);
634 (complete_offset & 0x3F) << 6 |
718 return eoe->
dev->name;
762 #if EOE_DEBUG_LEVEL >= 1 764 " check datagram for %s.\n", eoe->
dev->name);
765 eoe->
stats.rx_errors++;
803 eoe->
stats.rx_errors++;
804 #if EOE_DEBUG_LEVEL >= 1 806 " fetch datagram for %s.\n", eoe->
dev->name);
829 size_t rec_size, data_size;
830 uint8_t *data, eoe_type, last_fragment, time_appended, mbox_prot;
831 uint8_t fragment_offset, fragment_number;
832 #if EOE_DEBUG_LEVEL >= 2 833 uint8_t frame_number;
836 #if EOE_DEBUG_LEVEL >= 3 854 &mbox_prot, &rec_size);
856 eoe->
stats.rx_errors++;
857 #if EOE_DEBUG_LEVEL >= 1 865 if (mbox_prot != EC_MBOX_TYPE_EOE) {
866 eoe->
stats.rx_errors++;
867 #if EOE_DEBUG_LEVEL >= 1 877 if (eoe_type != EC_EOE_TYPE_FRAME_FRAG) {
879 " response (type %x). Dropping.\n", eoe->
dev->name, eoe_type);
880 eoe->
stats.rx_dropped++;
890 fragment_offset = (
EC_READ_U16(data + 2) >> 6) & 0x003F;
891 #if EOE_DEBUG_LEVEL >= 2 892 frame_number = (
EC_READ_U16(data + 2) >> 12) & 0x000F;
895 #if EOE_DEBUG_LEVEL >= 2 897 " frame %u%s, %zu octets\n", eoe->
dev->name, fragment_number,
898 last_fragment ?
"" :
"+", fragment_offset, frame_number,
899 time_appended ?
", + timestamp" :
"",
900 time_appended ? rec_size - 8 : rec_size - 4);
903 #if EOE_DEBUG_LEVEL >= 3 905 for (i = 0; i < rec_size - 4; i++) {
906 printk(KERN_CONT
"%02X ", data[i + 4]);
907 if ((i + 1) % 16 == 0) {
908 printk(KERN_CONT
"\n");
912 printk(KERN_CONT
"\n");
915 data_size = time_appended ? rec_size - 8 : rec_size - 4;
917 if (!fragment_number) {
920 dev_kfree_skb(eoe->
rx_skb);
924 if (!(eoe->
rx_skb = dev_alloc_skb(fragment_offset * 32))) {
925 if (printk_ratelimit())
927 " frame dropped.\n");
928 eoe->
stats.rx_dropped++;
939 eoe->
stats.rx_dropped++;
944 offset = fragment_offset * 32;
948 dev_kfree_skb(eoe->
rx_skb);
950 eoe->
stats.rx_errors++;
951 #if EOE_DEBUG_LEVEL >= 1 961 memcpy(skb_put(eoe->
rx_skb, data_size), data + 4, data_size);
966 eoe->
stats.rx_packets++;
970 #if EOE_DEBUG_LEVEL >= 2 972 " with %u octets.\n", eoe->
dev->name, eoe->
rx_skb->len);
978 eoe->
rx_skb->ip_summed = CHECKSUM_UNNECESSARY;
979 if (netif_rx_ni(eoe->
rx_skb)) {
988 #if EOE_DEBUG_LEVEL >= 2 1007 #if EOE_DEBUG_LEVEL >= 2 1008 unsigned int wakeup = 0;
1022 netif_wake_queue(eoe->
dev);
1043 netif_wake_queue(eoe->
dev);
1044 #if EOE_DEBUG_LEVEL >= 2 1057 dev_kfree_skb(eoe->
tx_skb);
1059 eoe->
stats.tx_errors++;
1061 #if EOE_DEBUG_LEVEL >= 1 1067 #if EOE_DEBUG_LEVEL >= 2 1092 #if EOE_DEBUG_LEVEL >= 1 1094 if (eoe->
stats.tx_errors++ % 1000 == 0) {
1096 " datagram for %s after %u tries.\n",
1100 eoe->
stats.tx_errors++;
1112 eoe->
stats.tx_errors++;
1113 #if EOE_DEBUG_LEVEL >= 1 1115 " for %s after %u tries.\n",
1125 eoe->
stats.tx_packets++;
1128 dev_kfree_skb(eoe->
tx_skb);
1134 dev_kfree_skb(eoe->
tx_skb);
1136 eoe->
stats.tx_errors++;
1137 #if EOE_DEBUG_LEVEL >= 1 1159 netif_carrier_off(dev);
1166 netif_start_queue(dev);
1167 #if EOE_DEBUG_LEVEL >= 2 1174 netif_carrier_on(dev);
1191 netif_carrier_off(dev);
1192 netif_stop_queue(dev);
1198 #if EOE_DEBUG_LEVEL >= 2 1211 struct net_device *dev
1219 eoe->
stats.tx_dropped++;
1222 return NETDEV_TX_OK;
1228 " exceeds MTU. dropping.\n", skb->len);
1230 eoe->
stats.tx_dropped++;
1245 netif_stop_queue(dev);
1249 #if EOE_DEBUG_LEVEL >= 2 1251 " with %u octets (%u frames queued).\n",
1268 struct net_device *dev
unsigned int tx_ring_size
Transmit ring size.
void ec_eoe_queue(ec_eoe_t *eoe)
Queues the datagram, if necessary.
ec_mbox_data_t mbox_eoe_frag_data
Received mailbox data for EoE, type frame fragment.
int ec_eoedev_tx(struct sk_buff *, struct net_device *)
Transmits data via the virtual network device.
uint8_t * ec_slave_mbox_prepare_send(const ec_slave_t *slave, ec_datagram_t *datagram, uint8_t type, size_t size)
Prepares a mailbox-send datagram.
uint16_t ring_position
Ring position.
#define EC_DATAGRAM_NAME_SIZE
Size of the datagram description string.
uint32_t tx_counter
octets transmitted during last second
static const struct net_device_ops ec_eoedev_ops
Device operations for EoE interfaces.
char * ec_eoe_name(const ec_eoe_t *eoe)
Returns the eoe device name.
uint16_t configured_tx_mailbox_size
Configured send mailbox size.
void ec_eoe_state_rx_fetch(ec_eoe_t *)
State: RX_FETCH.
#define EC_SLAVE_DBG(slave, level, fmt, args...)
Convenience macro for printing slave-specific debug messages to syslog.
uint8_t tx_fragment_number
number of the fragment
int ec_eoe_send(ec_eoe_t *eoe)
Sends a frame or the next fragment.
ec_slave_t * slave
pointer to the corresponding slave
unsigned int tx_ring_count
Transmit ring count.
void ec_master_queue_datagram_ext(ec_master_t *master, ec_datagram_t *datagram)
Places a datagram in the non-application datagram queue.
size_t rx_skb_size
size of the allocated socket buffer memory
size_t tx_offset
number of octets sent
#define EC_EOE_TX_RING_SIZE
Size of the EoE tx ring.
static unsigned int eoe_tx_unused_frames(ec_eoe_t *)
EtherCAT slave structure.
int ec_slave_mbox_prepare_fetch(const ec_slave_t *slave, ec_datagram_t *datagram)
Prepares a datagram to fetch mailbox data.
void ec_eoe_state_tx_start(ec_eoe_t *)
State: TX START.
#define EC_SLAVE_WARN(slave, fmt, args...)
Convenience macro for printing slave-specific warnings to syslog.
#define EC_WRITE_U8(DATA, VAL)
Write an 8-bit unsigned value to EtherCAT data.
void ec_eoe_state_rx_check(ec_eoe_t *)
State: RX_CHECK.
unsigned int tx_queue_active
kernel netif queue started
char name[EC_DATAGRAM_NAME_SIZE]
Description of the datagram.
int ec_eoe_parse(const char *eoe, int *master_idx, uint16_t *alias, uint16_t *posn)
Parse an eoe interface from a string.
uint8_t * ec_slave_mbox_fetch(const ec_slave_t *slave, ec_mbox_data_t *response_data, uint8_t *type, size_t *size)
Processes received mailbox data.
uint16_t working_counter
Working counter.
uint8_t link_state
device link state
#define EC_EOE_TRIES
Number of tries.
Sent (still in the queue).
void ec_eoe_flush(ec_eoe_t *)
Empties the transmit queue.
uint32_t tx_rate
transmit rate (bps)
void ec_datagram_output_stats(ec_datagram_t *datagram)
Outputs datagram statistics at most every second.
Global definitions and macros.
uint8_t rx_expected_fragment
next expected fragment number
EtherCAT master structure.
void ec_eoe_state_rx_start(ec_eoe_t *)
State: RX_START.
#define EC_MASTER_DBG(master, level, fmt, args...)
Convenience macro for printing master-specific debug messages to syslog.
unsigned int tx_next_to_use
index of frames added to the ring
unsigned int auto_created
auto created flag.
Ethernet over EtherCAT (EoE)
ec_datagram_state_t state
State.
int ec_eoe_is_idle(const ec_eoe_t *eoe)
Returns the idle state.
#define EC_SLAVE_ERR(slave, fmt, args...)
Convenience macro for printing slave-specific errors to syslog.
unsigned int tx_next_to_clean
index of frames being used from the ring
unsigned long rate_jiffies
time of last rate output
struct sk_buff ** tx_ring
ring for frames to send
unsigned int have_mbox_lock
flag to track if we have the mbox lock
#define EC_WRITE_U16(DATA, VAL)
Write a 16-bit unsigned value to EtherCAT data.
ec_master_t * master
pointer to the corresponding master
void ec_eoe_state_rx_fetch_data(ec_eoe_t *)
State: RX_FETCH DATA.
ec_master_t * master
Master owning the slave.
#define EC_MASTER_ERR(master, fmt, args...)
Convenience macro for printing master-specific errors to syslog.
int ec_read_mbox_locked(ec_slave_t *slave)
Return the current mailbox lock status and lock it if not locked.
void ec_eoe_state_tx_sent(ec_eoe_t *)
State: TX SENT.
unsigned int opened
net_device is opened
static int ec_eoedev_set_mac(struct net_device *netdev, void *p)
ec_eoedev_set_mac - Change the Ethernet Address of the NIC : network interface device structure : poi...
#define EC_SLAVE_INFO(slave, fmt, args...)
Convenience macro for printing slave-specific information to syslog.
off_t rx_skb_offset
current write pointer in the socket buffer
ec_datagram_t datagram
datagram
void ec_read_mbox_lock_clear(ec_slave_t *slave)
Clears the mailbox lock.
unsigned int ec_eoe_tx_queued_frames(const ec_eoe_t *eoe)
struct net_device_stats stats
device statistics
uint16_t effective_alias
Effective alias address.
int ec_slave_mbox_prepare_check(const ec_slave_t *slave, ec_datagram_t *datagram)
Prepares a datagram for checking the mailbox state.
unsigned int tx_idle
Idle flag.
#define EC_READ_U16(DATA)
Read a 16-bit unsigned value from EtherCAT data.
void ec_eoe_link_slave(ec_eoe_t *eoe, ec_slave_t *slave)
EoE link slave.
uint32_t rx_rate
receive rate (bps)
int ec_eoe_auto_init(ec_eoe_t *eoe, ec_slave_t *slave)
EoE auto constructor for slave.
struct sk_buff * rx_skb
current rx socket buffer
#define EC_ERR(fmt, args...)
Convenience macro for printing EtherCAT-specific errors to syslog.
void(* state)(ec_eoe_t *)
state function for the state machine
void ec_datagram_init(ec_datagram_t *datagram)
Constructor.
struct sk_buff * tx_skb
current TX frame
uint8_t tx_frame_number
number of the transmitted frame
uint32_t rx_counter
octets received during last second
uint16_t configured_rx_mailbox_size
Configured receive mailbox size.
int ec_eoedev_open(struct net_device *)
Opens the virtual network device.
void ec_eoe_run(ec_eoe_t *eoe)
Runs the EoE state machine.
#define EC_READ_U8(DATA)
Read an 8-bit unsigned value from EtherCAT data.
struct net_device * dev
pointer to the assigned net_device
int ec_eoedev_stop(struct net_device *)
Stops the virtual network device.
void ec_eoe_clear_slave(ec_eoe_t *eoe)
EoE clear slave.
void ec_eoe_clear(ec_eoe_t *eoe)
EoE destructor.
Ethernet over EtherCAT (EoE) handler.
#define EC_MASTER_INFO(master, fmt, args...)
Convenience macro for printing master-specific information to syslog.
unsigned int error_flag
Stop processing after an error.
unsigned int rx_idle
Idle flag.
ec_device_t devices[EC_MAX_NUM_DEVICES]
EtherCAT devices.
struct net_device_stats * ec_eoedev_stats(struct net_device *)
Gets statistics about the virtual network device.
int ec_eoe_is_open(const ec_eoe_t *eoe)
Returns the state of the device.
size_t payload_size
Size of the mailbox response payload data.
int ec_slave_mbox_check(const ec_datagram_t *datagram)
Processes a mailbox state checking datagram.
struct net_device * dev
net_device for virtual ethernet device
unsigned int queue_datagram
the datagram is ready for queuing
int ec_eoe_init(ec_master_t *master, ec_eoe_t *eoe, uint16_t alias, uint16_t ring_position)
EoE explicit init constructor.
void ec_datagram_clear(ec_datagram_t *datagram)
Destructor.