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_QUEUE_SIZE 100 64 #define EC_EOE_TRIES 100 87 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29) 111 struct sockaddr *addr = p;
113 if (!is_valid_ether_addr(addr->sa_data)) {
114 return -EADDRNOTAVAIL;
117 #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0) 118 eth_hw_addr_set(netdev, addr->sa_data);
120 memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
142 u8 mac_addr[ETH_ALEN];
144 struct net_device *dev;
145 unsigned char lo_mac[ETH_ALEN] = {0};
146 unsigned int use_master_mac = 0;
164 memset(&eoe->
stats, 0,
sizeof(
struct net_device_stats));
186 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0) 187 eoe->
dev = alloc_netdev(
sizeof(
ec_eoe_t *), name, NET_NAME_UNKNOWN,
190 eoe->
dev = alloc_netdev(
sizeof(
ec_eoe_t *), name, ether_setup);
194 " for EoE handler!\n", name);
200 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29) 220 dev = first_net_device(&init_net);
223 if (dev->addr_len == ETH_ALEN) {
224 if (memcmp(dev->dev_addr, lo_mac, ETH_ALEN) != 0) {
225 if ((dev->dev_addr[0] & 0x02) != 0x02) {
232 dev = next_net_device(dev);
234 if (eoe->
dev->addr_len == ETH_ALEN) {
240 " NIC part of %s MAC address\n",
241 eoe->
dev->name, dev->name);
242 mac_addr[1] = dev->dev_addr[3];
243 mac_addr[2] = dev->dev_addr[4];
244 mac_addr[3] = dev->dev_addr[5];
251 if (eoe->
dev->addr_len == ETH_ALEN) {
252 if (use_master_mac) {
254 " from NIC part of %s MAC address\n",
269 #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0) 270 eth_hw_addr_set(eoe->
dev, mac_addr);
272 memcpy(eoe->
dev->dev_addr, mac_addr,
sizeof(mac_addr));
277 priv = netdev_priv(eoe->
dev);
289 ret = register_netdev(eoe->
dev);
299 free_netdev(eoe->
dev);
313 unregister_netdev(eoe->
dev);
324 dev_kfree_skb(eoe->
rx_skb);
326 free_netdev(eoe->
dev);
341 list_for_each_entry_safe(frame, next, &eoe->
tx_queue, queue) {
342 list_del(&frame->
queue);
343 dev_kfree_skb(frame->
skb);
359 size_t remaining_size, current_size, complete_offset;
360 unsigned int last_fragment;
362 #if EOE_DEBUG_LEVEL >= 3 368 if (remaining_size <= eoe->slave->configured_tx_mailbox_size - 10) {
369 current_size = remaining_size;
382 complete_offset = remaining_size / 32 + 1;
385 #if EOE_DEBUG_LEVEL >= 2 387 " with %zu octets (%zu). %u frames queued.\n",
389 last_fragment ?
"" :
"+", current_size, complete_offset,
393 #if EOE_DEBUG_LEVEL >= 3 395 for (i = 0; i < current_size; i++) {
396 printk(KERN_CONT
"%02X ",
398 if ((i + 1) % 16 == 0) {
399 printk(KERN_CONT
"\n");
403 printk(KERN_CONT
"\n");
407 EC_MBOX_TYPE_EOE, current_size + 4);
409 return PTR_ERR(data);
415 (complete_offset & 0x3F) << 6 |
531 eoe->
stats.rx_errors++;
532 #if EOE_DEBUG_LEVEL >= 1 534 " check datagram for %s.\n", eoe->
dev->name);
571 eoe->
stats.rx_errors++;
572 #if EOE_DEBUG_LEVEL >= 1 574 " fetch datagram for %s.\n", eoe->
dev->name);
595 size_t rec_size, data_size;
596 uint8_t *data, eoe_type, last_fragment, time_appended, mbox_prot;
597 uint8_t fragment_offset, fragment_number;
598 #if EOE_DEBUG_LEVEL >= 2 599 uint8_t frame_number;
602 #if EOE_DEBUG_LEVEL >= 3 619 &mbox_prot, &rec_size);
621 eoe->
stats.rx_errors++;
622 #if EOE_DEBUG_LEVEL >= 1 630 if (mbox_prot != EC_MBOX_TYPE_EOE) {
631 eoe->
stats.rx_errors++;
632 #if EOE_DEBUG_LEVEL >= 1 642 if (eoe_type != EC_EOE_TYPE_FRAME_FRAG) {
644 " response (type %x). Dropping.\n", eoe->
dev->name, eoe_type);
645 eoe->
stats.rx_dropped++;
655 fragment_offset = (
EC_READ_U16(data + 2) >> 6) & 0x003F;
656 #if EOE_DEBUG_LEVEL >= 2 657 frame_number = (
EC_READ_U16(data + 2) >> 12) & 0x000F;
660 #if EOE_DEBUG_LEVEL >= 2 662 " frame %u%s, %zu octets\n", eoe->
dev->name, fragment_number,
663 last_fragment ?
"" :
"+", fragment_offset, frame_number,
664 time_appended ?
", + timestamp" :
"",
665 time_appended ? rec_size - 8 : rec_size - 4);
668 #if EOE_DEBUG_LEVEL >= 3 670 for (i = 0; i < rec_size - 4; i++) {
671 printk(KERN_CONT
"%02X ", data[i + 4]);
672 if ((i + 1) % 16 == 0) {
673 printk(KERN_CONT
"\n");
677 printk(KERN_CONT
"\n");
680 data_size = time_appended ? rec_size - 8 : rec_size - 4;
682 if (!fragment_number) {
685 dev_kfree_skb(eoe->
rx_skb);
689 if (!(eoe->
rx_skb = dev_alloc_skb(fragment_offset * 32))) {
690 if (printk_ratelimit())
692 " frame dropped.\n");
693 eoe->
stats.rx_dropped++;
704 eoe->
stats.rx_dropped++;
709 offset = fragment_offset * 32;
713 dev_kfree_skb(eoe->
rx_skb);
715 eoe->
stats.rx_errors++;
716 #if EOE_DEBUG_LEVEL >= 1 726 memcpy(skb_put(eoe->
rx_skb, data_size), data + 4, data_size);
731 eoe->
stats.rx_packets++;
735 #if EOE_DEBUG_LEVEL >= 2 737 " with %u octets.\n", eoe->
dev->name, eoe->
rx_skb->len);
743 eoe->
rx_skb->ip_summed = CHECKSUM_UNNECESSARY;
744 #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 18, 0) 745 if (netif_rx(eoe->
rx_skb)) {
747 if (netif_rx_ni(eoe->
rx_skb)) {
757 #if EOE_DEBUG_LEVEL >= 2 776 #if EOE_DEBUG_LEVEL >= 2 777 unsigned int wakeup = 0;
803 netif_wake_queue(eoe->
dev);
805 #if EOE_DEBUG_LEVEL >= 2 824 eoe->
stats.tx_errors++;
826 #if EOE_DEBUG_LEVEL >= 1 832 #if EOE_DEBUG_LEVEL >= 2 856 eoe->
stats.tx_errors++;
857 #if EOE_DEBUG_LEVEL >= 1 859 " datagram for %s after %u tries.\n",
872 eoe->
stats.tx_errors++;
873 #if EOE_DEBUG_LEVEL >= 1 875 " for %s after %u tries.\n",
885 eoe->
stats.tx_packets++;
898 eoe->
stats.tx_errors++;
899 #if EOE_DEBUG_LEVEL >= 1 922 netif_start_queue(dev);
924 #if EOE_DEBUG_LEVEL >= 2 939 netif_stop_queue(dev);
945 #if EOE_DEBUG_LEVEL >= 2 958 struct net_device *dev
967 " exceeds MTU. dropping.\n", skb->len);
969 eoe->
stats.tx_dropped++;
976 if (printk_ratelimit())
987 netif_stop_queue(dev);
992 #if EOE_DEBUG_LEVEL >= 2 994 " with %u octets (%u frames queued).\n",
1011 struct net_device *dev
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.
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
#define EC_EOE_TX_QUEUE_SIZE
Size of the EoE tx queue.
static const struct net_device_ops ec_eoedev_ops
Device operations for EoE interfaces.
struct sk_buff * skb
socket buffer
uint16_t configured_tx_mailbox_size
Configured send mailbox size.
void ec_eoe_state_rx_fetch(ec_eoe_t *)
State: RX_FETCH.
struct list_head tx_queue
queue for frames to send
#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
void ec_master_queue_datagram_ext(ec_master_t *master, ec_datagram_t *datagram)
Places a datagram in the non-application datagram queue.
struct net_device_stats * ec_eoedev_stats(struct net_device *)
Gets statistics about the virtual network device.
unsigned int tx_queue_size
Transmit queue size.
size_t rx_skb_size
size of the allocated socket buffer memory
size_t tx_offset
number of octets sent
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_eoedev_tx(struct sk_buff *, struct net_device *)
Transmits data via the virtual network device.
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.
int ec_eoe_init(ec_eoe_t *eoe, ec_slave_t *slave)
EoE constructor.
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.
Ethernet over EtherCAT (EoE)
ec_datagram_state_t state
State.
int ec_eoe_is_idle(const ec_eoe_t *eoe)
Returns the idle state.
ec_lock_t tx_queue_sem
Semaphore for the send queue.
#define EC_SLAVE_ERR(slave, fmt, args...)
Convenience macro for printing slave-specific errors to syslog.
unsigned long rate_jiffies
time of last rate output
#define EC_WRITE_U16(DATA, VAL)
Write a 16-bit unsigned value to EtherCAT data.
void ec_eoe_state_rx_fetch_data(ec_eoe_t *)
State: RX_FETCH DATA.
ec_master_t * master
Master owning the slave.
struct list_head queue
list item
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.
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.
uint32_t rx_rate
receive rate (bps)
struct sk_buff * rx_skb
current rx socket buffer
void(* state)(ec_eoe_t *)
state function for the state machine
void ec_datagram_init(ec_datagram_t *datagram)
Constructor.
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.
ec_eoe_frame_t * tx_frame
current TX frame
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(ec_eoe_t *eoe)
EoE destructor.
Ethernet over EtherCAT (EoE) handler.
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.
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
unsigned int tx_queued_frames
number of frames in the queue
void ec_datagram_clear(ec_datagram_t *datagram)
Destructor.