mirror of
https://gitlab.com/etherlab.org/ethercat.git
synced 2026-02-05 19:39:50 +08:00
Merge remote-tracking branch 'origin/devel-1.6' into 84-api-call-for-eoe-set-ip-command
This commit is contained in:
@@ -90,8 +90,8 @@ CFLAGS_rtdm-ioctl.o := @XENOMAI_RTDM_CFLAGS@
|
||||
endif
|
||||
|
||||
ifeq (@ENABLE_RTAI@, 1)
|
||||
CFLAGS_rtdm.o := -I@RTAI_DIR@/include
|
||||
CFLAGS_rtdm-ioctl.o := -I@RTAI_DIR@/include
|
||||
CFLAGS_rtdm.o := @RTAI_KERNEL_CFLAGS@
|
||||
CFLAGS_rtdm-ioctl.o := @RTAI_KERNEL_CFLAGS@
|
||||
endif
|
||||
|
||||
ec_master-objs += rtdm-ioctl.o
|
||||
|
||||
@@ -564,7 +564,7 @@ int ecdev_open(ec_device_t *device /**< EtherCAT device */)
|
||||
|
||||
ret = ec_device_open(device);
|
||||
if (ret) {
|
||||
EC_MASTER_ERR(master, "Failed to open device!\n");
|
||||
EC_MASTER_ERR(master, "Failed to open device: error %d!\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -440,14 +440,14 @@ void ecrt_domain_external_memory(ec_domain_t *domain, uint8_t *mem)
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
uint8_t *ecrt_domain_data(ec_domain_t *domain)
|
||||
uint8_t *ecrt_domain_data(const ec_domain_t *domain)
|
||||
{
|
||||
return domain->data;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
void ecrt_domain_process(ec_domain_t *domain)
|
||||
int ecrt_domain_process(ec_domain_t *domain)
|
||||
{
|
||||
uint16_t wc_sum[EC_MAX_NUM_DEVICES] = {}, wc_total;
|
||||
ec_datagram_pair_t *pair;
|
||||
@@ -633,11 +633,12 @@ void ecrt_domain_process(ec_domain_t *domain)
|
||||
domain->working_counter_changes = 0;
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
void ecrt_domain_queue(ec_domain_t *domain)
|
||||
int ecrt_domain_queue(ec_domain_t *domain)
|
||||
{
|
||||
ec_datagram_pair_t *datagram_pair;
|
||||
ec_device_index_t dev_idx;
|
||||
@@ -663,11 +664,12 @@ void ecrt_domain_queue(ec_domain_t *domain)
|
||||
&datagram_pair->datagrams[dev_idx]);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
void ecrt_domain_state(const ec_domain_t *domain, ec_domain_state_t *state)
|
||||
int ecrt_domain_state(const ec_domain_t *domain, ec_domain_state_t *state)
|
||||
{
|
||||
unsigned int dev_idx;
|
||||
uint16_t wc = 0;
|
||||
@@ -690,6 +692,7 @@ void ecrt_domain_state(const ec_domain_t *domain, ec_domain_state_t *state)
|
||||
}
|
||||
|
||||
state->redundancy_active = domain->redundancy_active;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
@@ -38,6 +38,16 @@
|
||||
#include "mailbox.h"
|
||||
#include "ethernet.h"
|
||||
|
||||
#ifdef CONFIG_SUSE_KERNEL
|
||||
#include <linux/suse_version.h>
|
||||
#else
|
||||
# ifndef SUSE_VERSION
|
||||
# define SUSE_VERSION 0
|
||||
# endif
|
||||
# ifndef SUSE_PATCHLEVEL
|
||||
# define SUSE_PATCHLEVEL 0
|
||||
# endif
|
||||
#endif
|
||||
/****************************************************************************/
|
||||
|
||||
/** Defines the debug level of EoE processing.
|
||||
@@ -156,7 +166,7 @@ int ec_eoe_init(
|
||||
// initialize net_device
|
||||
eoe->dev->netdev_ops = &ec_eoedev_ops;
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0)
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0) || (SUSE_VERSION == 15 && SUSE_PATCHLEVEL >= 5)
|
||||
eth_hw_addr_set(eoe->dev, mac_addr);
|
||||
#else
|
||||
memcpy(eoe->dev->dev_addr, mac_addr, sizeof(mac_addr));
|
||||
@@ -184,7 +194,7 @@ int ec_eoe_init(
|
||||
|
||||
// make the last address octet unique
|
||||
mac_addr[ETH_ALEN - 1] = (uint8_t) eoe->dev->ifindex;
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0)
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0) || (SUSE_VERSION == 15 && SUSE_PATCHLEVEL >= 5)
|
||||
eth_hw_addr_set(eoe->dev, mac_addr);
|
||||
#else
|
||||
memcpy(eoe->dev->dev_addr, mac_addr, sizeof(mac_addr));
|
||||
|
||||
@@ -33,8 +33,11 @@
|
||||
/****************************************************************************/
|
||||
|
||||
/** Timeout while waiting for AL state change [s].
|
||||
*
|
||||
* ETG2000_S_R_V1i0i15 section 5.3.7.2 mentions 10 s as maximum AL state
|
||||
* change timeout.
|
||||
*/
|
||||
#define EC_AL_STATE_CHANGE_TIMEOUT 5
|
||||
#define EC_AL_STATE_CHANGE_TIMEOUT 10
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
|
||||
@@ -1309,7 +1309,7 @@ void ec_fsm_coe_down_start(
|
||||
if (slave->configured_rx_mailbox_size <
|
||||
EC_MBOX_HEADER_SIZE + EC_COE_DOWN_REQ_HEADER_SIZE) {
|
||||
EC_SLAVE_ERR(slave, "Mailbox too small!\n");
|
||||
request->errno = EOVERFLOW;
|
||||
request->errno = ENOBUFS;
|
||||
fsm->state = ec_fsm_coe_error;
|
||||
return;
|
||||
}
|
||||
@@ -2463,7 +2463,7 @@ void ec_fsm_coe_up_seg_response(
|
||||
EC_SLAVE_ERR(slave, "SDO upload 0x%04X:%02X failed: Fragment"
|
||||
" exceeding complete size!\n",
|
||||
request->index, request->subindex);
|
||||
request->errno = EOVERFLOW;
|
||||
request->errno = ENOBUFS;
|
||||
fsm->state = ec_fsm_coe_error;
|
||||
return;
|
||||
}
|
||||
|
||||
501
master/ioctl.c
501
master/ioctl.c
File diff suppressed because it is too large
Load Diff
@@ -60,7 +60,7 @@ uint8_t *ec_slave_mbox_prepare_send(const ec_slave_t *slave, /**< slave */
|
||||
if (unlikely(total_size > slave->configured_rx_mailbox_size)) {
|
||||
EC_SLAVE_ERR(slave, "Data size (%zu) does not fit in mailbox (%u)!\n",
|
||||
total_size, slave->configured_rx_mailbox_size);
|
||||
return ERR_PTR(-EOVERFLOW);
|
||||
return ERR_PTR(-ENOBUFS);
|
||||
}
|
||||
|
||||
ret = ec_datagram_fpwr(datagram, slave->station_address,
|
||||
|
||||
@@ -107,6 +107,8 @@ static int ec_master_eoe_thread(void *);
|
||||
void ec_master_find_dc_ref_clock(ec_master_t *);
|
||||
void ec_master_clear_device_stats(ec_master_t *);
|
||||
void ec_master_update_device_stats(ec_master_t *);
|
||||
static void sc_reset_task_kicker(struct irq_work *work);
|
||||
static void sc_reset_task(struct work_struct *work);
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
@@ -316,6 +318,9 @@ int ec_master_init(ec_master_t *master, /**< EtherCAT master */
|
||||
master->dc_ref_config = NULL;
|
||||
master->dc_ref_clock = NULL;
|
||||
|
||||
INIT_WORK(&master->sc_reset_work, sc_reset_task);
|
||||
init_irq_work(&master->sc_reset_work_kicker, sc_reset_task_kicker);
|
||||
|
||||
// init character device
|
||||
ret = ec_cdev_init(&master->cdev, master, device_number);
|
||||
if (ret)
|
||||
@@ -383,6 +388,9 @@ void ec_master_clear(
|
||||
|
||||
ec_cdev_clear(&master->cdev);
|
||||
|
||||
irq_work_sync(&master->sc_reset_work_kicker);
|
||||
cancel_work_sync(&master->sc_reset_work);
|
||||
|
||||
#ifdef EC_EOE
|
||||
ec_master_clear_eoe_handlers(master);
|
||||
#endif
|
||||
@@ -2342,7 +2350,7 @@ int ecrt_master_activate(ec_master_t *master)
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
void ecrt_master_deactivate(ec_master_t *master)
|
||||
int ecrt_master_deactivate(ec_master_t *master)
|
||||
{
|
||||
ec_slave_t *slave;
|
||||
#ifdef EC_EOE
|
||||
@@ -2354,7 +2362,7 @@ void ecrt_master_deactivate(ec_master_t *master)
|
||||
|
||||
if (!master->active) {
|
||||
EC_MASTER_WARN(master, "%s: Master not active.\n", __func__);
|
||||
return;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ec_master_thread_stop(master);
|
||||
@@ -2408,11 +2416,12 @@ void ecrt_master_deactivate(ec_master_t *master)
|
||||
master->allow_scan = 0;
|
||||
|
||||
master->active = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
void ecrt_master_send(ec_master_t *master)
|
||||
int ecrt_master_send(ec_master_t *master)
|
||||
{
|
||||
ec_datagram_t *datagram, *n;
|
||||
ec_device_index_t dev_idx;
|
||||
@@ -2452,11 +2461,12 @@ void ecrt_master_send(ec_master_t *master)
|
||||
// send frames
|
||||
ec_master_send_datagrams(master, dev_idx);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
void ecrt_master_receive(ec_master_t *master)
|
||||
int ecrt_master_receive(ec_master_t *master)
|
||||
{
|
||||
unsigned int dev_idx;
|
||||
ec_datagram_t *datagram, *next;
|
||||
@@ -2504,11 +2514,12 @@ void ecrt_master_receive(ec_master_t *master)
|
||||
#endif /* RT_SYSLOG */
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
void ecrt_master_send_ext(ec_master_t *master)
|
||||
int ecrt_master_send_ext(ec_master_t *master)
|
||||
{
|
||||
ec_datagram_t *datagram, *next;
|
||||
|
||||
@@ -2520,7 +2531,7 @@ void ecrt_master_send_ext(ec_master_t *master)
|
||||
}
|
||||
up(&master->ext_queue_sem);
|
||||
|
||||
ecrt_master_send(master);
|
||||
return ecrt_master_send(master);
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
@@ -2719,7 +2730,7 @@ void ecrt_master_callbacks(ec_master_t *master,
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
void ecrt_master_state(const ec_master_t *master, ec_master_state_t *state)
|
||||
int ecrt_master_state(const ec_master_t *master, ec_master_state_t *state)
|
||||
{
|
||||
ec_device_index_t dev_idx;
|
||||
|
||||
@@ -2738,6 +2749,7 @@ void ecrt_master_state(const ec_master_t *master, ec_master_state_t *state)
|
||||
/* Signal link up if at least one device has link. */
|
||||
state->link_up |= master->devices[dev_idx].link_state;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
@@ -2758,13 +2770,14 @@ int ecrt_master_link_state(const ec_master_t *master, unsigned int dev_idx,
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
void ecrt_master_application_time(ec_master_t *master, uint64_t app_time)
|
||||
int ecrt_master_application_time(ec_master_t *master, uint64_t app_time)
|
||||
{
|
||||
master->app_time = app_time;
|
||||
|
||||
if (unlikely(!master->dc_ref_time)) {
|
||||
master->dc_ref_time = app_time;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
@@ -2789,17 +2802,20 @@ int ecrt_master_reference_clock_time(const ec_master_t *master,
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
void ecrt_master_sync_reference_clock(ec_master_t *master)
|
||||
int ecrt_master_sync_reference_clock(ec_master_t *master)
|
||||
{
|
||||
if (master->dc_ref_clock) {
|
||||
EC_WRITE_U32(master->ref_sync_datagram.data, master->app_time);
|
||||
ec_master_queue_datagram(master, &master->ref_sync_datagram);
|
||||
} else {
|
||||
return -ENXIO;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
void ecrt_master_sync_reference_clock_to(
|
||||
int ecrt_master_sync_reference_clock_to(
|
||||
ec_master_t *master,
|
||||
uint64_t sync_time
|
||||
)
|
||||
@@ -2807,25 +2823,32 @@ void ecrt_master_sync_reference_clock_to(
|
||||
if (master->dc_ref_clock) {
|
||||
EC_WRITE_U32(master->ref_sync_datagram.data, sync_time);
|
||||
ec_master_queue_datagram(master, &master->ref_sync_datagram);
|
||||
} else {
|
||||
return -ENXIO;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
void ecrt_master_sync_slave_clocks(ec_master_t *master)
|
||||
int ecrt_master_sync_slave_clocks(ec_master_t *master)
|
||||
{
|
||||
if (master->dc_ref_clock) {
|
||||
ec_datagram_zero(&master->sync_datagram);
|
||||
ec_master_queue_datagram(master, &master->sync_datagram);
|
||||
} else {
|
||||
return -ENXIO;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
void ecrt_master_sync_monitor_queue(ec_master_t *master)
|
||||
int ecrt_master_sync_monitor_queue(ec_master_t *master)
|
||||
{
|
||||
ec_datagram_zero(&master->sync_mon_datagram);
|
||||
ec_master_queue_datagram(master, &master->sync_mon_datagram);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
@@ -3069,7 +3092,7 @@ int ecrt_master_sdo_upload(ec_master_t *master, uint16_t slave_position,
|
||||
} else {
|
||||
if (request.data_size > target_size) {
|
||||
EC_SLAVE_ERR(slave, "%s(): Buffer too small.\n", __func__);
|
||||
ret = -EOVERFLOW;
|
||||
ret = -ENOBUFS;
|
||||
}
|
||||
else {
|
||||
memcpy(target, request.data, request.data_size);
|
||||
@@ -3227,7 +3250,7 @@ int ecrt_master_read_idn(ec_master_t *master, uint16_t slave_position,
|
||||
} else { // success
|
||||
if (request.data_size > target_size) {
|
||||
EC_SLAVE_ERR(slave, "%s(): Buffer too small.\n", __func__);
|
||||
ret = -EOVERFLOW;
|
||||
ret = -ENOBUFS;
|
||||
}
|
||||
else { // data fits in buffer
|
||||
if (result_size) {
|
||||
@@ -3244,7 +3267,7 @@ int ecrt_master_read_idn(ec_master_t *master, uint16_t slave_position,
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
void ecrt_master_reset(ec_master_t *master)
|
||||
int ecrt_master_reset(ec_master_t *master)
|
||||
{
|
||||
ec_slave_config_t *sc;
|
||||
|
||||
@@ -3253,6 +3276,28 @@ void ecrt_master_reset(ec_master_t *master)
|
||||
ec_slave_request_state(sc->slave, EC_SLAVE_STATE_OP);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
static void sc_reset_task_kicker(struct irq_work *work)
|
||||
{
|
||||
struct ec_master *master =
|
||||
container_of(work, struct ec_master, sc_reset_work_kicker);
|
||||
schedule_work(&master->sc_reset_work);
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
static void sc_reset_task(struct work_struct *work)
|
||||
{
|
||||
struct ec_master *master =
|
||||
container_of(work, struct ec_master, sc_reset_work);
|
||||
|
||||
down(&master->master_sem);
|
||||
ecrt_master_reset(master);
|
||||
up(&master->master_sem);
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
@@ -30,11 +30,13 @@
|
||||
#define __EC_MASTER_H__
|
||||
|
||||
#include <linux/version.h>
|
||||
#include <linux/irq_work.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/timer.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/kthread.h>
|
||||
#include <linux/rtmutex.h>
|
||||
#include <linux/workqueue.h>
|
||||
|
||||
#include "device.h"
|
||||
#include "domain.h"
|
||||
@@ -294,6 +296,9 @@ struct ec_master {
|
||||
|
||||
wait_queue_head_t request_queue; /**< Wait queue for external requests
|
||||
from user space. */
|
||||
struct work_struct sc_reset_work; /**< Task to reset slave configuration. */
|
||||
struct irq_work sc_reset_work_kicker; /**< NMI-Safe kicker to trigger
|
||||
reset task above. */
|
||||
};
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
@@ -89,24 +89,26 @@ ec_request_state_t ecrt_reg_request_state(const ec_reg_request_t *reg)
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
void ecrt_reg_request_write(ec_reg_request_t *reg, uint16_t address,
|
||||
int ecrt_reg_request_write(ec_reg_request_t *reg, uint16_t address,
|
||||
size_t size)
|
||||
{
|
||||
reg->dir = EC_DIR_OUTPUT;
|
||||
reg->address = address;
|
||||
reg->transfer_size = min(size, reg->mem_size);
|
||||
reg->state = EC_INT_REQUEST_QUEUED;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
void ecrt_reg_request_read(ec_reg_request_t *reg, uint16_t address,
|
||||
int ecrt_reg_request_read(ec_reg_request_t *reg, uint16_t address,
|
||||
size_t size)
|
||||
{
|
||||
reg->dir = EC_DIR_INPUT;
|
||||
reg->address = address;
|
||||
reg->transfer_size = min(size, reg->mem_size);
|
||||
reg->state = EC_INT_REQUEST_QUEUED;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
@@ -28,13 +28,15 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/mman.h>
|
||||
|
||||
#include <rtdm/rtdm_driver.h>
|
||||
|
||||
#include "master.h"
|
||||
#include "ioctl.h"
|
||||
#include "rtdm.h"
|
||||
#include "rtdm_details.h"
|
||||
|
||||
/* include last because it does some redefinitions */
|
||||
#include <rtdm/rtdm_driver.h>
|
||||
|
||||
/** Set to 1 to enable device operations debugging.
|
||||
*/
|
||||
#define DEBUG 0
|
||||
@@ -43,10 +45,11 @@
|
||||
|
||||
static int ec_rtdm_open(struct rtdm_dev_context *, rtdm_user_info_t *, int);
|
||||
static int ec_rtdm_close(struct rtdm_dev_context *, rtdm_user_info_t *);
|
||||
static int ec_rtdm_ioctl_nrt_handler(struct rtdm_dev_context *, rtdm_user_info_t *,
|
||||
unsigned int, void __user *);
|
||||
static int ec_rtdm_ioctl_rt_handler(struct rtdm_dev_context *, rtdm_user_info_t *,
|
||||
unsigned int, void __user *);
|
||||
static int ec_rtdm_ioctl_nrt_handler(struct rtdm_dev_context *,
|
||||
rtdm_user_info_t *, unsigned int, void __user *);
|
||||
static int ec_rtdm_ioctl_rt_handler(struct rtdm_dev_context *,
|
||||
rtdm_user_info_t *, unsigned int, void __user *);
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
/** Initialize an RTDM device.
|
||||
@@ -198,6 +201,8 @@ static int ec_rtdm_ioctl_nrt_handler(
|
||||
return ec_ioctl_rtdm_nrt(rtdm_dev->master, &ctx->ioctl_ctx, request, arg);
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
static int ec_rtdm_ioctl_rt_handler(
|
||||
struct rtdm_dev_context *context, /**< Context. */
|
||||
rtdm_user_info_t *user_info, /**< User data. */
|
||||
@@ -214,7 +219,8 @@ static int ec_rtdm_ioctl_rt_handler(
|
||||
" on RTDM device %s.\n", request, _IOC_NR(request),
|
||||
context->device->device_name);
|
||||
#endif
|
||||
result = ec_ioctl_rtdm_rt(rtdm_dev->master, &ctx->ioctl_ctx, request, arg);
|
||||
result =
|
||||
ec_ioctl_rtdm_rt(rtdm_dev->master, &ctx->ioctl_ctx, request, arg);
|
||||
|
||||
if (result == -ENOTTY) {
|
||||
/* Try again with nrt ioctl handler above in secondary mode. */
|
||||
|
||||
@@ -16,13 +16,8 @@
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with the IgH EtherCAT master. 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
#ifndef __EC_RTDM_DETAILS_H__
|
||||
#define __EC_RTDM_DETAILS_H__
|
||||
|
||||
@@ -60,5 +55,6 @@ static inline EC_RTDM_USERFD_T *ec_ioctl_to_rtdm(ec_ioctl_context_t *ctx)
|
||||
return container_of(ctx, ec_rtdm_context_t, ioctl_ctx)->user_fd;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
#endif // __EC_RTDM_DETAILS_H__
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
/*****************************************************************************
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2009-2010 Moehwald GmbH B. Benner
|
||||
* 2011 IgH Andreas Stewering-Bone
|
||||
* 2012 Florian Pose <fp@igh-essen.com>
|
||||
* 2012 Florian Pose <fp@igh.de>
|
||||
*
|
||||
* This file is part of the IgH EtherCAT master.
|
||||
*
|
||||
@@ -20,10 +18,6 @@
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with the IgH EtherCAT master. 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/** \file
|
||||
@@ -43,6 +37,8 @@
|
||||
*/
|
||||
#define DEBUG_RTDM 0
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
static int ec_rtdm_open(struct rtdm_fd *fd, int oflags)
|
||||
{
|
||||
struct ec_rtdm_context *ctx = rtdm_fd_to_private(fd);
|
||||
@@ -66,6 +62,8 @@ static int ec_rtdm_open(struct rtdm_fd *fd, int oflags)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
static void ec_rtdm_close(struct rtdm_fd *fd)
|
||||
{
|
||||
struct ec_rtdm_context *ctx = rtdm_fd_to_private(fd);
|
||||
@@ -84,6 +82,8 @@ static void ec_rtdm_close(struct rtdm_fd *fd)
|
||||
#endif
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
static int ec_rtdm_ioctl_rt_handler(struct rtdm_fd *fd, unsigned int request,
|
||||
void __user *arg)
|
||||
{
|
||||
@@ -92,7 +92,8 @@ static int ec_rtdm_ioctl_rt_handler(struct rtdm_fd *fd, unsigned int request,
|
||||
struct rtdm_device *dev = rtdm_fd_device(fd);
|
||||
ec_rtdm_dev_t *rtdm_dev = dev->device_data;
|
||||
|
||||
result = ec_ioctl_rtdm_rt(rtdm_dev->master, &ctx->ioctl_ctx, request, arg);
|
||||
result =
|
||||
ec_ioctl_rtdm_rt(rtdm_dev->master, &ctx->ioctl_ctx, request, arg);
|
||||
|
||||
if (result == -ENOTTY)
|
||||
/* Try again with nrt ioctl handler below in secondary mode. */
|
||||
@@ -101,6 +102,8 @@ static int ec_rtdm_ioctl_rt_handler(struct rtdm_fd *fd, unsigned int request,
|
||||
return result;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
static int ec_rtdm_ioctl_nrt_handler(struct rtdm_fd *fd, unsigned int request,
|
||||
void __user *arg)
|
||||
{
|
||||
@@ -111,12 +114,17 @@ static int ec_rtdm_ioctl_nrt_handler(struct rtdm_fd *fd, unsigned int request,
|
||||
return ec_ioctl_rtdm_nrt(rtdm_dev->master, &ctx->ioctl_ctx, request, arg);
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
static int ec_rtdm_mmap(struct rtdm_fd *fd, struct vm_area_struct *vma)
|
||||
{
|
||||
struct ec_rtdm_context *ctx = (struct ec_rtdm_context *) rtdm_fd_to_private(fd);
|
||||
struct ec_rtdm_context *ctx =
|
||||
(struct ec_rtdm_context *) rtdm_fd_to_private(fd);
|
||||
return rtdm_mmap_kmem(vma, (void *)ctx->ioctl_ctx.process_data);
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
static struct rtdm_driver ec_rtdm_driver = {
|
||||
.profile_info = RTDM_PROFILE_INFO(ec_rtdm,
|
||||
RTDM_CLASS_EXPERIMENTAL,
|
||||
@@ -134,6 +142,8 @@ static struct rtdm_driver ec_rtdm_driver = {
|
||||
},
|
||||
};
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
int ec_rtdm_dev_init(ec_rtdm_dev_t *rtdm_dev, ec_master_t *master)
|
||||
{
|
||||
struct rtdm_device *dev;
|
||||
@@ -167,6 +177,8 @@ int ec_rtdm_dev_init(ec_rtdm_dev_t *rtdm_dev, ec_master_t *master)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
void ec_rtdm_dev_clear(ec_rtdm_dev_t *rtdm_dev)
|
||||
{
|
||||
rtdm_dev_unregister(rtdm_dev->dev);
|
||||
@@ -176,3 +188,5 @@ void ec_rtdm_dev_clear(ec_rtdm_dev_t *rtdm_dev)
|
||||
|
||||
kfree(rtdm_dev->dev);
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
@@ -178,18 +178,20 @@ int ec_sdo_request_timed_out(const ec_sdo_request_t *req /**< SDO request. */)
|
||||
* Application interface.
|
||||
****************************************************************************/
|
||||
|
||||
void ecrt_sdo_request_index(ec_sdo_request_t *req, uint16_t index,
|
||||
int ecrt_sdo_request_index(ec_sdo_request_t *req, uint16_t index,
|
||||
uint8_t subindex)
|
||||
{
|
||||
req->index = index;
|
||||
req->subindex = subindex;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
void ecrt_sdo_request_timeout(ec_sdo_request_t *req, uint32_t timeout)
|
||||
int ecrt_sdo_request_timeout(ec_sdo_request_t *req, uint32_t timeout)
|
||||
{
|
||||
req->issue_timeout = timeout;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
@@ -215,24 +217,26 @@ ec_request_state_t ecrt_sdo_request_state(const ec_sdo_request_t *req)
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
void ecrt_sdo_request_read(ec_sdo_request_t *req)
|
||||
int ecrt_sdo_request_read(ec_sdo_request_t *req)
|
||||
{
|
||||
req->dir = EC_DIR_INPUT;
|
||||
req->state = EC_INT_REQUEST_QUEUED;
|
||||
req->errno = 0;
|
||||
req->abort_code = 0x00000000;
|
||||
req->jiffies_start = jiffies;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
void ecrt_sdo_request_write(ec_sdo_request_t *req)
|
||||
int ecrt_sdo_request_write(ec_sdo_request_t *req)
|
||||
{
|
||||
req->dir = EC_DIR_OUTPUT;
|
||||
req->state = EC_INT_REQUEST_QUEUED;
|
||||
req->errno = 0;
|
||||
req->abort_code = 0x00000000;
|
||||
req->jiffies_start = jiffies;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
@@ -656,7 +656,7 @@ int ecrt_slave_config_sync_manager(ec_slave_config_t *sc, uint8_t sync_index,
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
void ecrt_slave_config_watchdog(ec_slave_config_t *sc,
|
||||
int ecrt_slave_config_watchdog(ec_slave_config_t *sc,
|
||||
uint16_t divider, uint16_t intervals)
|
||||
{
|
||||
EC_CONFIG_DBG(sc, 1, "%s(sc = 0x%p, divider = %u, intervals = %u)\n",
|
||||
@@ -664,6 +664,7 @@ void ecrt_slave_config_watchdog(ec_slave_config_t *sc,
|
||||
|
||||
sc->watchdog_divider = divider;
|
||||
sc->watchdog_intervals = intervals;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
@@ -698,7 +699,7 @@ int ecrt_slave_config_pdo_assign_add(ec_slave_config_t *sc,
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
void ecrt_slave_config_pdo_assign_clear(ec_slave_config_t *sc,
|
||||
int ecrt_slave_config_pdo_assign_clear(ec_slave_config_t *sc,
|
||||
uint8_t sync_index)
|
||||
{
|
||||
EC_CONFIG_DBG(sc, 1, "%s(sc = 0x%p, sync_index = %u)\n",
|
||||
@@ -706,12 +707,13 @@ void ecrt_slave_config_pdo_assign_clear(ec_slave_config_t *sc,
|
||||
|
||||
if (sync_index >= EC_MAX_SYNC_MANAGERS) {
|
||||
EC_CONFIG_ERR(sc, "Invalid sync manager index %u!\n", sync_index);
|
||||
return;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
down(&sc->master->master_sem);
|
||||
ec_pdo_list_clear_pdos(&sc->sync_configs[sync_index].pdos);
|
||||
up(&sc->master->master_sem);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
@@ -753,7 +755,7 @@ int ecrt_slave_config_pdo_mapping_add(ec_slave_config_t *sc,
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
void ecrt_slave_config_pdo_mapping_clear(ec_slave_config_t *sc,
|
||||
int ecrt_slave_config_pdo_mapping_clear(ec_slave_config_t *sc,
|
||||
uint16_t pdo_index)
|
||||
{
|
||||
uint8_t sync_index;
|
||||
@@ -774,6 +776,7 @@ void ecrt_slave_config_pdo_mapping_clear(ec_slave_config_t *sc,
|
||||
} else {
|
||||
EC_CONFIG_WARN(sc, "PDO 0x%04X is not assigned.\n", pdo_index);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
@@ -965,7 +968,7 @@ int ecrt_slave_config_reg_pdo_entry_pos(
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
void ecrt_slave_config_dc(ec_slave_config_t *sc, uint16_t assign_activate,
|
||||
int ecrt_slave_config_dc(ec_slave_config_t *sc, uint16_t assign_activate,
|
||||
uint32_t sync0_cycle_time, int32_t sync0_shift_time,
|
||||
uint32_t sync1_cycle_time, int32_t sync1_shift_time)
|
||||
{
|
||||
@@ -980,6 +983,7 @@ void ecrt_slave_config_dc(ec_slave_config_t *sc, uint16_t assign_activate,
|
||||
sc->dc_sync[0].shift_time = sync0_shift_time;
|
||||
sc->dc_sync[1].cycle_time = sync1_cycle_time;
|
||||
sc->dc_sync[1].shift_time = sync1_shift_time;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
@@ -1326,19 +1330,21 @@ ec_voe_handler_t *ecrt_slave_config_create_voe_handler(
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
void ecrt_slave_config_state(const ec_slave_config_t *sc,
|
||||
int ecrt_slave_config_state(const ec_slave_config_t *sc,
|
||||
ec_slave_config_state_t *state)
|
||||
{
|
||||
state->online = sc->slave ? 1 : 0;
|
||||
const ec_slave_t *slave = sc->slave;
|
||||
|
||||
state->online = slave ? 1 : 0;
|
||||
if (state->online) {
|
||||
state->operational =
|
||||
sc->slave->current_state == EC_SLAVE_STATE_OP
|
||||
&& !sc->slave->force_config;
|
||||
state->al_state = sc->slave->current_state;
|
||||
slave->current_state == EC_SLAVE_STATE_OP && !slave->force_config;
|
||||
state->al_state = slave->current_state;
|
||||
} else {
|
||||
state->operational = 0;
|
||||
state->al_state = EC_SLAVE_STATE_UNKNOWN;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
@@ -223,7 +223,7 @@ int ec_soe_request_append_data(
|
||||
|
||||
/** Request a read operation.
|
||||
*/
|
||||
void ec_soe_request_read(
|
||||
int ec_soe_request_read(
|
||||
ec_soe_request_t *req /**< SoE request. */
|
||||
)
|
||||
{
|
||||
@@ -231,13 +231,14 @@ void ec_soe_request_read(
|
||||
req->state = EC_INT_REQUEST_QUEUED;
|
||||
req->error_code = 0x0000;
|
||||
req->jiffies_start = jiffies;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
/** Request a write operation.
|
||||
*/
|
||||
void ec_soe_request_write(
|
||||
int ec_soe_request_write(
|
||||
ec_soe_request_t *req /**< SoE request. */
|
||||
)
|
||||
{
|
||||
@@ -245,6 +246,7 @@ void ec_soe_request_write(
|
||||
req->state = EC_INT_REQUEST_QUEUED;
|
||||
req->error_code = 0x0000;
|
||||
req->jiffies_start = jiffies;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
@@ -263,18 +265,20 @@ int ec_soe_request_timed_out(const ec_soe_request_t *req /**< SDO request. */)
|
||||
* Application interface.
|
||||
****************************************************************************/
|
||||
|
||||
void ecrt_soe_request_idn(ec_soe_request_t *req, uint8_t drive_no,
|
||||
int ecrt_soe_request_idn(ec_soe_request_t *req, uint8_t drive_no,
|
||||
uint16_t idn)
|
||||
{
|
||||
req->drive_no = drive_no;
|
||||
req->idn = idn;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
void ecrt_soe_request_timeout(ec_soe_request_t *req, uint32_t timeout)
|
||||
int ecrt_soe_request_timeout(ec_soe_request_t *req, uint32_t timeout)
|
||||
{
|
||||
req->issue_timeout = timeout;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
@@ -293,23 +297,23 @@ size_t ecrt_soe_request_data_size(const ec_soe_request_t *req)
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
ec_request_state_t ecrt_soe_request_state(ec_soe_request_t *req)
|
||||
ec_request_state_t ecrt_soe_request_state(const ec_soe_request_t *req)
|
||||
{
|
||||
return ec_request_state_translation_table[req->state];
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
void ecrt_soe_request_read(ec_soe_request_t *req)
|
||||
int ecrt_soe_request_read(ec_soe_request_t *req)
|
||||
{
|
||||
ec_soe_request_read(req);
|
||||
return ec_soe_request_read(req);
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
void ecrt_soe_request_write(ec_soe_request_t *req)
|
||||
int ecrt_soe_request_write(ec_soe_request_t *req)
|
||||
{
|
||||
ec_soe_request_write(req);
|
||||
return ec_soe_request_write(req);
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
@@ -67,8 +67,8 @@ void ec_soe_request_set_idn(ec_soe_request_t *, uint16_t);
|
||||
int ec_soe_request_alloc(ec_soe_request_t *, size_t);
|
||||
int ec_soe_request_copy_data(ec_soe_request_t *, const uint8_t *, size_t);
|
||||
int ec_soe_request_append_data(ec_soe_request_t *, const uint8_t *, size_t);
|
||||
void ec_soe_request_read(ec_soe_request_t *);
|
||||
void ec_soe_request_write(ec_soe_request_t *);
|
||||
int ec_soe_request_read(ec_soe_request_t *);
|
||||
int ec_soe_request_write(ec_soe_request_t *);
|
||||
int ec_soe_request_timed_out(const ec_soe_request_t *);
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
@@ -112,16 +112,17 @@ size_t ec_voe_handler_mem_size(
|
||||
* Application interface.
|
||||
****************************************************************************/
|
||||
|
||||
void ecrt_voe_handler_send_header(ec_voe_handler_t *voe, uint32_t vendor_id,
|
||||
int ecrt_voe_handler_send_header(ec_voe_handler_t *voe, uint32_t vendor_id,
|
||||
uint16_t vendor_type)
|
||||
{
|
||||
voe->vendor_id = vendor_id;
|
||||
voe->vendor_type = vendor_type;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
void ecrt_voe_handler_received_header(const ec_voe_handler_t *voe,
|
||||
int ecrt_voe_handler_received_header(const ec_voe_handler_t *voe,
|
||||
uint32_t *vendor_id, uint16_t *vendor_type)
|
||||
{
|
||||
uint8_t *header = voe->datagram.data + EC_MBOX_HEADER_SIZE;
|
||||
@@ -130,6 +131,7 @@ void ecrt_voe_handler_received_header(const ec_voe_handler_t *voe,
|
||||
*vendor_id = EC_READ_U32(header);
|
||||
if (vendor_type)
|
||||
*vendor_type = EC_READ_U16(header + 4);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
@@ -148,30 +150,33 @@ size_t ecrt_voe_handler_data_size(const ec_voe_handler_t *voe)
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
void ecrt_voe_handler_read(ec_voe_handler_t *voe)
|
||||
int ecrt_voe_handler_read(ec_voe_handler_t *voe)
|
||||
{
|
||||
voe->dir = EC_DIR_INPUT;
|
||||
voe->state = ec_voe_handler_state_read_start;
|
||||
voe->request_state = EC_INT_REQUEST_BUSY;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
void ecrt_voe_handler_read_nosync(ec_voe_handler_t *voe)
|
||||
int ecrt_voe_handler_read_nosync(ec_voe_handler_t *voe)
|
||||
{
|
||||
voe->dir = EC_DIR_INPUT;
|
||||
voe->state = ec_voe_handler_state_read_nosync_start;
|
||||
voe->request_state = EC_INT_REQUEST_BUSY;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
void ecrt_voe_handler_write(ec_voe_handler_t *voe, size_t size)
|
||||
int ecrt_voe_handler_write(ec_voe_handler_t *voe, size_t size)
|
||||
{
|
||||
voe->dir = EC_DIR_OUTPUT;
|
||||
voe->data_size = size;
|
||||
voe->state = ec_voe_handler_state_write_start;
|
||||
voe->request_state = EC_INT_REQUEST_BUSY;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
Reference in New Issue
Block a user