mirror of
https://gitlab.com/etherlab.org/ethercat.git
synced 2026-09-22 01:53:54 +08:00
Merge
This commit is contained in:
@@ -136,3 +136,5 @@ tool/Makefile
|
||||
tool/Makefile.in
|
||||
tool/TAGS
|
||||
tool/ethercat
|
||||
debuild.log
|
||||
|
||||
|
||||
@@ -579,6 +579,31 @@ if test "x${hrtimer}" = "x1"; then
|
||||
AC_DEFINE([EC_USE_HRTIMER], [1], [Use hrtimer for scheduling])
|
||||
fi
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# Use 2 datagrams (payload+last-byte) when sending to mailbox (reduces frame size)
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
AC_ARG_ENABLE([mboxframesize],
|
||||
AS_HELP_STRING([--enable-mboxframesize],
|
||||
[Reduced frame size when sending to mailbox, uses 2 datagrams (default: no)]),
|
||||
[
|
||||
case "${enableval}" in
|
||||
yes) mboxframesize=1
|
||||
;;
|
||||
no) mboxframesize=0
|
||||
;;
|
||||
*) AC_MSG_ERROR([Invalid value for --enable-mboxframesize])
|
||||
;;
|
||||
esac
|
||||
],
|
||||
[mboxframesize=0]
|
||||
)
|
||||
|
||||
if test "x${mboxframesize}" = "x1"; then
|
||||
AC_DEFINE([EC_REDUCE_MBOXFRAMESIZE], [1], [Reduced frame size when sending to mailbox])
|
||||
fi
|
||||
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# Read alias address from register
|
||||
#------------------------------------------------------------------------------
|
||||
@@ -603,6 +628,7 @@ if test "x${regalias}" = "x1"; then
|
||||
AC_DEFINE([EC_REGALIAS], [1], [Read alias adresses from register])
|
||||
fi
|
||||
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# Command-line tool
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
@@ -0,0 +1,357 @@
|
||||
/*******************************************************************************
|
||||
|
||||
Intel PRO/1000 Linux driver
|
||||
Copyright(c) 1999 - 2006 Intel Corporation.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms and conditions of the GNU General Public License,
|
||||
version 2, as published by the Free Software Foundation.
|
||||
|
||||
This program is distributed in the hope it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
The full GNU General Public License is included in this distribution in
|
||||
the file called "COPYING".
|
||||
|
||||
Contact Information:
|
||||
Linux NICS <linux.nics@intel.com>
|
||||
e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
|
||||
Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
|
||||
/* Linux PRO/1000 Ethernet Driver main header file */
|
||||
|
||||
#ifndef _E1000_H_
|
||||
#define _E1000_H_
|
||||
|
||||
#include <linux/stddef.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/types.h>
|
||||
#include <asm/byteorder.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/timer.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/pagemap.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/irq.h>
|
||||
#include <linux/capability.h>
|
||||
#include <linux/in.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/ipv6.h>
|
||||
#include <linux/tcp.h>
|
||||
#include <linux/udp.h>
|
||||
#include <net/pkt_sched.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/reboot.h>
|
||||
#include <net/checksum.h>
|
||||
#include <linux/mii.h>
|
||||
#include <linux/ethtool.h>
|
||||
#include <linux/if_vlan.h>
|
||||
#include "../ecdev.h"
|
||||
|
||||
|
||||
#define BAR_0 0
|
||||
#define BAR_1 1
|
||||
#define BAR_5 5
|
||||
|
||||
#define INTEL_E1000_ETHERNET_DEVICE(device_id) {\
|
||||
PCI_DEVICE(PCI_VENDOR_ID_INTEL, device_id)}
|
||||
|
||||
struct e1000_adapter;
|
||||
|
||||
#include "e1000_hw-2.6.31-ethercat.h"
|
||||
|
||||
#ifdef DBG
|
||||
#define E1000_DBG(args...) printk(KERN_DEBUG "ec_e1000: " args)
|
||||
#else
|
||||
#define E1000_DBG(args...)
|
||||
#endif
|
||||
|
||||
#define E1000_ERR(args...) printk(KERN_ERR "ec_e1000: " args)
|
||||
|
||||
#define PFX "ec_e1000: "
|
||||
|
||||
#define DPRINTK(nlevel, klevel, fmt, args...) \
|
||||
do { \
|
||||
if (NETIF_MSG_##nlevel & adapter->msg_enable) \
|
||||
printk(KERN_##klevel PFX "%s: %s: " fmt, \
|
||||
adapter->netdev->name, __func__, ##args); \
|
||||
} while (0)
|
||||
|
||||
#define E1000_MAX_INTR 10
|
||||
|
||||
/* TX/RX descriptor defines */
|
||||
#define E1000_DEFAULT_TXD 256
|
||||
#define E1000_MAX_TXD 256
|
||||
#define E1000_MIN_TXD 80
|
||||
#define E1000_MAX_82544_TXD 4096
|
||||
|
||||
#define E1000_DEFAULT_RXD 256
|
||||
#define E1000_MAX_RXD 256
|
||||
#define E1000_MIN_RXD 80
|
||||
#define E1000_MAX_82544_RXD 4096
|
||||
|
||||
/* this is the size past which hardware will drop packets when setting LPE=0 */
|
||||
#define MAXIMUM_ETHERNET_VLAN_SIZE 1522
|
||||
|
||||
/* Supported Rx Buffer Sizes */
|
||||
#define E1000_RXBUFFER_128 128 /* Used for packet split */
|
||||
#define E1000_RXBUFFER_256 256 /* Used for packet split */
|
||||
#define E1000_RXBUFFER_512 512
|
||||
#define E1000_RXBUFFER_1024 1024
|
||||
#define E1000_RXBUFFER_2048 2048
|
||||
#define E1000_RXBUFFER_4096 4096
|
||||
#define E1000_RXBUFFER_8192 8192
|
||||
#define E1000_RXBUFFER_16384 16384
|
||||
|
||||
/* SmartSpeed delimiters */
|
||||
#define E1000_SMARTSPEED_DOWNSHIFT 3
|
||||
#define E1000_SMARTSPEED_MAX 15
|
||||
|
||||
/* Packet Buffer allocations */
|
||||
#define E1000_PBA_BYTES_SHIFT 0xA
|
||||
#define E1000_TX_HEAD_ADDR_SHIFT 7
|
||||
#define E1000_PBA_TX_MASK 0xFFFF0000
|
||||
|
||||
/* Flow Control Watermarks */
|
||||
#define E1000_FC_HIGH_DIFF 0x1638 /* High: 5688 bytes below Rx FIFO size */
|
||||
#define E1000_FC_LOW_DIFF 0x1640 /* Low: 5696 bytes below Rx FIFO size */
|
||||
|
||||
#define E1000_FC_PAUSE_TIME 0x0680 /* 858 usec */
|
||||
|
||||
/* How many Tx Descriptors do we need to call netif_wake_queue ? */
|
||||
#define E1000_TX_QUEUE_WAKE 16
|
||||
/* How many Rx Buffers do we bundle into one write to the hardware ? */
|
||||
#define E1000_RX_BUFFER_WRITE 16 /* Must be power of 2 */
|
||||
|
||||
#define AUTO_ALL_MODES 0
|
||||
#define E1000_EEPROM_82544_APM 0x0004
|
||||
#define E1000_EEPROM_ICH8_APME 0x0004
|
||||
#define E1000_EEPROM_APME 0x0400
|
||||
|
||||
#ifndef E1000_MASTER_SLAVE
|
||||
/* Switch to override PHY master/slave setting */
|
||||
#define E1000_MASTER_SLAVE e1000_ms_hw_default
|
||||
#endif
|
||||
|
||||
#define E1000_MNG_VLAN_NONE (-1)
|
||||
|
||||
/* wrapper around a pointer to a socket buffer,
|
||||
* so a DMA handle can be stored along with the buffer */
|
||||
struct e1000_buffer {
|
||||
struct sk_buff *skb;
|
||||
dma_addr_t dma;
|
||||
unsigned long time_stamp;
|
||||
u16 length;
|
||||
u16 next_to_watch;
|
||||
};
|
||||
|
||||
struct e1000_tx_ring {
|
||||
/* pointer to the descriptor ring memory */
|
||||
void *desc;
|
||||
/* physical address of the descriptor ring */
|
||||
dma_addr_t dma;
|
||||
/* length of descriptor ring in bytes */
|
||||
unsigned int size;
|
||||
/* number of descriptors in the ring */
|
||||
unsigned int count;
|
||||
/* next descriptor to associate a buffer with */
|
||||
unsigned int next_to_use;
|
||||
/* next descriptor to check for DD status bit */
|
||||
unsigned int next_to_clean;
|
||||
/* array of buffer information structs */
|
||||
struct e1000_buffer *buffer_info;
|
||||
|
||||
u16 tdh;
|
||||
u16 tdt;
|
||||
bool last_tx_tso;
|
||||
};
|
||||
|
||||
struct e1000_rx_ring {
|
||||
/* pointer to the descriptor ring memory */
|
||||
void *desc;
|
||||
/* physical address of the descriptor ring */
|
||||
dma_addr_t dma;
|
||||
/* length of descriptor ring in bytes */
|
||||
unsigned int size;
|
||||
/* number of descriptors in the ring */
|
||||
unsigned int count;
|
||||
/* next descriptor to associate a buffer with */
|
||||
unsigned int next_to_use;
|
||||
/* next descriptor to check for DD status bit */
|
||||
unsigned int next_to_clean;
|
||||
/* array of buffer information structs */
|
||||
struct e1000_buffer *buffer_info;
|
||||
|
||||
/* cpu for rx queue */
|
||||
int cpu;
|
||||
|
||||
u16 rdh;
|
||||
u16 rdt;
|
||||
};
|
||||
|
||||
#define E1000_DESC_UNUSED(R) \
|
||||
((((R)->next_to_clean > (R)->next_to_use) \
|
||||
? 0 : (R)->count) + (R)->next_to_clean - (R)->next_to_use - 1)
|
||||
|
||||
#define E1000_RX_DESC_EXT(R, i) \
|
||||
(&(((union e1000_rx_desc_extended *)((R).desc))[i]))
|
||||
#define E1000_GET_DESC(R, i, type) (&(((struct type *)((R).desc))[i]))
|
||||
#define E1000_RX_DESC(R, i) E1000_GET_DESC(R, i, e1000_rx_desc)
|
||||
#define E1000_TX_DESC(R, i) E1000_GET_DESC(R, i, e1000_tx_desc)
|
||||
#define E1000_CONTEXT_DESC(R, i) E1000_GET_DESC(R, i, e1000_context_desc)
|
||||
|
||||
/* board specific private data structure */
|
||||
|
||||
struct e1000_adapter {
|
||||
struct timer_list tx_fifo_stall_timer;
|
||||
struct timer_list watchdog_timer;
|
||||
struct timer_list phy_info_timer;
|
||||
struct vlan_group *vlgrp;
|
||||
u16 mng_vlan_id;
|
||||
u32 bd_number;
|
||||
u32 rx_buffer_len;
|
||||
u32 wol;
|
||||
u32 smartspeed;
|
||||
u32 en_mng_pt;
|
||||
u16 link_speed;
|
||||
u16 link_duplex;
|
||||
spinlock_t stats_lock;
|
||||
unsigned int total_tx_bytes;
|
||||
unsigned int total_tx_packets;
|
||||
unsigned int total_rx_bytes;
|
||||
unsigned int total_rx_packets;
|
||||
/* Interrupt Throttle Rate */
|
||||
u32 itr;
|
||||
u32 itr_setting;
|
||||
u16 tx_itr;
|
||||
u16 rx_itr;
|
||||
|
||||
struct work_struct reset_task;
|
||||
u8 fc_autoneg;
|
||||
|
||||
struct timer_list blink_timer;
|
||||
unsigned long led_status;
|
||||
|
||||
/* TX */
|
||||
struct e1000_tx_ring *tx_ring; /* One per active queue */
|
||||
unsigned int restart_queue;
|
||||
unsigned long tx_queue_len;
|
||||
u32 txd_cmd;
|
||||
u32 tx_int_delay;
|
||||
u32 tx_abs_int_delay;
|
||||
u32 gotcl;
|
||||
u64 gotcl_old;
|
||||
u64 tpt_old;
|
||||
u64 colc_old;
|
||||
u32 tx_timeout_count;
|
||||
u32 tx_fifo_head;
|
||||
u32 tx_head_addr;
|
||||
u32 tx_fifo_size;
|
||||
u8 tx_timeout_factor;
|
||||
atomic_t tx_fifo_stall;
|
||||
bool pcix_82544;
|
||||
bool detect_tx_hung;
|
||||
|
||||
/* RX */
|
||||
bool (*clean_rx)(struct e1000_adapter *adapter,
|
||||
struct e1000_rx_ring *rx_ring,
|
||||
int *work_done, int work_to_do);
|
||||
void (*alloc_rx_buf)(struct e1000_adapter *adapter,
|
||||
struct e1000_rx_ring *rx_ring,
|
||||
int cleaned_count);
|
||||
struct e1000_rx_ring *rx_ring; /* One per active queue */
|
||||
struct napi_struct napi;
|
||||
|
||||
int num_tx_queues;
|
||||
int num_rx_queues;
|
||||
|
||||
u64 hw_csum_err;
|
||||
u64 hw_csum_good;
|
||||
u64 rx_hdr_split;
|
||||
u32 alloc_rx_buff_failed;
|
||||
u32 rx_int_delay;
|
||||
u32 rx_abs_int_delay;
|
||||
bool rx_csum;
|
||||
u32 gorcl;
|
||||
u64 gorcl_old;
|
||||
|
||||
/* OS defined structs */
|
||||
struct net_device *netdev;
|
||||
struct pci_dev *pdev;
|
||||
struct net_device_stats net_stats;
|
||||
|
||||
/* structs defined in e1000_hw.h */
|
||||
struct e1000_hw hw;
|
||||
struct e1000_hw_stats stats;
|
||||
struct e1000_phy_info phy_info;
|
||||
struct e1000_phy_stats phy_stats;
|
||||
|
||||
u32 test_icr;
|
||||
struct e1000_tx_ring test_tx_ring;
|
||||
struct e1000_rx_ring test_rx_ring;
|
||||
|
||||
int msg_enable;
|
||||
bool have_msi;
|
||||
|
||||
/* to not mess up cache alignment, always add to the bottom */
|
||||
bool tso_force;
|
||||
bool smart_power_down; /* phy smart power down */
|
||||
bool quad_port_a;
|
||||
unsigned long flags;
|
||||
u32 eeprom_wol;
|
||||
|
||||
/* for ioport free */
|
||||
int bars;
|
||||
int need_ioport;
|
||||
|
||||
ec_device_t *ecdev;
|
||||
unsigned long ec_watchdog_jiffies;
|
||||
};
|
||||
|
||||
enum e1000_state_t {
|
||||
__E1000_TESTING,
|
||||
__E1000_RESETTING,
|
||||
__E1000_DOWN
|
||||
};
|
||||
|
||||
extern char e1000_driver_name[];
|
||||
extern const char e1000_driver_version[];
|
||||
|
||||
extern int e1000_up(struct e1000_adapter *adapter);
|
||||
extern void e1000_down(struct e1000_adapter *adapter);
|
||||
extern void e1000_reinit_locked(struct e1000_adapter *adapter);
|
||||
extern void e1000_reset(struct e1000_adapter *adapter);
|
||||
extern int e1000_set_spd_dplx(struct e1000_adapter *adapter, u16 spddplx);
|
||||
extern int e1000_setup_all_rx_resources(struct e1000_adapter *adapter);
|
||||
extern int e1000_setup_all_tx_resources(struct e1000_adapter *adapter);
|
||||
extern void e1000_free_all_rx_resources(struct e1000_adapter *adapter);
|
||||
extern void e1000_free_all_tx_resources(struct e1000_adapter *adapter);
|
||||
extern void e1000_update_stats(struct e1000_adapter *adapter);
|
||||
extern void e1000_power_up_phy(struct e1000_adapter *);
|
||||
extern void e1000_set_ethtool_ops(struct net_device *netdev);
|
||||
extern void e1000_check_options(struct e1000_adapter *adapter);
|
||||
|
||||
#endif /* _E1000_H_ */
|
||||
@@ -0,0 +1,352 @@
|
||||
/*******************************************************************************
|
||||
|
||||
Intel PRO/1000 Linux driver
|
||||
Copyright(c) 1999 - 2006 Intel Corporation.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms and conditions of the GNU General Public License,
|
||||
version 2, as published by the Free Software Foundation.
|
||||
|
||||
This program is distributed in the hope it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
The full GNU General Public License is included in this distribution in
|
||||
the file called "COPYING".
|
||||
|
||||
Contact Information:
|
||||
Linux NICS <linux.nics@intel.com>
|
||||
e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
|
||||
Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
|
||||
/* Linux PRO/1000 Ethernet Driver main header file */
|
||||
|
||||
#ifndef _E1000_H_
|
||||
#define _E1000_H_
|
||||
|
||||
#include <linux/stddef.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/types.h>
|
||||
#include <asm/byteorder.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/timer.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/pagemap.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/irq.h>
|
||||
#include <linux/capability.h>
|
||||
#include <linux/in.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/ipv6.h>
|
||||
#include <linux/tcp.h>
|
||||
#include <linux/udp.h>
|
||||
#include <net/pkt_sched.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/reboot.h>
|
||||
#include <net/checksum.h>
|
||||
#include <linux/mii.h>
|
||||
#include <linux/ethtool.h>
|
||||
#include <linux/if_vlan.h>
|
||||
|
||||
#define BAR_0 0
|
||||
#define BAR_1 1
|
||||
#define BAR_5 5
|
||||
|
||||
#define INTEL_E1000_ETHERNET_DEVICE(device_id) {\
|
||||
PCI_DEVICE(PCI_VENDOR_ID_INTEL, device_id)}
|
||||
|
||||
struct e1000_adapter;
|
||||
|
||||
#include "e1000_hw.h"
|
||||
|
||||
#ifdef DBG
|
||||
#define E1000_DBG(args...) printk(KERN_DEBUG "e1000: " args)
|
||||
#else
|
||||
#define E1000_DBG(args...)
|
||||
#endif
|
||||
|
||||
#define E1000_ERR(args...) printk(KERN_ERR "e1000: " args)
|
||||
|
||||
#define PFX "e1000: "
|
||||
|
||||
#define DPRINTK(nlevel, klevel, fmt, args...) \
|
||||
do { \
|
||||
if (NETIF_MSG_##nlevel & adapter->msg_enable) \
|
||||
printk(KERN_##klevel PFX "%s: %s: " fmt, \
|
||||
adapter->netdev->name, __func__, ##args); \
|
||||
} while (0)
|
||||
|
||||
#define E1000_MAX_INTR 10
|
||||
|
||||
/* TX/RX descriptor defines */
|
||||
#define E1000_DEFAULT_TXD 256
|
||||
#define E1000_MAX_TXD 256
|
||||
#define E1000_MIN_TXD 80
|
||||
#define E1000_MAX_82544_TXD 4096
|
||||
|
||||
#define E1000_DEFAULT_RXD 256
|
||||
#define E1000_MAX_RXD 256
|
||||
#define E1000_MIN_RXD 80
|
||||
#define E1000_MAX_82544_RXD 4096
|
||||
|
||||
/* this is the size past which hardware will drop packets when setting LPE=0 */
|
||||
#define MAXIMUM_ETHERNET_VLAN_SIZE 1522
|
||||
|
||||
/* Supported Rx Buffer Sizes */
|
||||
#define E1000_RXBUFFER_128 128 /* Used for packet split */
|
||||
#define E1000_RXBUFFER_256 256 /* Used for packet split */
|
||||
#define E1000_RXBUFFER_512 512
|
||||
#define E1000_RXBUFFER_1024 1024
|
||||
#define E1000_RXBUFFER_2048 2048
|
||||
#define E1000_RXBUFFER_4096 4096
|
||||
#define E1000_RXBUFFER_8192 8192
|
||||
#define E1000_RXBUFFER_16384 16384
|
||||
|
||||
/* SmartSpeed delimiters */
|
||||
#define E1000_SMARTSPEED_DOWNSHIFT 3
|
||||
#define E1000_SMARTSPEED_MAX 15
|
||||
|
||||
/* Packet Buffer allocations */
|
||||
#define E1000_PBA_BYTES_SHIFT 0xA
|
||||
#define E1000_TX_HEAD_ADDR_SHIFT 7
|
||||
#define E1000_PBA_TX_MASK 0xFFFF0000
|
||||
|
||||
/* Flow Control Watermarks */
|
||||
#define E1000_FC_HIGH_DIFF 0x1638 /* High: 5688 bytes below Rx FIFO size */
|
||||
#define E1000_FC_LOW_DIFF 0x1640 /* Low: 5696 bytes below Rx FIFO size */
|
||||
|
||||
#define E1000_FC_PAUSE_TIME 0x0680 /* 858 usec */
|
||||
|
||||
/* How many Tx Descriptors do we need to call netif_wake_queue ? */
|
||||
#define E1000_TX_QUEUE_WAKE 16
|
||||
/* How many Rx Buffers do we bundle into one write to the hardware ? */
|
||||
#define E1000_RX_BUFFER_WRITE 16 /* Must be power of 2 */
|
||||
|
||||
#define AUTO_ALL_MODES 0
|
||||
#define E1000_EEPROM_82544_APM 0x0004
|
||||
#define E1000_EEPROM_ICH8_APME 0x0004
|
||||
#define E1000_EEPROM_APME 0x0400
|
||||
|
||||
#ifndef E1000_MASTER_SLAVE
|
||||
/* Switch to override PHY master/slave setting */
|
||||
#define E1000_MASTER_SLAVE e1000_ms_hw_default
|
||||
#endif
|
||||
|
||||
#define E1000_MNG_VLAN_NONE (-1)
|
||||
|
||||
/* wrapper around a pointer to a socket buffer,
|
||||
* so a DMA handle can be stored along with the buffer */
|
||||
struct e1000_buffer {
|
||||
struct sk_buff *skb;
|
||||
dma_addr_t dma;
|
||||
unsigned long time_stamp;
|
||||
u16 length;
|
||||
u16 next_to_watch;
|
||||
};
|
||||
|
||||
struct e1000_tx_ring {
|
||||
/* pointer to the descriptor ring memory */
|
||||
void *desc;
|
||||
/* physical address of the descriptor ring */
|
||||
dma_addr_t dma;
|
||||
/* length of descriptor ring in bytes */
|
||||
unsigned int size;
|
||||
/* number of descriptors in the ring */
|
||||
unsigned int count;
|
||||
/* next descriptor to associate a buffer with */
|
||||
unsigned int next_to_use;
|
||||
/* next descriptor to check for DD status bit */
|
||||
unsigned int next_to_clean;
|
||||
/* array of buffer information structs */
|
||||
struct e1000_buffer *buffer_info;
|
||||
|
||||
u16 tdh;
|
||||
u16 tdt;
|
||||
bool last_tx_tso;
|
||||
};
|
||||
|
||||
struct e1000_rx_ring {
|
||||
/* pointer to the descriptor ring memory */
|
||||
void *desc;
|
||||
/* physical address of the descriptor ring */
|
||||
dma_addr_t dma;
|
||||
/* length of descriptor ring in bytes */
|
||||
unsigned int size;
|
||||
/* number of descriptors in the ring */
|
||||
unsigned int count;
|
||||
/* next descriptor to associate a buffer with */
|
||||
unsigned int next_to_use;
|
||||
/* next descriptor to check for DD status bit */
|
||||
unsigned int next_to_clean;
|
||||
/* array of buffer information structs */
|
||||
struct e1000_buffer *buffer_info;
|
||||
|
||||
/* cpu for rx queue */
|
||||
int cpu;
|
||||
|
||||
u16 rdh;
|
||||
u16 rdt;
|
||||
};
|
||||
|
||||
#define E1000_DESC_UNUSED(R) \
|
||||
((((R)->next_to_clean > (R)->next_to_use) \
|
||||
? 0 : (R)->count) + (R)->next_to_clean - (R)->next_to_use - 1)
|
||||
|
||||
#define E1000_RX_DESC_EXT(R, i) \
|
||||
(&(((union e1000_rx_desc_extended *)((R).desc))[i]))
|
||||
#define E1000_GET_DESC(R, i, type) (&(((struct type *)((R).desc))[i]))
|
||||
#define E1000_RX_DESC(R, i) E1000_GET_DESC(R, i, e1000_rx_desc)
|
||||
#define E1000_TX_DESC(R, i) E1000_GET_DESC(R, i, e1000_tx_desc)
|
||||
#define E1000_CONTEXT_DESC(R, i) E1000_GET_DESC(R, i, e1000_context_desc)
|
||||
|
||||
/* board specific private data structure */
|
||||
|
||||
struct e1000_adapter {
|
||||
struct timer_list tx_fifo_stall_timer;
|
||||
struct timer_list watchdog_timer;
|
||||
struct timer_list phy_info_timer;
|
||||
struct vlan_group *vlgrp;
|
||||
u16 mng_vlan_id;
|
||||
u32 bd_number;
|
||||
u32 rx_buffer_len;
|
||||
u32 wol;
|
||||
u32 smartspeed;
|
||||
u32 en_mng_pt;
|
||||
u16 link_speed;
|
||||
u16 link_duplex;
|
||||
spinlock_t stats_lock;
|
||||
unsigned int total_tx_bytes;
|
||||
unsigned int total_tx_packets;
|
||||
unsigned int total_rx_bytes;
|
||||
unsigned int total_rx_packets;
|
||||
/* Interrupt Throttle Rate */
|
||||
u32 itr;
|
||||
u32 itr_setting;
|
||||
u16 tx_itr;
|
||||
u16 rx_itr;
|
||||
|
||||
struct work_struct reset_task;
|
||||
u8 fc_autoneg;
|
||||
|
||||
struct timer_list blink_timer;
|
||||
unsigned long led_status;
|
||||
|
||||
/* TX */
|
||||
struct e1000_tx_ring *tx_ring; /* One per active queue */
|
||||
unsigned int restart_queue;
|
||||
unsigned long tx_queue_len;
|
||||
u32 txd_cmd;
|
||||
u32 tx_int_delay;
|
||||
u32 tx_abs_int_delay;
|
||||
u32 gotcl;
|
||||
u64 gotcl_old;
|
||||
u64 tpt_old;
|
||||
u64 colc_old;
|
||||
u32 tx_timeout_count;
|
||||
u32 tx_fifo_head;
|
||||
u32 tx_head_addr;
|
||||
u32 tx_fifo_size;
|
||||
u8 tx_timeout_factor;
|
||||
atomic_t tx_fifo_stall;
|
||||
bool pcix_82544;
|
||||
bool detect_tx_hung;
|
||||
|
||||
/* RX */
|
||||
bool (*clean_rx)(struct e1000_adapter *adapter,
|
||||
struct e1000_rx_ring *rx_ring,
|
||||
int *work_done, int work_to_do);
|
||||
void (*alloc_rx_buf)(struct e1000_adapter *adapter,
|
||||
struct e1000_rx_ring *rx_ring,
|
||||
int cleaned_count);
|
||||
struct e1000_rx_ring *rx_ring; /* One per active queue */
|
||||
struct napi_struct napi;
|
||||
|
||||
int num_tx_queues;
|
||||
int num_rx_queues;
|
||||
|
||||
u64 hw_csum_err;
|
||||
u64 hw_csum_good;
|
||||
u64 rx_hdr_split;
|
||||
u32 alloc_rx_buff_failed;
|
||||
u32 rx_int_delay;
|
||||
u32 rx_abs_int_delay;
|
||||
bool rx_csum;
|
||||
u32 gorcl;
|
||||
u64 gorcl_old;
|
||||
|
||||
/* OS defined structs */
|
||||
struct net_device *netdev;
|
||||
struct pci_dev *pdev;
|
||||
struct net_device_stats net_stats;
|
||||
|
||||
/* structs defined in e1000_hw.h */
|
||||
struct e1000_hw hw;
|
||||
struct e1000_hw_stats stats;
|
||||
struct e1000_phy_info phy_info;
|
||||
struct e1000_phy_stats phy_stats;
|
||||
|
||||
u32 test_icr;
|
||||
struct e1000_tx_ring test_tx_ring;
|
||||
struct e1000_rx_ring test_rx_ring;
|
||||
|
||||
int msg_enable;
|
||||
bool have_msi;
|
||||
|
||||
/* to not mess up cache alignment, always add to the bottom */
|
||||
bool tso_force;
|
||||
bool smart_power_down; /* phy smart power down */
|
||||
bool quad_port_a;
|
||||
unsigned long flags;
|
||||
u32 eeprom_wol;
|
||||
|
||||
/* for ioport free */
|
||||
int bars;
|
||||
int need_ioport;
|
||||
};
|
||||
|
||||
enum e1000_state_t {
|
||||
__E1000_TESTING,
|
||||
__E1000_RESETTING,
|
||||
__E1000_DOWN
|
||||
};
|
||||
|
||||
extern char e1000_driver_name[];
|
||||
extern const char e1000_driver_version[];
|
||||
|
||||
extern int e1000_up(struct e1000_adapter *adapter);
|
||||
extern void e1000_down(struct e1000_adapter *adapter);
|
||||
extern void e1000_reinit_locked(struct e1000_adapter *adapter);
|
||||
extern void e1000_reset(struct e1000_adapter *adapter);
|
||||
extern int e1000_set_spd_dplx(struct e1000_adapter *adapter, u16 spddplx);
|
||||
extern int e1000_setup_all_rx_resources(struct e1000_adapter *adapter);
|
||||
extern int e1000_setup_all_tx_resources(struct e1000_adapter *adapter);
|
||||
extern void e1000_free_all_rx_resources(struct e1000_adapter *adapter);
|
||||
extern void e1000_free_all_tx_resources(struct e1000_adapter *adapter);
|
||||
extern void e1000_update_stats(struct e1000_adapter *adapter);
|
||||
extern void e1000_power_up_phy(struct e1000_adapter *);
|
||||
extern void e1000_set_ethtool_ops(struct net_device *netdev);
|
||||
extern void e1000_check_options(struct e1000_adapter *adapter);
|
||||
|
||||
#endif /* _E1000_H_ */
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -3457,7 +3457,7 @@ static irqreturn_t e1000_intr(int irq, void *data)
|
||||
if (unlikely((!icr) || test_bit(__E1000_DOWN, &adapter->flags)))
|
||||
return IRQ_NONE; /* Not our interrupt */
|
||||
|
||||
if (!adapter->ecdev && unlikely(icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC))) {
|
||||
if (unlikely(icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC))) {
|
||||
hw->get_link_status = 1;
|
||||
/* guard against interrupt when we're going down */
|
||||
if (!test_bit(__E1000_DOWN, &adapter->flags))
|
||||
|
||||
@@ -0,0 +1,113 @@
|
||||
/*******************************************************************************
|
||||
|
||||
Intel PRO/1000 Linux driver
|
||||
Copyright(c) 1999 - 2006 Intel Corporation.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms and conditions of the GNU General Public License,
|
||||
version 2, as published by the Free Software Foundation.
|
||||
|
||||
This program is distributed in the hope it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
The full GNU General Public License is included in this distribution in
|
||||
the file called "COPYING".
|
||||
|
||||
Contact Information:
|
||||
Linux NICS <linux.nics@intel.com>
|
||||
e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
|
||||
Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
|
||||
/* glue for the OS independent part of e1000
|
||||
* includes register access macros
|
||||
*/
|
||||
|
||||
#ifndef _E1000_OSDEP_H_
|
||||
#define _E1000_OSDEP_H_
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/delay.h>
|
||||
#include <asm/io.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/sched.h>
|
||||
|
||||
#ifdef DBG
|
||||
#define DEBUGOUT(S) printk(KERN_DEBUG S "\n")
|
||||
#define DEBUGOUT1(S, A...) printk(KERN_DEBUG S "\n", A)
|
||||
#else
|
||||
#define DEBUGOUT(S)
|
||||
#define DEBUGOUT1(S, A...)
|
||||
#endif
|
||||
|
||||
#define DEBUGFUNC(F) DEBUGOUT(F "\n")
|
||||
#define DEBUGOUT2 DEBUGOUT1
|
||||
#define DEBUGOUT3 DEBUGOUT2
|
||||
#define DEBUGOUT7 DEBUGOUT3
|
||||
|
||||
|
||||
#define er32(reg) \
|
||||
(readl(hw->hw_addr + ((hw->mac_type >= e1000_82543) \
|
||||
? E1000_##reg : E1000_82542_##reg)))
|
||||
|
||||
#define ew32(reg, value) \
|
||||
(writel((value), (hw->hw_addr + ((hw->mac_type >= e1000_82543) \
|
||||
? E1000_##reg : E1000_82542_##reg))))
|
||||
|
||||
#define E1000_WRITE_REG_ARRAY(a, reg, offset, value) ( \
|
||||
writel((value), ((a)->hw_addr + \
|
||||
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||
((offset) << 2))))
|
||||
|
||||
#define E1000_READ_REG_ARRAY(a, reg, offset) ( \
|
||||
readl((a)->hw_addr + \
|
||||
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||
((offset) << 2)))
|
||||
|
||||
#define E1000_READ_REG_ARRAY_DWORD E1000_READ_REG_ARRAY
|
||||
#define E1000_WRITE_REG_ARRAY_DWORD E1000_WRITE_REG_ARRAY
|
||||
|
||||
#define E1000_WRITE_REG_ARRAY_WORD(a, reg, offset, value) ( \
|
||||
writew((value), ((a)->hw_addr + \
|
||||
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||
((offset) << 1))))
|
||||
|
||||
#define E1000_READ_REG_ARRAY_WORD(a, reg, offset) ( \
|
||||
readw((a)->hw_addr + \
|
||||
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||
((offset) << 1)))
|
||||
|
||||
#define E1000_WRITE_REG_ARRAY_BYTE(a, reg, offset, value) ( \
|
||||
writeb((value), ((a)->hw_addr + \
|
||||
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||
(offset))))
|
||||
|
||||
#define E1000_READ_REG_ARRAY_BYTE(a, reg, offset) ( \
|
||||
readb((a)->hw_addr + \
|
||||
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||
(offset)))
|
||||
|
||||
#define E1000_WRITE_FLUSH() er32(STATUS)
|
||||
|
||||
#define E1000_WRITE_ICH_FLASH_REG(a, reg, value) ( \
|
||||
writel((value), ((a)->flash_address + reg)))
|
||||
|
||||
#define E1000_READ_ICH_FLASH_REG(a, reg) ( \
|
||||
readl((a)->flash_address + reg))
|
||||
|
||||
#define E1000_WRITE_ICH_FLASH_REG16(a, reg, value) ( \
|
||||
writew((value), ((a)->flash_address + reg)))
|
||||
|
||||
#define E1000_READ_ICH_FLASH_REG16(a, reg) ( \
|
||||
readw((a)->flash_address + reg))
|
||||
|
||||
#endif /* _E1000_OSDEP_H_ */
|
||||
@@ -0,0 +1,113 @@
|
||||
/*******************************************************************************
|
||||
|
||||
Intel PRO/1000 Linux driver
|
||||
Copyright(c) 1999 - 2006 Intel Corporation.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms and conditions of the GNU General Public License,
|
||||
version 2, as published by the Free Software Foundation.
|
||||
|
||||
This program is distributed in the hope it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
The full GNU General Public License is included in this distribution in
|
||||
the file called "COPYING".
|
||||
|
||||
Contact Information:
|
||||
Linux NICS <linux.nics@intel.com>
|
||||
e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
|
||||
Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
|
||||
/* glue for the OS independent part of e1000
|
||||
* includes register access macros
|
||||
*/
|
||||
|
||||
#ifndef _E1000_OSDEP_H_
|
||||
#define _E1000_OSDEP_H_
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/delay.h>
|
||||
#include <asm/io.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/sched.h>
|
||||
|
||||
#ifdef DBG
|
||||
#define DEBUGOUT(S) printk(KERN_DEBUG S "\n")
|
||||
#define DEBUGOUT1(S, A...) printk(KERN_DEBUG S "\n", A)
|
||||
#else
|
||||
#define DEBUGOUT(S)
|
||||
#define DEBUGOUT1(S, A...)
|
||||
#endif
|
||||
|
||||
#define DEBUGFUNC(F) DEBUGOUT(F "\n")
|
||||
#define DEBUGOUT2 DEBUGOUT1
|
||||
#define DEBUGOUT3 DEBUGOUT2
|
||||
#define DEBUGOUT7 DEBUGOUT3
|
||||
|
||||
|
||||
#define er32(reg) \
|
||||
(readl(hw->hw_addr + ((hw->mac_type >= e1000_82543) \
|
||||
? E1000_##reg : E1000_82542_##reg)))
|
||||
|
||||
#define ew32(reg, value) \
|
||||
(writel((value), (hw->hw_addr + ((hw->mac_type >= e1000_82543) \
|
||||
? E1000_##reg : E1000_82542_##reg))))
|
||||
|
||||
#define E1000_WRITE_REG_ARRAY(a, reg, offset, value) ( \
|
||||
writel((value), ((a)->hw_addr + \
|
||||
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||
((offset) << 2))))
|
||||
|
||||
#define E1000_READ_REG_ARRAY(a, reg, offset) ( \
|
||||
readl((a)->hw_addr + \
|
||||
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||
((offset) << 2)))
|
||||
|
||||
#define E1000_READ_REG_ARRAY_DWORD E1000_READ_REG_ARRAY
|
||||
#define E1000_WRITE_REG_ARRAY_DWORD E1000_WRITE_REG_ARRAY
|
||||
|
||||
#define E1000_WRITE_REG_ARRAY_WORD(a, reg, offset, value) ( \
|
||||
writew((value), ((a)->hw_addr + \
|
||||
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||
((offset) << 1))))
|
||||
|
||||
#define E1000_READ_REG_ARRAY_WORD(a, reg, offset) ( \
|
||||
readw((a)->hw_addr + \
|
||||
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||
((offset) << 1)))
|
||||
|
||||
#define E1000_WRITE_REG_ARRAY_BYTE(a, reg, offset, value) ( \
|
||||
writeb((value), ((a)->hw_addr + \
|
||||
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||
(offset))))
|
||||
|
||||
#define E1000_READ_REG_ARRAY_BYTE(a, reg, offset) ( \
|
||||
readb((a)->hw_addr + \
|
||||
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||
(offset)))
|
||||
|
||||
#define E1000_WRITE_FLUSH() er32(STATUS)
|
||||
|
||||
#define E1000_WRITE_ICH_FLASH_REG(a, reg, value) ( \
|
||||
writel((value), ((a)->flash_address + reg)))
|
||||
|
||||
#define E1000_READ_ICH_FLASH_REG(a, reg) ( \
|
||||
readl((a)->flash_address + reg))
|
||||
|
||||
#define E1000_WRITE_ICH_FLASH_REG16(a, reg, value) ( \
|
||||
writew((value), ((a)->flash_address + reg)))
|
||||
|
||||
#define E1000_READ_ICH_FLASH_REG16(a, reg) ( \
|
||||
readw((a)->flash_address + reg))
|
||||
|
||||
#endif /* _E1000_OSDEP_H_ */
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -229,8 +229,8 @@ void run(long data)
|
||||
}
|
||||
ecrt_master_sync_slave_clocks(master);
|
||||
ecrt_domain_queue(domain1);
|
||||
ecrt_master_send(master);
|
||||
rt_sem_signal(&master_sem);
|
||||
ecrt_master_send(master);
|
||||
|
||||
rt_task_wait_period();
|
||||
}
|
||||
@@ -238,30 +238,18 @@ void run(long data)
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void send_callback(void *cb_data)
|
||||
void request_lock_callback(void *cb_data)
|
||||
{
|
||||
ec_master_t *m = (ec_master_t *) cb_data;
|
||||
|
||||
// too close to the next real time cycle: deny access...
|
||||
if (get_cycles() - t_last_cycle <= t_critical) {
|
||||
rt_sem_wait(&master_sem);
|
||||
ecrt_master_send_ext(m);
|
||||
rt_sem_signal(&master_sem);
|
||||
}
|
||||
rt_sem_wait(&master_sem);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void receive_callback(void *cb_data)
|
||||
void release_lock_callback(void *cb_data)
|
||||
{
|
||||
ec_master_t *m = (ec_master_t *) cb_data;
|
||||
|
||||
// too close to the next real time cycle: deny access...
|
||||
if (get_cycles() - t_last_cycle <= t_critical) {
|
||||
rt_sem_wait(&master_sem);
|
||||
ecrt_master_receive(m);
|
||||
rt_sem_signal(&master_sem);
|
||||
}
|
||||
rt_sem_signal(&master_sem);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
@@ -285,7 +273,7 @@ int __init init_mod(void)
|
||||
goto out_return;
|
||||
}
|
||||
|
||||
ecrt_master_callbacks(master, send_callback, receive_callback, master);
|
||||
ecrt_master_callbacks(master, request_lock_callback, release_lock_callback, master);
|
||||
|
||||
printk(KERN_INFO PFX "Registering domain...\n");
|
||||
if (!(domain1 = ecrt_master_create_domain(master))) {
|
||||
|
||||
@@ -346,10 +346,9 @@ void cyclic_task(unsigned long data)
|
||||
EC_WRITE_U8(domain1_pd + off_dig_out, blink ? 0x06 : 0x09);
|
||||
|
||||
// send process data
|
||||
down(&master_sem);
|
||||
ecrt_domain_queue(domain1);
|
||||
ecrt_master_send(master);
|
||||
up(&master_sem);
|
||||
ecrt_master_send(master);
|
||||
|
||||
// restart timer
|
||||
timer.expires += HZ / FREQUENCY;
|
||||
@@ -358,21 +357,17 @@ void cyclic_task(unsigned long data)
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void send_callback(void *cb_data)
|
||||
void request_lock_callback(void *cb_data)
|
||||
{
|
||||
ec_master_t *m = (ec_master_t *) cb_data;
|
||||
down(&master_sem);
|
||||
ecrt_master_send_ext(m);
|
||||
up(&master_sem);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void receive_callback(void *cb_data)
|
||||
void release_lock_callback(void *cb_data)
|
||||
{
|
||||
ec_master_t *m = (ec_master_t *) cb_data;
|
||||
down(&master_sem);
|
||||
ecrt_master_receive(m);
|
||||
up(&master_sem);
|
||||
}
|
||||
|
||||
@@ -398,7 +393,7 @@ int __init init_mini_module(void)
|
||||
}
|
||||
|
||||
sema_init(&master_sem, 1);
|
||||
ecrt_master_callbacks(master, send_callback, receive_callback, master);
|
||||
ecrt_master_callbacks(master, request_lock_callback, release_lock_callback, master);
|
||||
|
||||
printk(KERN_INFO PFX "Registering domain...\n");
|
||||
if (!(domain1 = ecrt_master_create_domain(master))) {
|
||||
|
||||
@@ -234,8 +234,8 @@ void run(long data)
|
||||
|
||||
rt_sem_wait(&master_sem);
|
||||
ecrt_domain_queue(domain1);
|
||||
ecrt_master_send(master);
|
||||
rt_sem_signal(&master_sem);
|
||||
ecrt_master_send(master);
|
||||
|
||||
rt_task_wait_period();
|
||||
}
|
||||
@@ -243,30 +243,18 @@ void run(long data)
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void send_callback(void *cb_data)
|
||||
void request_lock_callback(void *cb_data)
|
||||
{
|
||||
ec_master_t *m = (ec_master_t *) cb_data;
|
||||
|
||||
// too close to the next real time cycle: deny access...
|
||||
if (get_cycles() - t_last_cycle <= t_critical) {
|
||||
rt_sem_wait(&master_sem);
|
||||
ecrt_master_send_ext(m);
|
||||
rt_sem_signal(&master_sem);
|
||||
}
|
||||
rt_sem_wait(&master_sem);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void receive_callback(void *cb_data)
|
||||
void release_lock_callback(void *cb_data)
|
||||
{
|
||||
ec_master_t *m = (ec_master_t *) cb_data;
|
||||
|
||||
// too close to the next real time cycle: deny access...
|
||||
if (get_cycles() - t_last_cycle <= t_critical) {
|
||||
rt_sem_wait(&master_sem);
|
||||
ecrt_master_receive(m);
|
||||
rt_sem_signal(&master_sem);
|
||||
}
|
||||
rt_sem_signal(&master_sem);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
@@ -292,7 +280,7 @@ int __init init_mod(void)
|
||||
goto out_return;
|
||||
}
|
||||
|
||||
ecrt_master_callbacks(master, send_callback, receive_callback, master);
|
||||
ecrt_master_callbacks(master, request_lock_callback, release_lock_callback, master);
|
||||
|
||||
printk(KERN_INFO PFX "Registering domain...\n");
|
||||
if (!(domain1 = ecrt_master_create_domain(master))) {
|
||||
|
||||
+4
-8
@@ -141,8 +141,8 @@ void cyclic_task(unsigned long data)
|
||||
// send process data
|
||||
down(&master_sem);
|
||||
ecrt_domain_queue(domain1);
|
||||
ecrt_master_send(master);
|
||||
up(&master_sem);
|
||||
ecrt_master_send(master);
|
||||
|
||||
// restart timer
|
||||
timer.expires += HZ / FREQUENCY;
|
||||
@@ -151,21 +151,17 @@ void cyclic_task(unsigned long data)
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void send_callback(void *cb_data)
|
||||
void request_lock_callback(void *cb_data)
|
||||
{
|
||||
ec_master_t *m = (ec_master_t *) cb_data;
|
||||
down(&master_sem);
|
||||
ecrt_master_send_ext(m);
|
||||
up(&master_sem);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void receive_callback(void *cb_data)
|
||||
void release_lock_callback(void *cb_data)
|
||||
{
|
||||
ec_master_t *m = (ec_master_t *) cb_data;
|
||||
down(&master_sem);
|
||||
ecrt_master_receive(m);
|
||||
up(&master_sem);
|
||||
}
|
||||
|
||||
@@ -186,7 +182,7 @@ int __init init_mini_module(void)
|
||||
}
|
||||
|
||||
sema_init(&master_sem, 1);
|
||||
ecrt_master_callbacks(master, send_callback, receive_callback, master);
|
||||
ecrt_master_callbacks(master, request_lock_callback, release_lock_callback, master);
|
||||
|
||||
printk(KERN_INFO PFX "Registering domain...\n");
|
||||
if (!(domain1 = ecrt_master_create_domain(master))) {
|
||||
|
||||
+87
-50
@@ -5,7 +5,7 @@
|
||||
* Copyright (C) 2006-2008 Florian Pose, Ingenieurgemeinschaft IgH
|
||||
*
|
||||
* This file is part of the IgH EtherCAT master userspace library.
|
||||
*
|
||||
*
|
||||
* The IgH EtherCAT master userspace library is free software; you can
|
||||
* redistribute it and/or modify it under the terms of the GNU Lesser General
|
||||
* Public License as published by the Free Software Foundation; version 2.1
|
||||
@@ -19,9 +19,9 @@
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with the IgH EtherCAT master userspace library. If not, see
|
||||
* <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
* ---
|
||||
*
|
||||
*
|
||||
* The license mentioned above concerns the source code only. Using the
|
||||
* EtherCAT technology and brand is only permitted in compliance with the
|
||||
* industrial property and similar rights of Beckhoff Automation GmbH.
|
||||
@@ -47,11 +47,9 @@
|
||||
* ecrt_master_sync_slave_clocks() for offset and drift compensation. The
|
||||
* EC_TIMEVAL2NANO() macro can be used for epoch time conversion, while the
|
||||
* ecrt_master_sync_monitor_queue() and ecrt_master_sync_monitor_process()
|
||||
* methods can be used to monitor the synchrony.
|
||||
* methods can be used to monitor the synchrony.
|
||||
* - Improved the callback mechanism. ecrt_master_callbacks() now takes two
|
||||
* callback functions for sending and receiving datagrams.
|
||||
* ecrt_master_send_ext() is used to execute the sending of non-application
|
||||
* datagrams.
|
||||
* callback functions for locking and unlocking the fsm datagram queue.
|
||||
* - Added watchdog configuration (method ecrt_slave_config_watchdog(),
|
||||
* #ec_watchdog_mode_t, \a watchdog_mode parameter in ec_sync_info_t and
|
||||
* ecrt_slave_config_sync_manager()).
|
||||
@@ -79,6 +77,9 @@
|
||||
* and ecrt_master_read_idn() and ecrt_master_write_idn() to read/write IDNs
|
||||
* ad-hoc via the user-space library.
|
||||
* - Added ecrt_master_reset() to initiate retrying to configure slaves.
|
||||
* - Added support for overlapping PDOs which allows inputs to use the same
|
||||
* space as outputs on the frame. This reduces the frame length.
|
||||
*
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
@@ -136,6 +137,9 @@
|
||||
*/
|
||||
#define EC_MAX_STRING_LENGTH 64
|
||||
|
||||
/** Maximum number of slave ports. */
|
||||
#define EC_MAX_PORTS 4
|
||||
|
||||
/** Timeval to nanoseconds conversion.
|
||||
*
|
||||
* This macro converts a Unix epoch time to EtherCAT DC time.
|
||||
@@ -148,7 +152,7 @@
|
||||
(((TV).tv_sec - 946684800ULL) * 1000000000ULL + (TV).tv_usec * 1000ULL)
|
||||
|
||||
/******************************************************************************
|
||||
* Data types
|
||||
* Data types
|
||||
*****************************************************************************/
|
||||
|
||||
struct ec_master;
|
||||
@@ -193,7 +197,7 @@ typedef struct {
|
||||
/** Slave configuration state.
|
||||
*
|
||||
* This is used as an output parameter of ecrt_slave_config_state().
|
||||
*
|
||||
*
|
||||
* \see ecrt_slave_config_state().
|
||||
*/
|
||||
typedef struct {
|
||||
@@ -221,12 +225,33 @@ typedef struct {
|
||||
typedef struct {
|
||||
unsigned int slave_count; /**< Number of slaves in the bus. */
|
||||
unsigned int link_up : 1; /**< \a true, if the network link is up. */
|
||||
uint8_t scan_busy; /**< \a true, while the master is scanning the bus */
|
||||
uint8_t scan_busy; /**< \a true, while the master is scanning the bus */
|
||||
uint64_t app_time; /**< Application time. */
|
||||
} ec_master_info_t;
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/** EtherCAT slave port descriptor.
|
||||
*/
|
||||
typedef enum {
|
||||
EC_PORT_NOT_IMPLEMENTED, /**< Port is not implemented. */
|
||||
EC_PORT_NOT_CONFIGURED, /**< Port is not configured. */
|
||||
EC_PORT_EBUS, /**< Port is an e-bus. */
|
||||
EC_PORT_MII /**< Port is a mii. */
|
||||
} ec_slave_port_desc_t;
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/** EtherCAT slave port information.
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t link_up; /**< Link detected. */
|
||||
uint8_t loop_closed; /**< Loop closed. */
|
||||
uint8_t signal_detected; /**< Detected signal on RX port. */
|
||||
} ec_slave_port_link_t;
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/** Slave information.
|
||||
*
|
||||
* This is used as an output parameter of ecrt_master_get_slave().
|
||||
@@ -241,6 +266,13 @@ typedef struct {
|
||||
uint32_t serial_number; /**< Serial-Number stored on the slave. */
|
||||
uint16_t alias; /**< The slaves alias if not equal to 0. */
|
||||
int16_t current_on_ebus; /**< Used current in mA. */
|
||||
struct {
|
||||
ec_slave_port_desc_t desc;
|
||||
ec_slave_port_link_t link;
|
||||
uint32_t receive_time;
|
||||
uint16_t next_slave;
|
||||
uint32_t delay_to_next_dc;
|
||||
} ports[EC_MAX_PORTS];
|
||||
uint8_t al_state; /**< Current state of the slave. */
|
||||
uint8_t error_flag; /**< Error flag for that slave. */
|
||||
uint8_t sync_count; /**< Number of sync managers. */
|
||||
@@ -312,9 +344,9 @@ typedef struct {
|
||||
/*****************************************************************************/
|
||||
|
||||
/** PDO configuration information.
|
||||
*
|
||||
*
|
||||
* This is the data type of the \a pdos field in ec_sync_info_t.
|
||||
*
|
||||
*
|
||||
* \see ecrt_slave_config_pdos().
|
||||
*/
|
||||
typedef struct {
|
||||
@@ -363,7 +395,7 @@ typedef struct {
|
||||
uint8_t subindex; /**< PDO entry subindex. */
|
||||
unsigned int *offset; /**< Pointer to a variable to store the PDO entry's
|
||||
(byte-)offset in the process data. */
|
||||
unsigned int *bit_position; /**< Pointer to a variable to store a bit
|
||||
unsigned int *bit_position; /**< Pointer to a variable to store a bit
|
||||
position (0-7) within the \a offset. Can be
|
||||
NULL, in which case an error is raised if the
|
||||
PDO entry does not byte-align. */
|
||||
@@ -409,7 +441,7 @@ extern "C" {
|
||||
unsigned int ecrt_version_magic(void);
|
||||
|
||||
/** Requests an EtherCAT master for realtime operation.
|
||||
*
|
||||
*
|
||||
* Before an application can access an EtherCAT master, it has to reserve one
|
||||
* for exclusive use.
|
||||
*
|
||||
@@ -496,28 +528,19 @@ int ecrt_master_reserve(
|
||||
|
||||
/** Sets the locking callbacks.
|
||||
*
|
||||
* For concurrent master access, i. e. if other instances than the application
|
||||
* want to send and receive datagrams on the bus, the application has to
|
||||
* provide a callback mechanism. This method takes two function pointers as
|
||||
* its parameters. Asynchronous master access (like EoE processing) is only
|
||||
* possible if the callbacks have been set.
|
||||
* For concurrent master access, the application has to provide a locking
|
||||
* mechanism. The method takes two function pointers and a data value as
|
||||
* its parameters.
|
||||
* The arbitrary \a cb_data value will be passed as argument on every callback.
|
||||
*
|
||||
* The task of the send callback (\a send_cb) is to decide, if the bus is
|
||||
* currently accessible and whether or not to call the ecrt_master_send_ext()
|
||||
* method.
|
||||
*
|
||||
* The task of the receive callback (\a receive_cb) is to decide, if a call to
|
||||
* ecrt_master_receive() is allowed and to execute it respectively.
|
||||
*/
|
||||
void ecrt_master_callbacks(
|
||||
ec_master_t *master, /**< EtherCAT master */
|
||||
void (*send_cb)(void *), /**< Datagram sending callback. */
|
||||
void (*receive_cb)(void *), /**< Receive callback. */
|
||||
void *cb_data /**< Arbitraty pointer passed to the callback functions.
|
||||
*/
|
||||
void (*lock_cb)(void *), /**< Lock function. */
|
||||
void (*unlock_cb)(void *), /**< Unlock function. */
|
||||
void *cb_data /**< Arbitrary user data. */
|
||||
);
|
||||
|
||||
|
||||
/** Returns domain structure pointer
|
||||
*
|
||||
* This functions return the domain structure pointer for usage inside the
|
||||
@@ -832,15 +855,6 @@ void ecrt_master_receive(
|
||||
ec_master_t *master /**< EtherCAT master. */
|
||||
);
|
||||
|
||||
/** Sends non-application datagrams.
|
||||
*
|
||||
* This method has to be called in the send callback function passed via
|
||||
* ecrt_master_callbacks() to allow the sending of non-application datagrams.
|
||||
*/
|
||||
void ecrt_master_send_ext(
|
||||
ec_master_t *master /**< EtherCAT master. */
|
||||
);
|
||||
|
||||
/** Reads the current master state.
|
||||
*
|
||||
* Stores the master state information in the given \a state structure.
|
||||
@@ -850,17 +864,29 @@ void ecrt_master_state(
|
||||
ec_master_state_t *state /**< Structure to store the information. */
|
||||
);
|
||||
|
||||
/** Reads the current master state and the al_state of all configured slaves.
|
||||
*
|
||||
* use this function instead of ecrt_master_state if there are unused
|
||||
* slaves on the bus
|
||||
* Stores the master state information in the given \a state structure.
|
||||
* \see ecrt_master_state()
|
||||
*/
|
||||
void ecrt_master_configured_slaves_state(
|
||||
const ec_master_t *master, /**< EtherCAT master. */
|
||||
ec_master_state_t *state /**< Structure to store the information. */
|
||||
);
|
||||
|
||||
/** Sets the application time.
|
||||
*
|
||||
* The master has to know the application's time when operating slaves with
|
||||
* distributed clocks. The time is not incremented by the master itself, so
|
||||
* this method has to be called cyclically.
|
||||
*
|
||||
*
|
||||
* The time is used when setting the slaves' <tt>System Time Offset</tt> and
|
||||
* <tt>Cyclic Operation Start Time</tt> registers and when synchronizing the
|
||||
* DC reference clock to the application time via
|
||||
* ecrt_master_sync_reference_clock().
|
||||
*
|
||||
*
|
||||
* The time is defined as nanoseconds from 2000-01-01 00:00. Converting an
|
||||
* epoch time can be done with the EC_TIMEVAL2NANO() macro.
|
||||
*/
|
||||
@@ -952,6 +978,17 @@ void ecrt_slave_config_watchdog(
|
||||
*/
|
||||
);
|
||||
|
||||
/** Configure wether a slave allows overlapping PDOs.
|
||||
*
|
||||
* Overlapping PDOs allows inputs to use the same space as outputs on the frame.
|
||||
* This reduces the frame length.
|
||||
*/
|
||||
void ecrt_slave_config_overlapping_pdos(
|
||||
ec_slave_config_t *sc, /**< Slave configuration. */
|
||||
uint8_t allow_overlapping_pdos /**< Allow overlapping PDOs */
|
||||
);
|
||||
|
||||
|
||||
/** Add a PDO to a sync manager's PDO assignment.
|
||||
*
|
||||
* \see ecrt_slave_config_pdos()
|
||||
@@ -969,7 +1006,7 @@ int ecrt_slave_config_pdo_assign_add(
|
||||
* This can be called before assigning PDOs via
|
||||
* ecrt_slave_config_pdo_assign_add(), to clear the default assignment of a
|
||||
* sync manager.
|
||||
*
|
||||
*
|
||||
* \see ecrt_slave_config_pdos()
|
||||
*/
|
||||
void ecrt_slave_config_pdo_assign_clear(
|
||||
@@ -1023,28 +1060,28 @@ void ecrt_slave_config_pdo_mapping_clear(
|
||||
* {0x3101, 1, 8}, // status
|
||||
* {0x3101, 2, 16} // value
|
||||
* };
|
||||
*
|
||||
*
|
||||
* ec_pdo_entry_info_t el3162_channel2[] = {
|
||||
* {0x3102, 1, 8}, // status
|
||||
* {0x3102, 2, 16} // value
|
||||
* };
|
||||
*
|
||||
*
|
||||
* ec_pdo_info_t el3162_pdos[] = {
|
||||
* {0x1A00, 2, el3162_channel1},
|
||||
* {0x1A01, 2, el3162_channel2}
|
||||
* };
|
||||
*
|
||||
*
|
||||
* ec_sync_info_t el3162_syncs[] = {
|
||||
* {2, EC_DIR_OUTPUT},
|
||||
* {3, EC_DIR_INPUT, 2, el3162_pdos},
|
||||
* {0xff}
|
||||
* };
|
||||
*
|
||||
*
|
||||
* if (ecrt_slave_config_pdos(sc_ana_in, EC_END, el3162_syncs)) {
|
||||
* // handle error
|
||||
* }
|
||||
* \endcode
|
||||
*
|
||||
*
|
||||
* The next example shows, how to configure the PDO assignment only. The
|
||||
* entries for each assigned PDO are taken from the PDO's default mapping.
|
||||
* Please note, that PDO entry registration will fail, if the PDO
|
||||
@@ -1055,11 +1092,11 @@ void ecrt_slave_config_pdo_mapping_clear(
|
||||
* {0x1600}, // Channel 1
|
||||
* {0x1601} // Channel 2
|
||||
* };
|
||||
*
|
||||
*
|
||||
* ec_sync_info_t syncs[] = {
|
||||
* {3, EC_DIR_INPUT, 2, pdos},
|
||||
* };
|
||||
*
|
||||
*
|
||||
* if (ecrt_slave_config_pdos(slave_config_ana_in, 1, syncs)) {
|
||||
* // handle error
|
||||
* }
|
||||
@@ -1101,7 +1138,7 @@ int ecrt_slave_config_reg_pdo_entry(
|
||||
uint16_t entry_index, /**< Index of the PDO entry to register. */
|
||||
uint8_t entry_subindex, /**< Subindex of the PDO entry to register. */
|
||||
ec_domain_t *domain, /**< Domain. */
|
||||
unsigned int *bit_position /**< Optional address if bit addressing
|
||||
unsigned int *bit_position /**< Optional address if bit addressing
|
||||
is desired */
|
||||
);
|
||||
|
||||
|
||||
+32
-13
@@ -1,11 +1,11 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
*
|
||||
* Copyright (C) 2006-2009 Florian Pose, Ingenieurgemeinschaft IgH
|
||||
*
|
||||
*
|
||||
* This file is part of the IgH EtherCAT master userspace library.
|
||||
*
|
||||
*
|
||||
* The IgH EtherCAT master userspace library is free software; you can
|
||||
* redistribute it and/or modify it under the terms of the GNU Lesser General
|
||||
* Public License as published by the Free Software Foundation; version 2.1
|
||||
@@ -19,9 +19,9 @@
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with the IgH EtherCAT master userspace library. If not, see
|
||||
* <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
* ---
|
||||
*
|
||||
*
|
||||
* The license mentioned above concerns the source code only. Using the
|
||||
* EtherCAT technology and brand is only permitted in compliance with the
|
||||
* industrial property and similar rights of Beckhoff Automation GmbH.
|
||||
@@ -118,12 +118,12 @@ ec_domain_t *ecrt_master_create_domain(ec_master_t *master)
|
||||
fprintf(stderr, "Failed to allocate memory.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
index = ioctl(master->fd, EC_IOCTL_CREATE_DOMAIN, NULL);
|
||||
if (index == -1) {
|
||||
fprintf(stderr, "Failed to create domain: %s\n", strerror(errno));
|
||||
free(domain);
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
domain->next = NULL;
|
||||
@@ -166,17 +166,17 @@ ec_slave_config_t *ecrt_master_slave_config(ec_master_t *master,
|
||||
fprintf(stderr, "Failed to allocate memory.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
data.alias = alias;
|
||||
data.position = position;
|
||||
data.vendor_id = vendor_id;
|
||||
data.product_code = product_code;
|
||||
|
||||
|
||||
if (ioctl(master->fd, EC_IOCTL_CREATE_SLAVE_CONFIG, &data) == -1) {
|
||||
fprintf(stderr, "Failed to create slave config: %s\n",
|
||||
strerror(errno));
|
||||
free(sc);
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
sc->next = NULL;
|
||||
@@ -216,7 +216,7 @@ int ecrt_master_get_slave(ec_master_t *master, uint16_t slave_position,
|
||||
ec_slave_info_t *slave_info)
|
||||
{
|
||||
ec_ioctl_slave_t data;
|
||||
int index;
|
||||
int index, i;
|
||||
|
||||
data.position = slave_position;
|
||||
|
||||
@@ -232,6 +232,15 @@ int ecrt_master_get_slave(ec_master_t *master, uint16_t slave_position,
|
||||
slave_info->serial_number = data.serial_number;
|
||||
slave_info->alias = data.alias;
|
||||
slave_info->current_on_ebus = data.current_on_ebus;
|
||||
for ( i = 0; i < EC_MAX_PORTS; i++ ) {
|
||||
slave_info->ports[i].desc = data.ports[i].desc;
|
||||
slave_info->ports[i].link.link_up = data.ports[i].link.link_up;
|
||||
slave_info->ports[i].link.loop_closed = data.ports[i].link.loop_closed;
|
||||
slave_info->ports[i].link.signal_detected = data.ports[i].link.signal_detected;
|
||||
slave_info->ports[i].receive_time = data.ports[i].receive_time;
|
||||
slave_info->ports[i].next_slave = data.ports[i].next_slave;
|
||||
slave_info->ports[i].delay_to_next_dc = data.ports[i].delay_to_next_dc;
|
||||
}
|
||||
slave_info->al_state = data.al_state;
|
||||
slave_info->error_flag = data.error_flag;
|
||||
slave_info->sync_count = data.sync_count;
|
||||
@@ -455,7 +464,7 @@ int ecrt_master_activate(ec_master_t *master)
|
||||
}
|
||||
|
||||
// Access the mapped region to cause the initial page fault
|
||||
printf("pd: %x\n", master->process_data[0]);
|
||||
memset(master->process_data, 0, master->process_data_size);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -515,6 +524,16 @@ void ecrt_master_state(const ec_master_t *master, ec_master_state_t *state)
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void ecrt_master_configured_slaves_state(const ec_master_t *master,
|
||||
ec_master_state_t *state)
|
||||
{
|
||||
if (ioctl(master->fd, EC_IOCTL_MASTER_SC_STATE, state) == -1) {
|
||||
fprintf(stderr, "Failed to get master state: %s\n", strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void ecrt_master_application_time(ec_master_t *master, uint64_t app_time)
|
||||
{
|
||||
ec_ioctl_app_time_t data;
|
||||
|
||||
+19
-2
@@ -110,6 +110,23 @@ void ecrt_slave_config_watchdog(ec_slave_config_t *sc,
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void ecrt_slave_config_overlapping_pdos(ec_slave_config_t *sc,
|
||||
uint8_t allow_overlapping_pdos)
|
||||
{
|
||||
ec_ioctl_config_t data;
|
||||
|
||||
memset(&data, 0x00, sizeof(ec_ioctl_config_t));
|
||||
data.config_index = sc->index;
|
||||
data.allow_overlapping_pdos = allow_overlapping_pdos;
|
||||
|
||||
if (ioctl(sc->master->fd, EC_IOCTL_SC_OVERLAPPING_IO, &data) == -1) {
|
||||
fprintf(stderr, "Failed to config overlapping PDOs: %s\n",
|
||||
strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
int ecrt_slave_config_pdo_assign_add(ec_slave_config_t *sc,
|
||||
uint8_t sync_index, uint16_t pdo_index)
|
||||
{
|
||||
@@ -415,7 +432,7 @@ ec_sdo_request_t *ecrt_slave_config_create_sdo_request(ec_slave_config_t *sc,
|
||||
if (size) {
|
||||
req->data = malloc(size);
|
||||
if (!req->data) {
|
||||
fprintf(stderr, "Failed to allocate %u bytes of SDO data"
|
||||
fprintf(stderr, "Failed to allocate %zu bytes of SDO data"
|
||||
" memory.\n", size);
|
||||
free(req);
|
||||
return 0;
|
||||
@@ -484,7 +501,7 @@ ec_voe_handler_t *ecrt_slave_config_create_voe_handler(ec_slave_config_t *sc,
|
||||
if (size) {
|
||||
voe->data = malloc(size);
|
||||
if (!voe->data) {
|
||||
fprintf(stderr, "Failed to allocate %u bytes of VoE data"
|
||||
fprintf(stderr, "Failed to allocate %zu bytes of VoE data"
|
||||
" memory.\n", size);
|
||||
free(voe);
|
||||
return 0;
|
||||
|
||||
+500
-444
File diff suppressed because it is too large
Load Diff
@@ -87,13 +87,17 @@ static const char *type_strings[] = {
|
||||
*/
|
||||
void ec_datagram_init(ec_datagram_t *datagram /**< EtherCAT datagram. */)
|
||||
{
|
||||
INIT_LIST_HEAD(&datagram->list); // mark as unqueued
|
||||
INIT_LIST_HEAD(&datagram->queue); // mark as unqueued
|
||||
INIT_LIST_HEAD(&datagram->fsm_queue); // mark as unqueued
|
||||
INIT_LIST_HEAD(&datagram->sent); // mark as unqueued
|
||||
datagram->type = EC_DATAGRAM_NONE;
|
||||
memset(datagram->address, 0x00, EC_ADDR_LEN);
|
||||
datagram->data = NULL;
|
||||
datagram->data_origin = EC_ORIG_INTERNAL;
|
||||
datagram->mem_size = 0;
|
||||
datagram->data_size = 0;
|
||||
datagram->domain = NULL;
|
||||
datagram->index = 0x00;
|
||||
datagram->working_counter = 0x0000;
|
||||
datagram->state = EC_DATAGRAM_INIT;
|
||||
@@ -130,6 +134,9 @@ void ec_datagram_clear(ec_datagram_t *datagram /**< EtherCAT datagram. */)
|
||||
*/
|
||||
void ec_datagram_unqueue(ec_datagram_t *datagram /**< EtherCAT datagram. */)
|
||||
{
|
||||
if (!list_empty(&datagram->fsm_queue)) {
|
||||
list_del_init(&datagram->fsm_queue);
|
||||
}
|
||||
if (!list_empty(&datagram->queue)) {
|
||||
list_del_init(&datagram->queue);
|
||||
}
|
||||
|
||||
+3
-1
@@ -86,7 +86,8 @@ typedef enum {
|
||||
*/
|
||||
typedef struct {
|
||||
struct list_head list; /**< Needed by domain datagram lists. */
|
||||
struct list_head queue; /**< Master datagram queue item. */
|
||||
struct list_head queue; /**< Master datagram send-receive queue item. */
|
||||
struct list_head fsm_queue; /**< Master datagram fsm queue item. */
|
||||
struct list_head sent; /**< Master list item for sent datagrams. */
|
||||
ec_datagram_type_t type; /**< Datagram type (APRD, BWR, etc.). */
|
||||
uint8_t address[EC_ADDR_LEN]; /**< Recipient address. */
|
||||
@@ -94,6 +95,7 @@ typedef struct {
|
||||
ec_origin_t data_origin; /**< Origin of the \a data memory. */
|
||||
size_t mem_size; /**< Datagram \a data memory size. */
|
||||
size_t data_size; /**< Size of the data in \a data. */
|
||||
ec_domain_t *domain; /**< Owning domain (may be null for non-domain datagrams) */
|
||||
uint8_t index; /**< Index (set by master). */
|
||||
uint16_t working_counter; /**< Working counter. */
|
||||
ec_datagram_state_t state; /**< State. */
|
||||
|
||||
+2
-2
@@ -501,9 +501,9 @@ void ecdev_withdraw(ec_device_t *device /**< EtherCAT device */)
|
||||
ec_mac_print(device->dev->dev_addr, str);
|
||||
EC_MASTER_INFO(master, "Releasing main device %s.\n", str);
|
||||
|
||||
down(&master->device_sem);
|
||||
ec_mutex_lock(&master->device_mutex);
|
||||
ec_device_detach(device);
|
||||
up(&master->device_sem);
|
||||
ec_mutex_unlock(&master->device_mutex);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
+8
-4
@@ -60,6 +60,7 @@ void ec_domain_init(
|
||||
domain->index = index;
|
||||
INIT_LIST_HEAD(&domain->fmmu_configs);
|
||||
domain->data_size = 0;
|
||||
domain->tx_size = 0;
|
||||
domain->data = NULL;
|
||||
domain->data_origin = EC_ORIG_INTERNAL;
|
||||
domain->logical_base_address = 0x00000000;
|
||||
@@ -113,6 +114,7 @@ void ec_domain_add_fmmu_config(
|
||||
fmmu->domain = domain;
|
||||
|
||||
domain->data_size += fmmu->data_size;
|
||||
domain->tx_size += fmmu->tx_size;
|
||||
list_add_tail(&fmmu->list, &domain->fmmu_configs);
|
||||
|
||||
EC_MASTER_DBG(domain->master, 1, "Domain %u:"
|
||||
@@ -179,6 +181,7 @@ int ec_domain_add_datagram(
|
||||
|
||||
ec_datagram_zero(datagram);
|
||||
list_add_tail(&datagram->list, &domain->datagrams);
|
||||
datagram->domain = domain;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -238,6 +241,7 @@ int ec_domain_finish(
|
||||
list_for_each_entry(fmmu, &domain->fmmu_configs, list) {
|
||||
// Correct logical FMMU address
|
||||
fmmu->logical_start_address += base_address;
|
||||
fmmu->domain_address += base_address;
|
||||
|
||||
// Increment Input/Output counter to determine datagram types
|
||||
// and calculate expected working counters
|
||||
@@ -249,7 +253,7 @@ int ec_domain_finish(
|
||||
|
||||
// If the current FMMU's data do not fit in the current datagram,
|
||||
// allocate a new one.
|
||||
if (datagram_size + fmmu->data_size > EC_MAX_DATA_SIZE) {
|
||||
if (datagram_size + fmmu->tx_size > EC_MAX_DATA_SIZE) {
|
||||
ret = ec_domain_add_datagram(domain,
|
||||
domain->logical_base_address + datagram_offset,
|
||||
datagram_size, domain->data + datagram_offset,
|
||||
@@ -267,7 +271,7 @@ int ec_domain_finish(
|
||||
}
|
||||
}
|
||||
|
||||
datagram_size += fmmu->data_size;
|
||||
datagram_size += fmmu->tx_size;
|
||||
}
|
||||
|
||||
// Allocate last datagram, if data are left (this is also the case if the
|
||||
@@ -377,14 +381,14 @@ void ecrt_domain_external_memory(ec_domain_t *domain, uint8_t *mem)
|
||||
EC_MASTER_DBG(domain->master, 1, "ecrt_domain_external_memory("
|
||||
"domain = 0x%p, mem = 0x%p)\n", domain, mem);
|
||||
|
||||
down(&domain->master->master_sem);
|
||||
ec_mutex_lock(&domain->master->master_mutex);
|
||||
|
||||
ec_domain_clear_data(domain);
|
||||
|
||||
domain->data = mem;
|
||||
domain->data_origin = EC_ORIG_EXTERNAL;
|
||||
|
||||
up(&domain->master->master_sem);
|
||||
ec_mutex_unlock(&domain->master->master_mutex);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
@@ -59,6 +59,7 @@ struct ec_domain
|
||||
|
||||
struct list_head fmmu_configs; /**< FMMU configurations contained. */
|
||||
size_t data_size; /**< Size of the process data. */
|
||||
size_t tx_size; /**< Size of the transmitted data. */
|
||||
uint8_t *data; /**< Memory for the process data. */
|
||||
ec_origin_t data_origin; /**< Origin of the \a data memory. */
|
||||
uint32_t logical_base_address; /**< Logical offset address of the
|
||||
|
||||
+23
-19
@@ -111,6 +111,7 @@ int ec_eoe_init(
|
||||
eoe->slave = slave;
|
||||
|
||||
ec_datagram_init(&eoe->datagram);
|
||||
ec_mbox_init(&eoe->mbox,&eoe->datagram);
|
||||
eoe->queue_datagram = 0;
|
||||
eoe->state = ec_eoe_state_rx_start;
|
||||
eoe->opened = 0;
|
||||
@@ -122,7 +123,7 @@ int ec_eoe_init(
|
||||
eoe->tx_queue_size = EC_EOE_TX_QUEUE_SIZE;
|
||||
eoe->tx_queued_frames = 0;
|
||||
|
||||
sema_init(&eoe->tx_queue_sem, 1);
|
||||
ec_mutex_init(&eoe->tx_queue_mutex);
|
||||
eoe->tx_frame_number = 0xFF;
|
||||
memset(&eoe->stats, 0, sizeof(struct net_device_stats));
|
||||
|
||||
@@ -220,6 +221,7 @@ void ec_eoe_clear(ec_eoe_t *eoe /**< EoE handler */)
|
||||
|
||||
free_netdev(eoe->dev);
|
||||
|
||||
ec_mbox_clear(&eoe->mbox);
|
||||
ec_datagram_clear(&eoe->datagram);
|
||||
}
|
||||
|
||||
@@ -231,7 +233,7 @@ void ec_eoe_flush(ec_eoe_t *eoe /**< EoE handler */)
|
||||
{
|
||||
ec_eoe_frame_t *frame, *next;
|
||||
|
||||
down(&eoe->tx_queue_sem);
|
||||
ec_mutex_lock(&eoe->tx_queue_mutex);
|
||||
|
||||
list_for_each_entry_safe(frame, next, &eoe->tx_queue, queue) {
|
||||
list_del(&frame->queue);
|
||||
@@ -240,7 +242,7 @@ void ec_eoe_flush(ec_eoe_t *eoe /**< EoE handler */)
|
||||
}
|
||||
eoe->tx_queued_frames = 0;
|
||||
|
||||
up(&eoe->tx_queue_sem);
|
||||
ec_mutex_unlock(&eoe->tx_queue_mutex);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
@@ -294,7 +296,7 @@ int ec_eoe_send(ec_eoe_t *eoe /**< EoE handler */)
|
||||
printk("\n");
|
||||
#endif
|
||||
|
||||
data = ec_slave_mbox_prepare_send(eoe->slave, &eoe->datagram,
|
||||
data = ec_slave_mbox_prepare_send(eoe->slave, &eoe->mbox,
|
||||
0x02, current_size + 4);
|
||||
if (IS_ERR(data))
|
||||
return PTR_ERR(data);
|
||||
@@ -323,7 +325,9 @@ void ec_eoe_run(ec_eoe_t *eoe /**< EoE handler */)
|
||||
return;
|
||||
|
||||
// if the datagram was not sent, or is not yet received, skip this cycle
|
||||
if (eoe->queue_datagram || eoe->datagram.state == EC_DATAGRAM_SENT)
|
||||
if (eoe->queue_datagram ||
|
||||
ec_mbox_is_datagram_state(&eoe->mbox,EC_DATAGRAM_QUEUED) ||
|
||||
ec_mbox_is_datagram_state(&eoe->mbox,EC_DATAGRAM_SENT))
|
||||
return;
|
||||
|
||||
// call state function
|
||||
@@ -348,7 +352,7 @@ void ec_eoe_run(ec_eoe_t *eoe /**< EoE handler */)
|
||||
void ec_eoe_queue(ec_eoe_t *eoe /**< EoE handler */)
|
||||
{
|
||||
if (eoe->queue_datagram) {
|
||||
ec_master_queue_datagram_ext(eoe->slave->master, &eoe->datagram);
|
||||
ec_master_mbox_queue_datagrams(eoe->slave->master, &eoe->mbox);
|
||||
eoe->queue_datagram = 0;
|
||||
}
|
||||
}
|
||||
@@ -394,7 +398,7 @@ void ec_eoe_state_rx_start(ec_eoe_t *eoe /**< EoE handler */)
|
||||
return;
|
||||
}
|
||||
|
||||
ec_slave_mbox_prepare_check(eoe->slave, &eoe->datagram);
|
||||
ec_slave_mbox_prepare_check(eoe->slave, &eoe->mbox);
|
||||
eoe->queue_datagram = 1;
|
||||
eoe->state = ec_eoe_state_rx_check;
|
||||
}
|
||||
@@ -408,7 +412,7 @@ void ec_eoe_state_rx_start(ec_eoe_t *eoe /**< EoE handler */)
|
||||
*/
|
||||
void ec_eoe_state_rx_check(ec_eoe_t *eoe /**< EoE handler */)
|
||||
{
|
||||
if (eoe->datagram.state != EC_DATAGRAM_RECEIVED) {
|
||||
if (!ec_mbox_is_datagram_state(&eoe->mbox,EC_DATAGRAM_RECEIVED)) {
|
||||
eoe->stats.rx_errors++;
|
||||
#if EOE_DEBUG_LEVEL >= 1
|
||||
EC_SLAVE_WARN(eoe->slave, "Failed to receive mbox"
|
||||
@@ -418,14 +422,14 @@ void ec_eoe_state_rx_check(ec_eoe_t *eoe /**< EoE handler */)
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ec_slave_mbox_check(&eoe->datagram)) {
|
||||
if (!ec_slave_mbox_check(&eoe->mbox)) {
|
||||
eoe->rx_idle = 1;
|
||||
eoe->state = ec_eoe_state_tx_start;
|
||||
return;
|
||||
}
|
||||
|
||||
eoe->rx_idle = 0;
|
||||
ec_slave_mbox_prepare_fetch(eoe->slave, &eoe->datagram);
|
||||
ec_slave_mbox_prepare_fetch(eoe->slave, &eoe->mbox);
|
||||
eoe->queue_datagram = 1;
|
||||
eoe->state = ec_eoe_state_rx_fetch;
|
||||
}
|
||||
@@ -447,7 +451,7 @@ void ec_eoe_state_rx_fetch(ec_eoe_t *eoe /**< EoE handler */)
|
||||
unsigned int i;
|
||||
#endif
|
||||
|
||||
if (eoe->datagram.state != EC_DATAGRAM_RECEIVED) {
|
||||
if (!ec_mbox_is_datagram_state(&eoe->mbox,EC_DATAGRAM_RECEIVED)) {
|
||||
eoe->stats.rx_errors++;
|
||||
#if EOE_DEBUG_LEVEL >= 1
|
||||
EC_SLAVE_WARN(eoe->slave, "Failed to receive mbox"
|
||||
@@ -457,7 +461,7 @@ void ec_eoe_state_rx_fetch(ec_eoe_t *eoe /**< EoE handler */)
|
||||
return;
|
||||
}
|
||||
|
||||
data = ec_slave_mbox_fetch(eoe->slave, &eoe->datagram,
|
||||
data = ec_slave_mbox_fetch(eoe->slave, &eoe->mbox,
|
||||
&mbox_prot, &rec_size);
|
||||
if (IS_ERR(data)) {
|
||||
eoe->stats.rx_errors++;
|
||||
@@ -620,10 +624,10 @@ void ec_eoe_state_tx_start(ec_eoe_t *eoe /**< EoE handler */)
|
||||
return;
|
||||
}
|
||||
|
||||
down(&eoe->tx_queue_sem);
|
||||
ec_mutex_lock(&eoe->tx_queue_mutex);
|
||||
|
||||
if (!eoe->tx_queued_frames || list_empty(&eoe->tx_queue)) {
|
||||
up(&eoe->tx_queue_sem);
|
||||
ec_mutex_unlock(&eoe->tx_queue_mutex);
|
||||
eoe->tx_idle = 1;
|
||||
// no data available.
|
||||
// start a new receive immediately.
|
||||
@@ -644,7 +648,7 @@ void ec_eoe_state_tx_start(ec_eoe_t *eoe /**< EoE handler */)
|
||||
}
|
||||
|
||||
eoe->tx_queued_frames--;
|
||||
up(&eoe->tx_queue_sem);
|
||||
ec_mutex_unlock(&eoe->tx_queue_mutex);
|
||||
|
||||
eoe->tx_idle = 0;
|
||||
|
||||
@@ -684,7 +688,7 @@ void ec_eoe_state_tx_start(ec_eoe_t *eoe /**< EoE handler */)
|
||||
*/
|
||||
void ec_eoe_state_tx_sent(ec_eoe_t *eoe /**< EoE handler */)
|
||||
{
|
||||
if (eoe->datagram.state != EC_DATAGRAM_RECEIVED) {
|
||||
if (!ec_mbox_is_datagram_state(&eoe->mbox,EC_DATAGRAM_RECEIVED)) {
|
||||
if (eoe->tries) {
|
||||
eoe->tries--; // try again
|
||||
eoe->queue_datagram = 1;
|
||||
@@ -700,7 +704,7 @@ void ec_eoe_state_tx_sent(ec_eoe_t *eoe /**< EoE handler */)
|
||||
return;
|
||||
}
|
||||
|
||||
if (eoe->datagram.working_counter != 1) {
|
||||
if (!ec_mbox_is_datagram_wc(&eoe->mbox,1)) {
|
||||
if (eoe->tries) {
|
||||
eoe->tries--; // try again
|
||||
eoe->queue_datagram = 1;
|
||||
@@ -812,14 +816,14 @@ int ec_eoedev_tx(struct sk_buff *skb, /**< transmit socket buffer */
|
||||
|
||||
frame->skb = skb;
|
||||
|
||||
down(&eoe->tx_queue_sem);
|
||||
ec_mutex_lock(&eoe->tx_queue_mutex);
|
||||
list_add_tail(&frame->queue, &eoe->tx_queue);
|
||||
eoe->tx_queued_frames++;
|
||||
if (eoe->tx_queued_frames == eoe->tx_queue_size) {
|
||||
netif_stop_queue(dev);
|
||||
eoe->tx_queue_active = 0;
|
||||
}
|
||||
up(&eoe->tx_queue_sem);
|
||||
ec_mutex_unlock(&eoe->tx_queue_mutex);
|
||||
|
||||
#if EOE_DEBUG_LEVEL >= 2
|
||||
EC_SLAVE_DBG(eoe->slave, 0, "EoE %s TX queued frame"
|
||||
|
||||
+2
-1
@@ -73,6 +73,7 @@ struct ec_eoe
|
||||
struct list_head list; /**< list item */
|
||||
ec_slave_t *slave; /**< pointer to the corresponding slave */
|
||||
ec_datagram_t datagram; /**< datagram */
|
||||
ec_mailbox_t mbox; /**< mailbox */
|
||||
unsigned int queue_datagram; /**< the datagram is ready for queuing */
|
||||
void (*state)(ec_eoe_t *); /**< state function for the state machine */
|
||||
struct net_device *dev; /**< net_device for virtual ethernet device */
|
||||
@@ -92,7 +93,7 @@ struct ec_eoe
|
||||
unsigned int tx_queue_size; /**< Transmit queue size. */
|
||||
unsigned int tx_queue_active; /**< kernel netif queue started */
|
||||
unsigned int tx_queued_frames; /**< number of frames in the queue */
|
||||
struct semaphore tx_queue_sem; /**< Semaphore for the send queue. */
|
||||
struct ec_mutex_t tx_queue_mutex; /**< Mutex for the send queue. */
|
||||
ec_eoe_frame_t *tx_frame; /**< current TX frame */
|
||||
uint8_t tx_frame_number; /**< number of the transmitted frame */
|
||||
uint8_t tx_fragment_number; /**< number of the fragment */
|
||||
|
||||
+26
-8
@@ -43,14 +43,12 @@
|
||||
|
||||
/** FMMU configuration constructor.
|
||||
*
|
||||
* Inits an FMMU configuration, sets the logical start address and adds the
|
||||
* process data size for the mapped PDOs of the given direction to the domain
|
||||
* data size.
|
||||
* Inits an FMMU configuration and the process data size forthe mapped PDOs
|
||||
* of the given direction to the domain data size.
|
||||
*/
|
||||
void ec_fmmu_config_init(
|
||||
ec_fmmu_config_t *fmmu, /**< EtherCAT FMMU configuration. */
|
||||
ec_slave_config_t *sc, /**< EtherCAT slave configuration. */
|
||||
ec_domain_t *domain, /**< EtherCAT domain. */
|
||||
uint8_t sync_index, /**< Sync manager index to use. */
|
||||
ec_direction_t dir /**< PDO direction. */
|
||||
)
|
||||
@@ -59,14 +57,32 @@ void ec_fmmu_config_init(
|
||||
fmmu->sc = sc;
|
||||
fmmu->sync_index = sync_index;
|
||||
fmmu->dir = dir;
|
||||
|
||||
fmmu->logical_start_address = domain->data_size;
|
||||
fmmu->data_size = ec_pdo_list_total_size(
|
||||
&sc->sync_configs[sync_index].pdos);
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/** Sets FMMU domain
|
||||
*
|
||||
* Sets the logical start address and the size of the transmitted data
|
||||
*/
|
||||
void ec_fmmu_config_domain(
|
||||
ec_fmmu_config_t *fmmu, /**< EtherCAT FMMU configuration. */
|
||||
ec_domain_t *domain, /**< EtherCAT domain. */
|
||||
uint32_t logical_start_address, /**< FMMU logical start address. */
|
||||
size_t tx_size /**< Size of transmitted data */
|
||||
)
|
||||
{
|
||||
fmmu->domain = domain;
|
||||
fmmu->domain_address = domain->data_size;
|
||||
fmmu->logical_start_address = logical_start_address;
|
||||
fmmu->tx_size = tx_size;
|
||||
ec_domain_add_fmmu_config(domain, fmmu);
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/** Initializes an FMMU configuration page.
|
||||
@@ -79,9 +95,11 @@ void ec_fmmu_config_page(
|
||||
uint8_t *data /**> Configuration page memory. */
|
||||
)
|
||||
{
|
||||
EC_CONFIG_DBG(fmmu->sc, 1, "FMMU: LogAddr 0x%08X, Size %3u,"
|
||||
EC_CONFIG_DBG(fmmu->sc, 1, "FMMU: LogAddr 0x%08X, DomAddr 0x%08X,"
|
||||
" Size %3u, Tx %3u"
|
||||
" PhysAddr 0x%04X, SM%u, Dir %s\n",
|
||||
fmmu->logical_start_address, fmmu->data_size,
|
||||
fmmu->logical_start_address, fmmu->domain_address,
|
||||
fmmu->data_size, fmmu->data_size,
|
||||
sync->physical_start_address, fmmu->sync_index,
|
||||
fmmu->dir == EC_DIR_INPUT ? "in" : "out");
|
||||
|
||||
|
||||
@@ -50,13 +50,18 @@ typedef struct {
|
||||
uint8_t sync_index; /**< Index of sync manager to use. */
|
||||
ec_direction_t dir; /**< FMMU direction. */
|
||||
uint32_t logical_start_address; /**< Logical start address. */
|
||||
size_t tx_size; /**< Transmitted (bus) size. */
|
||||
uint32_t domain_address; /** Domain start address */
|
||||
unsigned int data_size; /**< Covered PDO size. */
|
||||
} ec_fmmu_config_t;
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void ec_fmmu_config_init(ec_fmmu_config_t *, ec_slave_config_t *,
|
||||
ec_domain_t *, uint8_t, ec_direction_t);
|
||||
uint8_t, ec_direction_t);
|
||||
|
||||
void ec_fmmu_config_domain(ec_fmmu_config_t *, ec_domain_t *,
|
||||
uint32_t , size_t);
|
||||
|
||||
void ec_fmmu_config_page(const ec_fmmu_config_t *, const ec_sync_t *,
|
||||
uint8_t *);
|
||||
|
||||
+174
-149
File diff suppressed because it is too large
Load Diff
+3
-2
@@ -39,6 +39,7 @@
|
||||
|
||||
#include "globals.h"
|
||||
#include "datagram.h"
|
||||
#include "mailbox.h"
|
||||
#include "slave.h"
|
||||
#include "sdo.h"
|
||||
#include "sdo_request.h"
|
||||
@@ -51,7 +52,7 @@ typedef struct ec_fsm_coe ec_fsm_coe_t; /**< \see ec_fsm_coe */
|
||||
*/
|
||||
struct ec_fsm_coe {
|
||||
ec_slave_t *slave; /**< slave the FSM runs on */
|
||||
ec_datagram_t *datagram; /**< datagram used in the state machine */
|
||||
ec_mailbox_t *mbox; /**< mailbox used in the state machine */
|
||||
unsigned int retries; /**< retries upon datagram timeout */
|
||||
|
||||
void (*state)(ec_fsm_coe_t *); /**< CoE state function */
|
||||
@@ -67,7 +68,7 @@ struct ec_fsm_coe {
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void ec_fsm_coe_init(ec_fsm_coe_t *, ec_datagram_t *);
|
||||
void ec_fsm_coe_init(ec_fsm_coe_t *, ec_mailbox_t *);
|
||||
void ec_fsm_coe_clear(ec_fsm_coe_t *);
|
||||
|
||||
void ec_fsm_coe_dictionary(ec_fsm_coe_t *, ec_slave_t *);
|
||||
|
||||
+51
-43
@@ -107,11 +107,11 @@ void ec_fsm_foe_read_start(ec_fsm_foe_t *);
|
||||
/** Constructor.
|
||||
*/
|
||||
void ec_fsm_foe_init(ec_fsm_foe_t *fsm, /**< finite state machine */
|
||||
ec_datagram_t *datagram /**< datagram */
|
||||
ec_mailbox_t *mbox /**< mailbox */
|
||||
)
|
||||
{
|
||||
fsm->state = NULL;
|
||||
fsm->datagram = datagram;
|
||||
fsm->state = NULL;
|
||||
fsm->mbox = mbox;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
@@ -207,7 +207,7 @@ int ec_foe_prepare_data_send(ec_fsm_foe_t *fsm)
|
||||
}
|
||||
|
||||
data = ec_slave_mbox_prepare_send(fsm->slave,
|
||||
fsm->datagram, EC_MBOX_TYPE_FILEACCESS,
|
||||
fsm->mbox,EC_MBOX_TYPE_FILEACCESS,
|
||||
current_size + EC_FOE_HEADER_SIZE);
|
||||
if (IS_ERR(data))
|
||||
return -1;
|
||||
@@ -238,7 +238,7 @@ int ec_foe_prepare_wrq_send(ec_fsm_foe_t *fsm)
|
||||
|
||||
current_size = fsm->tx_filename_len;
|
||||
|
||||
data = ec_slave_mbox_prepare_send(fsm->slave, fsm->datagram,
|
||||
data = ec_slave_mbox_prepare_send(fsm->slave, fsm->mbox,
|
||||
EC_MBOX_TYPE_FILEACCESS, current_size + EC_FOE_HEADER_SIZE);
|
||||
if (IS_ERR(data))
|
||||
return -1;
|
||||
@@ -308,21 +308,22 @@ void ec_fsm_foe_state_ack_check(
|
||||
ec_fsm_foe_t *fsm /**< FoE statemachine. */
|
||||
)
|
||||
{
|
||||
ec_datagram_t *datagram = fsm->datagram;
|
||||
ec_mailbox_t *mbox = fsm->mbox;
|
||||
ec_datagram_t *datagram = mbox->datagram;
|
||||
ec_slave_t *slave = fsm->slave;
|
||||
|
||||
#ifdef DEBUG_FOE
|
||||
printk("ec_fsm_foe_ack_check()\n");
|
||||
#endif
|
||||
|
||||
if (datagram->state != EC_DATAGRAM_RECEIVED) {
|
||||
if (!ec_mbox_is_datagram_state(mbox,EC_DATAGRAM_RECEIVED)) {
|
||||
ec_foe_set_rx_error(fsm, FOE_RECEIVE_ERROR);
|
||||
EC_SLAVE_ERR(slave, "Failed to receive FoE mailbox check datagram: ");
|
||||
ec_datagram_print_state(datagram);
|
||||
return;
|
||||
}
|
||||
|
||||
if (datagram->working_counter != 1) {
|
||||
if (!ec_mbox_is_datagram_wc(mbox,1)) {
|
||||
// slave did not put anything in the mailbox yet
|
||||
ec_foe_set_rx_error(fsm, FOE_WC_ERROR);
|
||||
EC_SLAVE_ERR(slave, "Reception of FoE mailbox check datagram"
|
||||
@@ -331,7 +332,7 @@ void ec_fsm_foe_state_ack_check(
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ec_slave_mbox_check(datagram)) {
|
||||
if (!ec_slave_mbox_check(mbox)) {
|
||||
unsigned long diff_ms =
|
||||
(datagram->jiffies_received - fsm->jiffies_start) * 1000 / HZ;
|
||||
if (diff_ms >= EC_FSM_FOE_TIMEOUT) {
|
||||
@@ -340,13 +341,13 @@ void ec_fsm_foe_state_ack_check(
|
||||
return;
|
||||
}
|
||||
|
||||
ec_slave_mbox_prepare_check(slave, datagram); // can not fail.
|
||||
ec_slave_mbox_prepare_check(slave, mbox); // can not fail.
|
||||
fsm->retries = EC_FSM_RETRIES;
|
||||
return;
|
||||
}
|
||||
|
||||
// Fetch response
|
||||
ec_slave_mbox_prepare_fetch(slave, datagram); // can not fail.
|
||||
ec_slave_mbox_prepare_fetch(slave, mbox); // can not fail.
|
||||
|
||||
fsm->retries = EC_FSM_RETRIES;
|
||||
fsm->state = ec_fsm_foe_state_ack_read;
|
||||
@@ -360,7 +361,8 @@ void ec_fsm_foe_state_ack_read(
|
||||
ec_fsm_foe_t *fsm /**< FoE statemachine. */
|
||||
)
|
||||
{
|
||||
ec_datagram_t *datagram = fsm->datagram;
|
||||
ec_mailbox_t *mbox = fsm->mbox;
|
||||
ec_datagram_t *datagram = mbox->datagram;
|
||||
ec_slave_t *slave = fsm->slave;
|
||||
uint8_t *data, mbox_prot;
|
||||
uint8_t opCode;
|
||||
@@ -370,21 +372,21 @@ void ec_fsm_foe_state_ack_read(
|
||||
printk("ec_fsm_foe_ack_read()\n");
|
||||
#endif
|
||||
|
||||
if (datagram->state != EC_DATAGRAM_RECEIVED) {
|
||||
if (!ec_mbox_is_datagram_state(mbox,EC_DATAGRAM_RECEIVED)) {
|
||||
ec_foe_set_rx_error(fsm, FOE_RECEIVE_ERROR);
|
||||
EC_SLAVE_ERR(slave, "Failed to receive FoE ack response datagram: ");
|
||||
ec_datagram_print_state(datagram);
|
||||
return;
|
||||
}
|
||||
|
||||
if (datagram->working_counter != 1) {
|
||||
if (!ec_mbox_is_datagram_wc(mbox,1)) {
|
||||
ec_foe_set_rx_error(fsm, FOE_WC_ERROR);
|
||||
EC_SLAVE_ERR(slave, "Reception of FoE ack response failed: ");
|
||||
ec_datagram_print_wc_error(datagram);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(data = ec_slave_mbox_fetch(fsm->slave, datagram,
|
||||
if (!(data = ec_slave_mbox_fetch(fsm->slave, fsm->mbox,
|
||||
&mbox_prot, &rec_size))) {
|
||||
ec_foe_set_tx_error(fsm, FOE_PROT_ERROR);
|
||||
return;
|
||||
@@ -440,21 +442,22 @@ void ec_fsm_foe_state_wrq_sent(
|
||||
ec_fsm_foe_t *fsm /**< FoE statemachine. */
|
||||
)
|
||||
{
|
||||
ec_datagram_t *datagram = fsm->datagram;
|
||||
ec_mailbox_t *mbox = fsm->mbox;
|
||||
ec_datagram_t *datagram = mbox->datagram;
|
||||
ec_slave_t *slave = fsm->slave;
|
||||
|
||||
#ifdef DEBUG_FOE
|
||||
printk("ec_foe_state_sent_wrq()\n");
|
||||
#endif
|
||||
|
||||
if (datagram->state != EC_DATAGRAM_RECEIVED) {
|
||||
if (!ec_mbox_is_datagram_state(mbox,EC_DATAGRAM_RECEIVED)) {
|
||||
ec_foe_set_rx_error(fsm, FOE_RECEIVE_ERROR);
|
||||
EC_SLAVE_ERR(slave, "Failed to send FoE WRQ: ");
|
||||
ec_datagram_print_state(datagram);
|
||||
return;
|
||||
}
|
||||
|
||||
if (datagram->working_counter != 1) {
|
||||
if (!ec_mbox_is_datagram_wc(mbox,1)) {
|
||||
// slave did not put anything in the mailbox yet
|
||||
ec_foe_set_rx_error(fsm, FOE_WC_ERROR);
|
||||
EC_SLAVE_ERR(slave, "Reception of FoE WRQ failed: ");
|
||||
@@ -464,7 +467,7 @@ void ec_fsm_foe_state_wrq_sent(
|
||||
|
||||
fsm->jiffies_start = datagram->jiffies_sent;
|
||||
|
||||
ec_slave_mbox_prepare_check(fsm->slave, datagram); // can not fail.
|
||||
ec_slave_mbox_prepare_check(fsm->slave, fsm->mbox); // can not fail.
|
||||
|
||||
fsm->retries = EC_FSM_RETRIES;
|
||||
fsm->state = ec_fsm_foe_state_ack_check;
|
||||
@@ -481,28 +484,29 @@ void ec_fsm_foe_state_data_sent(
|
||||
ec_fsm_foe_t *fsm /**< Foe statemachine. */
|
||||
)
|
||||
{
|
||||
ec_datagram_t *datagram = fsm->datagram;
|
||||
ec_mailbox_t *mbox = fsm->mbox;
|
||||
ec_datagram_t *datagram = mbox->datagram;
|
||||
ec_slave_t *slave = fsm->slave;
|
||||
|
||||
#ifdef DEBUG_FOE
|
||||
printk("ec_fsm_foe_state_data_sent()\n");
|
||||
#endif
|
||||
|
||||
if (fsm->datagram->state != EC_DATAGRAM_RECEIVED) {
|
||||
if (!ec_mbox_is_datagram_state(mbox,EC_DATAGRAM_RECEIVED)) {
|
||||
ec_foe_set_tx_error(fsm, FOE_RECEIVE_ERROR);
|
||||
EC_SLAVE_ERR(slave, "Failed to receive FoE ack response datagram: ");
|
||||
ec_datagram_print_state(datagram);
|
||||
return;
|
||||
}
|
||||
|
||||
if (fsm->datagram->working_counter != 1) {
|
||||
if (!ec_mbox_is_datagram_wc(mbox,1)) {
|
||||
ec_foe_set_tx_error(fsm, FOE_WC_ERROR);
|
||||
EC_SLAVE_ERR(slave, "Reception of FoE data send failed: ");
|
||||
ec_datagram_print_wc_error(datagram);
|
||||
return;
|
||||
}
|
||||
|
||||
ec_slave_mbox_prepare_check(fsm->slave, fsm->datagram);
|
||||
ec_slave_mbox_prepare_check(slave, mbox);
|
||||
fsm->jiffies_start = jiffies;
|
||||
fsm->retries = EC_FSM_RETRIES;
|
||||
fsm->state = ec_fsm_foe_state_ack_check;
|
||||
@@ -519,7 +523,7 @@ int ec_foe_prepare_rrq_send(ec_fsm_foe_t *fsm)
|
||||
|
||||
current_size = fsm->rx_filename_len;
|
||||
|
||||
data = ec_slave_mbox_prepare_send(fsm->slave, fsm->datagram,
|
||||
data = ec_slave_mbox_prepare_send(fsm->slave, fsm->mbox,
|
||||
EC_MBOX_TYPE_FILEACCESS, current_size + EC_FOE_HEADER_SIZE);
|
||||
if (IS_ERR(data))
|
||||
return -1;
|
||||
@@ -546,7 +550,7 @@ int ec_foe_prepare_send_ack(
|
||||
{
|
||||
uint8_t *data;
|
||||
|
||||
data = ec_slave_mbox_prepare_send(foe->slave, foe->datagram,
|
||||
data = ec_slave_mbox_prepare_send(foe->slave, foe->mbox,
|
||||
EC_MBOX_TYPE_FILEACCESS, EC_FOE_HEADER_SIZE);
|
||||
if (IS_ERR(data))
|
||||
return -1;
|
||||
@@ -568,21 +572,22 @@ void ec_fsm_foe_state_rrq_sent(
|
||||
ec_fsm_foe_t *fsm /**< FoE statemachine. */
|
||||
)
|
||||
{
|
||||
ec_datagram_t *datagram = fsm->datagram;
|
||||
ec_mailbox_t *mbox = fsm->mbox;
|
||||
ec_datagram_t *datagram = mbox->datagram;
|
||||
ec_slave_t *slave = fsm->slave;
|
||||
|
||||
#ifdef DEBUG_FOE
|
||||
printk("ec_foe_state_rrq_sent()\n");
|
||||
#endif
|
||||
|
||||
if (datagram->state != EC_DATAGRAM_RECEIVED) {
|
||||
if (!ec_mbox_is_datagram_state(mbox,EC_DATAGRAM_RECEIVED)) {
|
||||
ec_foe_set_rx_error(fsm, FOE_RECEIVE_ERROR);
|
||||
EC_SLAVE_ERR(slave, "Failed to send FoE RRQ: ");
|
||||
ec_datagram_print_state(datagram);
|
||||
return;
|
||||
}
|
||||
|
||||
if (datagram->working_counter != 1) {
|
||||
if (!ec_mbox_is_datagram_wc(mbox,1)) {
|
||||
// slave did not put anything in the mailbox yet
|
||||
ec_foe_set_rx_error(fsm, FOE_WC_ERROR);
|
||||
EC_SLAVE_ERR(slave, "Reception of FoE RRQ failed: ");
|
||||
@@ -592,7 +597,7 @@ void ec_fsm_foe_state_rrq_sent(
|
||||
|
||||
fsm->jiffies_start = datagram->jiffies_sent;
|
||||
|
||||
ec_slave_mbox_prepare_check(fsm->slave, datagram); // can not fail.
|
||||
ec_slave_mbox_prepare_check(fsm->slave, fsm->mbox); // can not fail.
|
||||
|
||||
fsm->retries = EC_FSM_RETRIES;
|
||||
fsm->state = ec_fsm_foe_state_data_check;
|
||||
@@ -657,28 +662,29 @@ void ec_fsm_foe_state_data_check(
|
||||
ec_fsm_foe_t *fsm /**< FoE statemachine. */
|
||||
)
|
||||
{
|
||||
ec_datagram_t *datagram = fsm->datagram;
|
||||
ec_mailbox_t *mbox = fsm->mbox;
|
||||
ec_datagram_t *datagram = mbox->datagram;
|
||||
ec_slave_t *slave = fsm->slave;
|
||||
|
||||
#ifdef DEBUG_FOE
|
||||
printk("ec_fsm_foe_state_data_check()\n");
|
||||
#endif
|
||||
|
||||
if (datagram->state != EC_DATAGRAM_RECEIVED) {
|
||||
if (!ec_mbox_is_datagram_state(mbox,EC_DATAGRAM_RECEIVED)) {
|
||||
ec_foe_set_rx_error(fsm, FOE_RECEIVE_ERROR);
|
||||
EC_SLAVE_ERR(slave, "Failed to send FoE DATA READ: ");
|
||||
ec_datagram_print_state(datagram);
|
||||
return;
|
||||
}
|
||||
|
||||
if (datagram->working_counter != 1) {
|
||||
if (!ec_mbox_is_datagram_wc(mbox,1)) {
|
||||
ec_foe_set_rx_error(fsm, FOE_WC_ERROR);
|
||||
EC_SLAVE_ERR(slave, "Reception of FoE DATA READ: ");
|
||||
ec_datagram_print_wc_error(datagram);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ec_slave_mbox_check(datagram)) {
|
||||
if (!ec_slave_mbox_check(mbox)) {
|
||||
unsigned long diff_ms =
|
||||
(datagram->jiffies_received - fsm->jiffies_start) * 1000 / HZ;
|
||||
if (diff_ms >= EC_FSM_FOE_TIMEOUT) {
|
||||
@@ -687,13 +693,13 @@ void ec_fsm_foe_state_data_check(
|
||||
return;
|
||||
}
|
||||
|
||||
ec_slave_mbox_prepare_check(slave, datagram); // can not fail.
|
||||
ec_slave_mbox_prepare_check(slave, mbox); // can not fail.
|
||||
fsm->retries = EC_FSM_RETRIES;
|
||||
return;
|
||||
}
|
||||
|
||||
// Fetch response
|
||||
ec_slave_mbox_prepare_fetch(slave, datagram); // can not fail.
|
||||
ec_slave_mbox_prepare_fetch(slave, mbox); // can not fail.
|
||||
|
||||
fsm->retries = EC_FSM_RETRIES;
|
||||
fsm->state = ec_fsm_foe_state_data_read;
|
||||
@@ -711,28 +717,29 @@ void ec_fsm_foe_state_data_read(
|
||||
size_t rec_size;
|
||||
uint8_t *data, opCode, packet_no, mbox_prot;
|
||||
|
||||
ec_datagram_t *datagram = fsm->datagram;
|
||||
ec_mailbox_t *mbox = fsm->mbox;
|
||||
ec_datagram_t *datagram = mbox->datagram;
|
||||
ec_slave_t *slave = fsm->slave;
|
||||
|
||||
#ifdef DEBUG_FOE
|
||||
printk("ec_fsm_foe_state_data_read()\n");
|
||||
#endif
|
||||
|
||||
if (datagram->state != EC_DATAGRAM_RECEIVED) {
|
||||
if (!ec_mbox_is_datagram_state(mbox,EC_DATAGRAM_RECEIVED)) {
|
||||
ec_foe_set_rx_error(fsm, FOE_RECEIVE_ERROR);
|
||||
EC_SLAVE_ERR(slave, "Failed to receive FoE DATA READ datagram: ");
|
||||
ec_datagram_print_state(datagram);
|
||||
return;
|
||||
}
|
||||
|
||||
if (datagram->working_counter != 1) {
|
||||
if (!ec_mbox_is_datagram_wc(mbox,1)) {
|
||||
ec_foe_set_rx_error(fsm, FOE_WC_ERROR);
|
||||
EC_SLAVE_ERR(slave, "Reception of FoE DATA READ failed: ");
|
||||
ec_datagram_print_wc_error(datagram);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(data = ec_slave_mbox_fetch(slave, datagram, &mbox_prot, &rec_size))) {
|
||||
if (!(data = ec_slave_mbox_fetch(slave, mbox, &mbox_prot, &rec_size))) {
|
||||
ec_foe_set_rx_error(fsm, FOE_MBOX_FETCH_ERROR);
|
||||
return;
|
||||
}
|
||||
@@ -831,21 +838,22 @@ void ec_fsm_foe_state_sent_ack(
|
||||
ec_fsm_foe_t *fsm /**< FoE statemachine. */
|
||||
)
|
||||
{
|
||||
ec_datagram_t *datagram = fsm->datagram;
|
||||
ec_mailbox_t *mbox = fsm->mbox;
|
||||
ec_datagram_t *datagram = mbox->datagram;
|
||||
ec_slave_t *slave = fsm->slave;
|
||||
|
||||
#ifdef DEBUG_FOE
|
||||
printk("ec_foe_state_sent_ack()\n");
|
||||
#endif
|
||||
|
||||
if (datagram->state != EC_DATAGRAM_RECEIVED) {
|
||||
if (!ec_mbox_is_datagram_state(mbox,EC_DATAGRAM_RECEIVED)) {
|
||||
ec_foe_set_rx_error(fsm, FOE_RECEIVE_ERROR);
|
||||
EC_SLAVE_ERR(slave, "Failed to send FoE ACK: ");
|
||||
ec_datagram_print_state(datagram);
|
||||
return;
|
||||
}
|
||||
|
||||
if (datagram->working_counter != 1) {
|
||||
if (!ec_mbox_is_datagram_wc(mbox,1)) {
|
||||
// slave did not put anything into the mailbox yet
|
||||
ec_foe_set_rx_error(fsm, FOE_WC_ERROR);
|
||||
EC_SLAVE_ERR(slave, "Reception of FoE ACK failed: ");
|
||||
@@ -855,7 +863,7 @@ void ec_fsm_foe_state_sent_ack(
|
||||
|
||||
fsm->jiffies_start = datagram->jiffies_sent;
|
||||
|
||||
ec_slave_mbox_prepare_check(fsm->slave, datagram); // can not fail.
|
||||
ec_slave_mbox_prepare_check(fsm->slave, fsm->mbox); // can not fail.
|
||||
|
||||
if (fsm->rx_last_packet) {
|
||||
fsm->rx_expected_packet_no = 0;
|
||||
|
||||
+2
-2
@@ -51,7 +51,7 @@ typedef struct ec_fsm_foe ec_fsm_foe_t; /**< \see ec_fsm_foe */
|
||||
*/
|
||||
struct ec_fsm_foe {
|
||||
ec_slave_t *slave; /**< slave the FSM runs on */
|
||||
ec_datagram_t *datagram; /**< datagram used in the state machine */
|
||||
ec_mailbox_t *mbox; /**< mailbox used in the state machine */
|
||||
unsigned int retries; /**< retries upon datagram timeout */
|
||||
|
||||
void (*state)(ec_fsm_foe_t *); /**< FoE state function */
|
||||
@@ -80,7 +80,7 @@ struct ec_fsm_foe {
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void ec_fsm_foe_init(ec_fsm_foe_t *, ec_datagram_t *);
|
||||
void ec_fsm_foe_init(ec_fsm_foe_t *, ec_mailbox_t *);
|
||||
void ec_fsm_foe_clear(ec_fsm_foe_t *);
|
||||
|
||||
int ec_fsm_foe_exec(ec_fsm_foe_t *);
|
||||
|
||||
+124
-44
@@ -48,7 +48,11 @@
|
||||
|
||||
/** Time difference [ns] to tolerate without setting a new system time offset.
|
||||
*/
|
||||
#ifdef EC_HAVE_CYCLES
|
||||
#define EC_SYSTEM_TIME_TOLERANCE_NS 10000
|
||||
#else
|
||||
#define EC_SYSTEM_TIME_TOLERANCE_NS 100000000
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
@@ -81,6 +85,7 @@ void ec_fsm_master_init(
|
||||
{
|
||||
fsm->master = master;
|
||||
fsm->datagram = datagram;
|
||||
fsm->mbox = &master->fsm_mbox;
|
||||
fsm->state = ec_fsm_master_state_start;
|
||||
fsm->idle = 0;
|
||||
fsm->link_state = 0;
|
||||
@@ -89,7 +94,7 @@ void ec_fsm_master_init(
|
||||
fsm->slave_states = EC_SLAVE_STATE_UNKNOWN;
|
||||
|
||||
// init sub-state-machines
|
||||
ec_fsm_coe_init(&fsm->fsm_coe, fsm->datagram);
|
||||
ec_fsm_coe_init(&fsm->fsm_coe, fsm->mbox);
|
||||
ec_fsm_pdo_init(&fsm->fsm_pdo, &fsm->fsm_coe);
|
||||
ec_fsm_change_init(&fsm->fsm_change, fsm->datagram);
|
||||
ec_fsm_slave_config_init(&fsm->fsm_slave_config, fsm->datagram,
|
||||
@@ -129,12 +134,11 @@ int ec_fsm_master_exec(
|
||||
ec_fsm_master_t *fsm /**< Master state machine. */
|
||||
)
|
||||
{
|
||||
if (fsm->datagram->state == EC_DATAGRAM_SENT
|
||||
|| fsm->datagram->state == EC_DATAGRAM_QUEUED) {
|
||||
if (ec_mbox_is_datagram_state(fsm->mbox,EC_DATAGRAM_QUEUED)
|
||||
|| ec_mbox_is_datagram_state(fsm->mbox,EC_DATAGRAM_SENT)) {
|
||||
// datagram was not sent or received yet.
|
||||
return 0;
|
||||
}
|
||||
|
||||
fsm->state(fsm);
|
||||
return 1;
|
||||
}
|
||||
@@ -211,10 +215,6 @@ void ec_fsm_master_state_broadcast(
|
||||
EC_MASTER_DBG(master, 1, "Master state machine detected "
|
||||
"link down. Clearing slave list.\n");
|
||||
|
||||
#ifdef EC_EOE
|
||||
ec_master_eoe_stop(master);
|
||||
ec_master_clear_eoe_handlers(master);
|
||||
#endif
|
||||
ec_master_clear_slaves(master);
|
||||
fsm->slave_states = 0x00;
|
||||
}
|
||||
@@ -238,12 +238,12 @@ void ec_fsm_master_state_broadcast(
|
||||
}
|
||||
|
||||
if (fsm->rescan_required) {
|
||||
down(&master->scan_sem);
|
||||
ec_mutex_lock(&master->scan_mutex);
|
||||
if (!master->allow_scan) {
|
||||
up(&master->scan_sem);
|
||||
ec_mutex_unlock(&master->scan_mutex);
|
||||
} else {
|
||||
master->scan_busy = 1;
|
||||
up(&master->scan_sem);
|
||||
ec_mutex_unlock(&master->scan_mutex);
|
||||
|
||||
// clear all slaves and scan the bus
|
||||
fsm->rescan_required = 0;
|
||||
@@ -251,7 +251,6 @@ void ec_fsm_master_state_broadcast(
|
||||
fsm->scan_jiffies = jiffies;
|
||||
|
||||
#ifdef EC_EOE
|
||||
ec_master_eoe_stop(master);
|
||||
ec_master_clear_eoe_handlers(master);
|
||||
#endif
|
||||
ec_master_clear_slaves(master);
|
||||
@@ -392,6 +391,7 @@ int ec_fsm_master_action_process_register(
|
||||
"datagram size (%zu)!\n", request->length,
|
||||
fsm->datagram->mem_size);
|
||||
request->state = EC_INT_REQUEST_FAILURE;
|
||||
kref_put(&request->refcount,ec_master_reg_request_release);
|
||||
wake_up(&master->reg_queue);
|
||||
continue;
|
||||
}
|
||||
@@ -571,12 +571,12 @@ void ec_fsm_master_action_configure(
|
||||
|| slave->force_config) && !slave->error_flag) {
|
||||
|
||||
// Start slave configuration, if it is allowed.
|
||||
down(&master->config_sem);
|
||||
ec_mutex_lock(&master->config_mutex);
|
||||
if (!master->allow_config) {
|
||||
up(&master->config_sem);
|
||||
ec_mutex_unlock(&master->config_mutex);
|
||||
} else {
|
||||
master->config_busy = 1;
|
||||
up(&master->config_sem);
|
||||
ec_mutex_unlock(&master->config_mutex);
|
||||
|
||||
if (master->debug_level) {
|
||||
char old_state[EC_STATE_STRING_SIZE],
|
||||
@@ -802,11 +802,6 @@ void ec_fsm_master_state_scan_slave(
|
||||
// Attach slave configurations
|
||||
ec_master_attach_slave_configs(master);
|
||||
|
||||
#ifdef EC_EOE
|
||||
// check if EoE processing has to be started
|
||||
ec_master_eoe_start(master);
|
||||
#endif
|
||||
|
||||
if (master->slave_count) {
|
||||
fsm->slave = master->slaves; // begin with first slave
|
||||
ec_fsm_master_enter_write_system_times(fsm);
|
||||
@@ -889,26 +884,27 @@ u64 ec_fsm_master_dc_offset32(
|
||||
ec_fsm_master_t *fsm, /**< Master state machine. */
|
||||
u64 system_time, /**< System time register. */
|
||||
u64 old_offset, /**< Time offset register. */
|
||||
unsigned long jiffies_since_read /**< Jiffies for correction. */
|
||||
u64 correction /**< Correction. */
|
||||
)
|
||||
{
|
||||
ec_slave_t *slave = fsm->slave;
|
||||
u32 correction, system_time32, old_offset32, new_offset;
|
||||
u32 correction32, system_time32, old_offset32, new_offset;
|
||||
s32 time_diff;
|
||||
|
||||
system_time32 = (u32) system_time;
|
||||
old_offset32 = (u32) old_offset;
|
||||
system_time32 = (u32) system_time;
|
||||
// correct read system time by elapsed time between read operation
|
||||
// and app_time set time
|
||||
correction32 = (u32)correction;
|
||||
system_time32 -= correction32;
|
||||
old_offset32 = (u32) old_offset;
|
||||
|
||||
// correct read system time by elapsed time since read operation
|
||||
correction = jiffies_since_read * 1000 / HZ * 1000000;
|
||||
system_time32 += correction;
|
||||
time_diff = (u32) slave->master->app_time - system_time32;
|
||||
time_diff = (u32) slave->master->app_start_time - system_time32;
|
||||
|
||||
EC_SLAVE_DBG(slave, 1, "DC system time offset calculation:"
|
||||
" system_time=%u (corrected with %u),"
|
||||
" app_time=%llu, diff=%i\n",
|
||||
system_time32, correction,
|
||||
slave->master->app_time, time_diff);
|
||||
" app_start_time=%llu, diff=%i\n",
|
||||
system_time32, correction32,
|
||||
slave->master->app_start_time, time_diff);
|
||||
|
||||
if (EC_ABS(time_diff) > EC_SYSTEM_TIME_TOLERANCE_NS) {
|
||||
new_offset = time_diff + old_offset32;
|
||||
@@ -929,23 +925,23 @@ u64 ec_fsm_master_dc_offset64(
|
||||
ec_fsm_master_t *fsm, /**< Master state machine. */
|
||||
u64 system_time, /**< System time register. */
|
||||
u64 old_offset, /**< Time offset register. */
|
||||
unsigned long jiffies_since_read /**< Jiffies for correction. */
|
||||
u64 correction /**< Correction. */
|
||||
)
|
||||
{
|
||||
ec_slave_t *slave = fsm->slave;
|
||||
u64 new_offset, correction;
|
||||
u64 new_offset;
|
||||
s64 time_diff;
|
||||
|
||||
// correct read system time by elapsed time since read operation
|
||||
correction = (u64) (jiffies_since_read * 1000 / HZ) * 1000000;
|
||||
system_time += correction;
|
||||
time_diff = fsm->slave->master->app_time - system_time;
|
||||
// correct read system time by elapsed time between read operation
|
||||
// and app_time set time
|
||||
system_time -= correction;
|
||||
time_diff = fsm->slave->master->app_start_time - system_time;
|
||||
|
||||
EC_SLAVE_DBG(slave, 1, "DC system time offset calculation:"
|
||||
" system_time=%llu (corrected with %llu),"
|
||||
" app_time=%llu, diff=%lli\n",
|
||||
" app_start_time=%llu, diff=%lli\n",
|
||||
system_time, correction,
|
||||
slave->master->app_time, time_diff);
|
||||
slave->master->app_start_time, time_diff);
|
||||
|
||||
if (EC_ABS(time_diff) > EC_SYSTEM_TIME_TOLERANCE_NS) {
|
||||
new_offset = time_diff + old_offset;
|
||||
@@ -969,8 +965,7 @@ void ec_fsm_master_state_dc_read_offset(
|
||||
{
|
||||
ec_datagram_t *datagram = fsm->datagram;
|
||||
ec_slave_t *slave = fsm->slave;
|
||||
u64 system_time, old_offset, new_offset;
|
||||
unsigned long jiffies_since_read;
|
||||
u64 system_time, old_offset, new_offset, correction;
|
||||
|
||||
if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
|
||||
return;
|
||||
@@ -993,14 +988,25 @@ void ec_fsm_master_state_dc_read_offset(
|
||||
|
||||
system_time = EC_READ_U64(datagram->data); // 0x0910
|
||||
old_offset = EC_READ_U64(datagram->data + 16); // 0x0920
|
||||
jiffies_since_read = jiffies - datagram->jiffies_sent;
|
||||
/* correct read system time by elapsed time since read operation
|
||||
and the app_time set time */
|
||||
#ifdef EC_HAVE_CYCLES
|
||||
correction =
|
||||
(datagram->cycles_sent - slave->master->dc_cycles_app_start_time)
|
||||
* 1000000LL;
|
||||
do_div(correction,cpu_khz);
|
||||
#else
|
||||
correction =
|
||||
(u64) ((datagram->jiffies_sent-slave->master->dc_jiffies_app_start_time) * 1000 / HZ)
|
||||
* 1000000;
|
||||
#endif
|
||||
|
||||
if (slave->base_dc_range == EC_DC_32) {
|
||||
new_offset = ec_fsm_master_dc_offset32(fsm,
|
||||
system_time, old_offset, jiffies_since_read);
|
||||
system_time, old_offset, correction);
|
||||
} else {
|
||||
new_offset = ec_fsm_master_dc_offset64(fsm,
|
||||
system_time, old_offset, jiffies_since_read);
|
||||
system_time, old_offset, correction);
|
||||
}
|
||||
|
||||
// set DC system time offset and transmission delay
|
||||
@@ -1063,6 +1069,7 @@ void ec_fsm_master_state_write_sii(
|
||||
if (!ec_fsm_sii_success(&fsm->fsm_sii)) {
|
||||
EC_SLAVE_ERR(slave, "Failed to write SII data.\n");
|
||||
request->state = EC_INT_REQUEST_FAILURE;
|
||||
kref_put(&request->refcount,ec_master_sii_write_request_release);
|
||||
wake_up(&master->sii_queue);
|
||||
ec_fsm_master_restart(fsm);
|
||||
return;
|
||||
@@ -1091,6 +1098,7 @@ void ec_fsm_master_state_write_sii(
|
||||
// TODO: Evaluate other SII contents!
|
||||
|
||||
request->state = EC_INT_REQUEST_SUCCESS;
|
||||
kref_put(&request->refcount,ec_master_sii_write_request_release);
|
||||
wake_up(&master->sii_queue);
|
||||
|
||||
// check for another SII write request
|
||||
@@ -1184,6 +1192,7 @@ void ec_fsm_master_state_reg_request(
|
||||
" request datagram: ");
|
||||
ec_datagram_print_state(datagram);
|
||||
request->state = EC_INT_REQUEST_FAILURE;
|
||||
kref_put(&request->refcount,ec_master_reg_request_release);
|
||||
wake_up(&master->reg_queue);
|
||||
ec_fsm_master_restart(fsm);
|
||||
return;
|
||||
@@ -1198,6 +1207,7 @@ void ec_fsm_master_state_reg_request(
|
||||
EC_MASTER_ERR(master, "Failed to allocate %zu bytes"
|
||||
" of memory for register data.\n", request->length);
|
||||
request->state = EC_INT_REQUEST_FAILURE;
|
||||
kref_put(&request->refcount,ec_master_reg_request_release);
|
||||
wake_up(&master->reg_queue);
|
||||
ec_fsm_master_restart(fsm);
|
||||
return;
|
||||
@@ -1212,6 +1222,7 @@ void ec_fsm_master_state_reg_request(
|
||||
EC_MASTER_ERR(master, "Register request failed.\n");
|
||||
}
|
||||
|
||||
kref_put(&request->refcount,ec_master_reg_request_release);
|
||||
wake_up(&master->reg_queue);
|
||||
|
||||
// check for another register request
|
||||
@@ -1222,3 +1233,72 @@ void ec_fsm_master_state_reg_request(
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/** called by kref_put if the SII write request's refcount becomes zero.
|
||||
*
|
||||
*/
|
||||
void ec_master_sii_write_request_release(struct kref *ref)
|
||||
{
|
||||
ec_sii_write_request_t *request = container_of(ref, ec_sii_write_request_t, refcount);
|
||||
if (request->slave)
|
||||
EC_SLAVE_DBG(request->slave, 1, "Releasing SII write request %p.\n",request);
|
||||
kfree(request->words);
|
||||
kfree(request);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/** called by kref_put if the reg request's refcount becomes zero.
|
||||
*
|
||||
*/
|
||||
void ec_master_reg_request_release(struct kref *ref)
|
||||
{
|
||||
ec_reg_request_t *request = container_of(ref, ec_reg_request_t, refcount);
|
||||
if (request->slave)
|
||||
EC_SLAVE_DBG(request->slave, 1, "Releasing reg request %p.\n",request);
|
||||
if (request->data)
|
||||
kfree(request->data);
|
||||
kfree(request);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/** called by kref_put if the SDO request's refcount becomes zero.
|
||||
*
|
||||
*/
|
||||
void ec_master_sdo_request_release(struct kref *ref)
|
||||
{
|
||||
ec_master_sdo_request_t *request = container_of(ref, ec_master_sdo_request_t, refcount);
|
||||
if (request->slave)
|
||||
EC_SLAVE_DBG(request->slave, 1, "Releasing SDO request %p.\n",request);
|
||||
ec_sdo_request_clear(&request->req);
|
||||
kfree(request);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/** called by kref_put if the FoE request's refcount becomes zero.
|
||||
*
|
||||
*/
|
||||
void ec_master_foe_request_release(struct kref *ref)
|
||||
{
|
||||
ec_master_foe_request_t *request = container_of(ref, ec_master_foe_request_t, refcount);
|
||||
if (request->slave)
|
||||
EC_SLAVE_DBG(request->slave, 1, "Releasing FoE request %p.\n",request);
|
||||
ec_foe_request_clear(&request->req);
|
||||
kfree(request);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/** called by kref_put if the SoE request's refcount becomes zero.
|
||||
*
|
||||
*/
|
||||
void ec_master_soe_request_release(struct kref *ref)
|
||||
{
|
||||
ec_master_soe_request_t *request = container_of(ref, ec_master_soe_request_t, refcount);
|
||||
if (request->slave)
|
||||
EC_SLAVE_DBG(request->slave, 1, "Releasing SoE request %p.\n",request);
|
||||
ec_soe_request_clear(&request->req);
|
||||
kfree(request);
|
||||
}
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
|
||||
#include "globals.h"
|
||||
#include "datagram.h"
|
||||
#include "mailbox.h"
|
||||
#include "foe_request.h"
|
||||
#include "sdo_request.h"
|
||||
#include "soe_request.h"
|
||||
@@ -57,8 +58,11 @@ typedef struct {
|
||||
size_t nwords; /**< Number of words. */
|
||||
const uint16_t *words; /**< Pointer to the data words. */
|
||||
ec_internal_request_state_t state; /**< State of the request. */
|
||||
struct kref refcount;
|
||||
} ec_sii_write_request_t;
|
||||
|
||||
void ec_master_sii_write_request_release(struct kref *);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/** Register request.
|
||||
@@ -71,8 +75,11 @@ typedef struct {
|
||||
size_t length; /**< Number of bytes. */
|
||||
uint8_t *data; /**< Data to write / memory for read data. */
|
||||
ec_internal_request_state_t state; /**< State of the request. */
|
||||
struct kref refcount;
|
||||
} ec_reg_request_t;
|
||||
|
||||
void ec_master_reg_request_release(struct kref *);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/** Slave/SDO request record for master's SDO request list.
|
||||
@@ -81,8 +88,11 @@ typedef struct {
|
||||
struct list_head list; /**< List element. */
|
||||
ec_slave_t *slave; /**< Slave. */
|
||||
ec_sdo_request_t req; /**< SDO request. */
|
||||
struct kref refcount;
|
||||
} ec_master_sdo_request_t;
|
||||
|
||||
void ec_master_sdo_request_release(struct kref *);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/** FoE request.
|
||||
@@ -91,8 +101,11 @@ typedef struct {
|
||||
struct list_head list; /**< List head. */
|
||||
ec_slave_t *slave; /**< EtherCAT slave. */
|
||||
ec_foe_request_t req; /**< FoE request. */
|
||||
struct kref refcount;
|
||||
} ec_master_foe_request_t;
|
||||
|
||||
void ec_master_foe_request_release(struct kref *);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/** SoE request.
|
||||
@@ -101,8 +114,11 @@ typedef struct {
|
||||
struct list_head list; /**< List head. */
|
||||
ec_slave_t *slave; /**< EtherCAT slave. */
|
||||
ec_soe_request_t req; /**< SoE request. */
|
||||
struct kref refcount;
|
||||
} ec_master_soe_request_t;
|
||||
|
||||
void ec_master_soe_request_release(struct kref *);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
typedef struct ec_fsm_master ec_fsm_master_t; /**< \see ec_fsm_master */
|
||||
@@ -112,6 +128,7 @@ typedef struct ec_fsm_master ec_fsm_master_t; /**< \see ec_fsm_master */
|
||||
struct ec_fsm_master {
|
||||
ec_master_t *master; /**< master the FSM runs on */
|
||||
ec_datagram_t *datagram; /**< datagram used in the state machine */
|
||||
ec_mailbox_t* mbox; /**< mailbox used in the CoE state machine */
|
||||
unsigned int retries; /**< retries on datagram timeout. */
|
||||
|
||||
void (*state)(ec_fsm_master_t *); /**< master state function */
|
||||
|
||||
+62
-49
@@ -57,21 +57,21 @@ void ec_fsm_slave_state_soe_request(ec_fsm_slave_t *);
|
||||
void ec_fsm_slave_init(
|
||||
ec_fsm_slave_t *fsm, /**< Slave state machine. */
|
||||
ec_slave_t *slave, /**< EtherCAT slave. */
|
||||
ec_datagram_t *datagram /**< Datagram object to use. */
|
||||
ec_mailbox_t *mbox/**< Datagram object to use. */
|
||||
)
|
||||
{
|
||||
fsm->slave = slave;
|
||||
fsm->datagram = datagram;
|
||||
fsm->datagram->data_size = 0;
|
||||
fsm->mbox = mbox;
|
||||
slave->datagram.data_size = 0;
|
||||
|
||||
EC_SLAVE_DBG(slave, 1, "Init FSM.\n");
|
||||
|
||||
fsm->state = ec_fsm_slave_state_idle;
|
||||
|
||||
// init sub-state-machines
|
||||
ec_fsm_coe_init(&fsm->fsm_coe, fsm->datagram);
|
||||
ec_fsm_foe_init(&fsm->fsm_foe, fsm->datagram);
|
||||
ec_fsm_soe_init(&fsm->fsm_soe, fsm->datagram);
|
||||
ec_fsm_coe_init(&fsm->fsm_coe, fsm->mbox);
|
||||
ec_fsm_foe_init(&fsm->fsm_foe, fsm->mbox);
|
||||
ec_fsm_soe_init(&fsm->fsm_soe, fsm->mbox);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
@@ -94,19 +94,21 @@ void ec_fsm_slave_clear(
|
||||
*
|
||||
* If the state machine's datagram is not sent or received yet, the execution
|
||||
* of the state machine is delayed to the next cycle.
|
||||
*
|
||||
* \return true, if the state machine was executed
|
||||
*/
|
||||
void ec_fsm_slave_exec(
|
||||
int ec_fsm_slave_exec(
|
||||
ec_fsm_slave_t *fsm /**< Slave state machine. */
|
||||
)
|
||||
{
|
||||
if (fsm->datagram->state == EC_DATAGRAM_SENT
|
||||
|| fsm->datagram->state == EC_DATAGRAM_QUEUED) {
|
||||
if (ec_mbox_is_datagram_state(fsm->mbox,EC_DATAGRAM_QUEUED)
|
||||
|| ec_mbox_is_datagram_state(fsm->mbox,EC_DATAGRAM_SENT)) {
|
||||
// datagram was not sent or received yet.
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
||||
fsm->state(fsm);
|
||||
return;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
@@ -176,9 +178,10 @@ int ec_fsm_slave_action_process_sdo(
|
||||
|
||||
list_del_init(&request->list); // dequeue
|
||||
if (slave->current_state & EC_SLAVE_STATE_ACK_ERR) {
|
||||
EC_SLAVE_WARN(slave, "Aborting SDO request,"
|
||||
" slave has error flag set.\n");
|
||||
EC_SLAVE_WARN(slave, "Aborting SDO request %p,"
|
||||
" slave has error flag set.\n",request);
|
||||
request->req.state = EC_INT_REQUEST_FAILURE;
|
||||
kref_put(&request->refcount,ec_master_sdo_request_release);
|
||||
wake_up(&slave->sdo_queue);
|
||||
fsm->sdo_request = NULL;
|
||||
fsm->state = ec_fsm_slave_state_idle;
|
||||
@@ -186,8 +189,9 @@ int ec_fsm_slave_action_process_sdo(
|
||||
}
|
||||
|
||||
if (slave->current_state == EC_SLAVE_STATE_INIT) {
|
||||
EC_SLAVE_WARN(slave, "Aborting SDO request, slave is in INIT.\n");
|
||||
EC_SLAVE_WARN(slave, "Aborting SDO request %p, slave is in INIT.\n",request);
|
||||
request->req.state = EC_INT_REQUEST_FAILURE;
|
||||
kref_put(&request->refcount,ec_master_sdo_request_release);
|
||||
wake_up(&slave->sdo_queue);
|
||||
fsm->sdo_request = NULL;
|
||||
fsm->state = ec_fsm_slave_state_idle;
|
||||
@@ -197,14 +201,14 @@ int ec_fsm_slave_action_process_sdo(
|
||||
request->req.state = EC_INT_REQUEST_BUSY;
|
||||
|
||||
// Found pending SDO request. Execute it!
|
||||
EC_SLAVE_DBG(slave, 1, "Processing SDO request...\n");
|
||||
EC_SLAVE_DBG(slave, 1, "Processing SDO request %p...\n",request);
|
||||
|
||||
// Start SDO transfer
|
||||
fsm->sdo_request = &request->req;
|
||||
fsm->sdo_request = request;
|
||||
fsm->state = ec_fsm_slave_state_sdo_request;
|
||||
ec_fsm_coe_transfer(&fsm->fsm_coe, slave, &request->req);
|
||||
ec_fsm_coe_exec(&fsm->fsm_coe); // execute immediately
|
||||
ec_master_queue_external_datagram(fsm->slave->master,fsm->datagram);
|
||||
ec_slave_mbox_queue_datagrams(slave, fsm->mbox);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
@@ -219,26 +223,28 @@ void ec_fsm_slave_state_sdo_request(
|
||||
)
|
||||
{
|
||||
ec_slave_t *slave = fsm->slave;
|
||||
ec_sdo_request_t *request = fsm->sdo_request;
|
||||
ec_master_sdo_request_t *request = fsm->sdo_request;
|
||||
|
||||
if (ec_fsm_coe_exec(&fsm->fsm_coe))
|
||||
{
|
||||
ec_master_queue_external_datagram(fsm->slave->master,fsm->datagram);
|
||||
ec_slave_mbox_queue_datagrams(slave, fsm->mbox);
|
||||
return;
|
||||
}
|
||||
if (!ec_fsm_coe_success(&fsm->fsm_coe)) {
|
||||
EC_SLAVE_ERR(slave, "Failed to process SDO request.\n");
|
||||
request->state = EC_INT_REQUEST_FAILURE;
|
||||
EC_SLAVE_ERR(slave, "Failed to process SDO request %p.\n",request);
|
||||
request->req.state = EC_INT_REQUEST_FAILURE;
|
||||
kref_put(&request->refcount,ec_master_sdo_request_release);
|
||||
wake_up(&slave->sdo_queue);
|
||||
fsm->sdo_request = NULL;
|
||||
fsm->state = ec_fsm_slave_state_idle;
|
||||
return;
|
||||
}
|
||||
|
||||
EC_SLAVE_DBG(slave, 1, "Finished SDO request.\n");
|
||||
EC_SLAVE_DBG(slave, 1, "Finished SDO request %p.\n",request);
|
||||
|
||||
// SDO request finished
|
||||
request->state = EC_INT_REQUEST_SUCCESS;
|
||||
request->req.state = EC_INT_REQUEST_SUCCESS;
|
||||
kref_put(&request->refcount,ec_master_sdo_request_release);
|
||||
wake_up(&slave->sdo_queue);
|
||||
|
||||
fsm->sdo_request = NULL;
|
||||
@@ -261,10 +267,11 @@ int ec_fsm_slave_action_process_foe(
|
||||
// search the first request to be processed
|
||||
list_for_each_entry_safe(request, next, &slave->foe_requests, list) {
|
||||
if (slave->current_state & EC_SLAVE_STATE_ACK_ERR) {
|
||||
EC_SLAVE_WARN(slave, "Aborting FOE request,"
|
||||
" slave has error flag set.\n");
|
||||
EC_SLAVE_WARN(slave, "Aborting FOE request %p,"
|
||||
" slave has error flag set.\n",request);
|
||||
request->req.state = EC_INT_REQUEST_FAILURE;
|
||||
wake_up(&slave->sdo_queue);
|
||||
kref_put(&request->refcount,ec_master_foe_request_release);
|
||||
wake_up(&slave->foe_queue);
|
||||
fsm->sdo_request = NULL;
|
||||
fsm->state = ec_fsm_slave_state_idle;
|
||||
return 0;
|
||||
@@ -272,13 +279,13 @@ int ec_fsm_slave_action_process_foe(
|
||||
list_del_init(&request->list); // dequeue
|
||||
request->req.state = EC_INT_REQUEST_BUSY;
|
||||
|
||||
EC_SLAVE_DBG(slave, 1, "Processing FoE request.\n");
|
||||
EC_SLAVE_DBG(slave, 1, "Processing FoE request %p.\n",request);
|
||||
|
||||
fsm->foe_request = &request->req;
|
||||
fsm->foe_request = request;
|
||||
fsm->state = ec_fsm_slave_state_foe_request;
|
||||
ec_fsm_foe_transfer(&fsm->fsm_foe, slave, &request->req);
|
||||
ec_fsm_foe_exec(&fsm->fsm_foe);
|
||||
ec_master_queue_external_datagram(fsm->slave->master,fsm->datagram);
|
||||
ec_slave_mbox_queue_datagrams(slave, fsm->mbox);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
@@ -293,17 +300,18 @@ void ec_fsm_slave_state_foe_request(
|
||||
)
|
||||
{
|
||||
ec_slave_t *slave = fsm->slave;
|
||||
ec_foe_request_t *request = fsm->foe_request;
|
||||
ec_master_foe_request_t *request = fsm->foe_request;
|
||||
|
||||
if (ec_fsm_foe_exec(&fsm->fsm_foe))
|
||||
{
|
||||
ec_master_queue_external_datagram(fsm->slave->master,fsm->datagram);
|
||||
ec_slave_mbox_queue_datagrams(slave, fsm->mbox);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ec_fsm_foe_success(&fsm->fsm_foe)) {
|
||||
EC_SLAVE_ERR(slave, "Failed to handle FoE request.\n");
|
||||
request->state = EC_INT_REQUEST_FAILURE;
|
||||
EC_SLAVE_ERR(slave, "Failed to handle FoE request %p.\n",request);
|
||||
request->req.state = EC_INT_REQUEST_FAILURE;
|
||||
kref_put(&request->refcount,ec_master_foe_request_release);
|
||||
wake_up(&slave->foe_queue);
|
||||
fsm->foe_request = NULL;
|
||||
fsm->state = ec_fsm_slave_state_idle;
|
||||
@@ -311,10 +319,11 @@ void ec_fsm_slave_state_foe_request(
|
||||
}
|
||||
|
||||
// finished transferring FoE
|
||||
EC_SLAVE_DBG(slave, 1, "Successfully transferred %zu bytes of FoE"
|
||||
" data.\n", request->data_size);
|
||||
EC_SLAVE_DBG(slave, 1, "FoE request %p successfully transferred %zu bytes.\n",
|
||||
request,request->req.data_size);
|
||||
|
||||
request->state = EC_INT_REQUEST_SUCCESS;
|
||||
request->req.state = EC_INT_REQUEST_SUCCESS;
|
||||
kref_put(&request->refcount,ec_master_foe_request_release);
|
||||
wake_up(&slave->foe_queue);
|
||||
|
||||
fsm->foe_request = NULL;
|
||||
@@ -332,16 +341,17 @@ int ec_fsm_slave_action_process_soe(
|
||||
)
|
||||
{
|
||||
ec_slave_t *slave = fsm->slave;
|
||||
ec_master_soe_request_t *req, *next;
|
||||
ec_master_soe_request_t *request, *next;
|
||||
|
||||
// search the first request to be processed
|
||||
list_for_each_entry_safe(req, next, &slave->soe_requests, list) {
|
||||
list_for_each_entry_safe(request, next, &slave->soe_requests, list) {
|
||||
|
||||
list_del_init(&req->list); // dequeue
|
||||
list_del_init(&request->list); // dequeue
|
||||
if (slave->current_state & EC_SLAVE_STATE_ACK_ERR) {
|
||||
EC_SLAVE_WARN(slave, "Aborting SoE request,"
|
||||
" slave has error flag set.\n");
|
||||
req->req.state = EC_INT_REQUEST_FAILURE;
|
||||
request->req.state = EC_INT_REQUEST_FAILURE;
|
||||
kref_put(&request->refcount,ec_master_soe_request_release);
|
||||
wake_up(&slave->soe_queue);
|
||||
fsm->state = ec_fsm_slave_state_idle;
|
||||
return 0;
|
||||
@@ -349,23 +359,24 @@ int ec_fsm_slave_action_process_soe(
|
||||
|
||||
if (slave->current_state == EC_SLAVE_STATE_INIT) {
|
||||
EC_SLAVE_WARN(slave, "Aborting SoE request, slave is in INIT.\n");
|
||||
req->req.state = EC_INT_REQUEST_FAILURE;
|
||||
request->req.state = EC_INT_REQUEST_FAILURE;
|
||||
kref_put(&request->refcount,ec_master_soe_request_release);
|
||||
wake_up(&slave->soe_queue);
|
||||
fsm->state = ec_fsm_slave_state_idle;
|
||||
return 0;
|
||||
}
|
||||
|
||||
req->req.state = EC_INT_REQUEST_BUSY;
|
||||
request->req.state = EC_INT_REQUEST_BUSY;
|
||||
|
||||
// Found pending request. Execute it!
|
||||
EC_SLAVE_DBG(slave, 1, "Processing SoE request...\n");
|
||||
|
||||
// Start SoE transfer
|
||||
fsm->soe_request = &req->req;
|
||||
fsm->soe_request = request;
|
||||
fsm->state = ec_fsm_slave_state_soe_request;
|
||||
ec_fsm_soe_transfer(&fsm->fsm_soe, slave, &req->req);
|
||||
ec_fsm_soe_transfer(&fsm->fsm_soe, slave, &request->req);
|
||||
ec_fsm_soe_exec(&fsm->fsm_soe); // execute immediately
|
||||
ec_master_queue_external_datagram(fsm->slave->master, fsm->datagram);
|
||||
ec_slave_mbox_queue_datagrams(slave, fsm->mbox);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
@@ -380,16 +391,17 @@ void ec_fsm_slave_state_soe_request(
|
||||
)
|
||||
{
|
||||
ec_slave_t *slave = fsm->slave;
|
||||
ec_soe_request_t *request = fsm->soe_request;
|
||||
ec_master_soe_request_t *request = fsm->soe_request;
|
||||
|
||||
if (ec_fsm_soe_exec(&fsm->fsm_soe)) {
|
||||
ec_master_queue_external_datagram(fsm->slave->master, fsm->datagram);
|
||||
ec_slave_mbox_queue_datagrams(slave, fsm->mbox);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ec_fsm_soe_success(&fsm->fsm_soe)) {
|
||||
EC_SLAVE_ERR(slave, "Failed to process SoE request.\n");
|
||||
request->state = EC_INT_REQUEST_FAILURE;
|
||||
request->req.state = EC_INT_REQUEST_FAILURE;
|
||||
kref_put(&request->refcount,ec_master_soe_request_release);
|
||||
wake_up(&slave->soe_queue);
|
||||
fsm->soe_request = NULL;
|
||||
fsm->state = ec_fsm_slave_state_idle;
|
||||
@@ -399,7 +411,8 @@ void ec_fsm_slave_state_soe_request(
|
||||
EC_SLAVE_DBG(slave, 1, "Finished SoE request.\n");
|
||||
|
||||
// SoE request finished
|
||||
request->state = EC_INT_REQUEST_SUCCESS;
|
||||
request->req.state = EC_INT_REQUEST_SUCCESS;
|
||||
kref_put(&request->refcount,ec_master_soe_request_release);
|
||||
wake_up(&slave->soe_queue);
|
||||
|
||||
fsm->soe_request = NULL;
|
||||
|
||||
+7
-6
@@ -42,6 +42,7 @@
|
||||
#include "fsm_coe.h"
|
||||
#include "fsm_foe.h"
|
||||
#include "fsm_soe.h"
|
||||
#include "fsm_master.h"
|
||||
|
||||
typedef struct ec_fsm_slave ec_fsm_slave_t; /**< \see ec_fsm_slave */
|
||||
|
||||
@@ -49,13 +50,13 @@ typedef struct ec_fsm_slave ec_fsm_slave_t; /**< \see ec_fsm_slave */
|
||||
*/
|
||||
struct ec_fsm_slave {
|
||||
ec_slave_t *slave; /**< slave the FSM runs on */
|
||||
ec_datagram_t *datagram; /**< datagram used in the state machine */
|
||||
ec_mailbox_t *mbox; /**< mailbox used in the state machine */
|
||||
|
||||
void (*state)(ec_fsm_slave_t *); /**< master state function */
|
||||
ec_sdo_request_t *sdo_request; /**< SDO request to process. */
|
||||
ec_foe_request_t *foe_request; /**< FoE request to process. */
|
||||
ec_master_sdo_request_t *sdo_request; /**< SDO request to process. */
|
||||
ec_master_foe_request_t *foe_request; /**< FoE request to process. */
|
||||
off_t foe_index; /**< index to FoE write request data */
|
||||
ec_soe_request_t *soe_request; /**< SoE request to process. */
|
||||
ec_master_soe_request_t *soe_request; /**< SoE request to process. */
|
||||
|
||||
ec_fsm_coe_t fsm_coe; /**< CoE state machine */
|
||||
ec_fsm_foe_t fsm_foe; /**< FoE state machine */
|
||||
@@ -64,10 +65,10 @@ struct ec_fsm_slave {
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void ec_fsm_slave_init(ec_fsm_slave_t *, ec_slave_t *, ec_datagram_t *);
|
||||
void ec_fsm_slave_init(ec_fsm_slave_t *, ec_slave_t *, ec_mailbox_t *);
|
||||
void ec_fsm_slave_clear(ec_fsm_slave_t *);
|
||||
|
||||
void ec_fsm_slave_exec(ec_fsm_slave_t *);
|
||||
int ec_fsm_slave_exec(ec_fsm_slave_t *);
|
||||
void ec_fsm_slave_ready(ec_fsm_slave_t *);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
@@ -177,8 +177,8 @@ int ec_fsm_slave_config_exec(
|
||||
ec_fsm_slave_config_t *fsm /**< slave state machine */
|
||||
)
|
||||
{
|
||||
if (fsm->datagram->state == EC_DATAGRAM_SENT
|
||||
|| fsm->datagram->state == EC_DATAGRAM_QUEUED) {
|
||||
if (fsm->datagram->state == EC_DATAGRAM_QUEUED
|
||||
|| fsm->datagram->state == EC_DATAGRAM_SENT) {
|
||||
// datagram was not sent or received yet.
|
||||
return ec_fsm_slave_config_running(fsm);
|
||||
}
|
||||
@@ -738,8 +738,7 @@ void ec_fsm_slave_config_enter_soe_conf_preop(
|
||||
ec_soe_request_write(&fsm->soe_request_copy);
|
||||
ec_fsm_soe_transfer(fsm_soe, fsm->slave, &fsm->soe_request_copy);
|
||||
ec_fsm_soe_exec(fsm_soe); // execute immediately
|
||||
ec_master_queue_external_datagram(slave->master,
|
||||
fsm_soe->datagram);
|
||||
ec_slave_mbox_queue_datagrams(slave, fsm_soe->mbox);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -760,7 +759,7 @@ void ec_fsm_slave_config_state_soe_conf_preop(
|
||||
ec_fsm_soe_t *fsm_soe = &slave->fsm.fsm_soe;
|
||||
|
||||
if (ec_fsm_soe_exec(fsm_soe)) {
|
||||
ec_master_queue_external_datagram(slave->master, fsm_soe->datagram);
|
||||
ec_slave_mbox_queue_datagrams(slave, fsm_soe->mbox);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -785,8 +784,7 @@ void ec_fsm_slave_config_state_soe_conf_preop(
|
||||
ec_soe_request_write(&fsm->soe_request_copy);
|
||||
ec_fsm_soe_transfer(fsm_soe, fsm->slave, &fsm->soe_request_copy);
|
||||
ec_fsm_soe_exec(fsm_soe); // execute immediately
|
||||
ec_master_queue_external_datagram(slave->master,
|
||||
fsm_soe->datagram);
|
||||
ec_slave_mbox_queue_datagrams(slave, fsm_soe->mbox);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -1248,7 +1246,7 @@ void ec_fsm_slave_config_state_dc_sync_check(
|
||||
abs_sync_diff = EC_READ_U32(datagram->data) & 0x7fffffff;
|
||||
diff_ms = (datagram->jiffies_received - fsm->jiffies_start) * 1000 / HZ;
|
||||
|
||||
if (abs_sync_diff > EC_DC_MAX_SYNC_DIFF_NS) {
|
||||
if (abs_sync_diff > EC_DC_MAX_SYNC_DIFF_NS) {
|
||||
|
||||
if (diff_ms >= EC_DC_SYNC_WAIT_MS) {
|
||||
EC_SLAVE_WARN(slave, "Slave did not sync after %lu ms.\n",
|
||||
@@ -1454,8 +1452,7 @@ void ec_fsm_slave_config_enter_soe_conf_safeop(
|
||||
ec_soe_request_write(&fsm->soe_request_copy);
|
||||
ec_fsm_soe_transfer(fsm_soe, fsm->slave, &fsm->soe_request_copy);
|
||||
ec_fsm_soe_exec(fsm_soe); // execute immediately
|
||||
ec_master_queue_external_datagram(slave->master,
|
||||
fsm_soe->datagram);
|
||||
ec_slave_mbox_queue_datagrams(slave, fsm_soe->mbox);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -1476,7 +1473,7 @@ void ec_fsm_slave_config_state_soe_conf_safeop(
|
||||
ec_fsm_soe_t *fsm_soe = &slave->fsm.fsm_soe;
|
||||
|
||||
if (ec_fsm_soe_exec(fsm_soe)) {
|
||||
ec_master_queue_external_datagram(slave->master, fsm_soe->datagram);
|
||||
ec_slave_mbox_queue_datagrams(slave, fsm_soe->mbox);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1501,8 +1498,7 @@ void ec_fsm_slave_config_state_soe_conf_safeop(
|
||||
ec_soe_request_write(&fsm->soe_request_copy);
|
||||
ec_fsm_soe_transfer(fsm_soe, fsm->slave, &fsm->soe_request_copy);
|
||||
ec_fsm_soe_exec(fsm_soe); // execute immediately
|
||||
ec_master_queue_external_datagram(slave->master,
|
||||
fsm_soe->datagram);
|
||||
ec_slave_mbox_queue_datagrams(slave, fsm_soe->mbox);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -137,8 +137,8 @@ int ec_fsm_slave_scan_running(const ec_fsm_slave_scan_t *fsm /**< slave state ma
|
||||
|
||||
int ec_fsm_slave_scan_exec(ec_fsm_slave_scan_t *fsm /**< slave state machine */)
|
||||
{
|
||||
if (fsm->datagram->state == EC_DATAGRAM_SENT
|
||||
|| fsm->datagram->state == EC_DATAGRAM_QUEUED) {
|
||||
if (fsm->datagram->state == EC_DATAGRAM_QUEUED
|
||||
|| fsm->datagram->state == EC_DATAGRAM_SENT) {
|
||||
// datagram was not sent or received yet.
|
||||
return ec_fsm_slave_scan_running(fsm);
|
||||
}
|
||||
|
||||
+60
-60
@@ -106,11 +106,11 @@ void ec_print_soe_error(const ec_slave_t *slave, uint16_t error_code)
|
||||
*/
|
||||
void ec_fsm_soe_init(
|
||||
ec_fsm_soe_t *fsm, /**< finite state machine */
|
||||
ec_datagram_t *datagram /**< datagram */
|
||||
ec_mailbox_t *mbox /**< mailbox */
|
||||
)
|
||||
{
|
||||
fsm->state = NULL;
|
||||
fsm->datagram = datagram;
|
||||
fsm->mbox = mbox;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
@@ -195,7 +195,7 @@ void ec_fsm_soe_print_error(ec_fsm_soe_t *fsm /**< Finite state machine */)
|
||||
*/
|
||||
void ec_fsm_soe_read_start(ec_fsm_soe_t *fsm /**< finite state machine */)
|
||||
{
|
||||
ec_datagram_t *datagram = fsm->datagram;
|
||||
ec_mailbox_t *mbox = fsm->mbox;
|
||||
ec_slave_t *slave = fsm->slave;
|
||||
ec_master_t *master = slave->master;
|
||||
ec_soe_request_t *request = fsm->request;
|
||||
@@ -211,7 +211,7 @@ void ec_fsm_soe_read_start(ec_fsm_soe_t *fsm /**< finite state machine */)
|
||||
return;
|
||||
}
|
||||
|
||||
data = ec_slave_mbox_prepare_send(slave, datagram, EC_MBOX_TYPE_SOE,
|
||||
data = ec_slave_mbox_prepare_send(slave, mbox, EC_MBOX_TYPE_SOE,
|
||||
EC_SOE_SIZE);
|
||||
if (IS_ERR(data)) {
|
||||
fsm->state = ec_fsm_soe_error;
|
||||
@@ -240,25 +240,25 @@ void ec_fsm_soe_read_start(ec_fsm_soe_t *fsm /**< finite state machine */)
|
||||
*/
|
||||
void ec_fsm_soe_read_request(ec_fsm_soe_t *fsm /**< finite state machine */)
|
||||
{
|
||||
ec_datagram_t *datagram = fsm->datagram;
|
||||
ec_mailbox_t *mbox = fsm->mbox;
|
||||
ec_slave_t *slave = fsm->slave;
|
||||
unsigned long diff_ms;
|
||||
|
||||
if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
|
||||
if (ec_mbox_is_datagram_state(mbox,EC_DATAGRAM_TIMED_OUT) && fsm->retries--)
|
||||
return; // FIXME: check for response first?
|
||||
|
||||
if (datagram->state != EC_DATAGRAM_RECEIVED) {
|
||||
if (!ec_mbox_is_datagram_state(mbox,EC_DATAGRAM_RECEIVED)) {
|
||||
fsm->state = ec_fsm_soe_error;
|
||||
EC_SLAVE_ERR(slave, "Failed to receive SoE read request: ");
|
||||
ec_datagram_print_state(datagram);
|
||||
ec_datagram_print_state(mbox->datagram);
|
||||
ec_fsm_soe_print_error(fsm);
|
||||
return;
|
||||
}
|
||||
|
||||
diff_ms = (jiffies - fsm->request->jiffies_sent) * 1000 / HZ;
|
||||
|
||||
if (datagram->working_counter != 1) {
|
||||
if (!datagram->working_counter) {
|
||||
if (!ec_mbox_is_datagram_wc(mbox,1)) {
|
||||
if (ec_mbox_is_datagram_wc(mbox,0)) {
|
||||
if (diff_ms < EC_SOE_RESPONSE_TIMEOUT) {
|
||||
// no response; send request datagram again
|
||||
return;
|
||||
@@ -267,13 +267,13 @@ void ec_fsm_soe_read_request(ec_fsm_soe_t *fsm /**< finite state machine */)
|
||||
fsm->state = ec_fsm_soe_error;
|
||||
EC_SLAVE_ERR(slave, "Reception of SoE read request"
|
||||
" failed after %lu ms: ", diff_ms);
|
||||
ec_datagram_print_wc_error(datagram);
|
||||
ec_datagram_print_wc_error(mbox->datagram);
|
||||
ec_fsm_soe_print_error(fsm);
|
||||
return;
|
||||
}
|
||||
|
||||
fsm->jiffies_start = datagram->jiffies_sent;
|
||||
ec_slave_mbox_prepare_check(slave, datagram); // can not fail.
|
||||
fsm->jiffies_start = mbox->datagram->jiffies_sent;
|
||||
ec_slave_mbox_prepare_check(slave, mbox); // can not fail.
|
||||
fsm->retries = EC_FSM_RETRIES;
|
||||
fsm->state = ec_fsm_soe_read_check;
|
||||
}
|
||||
@@ -284,32 +284,32 @@ void ec_fsm_soe_read_request(ec_fsm_soe_t *fsm /**< finite state machine */)
|
||||
*/
|
||||
void ec_fsm_soe_read_check(ec_fsm_soe_t *fsm /**< finite state machine */)
|
||||
{
|
||||
ec_datagram_t *datagram = fsm->datagram;
|
||||
ec_mailbox_t *mbox = fsm->mbox;
|
||||
ec_slave_t *slave = fsm->slave;
|
||||
|
||||
if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
|
||||
if (ec_mbox_is_datagram_state(mbox,EC_DATAGRAM_TIMED_OUT) && fsm->retries--)
|
||||
return;
|
||||
|
||||
if (datagram->state != EC_DATAGRAM_RECEIVED) {
|
||||
if (!ec_mbox_is_datagram_state(mbox,EC_DATAGRAM_RECEIVED)) {
|
||||
fsm->state = ec_fsm_soe_error;
|
||||
EC_SLAVE_ERR(slave, "Failed to receive SoE mailbox check datagram: ");
|
||||
ec_datagram_print_state(datagram);
|
||||
ec_datagram_print_state(mbox->datagram);
|
||||
ec_fsm_soe_print_error(fsm);
|
||||
return;
|
||||
}
|
||||
|
||||
if (datagram->working_counter != 1) {
|
||||
if (!ec_mbox_is_datagram_wc(mbox,1)) {
|
||||
fsm->state = ec_fsm_soe_error;
|
||||
EC_SLAVE_ERR(slave, "Reception of SoE mailbox check"
|
||||
" datagram failed: ");
|
||||
ec_datagram_print_wc_error(datagram);
|
||||
ec_datagram_print_wc_error(mbox->datagram);
|
||||
ec_fsm_soe_print_error(fsm);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ec_slave_mbox_check(datagram)) {
|
||||
if (!ec_slave_mbox_check(mbox)) {
|
||||
unsigned long diff_ms =
|
||||
(datagram->jiffies_received - fsm->jiffies_start) * 1000 / HZ;
|
||||
(mbox->datagram->jiffies_received - fsm->jiffies_start) * 1000 / HZ;
|
||||
if (diff_ms >= EC_SOE_RESPONSE_TIMEOUT) {
|
||||
fsm->state = ec_fsm_soe_error;
|
||||
EC_SLAVE_ERR(slave, "Timeout after %lu ms while waiting for"
|
||||
@@ -318,13 +318,13 @@ void ec_fsm_soe_read_check(ec_fsm_soe_t *fsm /**< finite state machine */)
|
||||
return;
|
||||
}
|
||||
|
||||
ec_slave_mbox_prepare_check(slave, datagram); // can not fail.
|
||||
ec_slave_mbox_prepare_check(slave, mbox); // can not fail.
|
||||
fsm->retries = EC_FSM_RETRIES;
|
||||
return;
|
||||
}
|
||||
|
||||
// Fetch response
|
||||
ec_slave_mbox_prepare_fetch(slave, datagram); // can not fail.
|
||||
ec_slave_mbox_prepare_fetch(slave, mbox); // can not fail.
|
||||
fsm->retries = EC_FSM_RETRIES;
|
||||
fsm->state = ec_fsm_soe_read_response;
|
||||
}
|
||||
@@ -335,7 +335,7 @@ void ec_fsm_soe_read_check(ec_fsm_soe_t *fsm /**< finite state machine */)
|
||||
*/
|
||||
void ec_fsm_soe_read_response(ec_fsm_soe_t *fsm /**< finite state machine */)
|
||||
{
|
||||
ec_datagram_t *datagram = fsm->datagram;
|
||||
ec_mailbox_t *mbox = fsm->mbox;
|
||||
ec_slave_t *slave = fsm->slave;
|
||||
ec_master_t *master = slave->master;
|
||||
uint8_t *data, mbox_prot, header, opcode, incomplete, error_flag,
|
||||
@@ -343,26 +343,26 @@ void ec_fsm_soe_read_response(ec_fsm_soe_t *fsm /**< finite state machine */)
|
||||
size_t rec_size, data_size;
|
||||
ec_soe_request_t *req = fsm->request;
|
||||
|
||||
if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
|
||||
if (ec_mbox_is_datagram_state(mbox,EC_DATAGRAM_TIMED_OUT) && fsm->retries--)
|
||||
return; // FIXME: request again?
|
||||
|
||||
if (datagram->state != EC_DATAGRAM_RECEIVED) {
|
||||
if (!ec_mbox_is_datagram_state(mbox,EC_DATAGRAM_RECEIVED)) {
|
||||
fsm->state = ec_fsm_soe_error;
|
||||
EC_SLAVE_ERR(slave, "Failed to receive SoE read response datagram: ");
|
||||
ec_datagram_print_state(datagram);
|
||||
ec_datagram_print_state(mbox->datagram);
|
||||
ec_fsm_soe_print_error(fsm);
|
||||
return;
|
||||
}
|
||||
|
||||
if (datagram->working_counter != 1) {
|
||||
if (!ec_mbox_is_datagram_wc(mbox,1)) {
|
||||
fsm->state = ec_fsm_soe_error;
|
||||
EC_SLAVE_ERR(slave, "Reception of SoE read response failed: ");
|
||||
ec_datagram_print_wc_error(datagram);
|
||||
ec_datagram_print_wc_error(mbox->datagram);
|
||||
ec_fsm_soe_print_error(fsm);
|
||||
return;
|
||||
}
|
||||
|
||||
data = ec_slave_mbox_fetch(slave, datagram, &mbox_prot, &rec_size);
|
||||
data = ec_slave_mbox_fetch(slave, mbox, &mbox_prot, &rec_size);
|
||||
if (IS_ERR(data)) {
|
||||
fsm->state = ec_fsm_soe_error;
|
||||
ec_fsm_soe_print_error(fsm);
|
||||
@@ -435,8 +435,8 @@ void ec_fsm_soe_read_response(ec_fsm_soe_t *fsm /**< finite state machine */)
|
||||
if (incomplete) {
|
||||
EC_SLAVE_DBG(slave, 1, "SoE data incomplete. Waiting for fragment"
|
||||
" at offset %zu.\n", req->data_size);
|
||||
fsm->jiffies_start = datagram->jiffies_sent;
|
||||
ec_slave_mbox_prepare_check(slave, datagram); // can not fail.
|
||||
fsm->jiffies_start = mbox->datagram->jiffies_sent;
|
||||
ec_slave_mbox_prepare_check(slave, mbox); // can not fail.
|
||||
fsm->retries = EC_FSM_RETRIES;
|
||||
fsm->state = ec_fsm_soe_read_check;
|
||||
} else {
|
||||
@@ -459,7 +459,7 @@ void ec_fsm_soe_write_next_fragment(
|
||||
ec_fsm_soe_t *fsm /**< finite state machine */
|
||||
)
|
||||
{
|
||||
ec_datagram_t *datagram = fsm->datagram;
|
||||
ec_mailbox_t *mbox = fsm->mbox;
|
||||
ec_slave_t *slave = fsm->slave;
|
||||
ec_master_t *master = slave->master;
|
||||
ec_soe_request_t *req = fsm->request;
|
||||
@@ -485,7 +485,7 @@ void ec_fsm_soe_write_next_fragment(
|
||||
fragments_left++;
|
||||
}
|
||||
|
||||
data = ec_slave_mbox_prepare_send(slave, datagram, EC_MBOX_TYPE_SOE,
|
||||
data = ec_slave_mbox_prepare_send(slave, mbox, EC_MBOX_TYPE_SOE,
|
||||
EC_SOE_SIZE + fragment_size);
|
||||
if (IS_ERR(data)) {
|
||||
fsm->state = ec_fsm_soe_error;
|
||||
@@ -539,25 +539,25 @@ void ec_fsm_soe_write_start(ec_fsm_soe_t *fsm /**< finite state machine */)
|
||||
*/
|
||||
void ec_fsm_soe_write_request(ec_fsm_soe_t *fsm /**< finite state machine */)
|
||||
{
|
||||
ec_datagram_t *datagram = fsm->datagram;
|
||||
ec_mailbox_t *mbox = fsm->mbox;
|
||||
ec_slave_t *slave = fsm->slave;
|
||||
unsigned long diff_ms;
|
||||
|
||||
if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
|
||||
if (ec_mbox_is_datagram_state(mbox,EC_DATAGRAM_TIMED_OUT) && fsm->retries--)
|
||||
return; // FIXME: check for response first?
|
||||
|
||||
if (datagram->state != EC_DATAGRAM_RECEIVED) {
|
||||
if (!ec_mbox_is_datagram_state(mbox,EC_DATAGRAM_RECEIVED)) {
|
||||
fsm->state = ec_fsm_soe_error;
|
||||
EC_SLAVE_ERR(slave, "Failed to receive SoE write request: ");
|
||||
ec_datagram_print_state(datagram);
|
||||
ec_datagram_print_state(mbox->datagram);
|
||||
ec_fsm_soe_print_error(fsm);
|
||||
return;
|
||||
}
|
||||
|
||||
diff_ms = (jiffies - fsm->request->jiffies_sent) * 1000 / HZ;
|
||||
|
||||
if (datagram->working_counter != 1) {
|
||||
if (!datagram->working_counter) {
|
||||
if (!ec_mbox_is_datagram_wc(mbox,1)) {
|
||||
if (ec_mbox_is_datagram_wc(mbox,0)) {
|
||||
if (diff_ms < EC_SOE_RESPONSE_TIMEOUT) {
|
||||
// no response; send request datagram again
|
||||
return;
|
||||
@@ -566,14 +566,14 @@ void ec_fsm_soe_write_request(ec_fsm_soe_t *fsm /**< finite state machine */)
|
||||
fsm->state = ec_fsm_soe_error;
|
||||
EC_SLAVE_ERR(slave, "Reception of SoE write request"
|
||||
" failed after %lu ms: ", diff_ms);
|
||||
ec_datagram_print_wc_error(datagram);
|
||||
ec_datagram_print_wc_error(mbox->datagram);
|
||||
ec_fsm_soe_print_error(fsm);
|
||||
return;
|
||||
}
|
||||
|
||||
fsm->jiffies_start = datagram->jiffies_sent;
|
||||
fsm->jiffies_start = mbox->datagram->jiffies_sent;
|
||||
|
||||
ec_slave_mbox_prepare_check(slave, datagram); // can not fail.
|
||||
ec_slave_mbox_prepare_check(slave, mbox); // can not fail.
|
||||
fsm->retries = EC_FSM_RETRIES;
|
||||
fsm->state = ec_fsm_soe_write_check;
|
||||
}
|
||||
@@ -584,25 +584,25 @@ void ec_fsm_soe_write_request(ec_fsm_soe_t *fsm /**< finite state machine */)
|
||||
*/
|
||||
void ec_fsm_soe_write_check(ec_fsm_soe_t *fsm /**< finite state machine */)
|
||||
{
|
||||
ec_datagram_t *datagram = fsm->datagram;
|
||||
ec_mailbox_t *mbox = fsm->mbox;
|
||||
ec_slave_t *slave = fsm->slave;
|
||||
ec_soe_request_t *req = fsm->request;
|
||||
|
||||
if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
|
||||
if (ec_mbox_is_datagram_state(mbox,EC_DATAGRAM_TIMED_OUT) && fsm->retries--)
|
||||
return;
|
||||
|
||||
if (datagram->state != EC_DATAGRAM_RECEIVED) {
|
||||
if (!ec_mbox_is_datagram_state(mbox,EC_DATAGRAM_RECEIVED)) {
|
||||
fsm->state = ec_fsm_soe_error;
|
||||
EC_SLAVE_ERR(slave, "Failed to receive SoE write request datagram: ");
|
||||
ec_datagram_print_state(datagram);
|
||||
ec_datagram_print_state(mbox->datagram);
|
||||
ec_fsm_soe_print_error(fsm);
|
||||
return;
|
||||
}
|
||||
|
||||
if (datagram->working_counter != 1) {
|
||||
if (!ec_mbox_is_datagram_wc(mbox,1)) {
|
||||
fsm->state = ec_fsm_soe_error;
|
||||
EC_SLAVE_ERR(slave, "Reception of SoE write request datagram: ");
|
||||
ec_datagram_print_wc_error(datagram);
|
||||
ec_datagram_print_wc_error(mbox->datagram);
|
||||
ec_fsm_soe_print_error(fsm);
|
||||
return;
|
||||
}
|
||||
@@ -610,9 +610,9 @@ void ec_fsm_soe_write_check(ec_fsm_soe_t *fsm /**< finite state machine */)
|
||||
if (fsm->offset < req->data_size) {
|
||||
ec_fsm_soe_write_next_fragment(fsm);
|
||||
} else {
|
||||
if (!ec_slave_mbox_check(datagram)) {
|
||||
if (!ec_slave_mbox_check(mbox)) {
|
||||
unsigned long diff_ms =
|
||||
(datagram->jiffies_received - fsm->jiffies_start) * 1000 / HZ;
|
||||
(mbox->datagram->jiffies_received - fsm->jiffies_start) * 1000 / HZ;
|
||||
if (diff_ms >= EC_SOE_RESPONSE_TIMEOUT) {
|
||||
fsm->state = ec_fsm_soe_error;
|
||||
EC_SLAVE_ERR(slave, "Timeout after %lu ms while waiting"
|
||||
@@ -621,13 +621,13 @@ void ec_fsm_soe_write_check(ec_fsm_soe_t *fsm /**< finite state machine */)
|
||||
return;
|
||||
}
|
||||
|
||||
ec_slave_mbox_prepare_check(slave, datagram); // can not fail.
|
||||
ec_slave_mbox_prepare_check(slave, mbox); // can not fail.
|
||||
fsm->retries = EC_FSM_RETRIES;
|
||||
return;
|
||||
}
|
||||
|
||||
// Fetch response
|
||||
ec_slave_mbox_prepare_fetch(slave, datagram); // can not fail.
|
||||
ec_slave_mbox_prepare_fetch(slave, mbox); // can not fail.
|
||||
fsm->retries = EC_FSM_RETRIES;
|
||||
fsm->state = ec_fsm_soe_write_response;
|
||||
}
|
||||
@@ -639,7 +639,7 @@ void ec_fsm_soe_write_check(ec_fsm_soe_t *fsm /**< finite state machine */)
|
||||
*/
|
||||
void ec_fsm_soe_write_response(ec_fsm_soe_t *fsm /**< finite state machine */)
|
||||
{
|
||||
ec_datagram_t *datagram = fsm->datagram;
|
||||
ec_mailbox_t *mbox = fsm->mbox;
|
||||
ec_slave_t *slave = fsm->slave;
|
||||
ec_master_t *master = slave->master;
|
||||
ec_soe_request_t *req = fsm->request;
|
||||
@@ -647,27 +647,27 @@ void ec_fsm_soe_write_response(ec_fsm_soe_t *fsm /**< finite state machine */)
|
||||
uint16_t idn;
|
||||
size_t rec_size;
|
||||
|
||||
if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
|
||||
if (ec_mbox_is_datagram_state(mbox,EC_DATAGRAM_TIMED_OUT) && fsm->retries--)
|
||||
return; // FIXME: request again?
|
||||
|
||||
if (datagram->state != EC_DATAGRAM_RECEIVED) {
|
||||
if (!ec_mbox_is_datagram_state(mbox,EC_DATAGRAM_RECEIVED)) {
|
||||
fsm->state = ec_fsm_soe_error;
|
||||
EC_SLAVE_ERR(slave, "Failed to receive SoE write"
|
||||
" response datagram: ");
|
||||
ec_datagram_print_state(datagram);
|
||||
ec_datagram_print_state(mbox->datagram);
|
||||
ec_fsm_soe_print_error(fsm);
|
||||
return;
|
||||
}
|
||||
|
||||
if (datagram->working_counter != 1) {
|
||||
if (!ec_mbox_is_datagram_wc(mbox,1)) {
|
||||
fsm->state = ec_fsm_soe_error;
|
||||
EC_SLAVE_ERR(slave, "Reception of SoE write response failed: ");
|
||||
ec_datagram_print_wc_error(datagram);
|
||||
ec_datagram_print_wc_error(mbox->datagram);
|
||||
ec_fsm_soe_print_error(fsm);
|
||||
return;
|
||||
}
|
||||
|
||||
data = ec_slave_mbox_fetch(slave, datagram, &mbox_prot, &rec_size);
|
||||
data = ec_slave_mbox_fetch(slave, mbox, &mbox_prot, &rec_size);
|
||||
if (IS_ERR(data)) {
|
||||
fsm->state = ec_fsm_soe_error;
|
||||
ec_fsm_soe_print_error(fsm);
|
||||
|
||||
+2
-2
@@ -50,7 +50,7 @@ typedef struct ec_fsm_soe ec_fsm_soe_t; /**< \see ec_fsm_soe */
|
||||
*/
|
||||
struct ec_fsm_soe {
|
||||
ec_slave_t *slave; /**< slave the FSM runs on */
|
||||
ec_datagram_t *datagram; /**< datagram used in the state machine */
|
||||
ec_mailbox_t *mbox; /**< mailbox used in the state machine */
|
||||
unsigned int retries; /**< retries upon datagram timeout */
|
||||
|
||||
void (*state)(ec_fsm_soe_t *); /**< CoE state function */
|
||||
@@ -61,7 +61,7 @@ struct ec_fsm_soe {
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void ec_fsm_soe_init(ec_fsm_soe_t *, ec_datagram_t *);
|
||||
void ec_fsm_soe_init(ec_fsm_soe_t *, ec_mailbox_t *);
|
||||
void ec_fsm_soe_clear(ec_fsm_soe_t *);
|
||||
|
||||
void ec_fsm_soe_transfer(ec_fsm_soe_t *, ec_slave_t *, ec_soe_request_t *);
|
||||
|
||||
+69
-22
@@ -39,6 +39,17 @@
|
||||
#include "../globals.h"
|
||||
#include "../include/ecrt.h"
|
||||
|
||||
#ifdef __KERNEL__
|
||||
#include <linux/version.h>
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
|
||||
#include <linux/rtmutex.h>
|
||||
#endif // KERNEL_VERSION(2,6,24)
|
||||
#endif // __KERNEL__
|
||||
|
||||
#ifdef CONFIG_TRACING
|
||||
//#define USE_TRACE_PRINTK
|
||||
#endif
|
||||
|
||||
/******************************************************************************
|
||||
* EtherCAT master
|
||||
*****************************************************************************/
|
||||
@@ -46,8 +57,8 @@
|
||||
/** Datagram timeout in microseconds. */
|
||||
#define EC_IO_TIMEOUT 500
|
||||
|
||||
/** SDO injection timeout in microseconds. */
|
||||
#define EC_SDO_INJECTION_TIMEOUT 10000
|
||||
/** FSM injection timeout in microseconds. */
|
||||
#define EC_FSM_INJECTION_TIMEOUT 10000
|
||||
|
||||
/** Time to send a byte in nanoseconds.
|
||||
*
|
||||
@@ -97,9 +108,6 @@
|
||||
/** Word offset of first SII category. */
|
||||
#define EC_FIRST_SII_CATEGORY_OFFSET 0x40
|
||||
|
||||
/** Maximum number of slave ports. */
|
||||
#define EC_MAX_PORTS 4
|
||||
|
||||
/** Size of a sync manager configuration page. */
|
||||
#define EC_SYNC_PAGE_SIZE 8
|
||||
|
||||
@@ -173,23 +181,6 @@ typedef struct {
|
||||
uint8_t enable_not_lrw : 1; /**< Slave does not support LRW. */
|
||||
} ec_sii_general_flags_t;
|
||||
|
||||
/** EtherCAT slave port descriptor.
|
||||
*/
|
||||
typedef enum {
|
||||
EC_PORT_NOT_IMPLEMENTED,
|
||||
EC_PORT_NOT_CONFIGURED,
|
||||
EC_PORT_EBUS,
|
||||
EC_PORT_MII
|
||||
} ec_slave_port_desc_t;
|
||||
|
||||
/** EtherCAT slave port information.
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t link_up; /**< Link detected. */
|
||||
uint8_t loop_closed; /**< Loop closed. */
|
||||
uint8_t signal_detected; /**< Detected signal on RX port. */
|
||||
} ec_slave_port_link_t;
|
||||
|
||||
/** EtherCAT slave distributed clocks range.
|
||||
*/
|
||||
typedef enum {
|
||||
@@ -325,4 +316,60 @@ typedef struct ec_slave ec_slave_t; /**< \see ec_slave. */
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
/** Mutual exclusion helpers.
|
||||
*
|
||||
*/
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
|
||||
#define ec_mutex_t rt_mutex
|
||||
static inline void ec_mutex_init(struct ec_mutex_t *mutex)
|
||||
{
|
||||
rt_mutex_init(mutex);
|
||||
}
|
||||
static inline void ec_mutex_lock(struct ec_mutex_t *mutex)
|
||||
{
|
||||
rt_mutex_lock(mutex);
|
||||
}
|
||||
static inline int ec_mutex_trylock(struct ec_mutex_t *mutex)
|
||||
{
|
||||
return rt_mutex_trylock(mutex);
|
||||
}
|
||||
static inline int ec_mutex_lock_interruptible(struct ec_mutex_t *mutex)
|
||||
{
|
||||
return rt_mutex_lock_interruptible(mutex,0);
|
||||
}
|
||||
static inline void ec_mutex_unlock(struct ec_mutex_t *mutex)
|
||||
{
|
||||
rt_mutex_unlock(mutex);
|
||||
}
|
||||
#else // < KERNEL_VERSION(2,6,24)
|
||||
#define ec_mutex_t semaphore
|
||||
static inline void ec_mutex_init(struct ec_mutex_t *sem)
|
||||
{
|
||||
sema_init(sem, 1);
|
||||
}
|
||||
static inline void ec_mutex_lock(struct ec_mutex_t *sem)
|
||||
{
|
||||
down(sem);
|
||||
}
|
||||
static inline int ec_mutex_trylock(struct ec_mutex_t *sem)
|
||||
{
|
||||
down(sem);
|
||||
return 1;
|
||||
}
|
||||
static inline int ec_mutex_lock_interruptible(struct ec_mutex_t *sem)
|
||||
{
|
||||
return down_interruptible(sem);
|
||||
}
|
||||
static inline void ec_mutex_unlock(struct ec_mutex_t *sem)
|
||||
{
|
||||
up(sem);
|
||||
}
|
||||
|
||||
#endif // KERNEL_VERSION(2,6,24)
|
||||
#endif // __KERNEL__
|
||||
|
||||
#endif
|
||||
|
||||
+6
-1
@@ -56,7 +56,7 @@
|
||||
*
|
||||
* Increment this when changing the ioctl interface!
|
||||
*/
|
||||
#define EC_IOCTL_VERSION_MAGIC 11
|
||||
#define EC_IOCTL_VERSION_MAGIC 12
|
||||
|
||||
// Command-line tool
|
||||
#define EC_IOCTL_MODULE EC_IOR(0x00, ec_ioctl_module_t)
|
||||
@@ -137,6 +137,8 @@
|
||||
#define EC_IOCTL_VOE_EXEC EC_IOWR(0x47, ec_ioctl_voe_t)
|
||||
#define EC_IOCTL_VOE_DATA EC_IOWR(0x48, ec_ioctl_voe_t)
|
||||
#define EC_IOCTL_SET_SEND_INTERVAL EC_IOW(0x49, size_t)
|
||||
#define EC_IOCTL_MASTER_SC_STATE EC_IOR(0x50, ec_master_state_t)
|
||||
#define EC_IOCTL_SC_OVERLAPPING_IO EC_IOW(0x51, ec_ioctl_config_t)
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
@@ -278,6 +280,7 @@ typedef struct {
|
||||
|
||||
// outputs
|
||||
uint32_t data_size;
|
||||
uint32_t tx_size;
|
||||
uint32_t logical_base_address;
|
||||
uint16_t working_counter;
|
||||
uint16_t expected_working_counter;
|
||||
@@ -297,6 +300,7 @@ typedef struct {
|
||||
uint8_t sync_index;
|
||||
ec_direction_t dir;
|
||||
uint32_t logical_address;
|
||||
uint32_t domain_address;
|
||||
uint32_t data_size;
|
||||
} ec_ioctl_domain_fmmu_t;
|
||||
|
||||
@@ -459,6 +463,7 @@ typedef struct {
|
||||
} syncs[EC_MAX_SYNC_MANAGERS];
|
||||
uint16_t watchdog_divider;
|
||||
uint16_t watchdog_intervals;
|
||||
uint8_t allow_overlapping_pdos;
|
||||
uint32_t sdo_count;
|
||||
uint32_t idn_count;
|
||||
int32_t slave_position;
|
||||
|
||||
+112
-12
@@ -37,10 +37,84 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
#include "slave.h"
|
||||
#include "mailbox.h"
|
||||
#include "datagram.h"
|
||||
#include "master.h"
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Mailbox constructor.
|
||||
*/
|
||||
|
||||
void ec_mbox_init(ec_mailbox_t* mbox, /** mailbox */
|
||||
ec_datagram_t* datagram /**< Datagram used for the mailbox content. */
|
||||
)
|
||||
{
|
||||
mbox->datagram = datagram;
|
||||
#ifdef EC_REDUCE_MBOXFRAMESIZE
|
||||
ec_datagram_init(&mbox->end_datagram);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Clears mailbox datagrams.
|
||||
*/
|
||||
|
||||
void ec_mbox_clear(ec_mailbox_t* mbox /** mailbox */
|
||||
)
|
||||
{
|
||||
#ifdef EC_REDUCE_MBOXFRAMESIZE
|
||||
ec_datagram_clear(&mbox->end_datagram);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Queues the slave datagrams.
|
||||
*/
|
||||
|
||||
void ec_slave_mbox_queue_datagrams(const ec_slave_t* slave, /** slave */
|
||||
ec_mailbox_t* mbox /** mailbox */
|
||||
)
|
||||
{
|
||||
ec_master_queue_request_fsm_datagram(slave->master, mbox->datagram);
|
||||
#ifdef EC_REDUCE_MBOXFRAMESIZE
|
||||
if (mbox->end_datagram.type != EC_DATAGRAM_NONE)
|
||||
{
|
||||
ec_master_queue_request_fsm_datagram(slave->master, &mbox->end_datagram);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Queues the datagrams.
|
||||
*/
|
||||
|
||||
void ec_master_mbox_queue_datagrams(ec_master_t* master, /** master */
|
||||
ec_mailbox_t* mbox /** mailbox */
|
||||
)
|
||||
{
|
||||
ec_master_queue_fsm_datagram(master, mbox->datagram);
|
||||
#ifdef EC_REDUCE_MBOXFRAMESIZE
|
||||
if (mbox->end_datagram.type != EC_DATAGRAM_NONE)
|
||||
{
|
||||
ec_master_queue_fsm_datagram(master, &mbox->end_datagram);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
@@ -48,12 +122,13 @@
|
||||
\return Pointer to mailbox datagram data, or ERR_PTR() code.
|
||||
*/
|
||||
|
||||
uint8_t *ec_slave_mbox_prepare_send(const ec_slave_t *slave, /**< slave */
|
||||
ec_datagram_t *datagram, /**< datagram */
|
||||
uint8_t *ec_slave_mbox_prepare_send(const ec_slave_t* slave, /** slave */
|
||||
ec_mailbox_t* mbox, /** mailbox */
|
||||
uint8_t type, /**< mailbox protocol */
|
||||
size_t size /**< size of the data */
|
||||
)
|
||||
{
|
||||
ec_datagram_t* datagram = mbox->datagram;
|
||||
size_t total_size;
|
||||
int ret;
|
||||
|
||||
@@ -72,8 +147,13 @@ uint8_t *ec_slave_mbox_prepare_send(const ec_slave_t *slave, /**< slave */
|
||||
}
|
||||
|
||||
ret = ec_datagram_fpwr(datagram, slave->station_address,
|
||||
slave->configured_rx_mailbox_offset,
|
||||
slave->configured_rx_mailbox_size);
|
||||
slave->configured_rx_mailbox_offset,
|
||||
#ifdef EC_REDUCE_MBOXFRAMESIZE
|
||||
total_size
|
||||
#else
|
||||
slave->configured_rx_mailbox_size
|
||||
#endif
|
||||
);
|
||||
if (ret)
|
||||
return ERR_PTR(ret);
|
||||
|
||||
@@ -82,6 +162,17 @@ uint8_t *ec_slave_mbox_prepare_send(const ec_slave_t *slave, /**< slave */
|
||||
EC_WRITE_U8 (datagram->data + 4, 0x00); // channel & priority
|
||||
EC_WRITE_U8 (datagram->data + 5, type); // underlying protocol type
|
||||
|
||||
#ifdef EC_REDUCE_MBOXFRAMESIZE
|
||||
/* in order to fulfil the ESC's mailbox protocol,
|
||||
at least the last byte of the mailbox must be written */
|
||||
if (total_size < slave->configured_rx_mailbox_size) {
|
||||
ret = ec_datagram_fpwr(&mbox->end_datagram, slave->station_address,
|
||||
slave->configured_rx_mailbox_offset+slave->configured_rx_mailbox_size-1,
|
||||
1);
|
||||
if (ret)
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
#endif
|
||||
return datagram->data + EC_MBOX_HEADER_SIZE;
|
||||
}
|
||||
|
||||
@@ -93,15 +184,19 @@ uint8_t *ec_slave_mbox_prepare_send(const ec_slave_t *slave, /**< slave */
|
||||
\return 0 in case of success, else < 0
|
||||
*/
|
||||
|
||||
int ec_slave_mbox_prepare_check(const ec_slave_t *slave, /**< slave */
|
||||
ec_datagram_t *datagram /**< datagram */
|
||||
int ec_slave_mbox_prepare_check(const ec_slave_t* slave, /** slave */
|
||||
ec_mailbox_t* mbox /** mailbox */
|
||||
)
|
||||
{
|
||||
ec_datagram_t* datagram = mbox->datagram;
|
||||
int ret = ec_datagram_fprd(datagram, slave->station_address, 0x808, 8);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ec_datagram_zero(datagram);
|
||||
#ifdef EC_REDUCE_MBOXFRAMESIZE
|
||||
mbox->end_datagram.type = EC_DATAGRAM_NONE;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -112,9 +207,9 @@ int ec_slave_mbox_prepare_check(const ec_slave_t *slave, /**< slave */
|
||||
\return 0 in case of success, else < 0
|
||||
*/
|
||||
|
||||
int ec_slave_mbox_check(const ec_datagram_t *datagram /**< datagram */)
|
||||
int ec_slave_mbox_check(ec_mailbox_t* mbox /** mailbox */)
|
||||
{
|
||||
return EC_READ_U8(datagram->data + 5) & 8 ? 1 : 0;
|
||||
return EC_READ_U8(mbox->datagram->data + 5) & 8 ? 1 : 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
@@ -124,10 +219,11 @@ int ec_slave_mbox_check(const ec_datagram_t *datagram /**< datagram */)
|
||||
\return 0 in case of success, else < 0
|
||||
*/
|
||||
|
||||
int ec_slave_mbox_prepare_fetch(const ec_slave_t *slave, /**< slave */
|
||||
ec_datagram_t *datagram /**< datagram */
|
||||
int ec_slave_mbox_prepare_fetch(const ec_slave_t* slave, /** slave */
|
||||
ec_mailbox_t* mbox /** mailbox */
|
||||
)
|
||||
{
|
||||
ec_datagram_t* datagram = mbox->datagram;
|
||||
int ret = ec_datagram_fprd(datagram, slave->station_address,
|
||||
slave->configured_tx_mailbox_offset,
|
||||
slave->configured_tx_mailbox_size);
|
||||
@@ -135,6 +231,9 @@ int ec_slave_mbox_prepare_fetch(const ec_slave_t *slave, /**< slave */
|
||||
return ret;
|
||||
|
||||
ec_datagram_zero(datagram);
|
||||
#ifdef EC_REDUCE_MBOXFRAMESIZE
|
||||
mbox->end_datagram.type = EC_DATAGRAM_NONE;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -162,12 +261,13 @@ const ec_code_msg_t mbox_error_messages[] = {
|
||||
*
|
||||
* \return Pointer to the received data, or ERR_PTR() code.
|
||||
*/
|
||||
uint8_t *ec_slave_mbox_fetch(const ec_slave_t *slave, /**< slave */
|
||||
ec_datagram_t *datagram, /**< datagram */
|
||||
uint8_t *ec_slave_mbox_fetch(const ec_slave_t* slave, /** slave */
|
||||
ec_mailbox_t* mbox, /** mailbox */
|
||||
uint8_t *type, /**< expected mailbox protocol */
|
||||
size_t *size /**< size of the received data */
|
||||
)
|
||||
{
|
||||
ec_datagram_t* datagram = mbox->datagram;
|
||||
size_t data_size;
|
||||
|
||||
data_size = EC_READ_U16(datagram->data);
|
||||
|
||||
+48
-6
@@ -37,7 +37,8 @@
|
||||
#ifndef __EC_MAILBOX_H__
|
||||
#define __EC_MAILBOX_H__
|
||||
|
||||
#include "slave.h"
|
||||
#include "globals.h"
|
||||
#include "datagram.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
@@ -47,12 +48,53 @@
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
uint8_t *ec_slave_mbox_prepare_send(const ec_slave_t *, ec_datagram_t *,
|
||||
/** EtherCAT slave mailbox.
|
||||
*/
|
||||
struct ec_mailbox
|
||||
{
|
||||
ec_datagram_t* datagram; /**< Datagram used for the mailbox content. */
|
||||
#ifdef EC_REDUCE_MBOXFRAMESIZE
|
||||
ec_datagram_t end_datagram; /**< Datagram used for writing the end byte to the mailbox. */
|
||||
#endif
|
||||
};
|
||||
typedef struct ec_mailbox ec_mailbox_t; /**< \see ec_mailbox. */
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void ec_mbox_init(ec_mailbox_t *, ec_datagram_t*);
|
||||
void ec_mbox_clear(ec_mailbox_t*);
|
||||
/**
|
||||
Checks the datagrams states.
|
||||
*/
|
||||
static inline int ec_mbox_is_datagram_state(ec_mailbox_t*mbox,
|
||||
ec_datagram_state_t state) {
|
||||
return (mbox->datagram->state == state)
|
||||
#ifdef EC_REDUCE_MBOXFRAMESIZE
|
||||
&& (mbox->end_datagram.type == EC_DATAGRAM_NONE || mbox->end_datagram.state == state)
|
||||
#endif
|
||||
;
|
||||
}
|
||||
|
||||
/**
|
||||
Checks the datagrams working counter.
|
||||
*/
|
||||
static inline int ec_mbox_is_datagram_wc(ec_mailbox_t*mbox,
|
||||
size_t wc) {
|
||||
return (mbox->datagram->working_counter == wc)
|
||||
#ifdef EC_REDUCE_MBOXFRAMESIZE
|
||||
&& (mbox->end_datagram.type == EC_DATAGRAM_NONE || mbox->end_datagram.working_counter == wc)
|
||||
#endif
|
||||
;
|
||||
}
|
||||
|
||||
void ec_slave_mbox_queue_datagrams(const ec_slave_t*,ec_mailbox_t*);
|
||||
void ec_master_mbox_queue_datagrams(ec_master_t*, ec_mailbox_t*);
|
||||
uint8_t *ec_slave_mbox_prepare_send(const ec_slave_t*,ec_mailbox_t *,
|
||||
uint8_t, size_t);
|
||||
int ec_slave_mbox_prepare_check(const ec_slave_t *, ec_datagram_t *);
|
||||
int ec_slave_mbox_check(const ec_datagram_t *);
|
||||
int ec_slave_mbox_prepare_fetch(const ec_slave_t *, ec_datagram_t *);
|
||||
uint8_t *ec_slave_mbox_fetch(const ec_slave_t *, ec_datagram_t *,
|
||||
int ec_slave_mbox_prepare_check(const ec_slave_t*,ec_mailbox_t *);
|
||||
int ec_slave_mbox_check(ec_mailbox_t *);
|
||||
int ec_slave_mbox_prepare_fetch(const ec_slave_t*,ec_mailbox_t *);
|
||||
uint8_t *ec_slave_mbox_fetch(const ec_slave_t*,ec_mailbox_t *,
|
||||
uint8_t *, size_t *);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user