fp@1255: /******************************************************************************
fp@2421: *
fp@1326: * $Id$
fp@2421: *
fp@1326: * Copyright (C) 2006-2009 Florian Pose, Ingenieurgemeinschaft IgH
fp@2421: *
fp@1326: * This file is part of the IgH EtherCAT master userspace library.
fp@2421: *
fp@1326: * The IgH EtherCAT master userspace library is free software; you can
fp@1326: * redistribute it and/or modify it under the terms of the GNU Lesser General
fp@1326: * Public License as published by the Free Software Foundation; version 2.1
fp@1326: * of the License.
fp@1287: *
fp@1326: * The IgH EtherCAT master userspace library is distributed in the hope that
fp@1326: * it will be useful, but WITHOUT ANY WARRANTY; without even the implied
fp@1326: * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
fp@1326: * GNU Lesser General Public License for more details.
fp@1287: *
fp@1326: * You should have received a copy of the GNU Lesser General Public License
fp@1326: * along with the IgH EtherCAT master userspace library. If not, see
fp@1326: * .
fp@2421: *
fp@1363: * ---
fp@2421: *
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@1255: *
fp@1255: *****************************************************************************/
fp@1255:
fp@1255: #include
fp@1255: #include
fp@1255: #include
fp@1255: #include
fp@1255: #include
fp@1255:
fp@1255: #include "slave_config.h"
fp@1255: #include "domain.h"
fp@1352: #include "sdo_request.h"
fp@1264: #include "voe_handler.h"
fp@1255: #include "master.h"
fp@1255: #include "master/ioctl.h"
fp@1255:
fp@1255: /*****************************************************************************/
fp@1255:
fp@1959: void ec_slave_config_clear(ec_slave_config_t *sc)
fp@1959: {
fp@1959: ec_sdo_request_t *r, *next_r;
fp@1959: ec_voe_handler_t *v, *next_v;
fp@1959:
fp@1959: r = sc->first_sdo_request;
fp@1959: while (r) {
fp@1959: next_r = r->next;
fp@1959: ec_sdo_request_clear(r);
fp@1959: r = next_r;
fp@1959: }
fp@1959:
fp@1959:
fp@1959: v = sc->first_voe_handler;
fp@1959: while (v) {
fp@1959: next_v = v->next;
fp@1959: ec_voe_handler_clear(v);
fp@1959: v = next_v;
fp@1959: }
fp@1959: }
fp@1959:
fp@1959: /*****************************************************************************/
fp@1959:
fp@1255: int ecrt_slave_config_sync_manager(ec_slave_config_t *sc, uint8_t sync_index,
fp@1509: ec_direction_t dir, ec_watchdog_mode_t watchdog_mode)
fp@1255: {
fp@1255: ec_ioctl_config_t data;
fp@1255:
fp@1255: if (sync_index >= EC_MAX_SYNC_MANAGERS)
fp@1313: return -ENOENT;
fp@1255:
fp@1255: memset(&data, 0x00, sizeof(ec_ioctl_config_t));
fp@1255: data.config_index = sc->index;
fp@1255: data.syncs[sync_index].dir = dir;
fp@1509: data.syncs[sync_index].watchdog_mode = watchdog_mode;
fp@1509: data.syncs[sync_index].config_this = 1;
fp@1255:
fp@1255: if (ioctl(sc->master->fd, EC_IOCTL_SC_SYNC, &data) == -1) {
fp@1255: fprintf(stderr, "Failed to config sync manager: %s\n",
fp@1255: strerror(errno));
fp@1313: return -1; // FIXME
fp@1255: }
fp@2421:
fp@1255: return 0;
fp@1255: }
fp@1255:
fp@1255: /*****************************************************************************/
fp@1255:
fp@1509: void ecrt_slave_config_watchdog(ec_slave_config_t *sc,
fp@1509: uint16_t divider, uint16_t intervals)
fp@1509: {
fp@1509: ec_ioctl_config_t data;
fp@1509:
fp@1509: memset(&data, 0x00, sizeof(ec_ioctl_config_t));
fp@1509: data.config_index = sc->index;
fp@1509: data.watchdog_divider = divider;
fp@1509: data.watchdog_intervals = intervals;
fp@1509:
fp@1509: if (ioctl(sc->master->fd, EC_IOCTL_SC_WATCHDOG, &data) == -1) {
fp@1509: fprintf(stderr, "Failed to config watchdog: %s\n",
fp@1509: strerror(errno));
fp@1509: }
fp@1509: }
fp@1509:
fp@1509: /*****************************************************************************/
fp@1509:
fp@1255: int ecrt_slave_config_pdo_assign_add(ec_slave_config_t *sc,
fp@1255: uint8_t sync_index, uint16_t pdo_index)
fp@1255: {
fp@1255: ec_ioctl_config_pdo_t data;
fp@1255:
fp@1255: data.config_index = sc->index;
fp@1255: data.sync_index = sync_index;
fp@1255: data.index = pdo_index;
fp@1255:
fp@1255: if (ioctl(sc->master->fd, EC_IOCTL_SC_ADD_PDO, &data) == -1) {
fp@1327: fprintf(stderr, "Failed to add PDO: %s\n",
fp@1255: strerror(errno));
fp@1313: return -1; // FIXME
fp@1255: }
fp@2421:
fp@1255: return 0;
fp@1255: }
fp@1255:
fp@1255: /*****************************************************************************/
fp@1255:
fp@1255: void ecrt_slave_config_pdo_assign_clear(ec_slave_config_t *sc,
fp@1255: uint8_t sync_index)
fp@1255: {
fp@1255: ec_ioctl_config_pdo_t data;
fp@1255:
fp@1255: data.config_index = sc->index;
fp@1255: data.sync_index = sync_index;
fp@1255:
fp@1255: if (ioctl(sc->master->fd, EC_IOCTL_SC_CLEAR_PDOS, &data) == -1) {
fp@1327: fprintf(stderr, "Failed to clear PDOs: %s\n",
fp@1255: strerror(errno));
fp@1255: }
fp@1255: }
fp@1255:
fp@1255: /*****************************************************************************/
fp@1255:
fp@1255: int ecrt_slave_config_pdo_mapping_add(ec_slave_config_t *sc,
fp@1255: uint16_t pdo_index, uint16_t entry_index, uint8_t entry_subindex,
fp@1255: uint8_t entry_bit_length)
fp@1255: {
fp@1255: ec_ioctl_add_pdo_entry_t data;
fp@1255:
fp@1255: data.config_index = sc->index;
fp@1255: data.pdo_index = pdo_index;
fp@1255: data.entry_index = entry_index;
fp@1255: data.entry_subindex = entry_subindex;
fp@1255: data.entry_bit_length = entry_bit_length;
fp@1255:
fp@1255: if (ioctl(sc->master->fd, EC_IOCTL_SC_ADD_ENTRY, &data) == -1) {
fp@1327: fprintf(stderr, "Failed to add PDO entry: %s\n",
fp@1255: strerror(errno));
fp@1313: return -1; // FIXME
fp@1255: }
fp@2421:
fp@1255: return 0;
fp@1255: }
fp@1255:
fp@1255: /*****************************************************************************/
fp@1255:
fp@1255: void ecrt_slave_config_pdo_mapping_clear(ec_slave_config_t *sc,
fp@1255: uint16_t pdo_index)
fp@1255: {
fp@1255: ec_ioctl_config_pdo_t data;
fp@1255:
fp@1255: data.config_index = sc->index;
fp@1255: data.index = pdo_index;
fp@1255:
fp@1255: if (ioctl(sc->master->fd, EC_IOCTL_SC_CLEAR_ENTRIES, &data) == -1) {
fp@1327: fprintf(stderr, "Failed to clear PDO entries: %s\n",
fp@1255: strerror(errno));
fp@1255: }
fp@1255: }
fp@1255:
fp@1255: /*****************************************************************************/
fp@1255:
fp@1255: int ecrt_slave_config_pdos(ec_slave_config_t *sc,
fp@1255: unsigned int n_syncs, const ec_sync_info_t syncs[])
fp@1255: {
fp@1313: int ret;
fp@1255: unsigned int i, j, k;
fp@1255: const ec_sync_info_t *sync_info;
fp@1255: const ec_pdo_info_t *pdo_info;
fp@1255: const ec_pdo_entry_info_t *entry_info;
fp@1255:
fp@1255: if (!syncs)
fp@1255: return 0;
fp@1255:
fp@1255: for (i = 0; i < n_syncs; i++) {
fp@1255: sync_info = &syncs[i];
fp@1255:
fp@1255: if (sync_info->index == (uint8_t) EC_END)
fp@1255: break;
fp@1255:
fp@1255: if (sync_info->index >= EC_MAX_SYNC_MANAGERS) {
fp@1255: fprintf(stderr, "Invalid sync manager index %u!\n",
fp@1255: sync_info->index);
fp@1313: return -ENOENT;
fp@1255: }
fp@1255:
fp@1509: ret = ecrt_slave_config_sync_manager(sc, sync_info->index,
fp@1509: sync_info->dir, sync_info->watchdog_mode);
fp@1313: if (ret)
fp@1313: return ret;
fp@1255:
fp@1255: if (sync_info->n_pdos && sync_info->pdos) {
fp@1255: ecrt_slave_config_pdo_assign_clear(sc, sync_info->index);
fp@1255:
fp@1255: for (j = 0; j < sync_info->n_pdos; j++) {
fp@1255: pdo_info = &sync_info->pdos[j];
fp@1255:
fp@1313: ret = ecrt_slave_config_pdo_assign_add(
fp@1313: sc, sync_info->index, pdo_info->index);
fp@1313: if (ret)
fp@1313: return ret;
fp@1255:
fp@1255: if (pdo_info->n_entries && pdo_info->entries) {
fp@1255: ecrt_slave_config_pdo_mapping_clear(sc, pdo_info->index);
fp@1255:
fp@1255: for (k = 0; k < pdo_info->n_entries; k++) {
fp@1255: entry_info = &pdo_info->entries[k];
fp@1255:
fp@1313: ret = ecrt_slave_config_pdo_mapping_add(sc,
fp@1313: pdo_info->index, entry_info->index,
fp@1313: entry_info->subindex,
fp@1313: entry_info->bit_length);
fp@1313: if (ret)
fp@1313: return ret;
fp@1255: }
fp@1255: }
fp@1255: }
fp@1255: }
fp@1255: }
fp@1255:
fp@1255: return 0;
fp@1255: }
fp@1255:
fp@1255: /*****************************************************************************/
fp@1255:
fp@1255: int ecrt_slave_config_reg_pdo_entry(
fp@1255: ec_slave_config_t *sc,
fp@1255: uint16_t index,
fp@1255: uint8_t subindex,
fp@1255: ec_domain_t *domain,
fp@1255: unsigned int *bit_position
fp@1255: )
fp@1255: {
fp@1255: ec_ioctl_reg_pdo_entry_t data;
fp@1255: int ret;
fp@1255:
fp@1255: data.config_index = sc->index;
fp@1255: data.entry_index = index;
fp@1255: data.entry_subindex = subindex;
fp@1255: data.domain_index = domain->index;
fp@1255:
fp@1255: ret = ioctl(sc->master->fd, EC_IOCTL_SC_REG_PDO_ENTRY, &data);
fp@1255: if (ret == -1) {
fp@1327: fprintf(stderr, "Failed to register PDO entry: %s\n",
fp@1255: strerror(errno));
fp@1313: return -2; // FIXME
fp@1255: }
fp@1255:
fp@1255: if (bit_position) {
fp@1255: *bit_position = data.bit_position;
fp@1255: } else {
fp@1255: if (data.bit_position) {
fp@1327: fprintf(stderr, "PDO entry 0x%04X:%02X does not byte-align "
fp@1255: "in config %u:%u.\n", index, subindex,
fp@1255: sc->alias, sc->position);
fp@1313: return -3; // FIXME
fp@1255: }
fp@1255: }
fp@1255:
fp@1255: return ret;
fp@1255: }
fp@1255:
fp@1255: /*****************************************************************************/
fp@1255:
fp@1448: void ecrt_slave_config_dc(ec_slave_config_t *sc, uint16_t assign_activate,
fp@1438: uint32_t sync0_cycle_time, uint32_t sync0_shift_time,
fp@1438: uint32_t sync1_cycle_time, uint32_t sync1_shift_time)
fp@1413: {
fp@1455: ec_ioctl_config_t data;
fp@1455:
fp@1455: data.config_index = sc->index;
fp@1455: data.dc_assign_activate = assign_activate;
fp@1508: data.dc_sync[0].cycle_time = sync0_cycle_time;
fp@1508: data.dc_sync[0].shift_time = sync0_shift_time;
fp@1508: data.dc_sync[1].cycle_time = sync1_cycle_time;
fp@1508: data.dc_sync[1].shift_time = sync1_shift_time;
fp@1438:
fp@1448: if (ioctl(sc->master->fd, EC_IOCTL_SC_DC, &data) == -1) {
fp@1413: fprintf(stderr, "Failed to set assign_activate word.\n");
fp@1413: }
fp@1413: }
fp@1413:
fp@1413: /*****************************************************************************/
fp@1413:
fp@1255: int ecrt_slave_config_sdo(ec_slave_config_t *sc, uint16_t index,
fp@1255: uint8_t subindex, const uint8_t *sdo_data, size_t size)
fp@1255: {
fp@1255: ec_ioctl_sc_sdo_t data;
fp@1255:
fp@1255: data.config_index = sc->index;
fp@1255: data.index = index;
fp@1255: data.subindex = subindex;
fp@1255: data.data = sdo_data;
fp@1255: data.size = size;
fp@1526: data.complete_access = 0;
fp@1526:
fp@1526: if (ioctl(sc->master->fd, EC_IOCTL_SC_SDO, &data) == -1) {
fp@1526: fprintf(stderr, "Failed to configure SDO.\n");
fp@1526: return -1; // FIXME
fp@1526: }
fp@1526:
fp@1526: return 0;
fp@1526: }
fp@1526:
fp@1526: /*****************************************************************************/
fp@1526:
fp@1526: int ecrt_slave_config_complete_sdo(ec_slave_config_t *sc, uint16_t index,
fp@1526: const uint8_t *sdo_data, size_t size)
fp@1526: {
fp@1526: ec_ioctl_sc_sdo_t data;
fp@1526:
fp@1526: data.config_index = sc->index;
fp@1526: data.index = index;
fp@1526: data.subindex = 0;
fp@1526: data.data = sdo_data;
fp@1526: data.size = size;
fp@1526: data.complete_access = 1;
fp@1255:
fp@1371: if (ioctl(sc->master->fd, EC_IOCTL_SC_SDO, &data) == -1) {
fp@1327: fprintf(stderr, "Failed to configure SDO.\n");
fp@1313: return -1; // FIXME
fp@1255: }
fp@1255:
fp@1255: return 0;
fp@1255: }
fp@1255:
fp@1255: /*****************************************************************************/
fp@1255:
fp@1255: int ecrt_slave_config_sdo8(ec_slave_config_t *sc, uint16_t index,
fp@1255: uint8_t subindex, uint8_t value)
fp@1255: {
fp@1255: uint8_t data[1];
fp@1255:
fp@1255: EC_WRITE_U8(data, value);
fp@1255: return ecrt_slave_config_sdo(sc, index, subindex, data, 1);
fp@1255: }
fp@1255:
fp@1255: /*****************************************************************************/
fp@1255:
fp@1255: int ecrt_slave_config_sdo16(ec_slave_config_t *sc, uint16_t index,
fp@1255: uint8_t subindex, uint16_t value)
fp@1255: {
fp@1255: uint8_t data[2];
fp@1255:
fp@1255: EC_WRITE_U16(data, value);
fp@1255: return ecrt_slave_config_sdo(sc, index, subindex, data, 2);
fp@1255: }
fp@1255:
fp@1255: /*****************************************************************************/
fp@1255:
fp@1255: int ecrt_slave_config_sdo32(ec_slave_config_t *sc, uint16_t index,
fp@1255: uint8_t subindex, uint32_t value)
fp@1255: {
fp@1255: uint8_t data[4];
fp@1255:
fp@1255: EC_WRITE_U32(data, value);
fp@1255: return ecrt_slave_config_sdo(sc, index, subindex, data, 4);
fp@1255: }
fp@1255:
fp@1255: /*****************************************************************************/
fp@1255:
fp@1959: void ec_slave_config_add_sdo_request(ec_slave_config_t *sc,
fp@1959: ec_sdo_request_t *req)
fp@1959: {
fp@1959: if (sc->first_sdo_request) {
fp@1959: ec_sdo_request_t *r = sc->first_sdo_request;
fp@1959: while (r->next) {
fp@1959: r = r->next;
fp@1959: }
fp@1959: r->next = req;
fp@1959: } else {
fp@1959: sc->first_sdo_request = req;
fp@1959: }
fp@1959: }
fp@1959:
fp@1959: /*****************************************************************************/
fp@1959:
fp@1255: ec_sdo_request_t *ecrt_slave_config_create_sdo_request(ec_slave_config_t *sc,
fp@1255: uint16_t index, uint8_t subindex, size_t size)
fp@1255: {
fp@1352: ec_ioctl_sdo_request_t data;
fp@1352: ec_sdo_request_t *req;
fp@1352:
fp@1352: req = malloc(sizeof(ec_sdo_request_t));
fp@1352: if (!req) {
fp@1352: fprintf(stderr, "Failed to allocate memory.\n");
fp@1352: return 0;
fp@1352: }
fp@1352:
fp@1352: if (size) {
fp@1352: req->data = malloc(size);
fp@1352: if (!req->data) {
fp@1352: fprintf(stderr, "Failed to allocate %u bytes of SDO data"
fp@1352: " memory.\n", size);
fp@1352: free(req);
fp@1352: return 0;
fp@1352: }
fp@1352: } else {
fp@1352: req->data = NULL;
fp@1352: }
fp@1352:
fp@1352: data.config_index = sc->index;
fp@1352: data.sdo_index = index;
fp@1352: data.sdo_subindex = subindex;
fp@1352: data.size = size;
fp@2421:
fp@1352: if (ioctl(sc->master->fd, EC_IOCTL_SC_SDO_REQUEST, &data) == -1) {
fp@1352: fprintf(stderr, "Failed to create SDO request: %s\n",
fp@1352: strerror(errno));
fp@1959: ec_sdo_request_clear(req);
fp@1352: free(req);
fp@2421: return NULL;
fp@1352: }
fp@1352:
fp@1959: req->next = NULL;
fp@1352: req->config = sc;
fp@1352: req->index = data.request_index;
fp@1352: req->sdo_index = data.sdo_index;
fp@1352: req->sdo_subindex = data.sdo_subindex;
fp@1352: req->data_size = size;
fp@1352: req->mem_size = size;
fp@1959:
fp@1959: ec_slave_config_add_sdo_request(sc, req);
fp@1959:
fp@1352: return req;
fp@1255: }
fp@1255:
fp@1255: /*****************************************************************************/
fp@1255:
fp@1959: void ec_slave_config_add_voe_handler(ec_slave_config_t *sc,
fp@1959: ec_voe_handler_t *voe)
fp@1959: {
fp@1959: if (sc->first_voe_handler) {
fp@1959: ec_voe_handler_t *v = sc->first_voe_handler;
fp@1959: while (v->next) {
fp@1959: v = v->next;
fp@1959: }
fp@1959: v->next = voe;
fp@1959: } else {
fp@1959: sc->first_voe_handler = voe;
fp@1959: }
fp@1959: }
fp@1959:
fp@1959: /*****************************************************************************/
fp@1959:
fp@1255: ec_voe_handler_t *ecrt_slave_config_create_voe_handler(ec_slave_config_t *sc,
fp@1255: size_t size)
fp@1255: {
fp@1264: ec_ioctl_voe_t data;
fp@1264: ec_voe_handler_t *voe;
fp@1264:
fp@1264: voe = malloc(sizeof(ec_voe_handler_t));
fp@1264: if (!voe) {
fp@1264: fprintf(stderr, "Failed to allocate memory.\n");
fp@1264: return 0;
fp@1264: }
fp@1264:
fp@1264: if (size) {
fp@1264: voe->data = malloc(size);
fp@1264: if (!voe->data) {
fp@1264: fprintf(stderr, "Failed to allocate %u bytes of VoE data"
fp@1264: " memory.\n", size);
fp@1264: free(voe);
fp@1264: return 0;
fp@1264: }
fp@1264: } else {
fp@1264: voe->data = NULL;
fp@1264: }
fp@1264:
fp@1264: data.config_index = sc->index;
fp@1264: data.size = size;
fp@2421:
fp@1264: if (ioctl(sc->master->fd, EC_IOCTL_SC_VOE, &data) == -1) {
fp@1264: fprintf(stderr, "Failed to create VoE handler: %s\n",
fp@1264: strerror(errno));
fp@1959: ec_voe_handler_clear(voe);
fp@1264: free(voe);
fp@2421: return NULL;
fp@1264: }
fp@1264:
fp@1959: voe->next = NULL;
fp@1264: voe->config = sc;
fp@1264: voe->index = data.voe_index;
fp@1264: voe->data_size = size;
fp@1264: voe->mem_size = size;
fp@1959:
fp@1959: ec_slave_config_add_voe_handler(sc, voe);
fp@1959:
fp@1264: return voe;
fp@1255: }
fp@1255:
fp@1255: /*****************************************************************************/
fp@1255:
fp@1255: void ecrt_slave_config_state(const ec_slave_config_t *sc,
fp@1255: ec_slave_config_state_t *state)
fp@1255: {
fp@1259: ec_ioctl_sc_state_t data;
fp@1259:
fp@1259: data.config_index = sc->index;
fp@1259: data.state = state;
fp@2421:
fp@1259: if (ioctl(sc->master->fd, EC_IOCTL_SC_STATE, &data) == -1) {
fp@1259: fprintf(stderr, "Failed to get slave configuration state: %s\n",
fp@1259: strerror(errno));
fp@1259: }
fp@1259: }
fp@1259:
fp@1259: /*****************************************************************************/
fp@1862:
fp@1952: int ecrt_slave_config_idn(ec_slave_config_t *sc, uint8_t drive_no,
fp@1952: uint16_t idn, ec_al_state_t al_state, const uint8_t *data, size_t size)
fp@1862: {
fp@1862: ec_ioctl_sc_idn_t io;
fp@1862:
fp@1862: io.config_index = sc->index;
fp@1952: io.drive_no = drive_no;
fp@1862: io.idn = idn;
fp@1945: io.al_state = al_state;
fp@1862: io.data = data;
fp@1862: io.size = size;
fp@1862:
fp@1862: if (ioctl(sc->master->fd, EC_IOCTL_SC_IDN, &io) == -1) {
fp@1862: fprintf(stderr, "Failed to configure IDN.\n");
fp@1862: return -1; // FIXME
fp@1862: }
fp@1862:
fp@1862: return 0;
fp@1862: }
fp@1862:
fp@1862: /*****************************************************************************/