fp@39: /****************************************************************************** fp@0: * fp@39: * $Id$ fp@0: * fp@1326: * Copyright (C) 2006-2008 Florian Pose, Ingenieurgemeinschaft IgH fp@197: * fp@197: * This file is part of the IgH EtherCAT Master. fp@197: * fp@1326: * The IgH EtherCAT Master is free software; you can redistribute it and/or fp@1326: * modify it under the terms of the GNU General Public License version 2, as fp@1326: * published by the Free Software Foundation. fp@1326: * fp@1326: * The IgH EtherCAT Master is distributed in the hope that it will be useful, fp@1326: * but WITHOUT ANY WARRANTY; without even the implied warranty of fp@1326: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General fp@1326: * Public License for more details. fp@1326: * fp@1326: * You should have received a copy of the GNU General Public License along fp@1326: * with the IgH EtherCAT Master; if not, write to the Free Software fp@197: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA fp@197: * fp@1363: * --- fp@1363: * fp@1363: * The license mentioned above concerns the source code only. Using the fp@1363: * EtherCAT technology and brand is only permitted in compliance with the fp@1363: * industrial property and similar rights of Beckhoff Automation GmbH. fp@246: * fp@39: *****************************************************************************/ fp@0: fp@199: /** fp@199: \file fp@199: EtherCAT master structure. fp@199: */ fp@199: fp@199: /*****************************************************************************/ fp@199: fp@883: #ifndef __EC_MASTER_H__ fp@883: #define __EC_MASTER_H__ fp@0: fp@1250: #include fp@95: #include fp@191: #include fp@601: #include fp@1241: #include fp@1369: fp@1369: #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27) fp@1369: #include fp@1369: #else fp@381: #include fp@1369: #endif fp@95: fp@54: #include "device.h" fp@54: #include "domain.h" fp@1485: #include "ethernet.h" fp@528: #include "fsm_master.h" fp@922: #include "cdev.h" fp@0: fp@39: /*****************************************************************************/ fp@0: fp@1921: /** Convenience macro for printing master-specific information to syslog. fp@1921: * fp@1921: * This will print the message in \a fmt with a prefixed "EtherCAT : ", fp@1921: * where INDEX is the master index. fp@1921: * fp@1921: * \param master EtherCAT master fp@1921: * \param fmt format string (like in printf()) fp@1921: * \param args arguments (optional) fp@1921: */ fp@1921: #define EC_MASTER_INFO(master, fmt, args...) \ fp@1921: printk(KERN_INFO "EtherCAT %u: " fmt, master->index, ##args) fp@1921: fp@1921: /** Convenience macro for printing master-specific errors to syslog. fp@1921: * fp@1921: * This will print the message in \a fmt with a prefixed "EtherCAT : ", fp@1921: * where INDEX is the master index. fp@1921: * fp@1921: * \param master EtherCAT master fp@1921: * \param fmt format string (like in printf()) fp@1921: * \param args arguments (optional) fp@1921: */ fp@1921: #define EC_MASTER_ERR(master, fmt, args...) \ fp@1921: printk(KERN_ERR "EtherCAT ERROR %u: " fmt, master->index, ##args) fp@1921: fp@1921: /** Convenience macro for printing master-specific warnings to syslog. fp@1921: * fp@1921: * This will print the message in \a fmt with a prefixed "EtherCAT : ", fp@1921: * where INDEX is the master index. fp@1921: * fp@1921: * \param master EtherCAT master fp@1921: * \param fmt format string (like in printf()) fp@1921: * \param args arguments (optional) fp@1921: */ fp@1921: #define EC_MASTER_WARN(master, fmt, args...) \ fp@1921: printk(KERN_WARNING "EtherCAT WARNING %u: " fmt, master->index, ##args) fp@1921: fp@1921: /** Convenience macro for printing master-specific debug messages to syslog. fp@1921: * fp@1921: * This will print the message in \a fmt with a prefixed "EtherCAT : ", fp@1921: * where INDEX is the master index. fp@1921: * fp@1921: * \param master EtherCAT master fp@1921: * \param fmt format string (like in printf()) fp@1921: * \param args arguments (optional) fp@1921: */ fp@1921: #define EC_MASTER_DBG(master, level, fmt, args...) \ fp@1921: do { \ fp@1921: if (master->debug_level >= level) { \ fp@1921: printk(KERN_DEBUG "EtherCAT DEBUG %u: " fmt, \ fp@1921: master->index, ##args); \ fp@1921: } \ fp@1921: } while (0) fp@1921: fp@1921: /*****************************************************************************/ fp@1921: fp@1029: /** EtherCAT master phase. fp@792: */ fp@792: typedef enum { fp@1029: EC_ORPHANED, /**< Orphaned phase. The master has no Ethernet device fp@1029: attached. */ fp@1029: EC_IDLE, /**< Idle phase. An Ethernet device is attached, but the master fp@1029: is not in use, yet. */ fp@1029: EC_OPERATION /**< Operation phase. The master was requested by a realtime fp@1029: application. */ fp@1029: } ec_master_phase_t; fp@191: fp@191: /*****************************************************************************/ fp@191: fp@792: /** Cyclic statistics. fp@792: */ fp@792: typedef struct { fp@293: unsigned int timeouts; /**< datagram timeouts */ fp@195: unsigned int corrupted; /**< corrupted frames */ fp@332: unsigned int unmatched; /**< unmatched datagrams (received, but not fp@332: queued any longer) */ fp@344: unsigned long output_jiffies; /**< time of last output */ fp@849: } ec_stats_t; fp@98: fp@98: /*****************************************************************************/ fp@98: fp@2158: /** Device statistics. fp@2158: */ fp@2158: typedef struct { fp@2158: u64 tx_count; /**< Number of frames sent. */ fp@2158: u64 last_tx_count; /**< Number of frames sent of last statistics cycle. */ fp@2158: u64 rx_count; /**< Number of frames received. */ fp@2158: u64 last_rx_count; /**< Number of frames received of last statistics fp@2158: cycle. */ fp@2158: u64 tx_bytes; /**< Number of bytes sent. */ fp@2158: u64 last_tx_bytes; /**< Number of bytes sent of last statistics cycle. */ fp@2158: u64 rx_bytes; /**< Number of bytes received. */ fp@2158: u64 last_rx_bytes; /**< Number of bytes received of last statistics cycle. fp@2158: */ fp@2158: u64 last_loss; /**< Tx/Rx difference of last statistics cycle. */ fp@2372: s32 tx_frame_rates[EC_RATE_COUNT]; /**< Transmit rates in frames/s for fp@2372: different statistics cycle periods. fp@2372: */ fp@2372: s32 rx_frame_rates[EC_RATE_COUNT]; /**< Receive rates in frames/s for fp@2372: different statistics cycle periods. fp@2372: */ fp@2372: s32 tx_byte_rates[EC_RATE_COUNT]; /**< Transmit rates in byte/s for fp@2372: different statistics cycle periods. */ fp@2372: s32 rx_byte_rates[EC_RATE_COUNT]; /**< Receive rates in byte/s for fp@2372: different statistics cycle periods. */ fp@2372: s32 loss_rates[EC_RATE_COUNT]; /**< Frame loss rates for different fp@2158: statistics cycle periods. */ fp@2158: unsigned long jiffies; /**< Jiffies of last statistic cycle. */ fp@2158: } ec_device_stats_t; fp@2158: fp@2158: /*****************************************************************************/ fp@2158: fp@792: /** EtherCAT master. fp@792: * fp@792: * Manages slaves, domains and IO. fp@792: */ fp@849: struct ec_master { fp@1029: unsigned int index; /**< Index. */ fp@1029: unsigned int reserved; /**< \a True, if the master is in use. */ fp@241: fp@922: ec_cdev_t cdev; /**< Master character device. */ fp@1250: #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) fp@1250: struct device *class_device; /**< Master class device. */ fp@1250: #else fp@1013: struct class_device *class_device; /**< Master class device. */ fp@1250: #endif fp@1250: fp@1075: struct semaphore master_sem; /**< Master semaphore. */ fp@922: fp@2267: ec_device_t devices[EC_NUM_DEVICES]; /**< EtherCAT devices. */ fp@2267: const uint8_t *macs[EC_NUM_DEVICES]; /**< Device MAC addresses. */ fp@1029: struct semaphore device_sem; /**< Device semaphore. */ fp@2158: ec_device_stats_t device_stats; /**< Device statistics. */ fp@1029: fp@1029: ec_fsm_master_t fsm; /**< Master state machine. */ fp@1029: ec_datagram_t fsm_datagram; /**< Datagram used for state machines. */ fp@1029: ec_master_phase_t phase; /**< Master phase. */ fp@1530: unsigned int active; /**< Master has been activated. */ fp@1925: unsigned int config_changed; /**< The configuration changed. */ fp@1029: unsigned int injection_seq_fsm; /**< Datagram injection sequence number fp@1029: for the FSM side. */ fp@1029: unsigned int injection_seq_rt; /**< Datagram injection sequence number fp@1029: for the realtime side. */ fp@334: fp@1000: ec_slave_t *slaves; /**< Array of slaves on the bus. */ fp@1000: unsigned int slave_count; /**< Number of slaves on the bus. */ fp@792: fp@1939: /* Configuration applied by the application. */ fp@1028: struct list_head configs; /**< List of slave configurations. */ fp@1939: struct list_head domains; /**< List of domains. */ fp@656: fp@1396: u64 app_time; /**< Time of the last ecrt_master_sync() call. */ fp@1436: u64 app_start_time; /**< Application start time. */ fp@1925: u8 has_app_time; /**< Application time is valid. */ fp@1396: ec_datagram_t ref_sync_datagram; /**< Datagram used for synchronizing the fp@1396: reference clock to the master clock. */ fp@1394: ec_datagram_t sync_datagram; /**< Datagram used for DC drift fp@1394: compensation. */ fp@1535: ec_datagram_t sync_mon_datagram; /**< Datagram used for DC synchronisation fp@1535: monitoring. */ fp@1425: ec_slave_t *dc_ref_clock; /**< DC reference clock slave. */ fp@1394: fp@900: unsigned int scan_busy; /**< Current scan state. */ fp@1029: unsigned int allow_scan; /**< \a True, if slave scanning is allowed. */ fp@1029: struct semaphore scan_sem; /**< Semaphore protecting the \a scan_busy fp@1029: variable and the \a allow_scan flag. */ fp@1029: wait_queue_head_t scan_queue; /**< Queue for processes that wait for fp@1029: slave scanning. */ fp@656: fp@900: unsigned int config_busy; /**< State of slave configuration. */ fp@1029: struct semaphore config_sem; /**< Semaphore protecting the \a config_busy fp@1029: variable and the allow_config flag. */ fp@1029: wait_queue_head_t config_queue; /**< Queue for processes that wait for fp@1029: slave configuration. */ fp@1029: fp@1029: struct list_head datagram_queue; /**< Datagram queue. */ fp@1029: uint8_t datagram_index; /**< Current datagram index. */ fp@1029: fp@1500: struct list_head ext_datagram_queue; /**< Queue for non-application fp@1500: datagrams. */ fp@1500: struct semaphore ext_queue_sem; /**< Semaphore protecting the \a fp@1500: ext_datagram_queue. */ fp@1500: martin@1597: struct list_head external_datagram_queue; /**< External Datagram queue. */ fp@2299: unsigned int send_interval; /**< Interval between two calls to fp@2299: ecrt_master_send(). */ fp@1907: size_t max_queue_size; /**< Maximum size of datagram queue */ fp@241: fp@1399: unsigned int debug_level; /**< Master debug level. */ fp@1029: ec_stats_t stats; /**< Cyclic statistics. */ fp@1029: fp@1241: struct task_struct *thread; /**< Master thread. */ fp@241: fp@715: #ifdef EC_EOE fp@1489: struct task_struct *eoe_thread; /**< EoE thread. */ fp@1327: struct list_head eoe_handlers; /**< Ethernet over EtherCAT handlers. */ fp@1029: #endif fp@1029: fp@1489: struct semaphore io_sem; /**< Semaphore used in \a IDLE phase. */ fp@1500: fp@1513: void (*send_cb)(void *); /**< Current send datagrams callback. */ fp@1513: void (*receive_cb)(void *); /**< Current receive datagrams callback. */ fp@1513: void *cb_data; /**< Current callback data. */ fp@1513: void (*app_send_cb)(void *); /**< Application's send datagrams fp@1500: callback. */ fp@1513: void (*app_receive_cb)(void *); /**< Application's receive datagrams fp@1500: callback. */ fp@1513: void *app_cb_data; /**< Application callback data. */ fp@1029: fp@1029: struct list_head sii_requests; /**< SII write requests. */ fp@1029: wait_queue_head_t sii_queue; /**< Wait queue for SII fp@1029: write requests from user space. */ fp@601: fp@1388: struct list_head reg_requests; /**< Register requests. */ fp@1388: wait_queue_head_t reg_queue; /**< Wait queue for register requests. */ fp@55: }; fp@0: fp@39: /*****************************************************************************/ fp@0: fp@1279: // static funtions fp@1279: void ec_master_init_static(void); fp@1279: fp@448: // master creation/deletion fp@997: int ec_master_init(ec_master_t *, unsigned int, const uint8_t *, fp@1399: const uint8_t *, dev_t, struct class *, unsigned int); fp@639: void ec_master_clear(ec_master_t *); fp@98: fp@1029: // phase transitions fp@1029: int ec_master_enter_idle_phase(ec_master_t *); fp@1029: void ec_master_leave_idle_phase(ec_master_t *); fp@1029: int ec_master_enter_operation_phase(ec_master_t *); fp@1029: void ec_master_leave_operation_phase(ec_master_t *); fp@191: fp@715: #ifdef EC_EOE fp@251: // EoE fp@251: void ec_master_eoe_start(ec_master_t *); fp@251: void ec_master_eoe_stop(ec_master_t *); fp@715: #endif fp@251: fp@446: // datagram IO fp@331: void ec_master_receive_datagrams(ec_master_t *, const uint8_t *, size_t); fp@2374: void ec_master_queue_datagram(ec_master_t *, ec_datagram_t *); fp@1500: void ec_master_queue_datagram_ext(ec_master_t *, ec_datagram_t *); fp@2374: void ec_master_queue_external_datagram(ec_master_t *, ec_datagram_t *); martin@1597: void ec_master_inject_external_datagrams(ec_master_t *); fp@0: fp@195: // misc. fp@1930: void ec_master_set_send_interval(ec_master_t *, unsigned int); fp@1028: void ec_master_attach_slave_configs(ec_master_t *); fp@927: ec_slave_t *ec_master_find_slave(ec_master_t *, uint16_t, uint16_t); fp@1077: const ec_slave_t *ec_master_find_slave_const(const ec_master_t *, uint16_t, fp@1077: uint16_t); fp@325: void ec_master_output_stats(ec_master_t *); fp@715: #ifdef EC_EOE fp@661: void ec_master_clear_eoe_handlers(ec_master_t *); fp@715: #endif fp@992: void ec_master_clear_slaves(ec_master_t *); fp@325: fp@990: unsigned int ec_master_config_count(const ec_master_t *); fp@1252: ec_slave_config_t *ec_master_get_config( fp@1252: const ec_master_t *, unsigned int); fp@990: const ec_slave_config_t *ec_master_get_config_const( fp@990: const ec_master_t *, unsigned int); fp@946: unsigned int ec_master_domain_count(const ec_master_t *); fp@946: ec_domain_t *ec_master_find_domain(ec_master_t *, unsigned int); fp@1078: const ec_domain_t *ec_master_find_domain_const(const ec_master_t *, fp@1078: unsigned int); fp@1516: #ifdef EC_EOE fp@1485: uint16_t ec_master_eoe_handler_count(const ec_master_t *); fp@1485: const ec_eoe_t *ec_master_get_eoe_handler_const(const ec_master_t *, uint16_t); fp@1516: #endif fp@946: fp@1399: int ec_master_debug_level(ec_master_t *, unsigned int); fp@956: fp@1312: ec_domain_t *ecrt_master_create_domain_err(ec_master_t *); fp@1312: ec_slave_config_t *ecrt_master_slave_config_err(ec_master_t *, uint16_t, fp@1312: uint16_t, uint32_t, uint32_t); fp@1312: fp@1425: void ec_master_calc_dc(ec_master_t *); fp@1925: void ec_master_request_op(ec_master_t *); fp@1425: fp@1513: void ec_master_internal_send_cb(void *); fp@1513: void ec_master_internal_receive_cb(void *); fp@1513: fp@2158: extern const unsigned int rate_intervals[EC_RATE_COUNT]; // see master.c fp@2158: fp@2158: /*****************************************************************************/ fp@2158: fp@2158: #endif