master/master.h
changeset 2589 2b9c78543663
parent 2117 afb40fd6018e
child 2620 0e4d098db815
--- a/master/master.h	Thu Sep 06 14:21:02 2012 +0200
+++ b/master/master.h	Mon Nov 03 15:20:05 2014 +0100
@@ -2,7 +2,7 @@
  *
  *  $Id$
  *
- *  Copyright (C) 2006-2008  Florian Pose, Ingenieurgemeinschaft IgH
+ *  Copyright (C) 2006-2012  Florian Pose, Ingenieurgemeinschaft IgH
  *
  *  This file is part of the IgH EtherCAT Master.
  *
@@ -43,12 +43,21 @@
 #include <linux/wait.h>
 #include <linux/kthread.h>
 
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
+#include <linux/semaphore.h>
+#else
+#include <asm/semaphore.h>
+#endif
+
 #include "device.h"
 #include "domain.h"
 #include "ethernet.h"
 #include "fsm_master.h"
 #include "cdev.h"
 
+#ifdef EC_RTDM
+#include "rtdm.h"
+#endif
 
 /*****************************************************************************/
 
@@ -61,16 +70,8 @@
  * \param fmt format string (like in printf())
  * \param args arguments (optional)
  */
-#ifdef USE_TRACE_PRINTK
-#define EC_MASTER_INFO(master, fmt, args...) \
-    do { \
-        __trace_printk(_THIS_IP_,"EtherCAT %u: " fmt, master->index, ##args); \
-        printk(KERN_INFO "EtherCAT %u: " fmt, master->index, ##args);   \
-    } while (0)
-#else
 #define EC_MASTER_INFO(master, fmt, args...) \
     printk(KERN_INFO "EtherCAT %u: " fmt, master->index, ##args)
-#endif
 
 /** Convenience macro for printing master-specific errors to syslog.
  *
@@ -81,16 +82,8 @@
  * \param fmt format string (like in printf())
  * \param args arguments (optional)
  */
-#ifdef USE_TRACE_PRINTK
-#define EC_MASTER_ERR(master, fmt, args...) \
-    do { \
-        __trace_printk(_THIS_IP_,"EtherCAT ERROR %u: " fmt, master->index, ##args); \
-        printk(KERN_ERR "EtherCAT ERROR %u: " fmt, master->index, ##args); \
-    } while (0)
-#else
 #define EC_MASTER_ERR(master, fmt, args...) \
     printk(KERN_ERR "EtherCAT ERROR %u: " fmt, master->index, ##args)
-#endif
 
 /** Convenience macro for printing master-specific warnings to syslog.
  *
@@ -101,16 +94,8 @@
  * \param fmt format string (like in printf())
  * \param args arguments (optional)
  */
-#ifdef USE_TRACE_PRINTK
-#define EC_MASTER_WARN(master, fmt, args...) \
-    do { \
-        __trace_printk(_THIS_IP_,"EtherCAT WARNING %u: " fmt, master->index, ##args); \
-        printk(KERN_WARNING "EtherCAT WARNING %u: " fmt, master->index, ##args);    \
-    } while (0)
-#else
 #define EC_MASTER_WARN(master, fmt, args...) \
     printk(KERN_WARNING "EtherCAT WARNING %u: " fmt, master->index, ##args)
-#endif
 
 /** Convenience macro for printing master-specific debug messages to syslog.
  *
@@ -118,20 +103,11 @@
  * where INDEX is the master index.
  *
  * \param master EtherCAT master
+ * \param level Debug level. Master's debug level must be >= \a level for
+ * output.
  * \param fmt format string (like in printf())
  * \param args arguments (optional)
  */
-#ifdef USE_TRACE_PRINTK
-#define EC_MASTER_DBG(master, level, fmt, args...) \
-    do { \
-        __trace_printk(_THIS_IP_,"EtherCAT DEBUG%u %u: " fmt, \
-            level,master->index, ##args); \
-        if (master->debug_level >= level) { \
-            printk(KERN_DEBUG "EtherCAT DEBUG %u: " fmt, \
-                    master->index, ##args); \
-        } \
-    } while (0)
-#else
 #define EC_MASTER_DBG(master, level, fmt, args...) \
     do { \
         if (master->debug_level >= level) { \
@@ -139,7 +115,13 @@
                     master->index, ##args); \
         } \
     } while (0)
-#endif
+
+
+/** Size of the external datagram ring.
+ *
+ * The external datagram ring is used for slave FSMs.
+ */
+#define EC_EXT_RING_SIZE 32
 
 /*****************************************************************************/
 
@@ -168,6 +150,43 @@
 
 /*****************************************************************************/
 
+/** Device statistics.
+ */
+typedef struct {
+    u64 tx_count; /**< Number of frames sent. */
+    u64 last_tx_count; /**< Number of frames sent of last statistics cycle. */
+    u64 rx_count; /**< Number of frames received. */
+    u64 last_rx_count; /**< Number of frames received of last statistics
+                         cycle. */
+    u64 tx_bytes; /**< Number of bytes sent. */
+    u64 last_tx_bytes; /**< Number of bytes sent of last statistics cycle. */
+    u64 rx_bytes; /**< Number of bytes received. */
+    u64 last_rx_bytes; /**< Number of bytes received of last statistics cycle.
+                        */
+    u64 last_loss; /**< Tx/Rx difference of last statistics cycle. */
+    s32 tx_frame_rates[EC_RATE_COUNT]; /**< Transmit rates in frames/s for
+                                         different statistics cycle periods.
+                                        */
+    s32 rx_frame_rates[EC_RATE_COUNT]; /**< Receive rates in frames/s for
+                                         different statistics cycle periods.
+                                        */
+    s32 tx_byte_rates[EC_RATE_COUNT]; /**< Transmit rates in byte/s for
+                                        different statistics cycle periods. */
+    s32 rx_byte_rates[EC_RATE_COUNT]; /**< Receive rates in byte/s for
+                                        different statistics cycle periods. */
+    s32 loss_rates[EC_RATE_COUNT]; /**< Frame loss rates for different
+                                     statistics cycle periods. */
+    unsigned long jiffies; /**< Jiffies of last statistic cycle. */
+} ec_device_stats_t;
+
+/*****************************************************************************/
+
+#if EC_MAX_NUM_DEVICES < 1
+#error Invalid number of devices
+#endif
+
+/*****************************************************************************/
+
 /** EtherCAT master.
  *
  * Manages slaves, domains and IO.
@@ -183,17 +202,24 @@
     struct class_device *class_device; /**< Master class device. */
 #endif
 
-    struct ec_mutex_t master_mutex; /**< Master mutex. */
-
-    ec_device_t main_device; /**< EtherCAT main device. */
-    const uint8_t *main_mac; /**< MAC address of main device. */
-    ec_device_t backup_device; /**< EtherCAT backup device. */
-    const uint8_t *backup_mac; /**< MAC address of backup device. */
-    struct ec_mutex_t device_mutex; /**< Device mutex. */
+#ifdef EC_RTDM
+    ec_rtdm_dev_t rtdm_dev; /**< RTDM device. */
+#endif
+
+    struct semaphore master_sem; /**< Master semaphore. */
+
+    ec_device_t devices[EC_MAX_NUM_DEVICES]; /**< EtherCAT devices. */
+    const uint8_t *macs[EC_MAX_NUM_DEVICES]; /**< Device MAC addresses. */
+#if EC_MAX_NUM_DEVICES > 1
+    unsigned int num_devices; /**< Number of devices. Access this always via
+                                ec_master_num_devices(), because it may be
+                                optimized! */
+#endif
+    struct semaphore device_sem; /**< Device semaphore. */
+    ec_device_stats_t device_stats; /**< Device statistics. */
 
     ec_fsm_master_t fsm; /**< Master state machine. */
     ec_datagram_t fsm_datagram; /**< Datagram used for state machines. */
-    ec_mailbox_t fsm_mbox; /**< Mailbox used for state machines. */
     ec_master_phase_t phase; /**< Master phase. */
     unsigned int active; /**< Master has been activated. */
     unsigned int config_changed; /**< The configuration changed. */
@@ -208,7 +234,7 @@
     /* Configuration applied by the application. */
     struct list_head configs; /**< List of slave configurations. */
     struct list_head domains; /**< List of domains. */
-    
+
     u64 app_time; /**< Time of the last ecrt_master_sync() call. */
     u64 app_start_time; /**< Application start time. */
     u8 has_app_time; /**< Application time is valid. */
@@ -218,21 +244,19 @@
                                    compensation. */
     ec_datagram_t sync_mon_datagram; /**< Datagram used for DC synchronisation
                                        monitoring. */
+    ec_slave_config_t *dc_ref_config; /**< Application-selected DC reference
+                                        clock slave config. */
     ec_slave_t *dc_ref_clock; /**< DC reference clock slave. */
-#ifdef EC_HAVE_CYCLES
-    cycles_t dc_cycles_app_start_time; /** cycles at last ecrt_master_sync() call.*/
-#endif
-    unsigned long dc_jiffies_app_start_time;/** jiffies at last
-                                            ecrt_master_sync() call.*/
+
     unsigned int scan_busy; /**< Current scan state. */
     unsigned int allow_scan; /**< \a True, if slave scanning is allowed. */
-    struct ec_mutex_t scan_mutex; /**< Mutex protecting the \a scan_busy
+    struct semaphore scan_sem; /**< Semaphore protecting the \a scan_busy
                                  variable and the \a allow_scan flag. */
     wait_queue_head_t scan_queue; /**< Queue for processes that wait for
                                     slave scanning. */
 
     unsigned int config_busy; /**< State of slave configuration. */
-    struct ec_mutex_t config_mutex; /**< Mutex protecting the \a config_busy
+    struct semaphore config_sem; /**< Semaphore protecting the \a config_busy
                                    variable and the allow_config flag. */
     wait_queue_head_t config_queue; /**< Queue for processes that wait for
                                       slave configuration. */
@@ -240,14 +264,25 @@
     struct list_head datagram_queue; /**< Datagram queue. */
     uint8_t datagram_index; /**< Current datagram index. */
 
-    struct ec_mutex_t fsm_queue_mutex; /**< Mutex protecting the \a
-                                      fsm_datagram_queue. */
-    struct list_head fsm_datagram_queue; /**< External Datagram queue. */
-
-    unsigned int send_interval; /**< Interval between calls to
-                                  ecrt_master_send */
+    struct list_head ext_datagram_queue; /**< Queue for non-application
+                                           datagrams. */
+    struct semaphore ext_queue_sem; /**< Semaphore protecting the \a
+                                      ext_datagram_queue. */
+
+    ec_datagram_t ext_datagram_ring[EC_EXT_RING_SIZE]; /**< External datagram
+                                                         ring. */
+    unsigned int ext_ring_idx_rt; /**< Index in external datagram ring for RT
+                                    side. */
+    unsigned int ext_ring_idx_fsm; /**< Index in external datagram ring for
+                                     FSM side. */
+    unsigned int send_interval; /**< Interval between two calls to
+                                  ecrt_master_send(). */
     size_t max_queue_size; /**< Maximum size of datagram queue */
 
+    ec_slave_t *fsm_slave; /**< Slave that is queried next for FSM exec. */
+    struct list_head fsm_exec_list; /**< Slave FSM execution list. */
+    unsigned int fsm_exec_count; /**< Number of entries in execution list. */
+
     unsigned int debug_level; /**< Master debug level. */
     ec_stats_t stats; /**< Cyclic statistics. */
 
@@ -258,25 +293,23 @@
     struct list_head eoe_handlers; /**< Ethernet over EtherCAT handlers. */
 #endif
 
-    struct ec_mutex_t io_mutex; /**< Mutex used in \a IDLE phase. */
-
-    void (*fsm_queue_lock_cb)(void *); /**< FSM queue lock callback. */
-    void (*fsm_queue_unlock_cb)(void *); /**< FSM queue unlock callback. */
-    void *fsm_queue_locking_data; /**< Data parameter of fsm queue locking
-                                    callbacks. */
-    void (*app_fsm_queue_lock_cb)(void *); /**< App's FSM queue lock callback.
-                                            */
-    void (*app_fsm_queue_unlock_cb)(void *); /**< App's FSM queue unlock
-                                               callback. */
-    void *app_fsm_queue_locking_data; /**< App's data parameter of fsm queue
-                                        locking callbacks. */
+    struct semaphore io_sem; /**< Semaphore used in \a IDLE phase. */
+
+    void (*send_cb)(void *); /**< Current send datagrams callback. */
+    void (*receive_cb)(void *); /**< Current receive datagrams callback. */
+    void *cb_data; /**< Current callback data. */
+    void (*app_send_cb)(void *); /**< Application's send datagrams
+                                          callback. */
+    void (*app_receive_cb)(void *); /**< Application's receive datagrams
+                                      callback. */
+    void *app_cb_data; /**< Application callback data. */
 
     struct list_head sii_requests; /**< SII write requests. */
-    wait_queue_head_t sii_queue; /**< Wait queue for SII
-                                      write requests from user space. */
-
-    struct list_head reg_requests; /**< Register requests. */
-    wait_queue_head_t reg_queue; /**< Wait queue for register requests. */
+    struct list_head emerg_reg_requests; /**< Emergency register access
+                                           requests. */
+
+    wait_queue_head_t request_queue; /**< Wait queue for external requests
+                                       from user space. */
 };
 
 /*****************************************************************************/
@@ -289,18 +322,31 @@
         const uint8_t *, dev_t, struct class *, unsigned int);
 void ec_master_clear(ec_master_t *);
 
+/** Number of Ethernet devices.
+ */
+#if EC_MAX_NUM_DEVICES > 1
+#define ec_master_num_devices(MASTER) ((MASTER)->num_devices)
+#else
+#define ec_master_num_devices(MASTER) 1
+#endif
+
 // phase transitions
 int ec_master_enter_idle_phase(ec_master_t *);
 void ec_master_leave_idle_phase(ec_master_t *);
 int ec_master_enter_operation_phase(ec_master_t *);
 void ec_master_leave_operation_phase(ec_master_t *);
 
+#ifdef EC_EOE
+// EoE
+void ec_master_eoe_start(ec_master_t *);
+void ec_master_eoe_stop(ec_master_t *);
+#endif
+
 // datagram IO
-void ec_master_receive_datagrams(ec_master_t *, const uint8_t *, size_t);
+void ec_master_receive_datagrams(ec_master_t *, ec_device_t *,
+        const uint8_t *, size_t);
 void ec_master_queue_datagram(ec_master_t *, ec_datagram_t *);
-void ec_master_queue_request_fsm_datagram(ec_master_t *, ec_datagram_t *);
-void ec_master_queue_fsm_datagram(ec_master_t *, ec_datagram_t *);
-void ec_master_inject_fsm_datagrams(ec_master_t *);
+void ec_master_queue_datagram_ext(ec_master_t *, ec_datagram_t *);
 
 // misc.
 void ec_master_set_send_interval(ec_master_t *, unsigned int);
@@ -337,6 +383,11 @@
 void ec_master_calc_dc(ec_master_t *);
 void ec_master_request_op(ec_master_t *);
 
-/*****************************************************************************/
-
-#endif
+void ec_master_internal_send_cb(void *);
+void ec_master_internal_receive_cb(void *);
+
+extern const unsigned int rate_intervals[EC_RATE_COUNT]; // see master.c
+
+/*****************************************************************************/
+
+#endif