fp@792: /****************************************************************************** fp@792: * fp@792: * $Id$ fp@792: * fp@792: * Copyright (C) 2006 Florian Pose, Ingenieurgemeinschaft IgH fp@792: * fp@792: * This file is part of the IgH EtherCAT Master. fp@792: * fp@792: * The IgH EtherCAT Master is free software; you can redistribute it fp@792: * and/or modify it under the terms of the GNU General Public License fp@792: * as published by the Free Software Foundation; either version 2 of the fp@792: * License, or (at your option) any later version. fp@792: * fp@792: * The IgH EtherCAT Master is distributed in the hope that it will be fp@792: * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of fp@792: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the fp@792: * GNU General Public License for more details. fp@792: * fp@792: * You should have received a copy of the GNU General Public License fp@792: * along with the IgH EtherCAT Master; if not, write to the Free Software fp@792: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA fp@792: * fp@792: * The right to use EtherCAT Technology is granted and comes free of fp@792: * charge under condition of compatibility of product made by fp@792: * Licensee. People intending to distribute/sell products based on the fp@792: * code, have to sign an agreement to guarantee that products using fp@792: * software based on IgH EtherCAT master stay compatible with the actual fp@792: * EtherCAT specification (which are released themselves as an open fp@792: * standard) as the (only) precondition to have the right to use EtherCAT fp@792: * Technology, IP and trade marks. fp@792: * fp@792: *****************************************************************************/ fp@792: fp@792: /** fp@792: \file fp@792: EtherCAT slave configuration methods. fp@792: */ fp@792: fp@792: /*****************************************************************************/ fp@792: fp@792: #include fp@792: fp@792: #include "globals.h" fp@792: #include "master.h" fp@792: fp@792: #include "slave_config.h" fp@792: fp@792: /*****************************************************************************/ fp@792: fp@792: void ec_slave_config_clear(struct kobject *); fp@792: ssize_t ec_show_slave_config_attribute(struct kobject *, struct attribute *, fp@792: char *); fp@792: fp@792: /*****************************************************************************/ fp@792: fp@792: /** \cond */ fp@792: fp@792: EC_SYSFS_READ_ATTR(info); fp@792: fp@792: static struct attribute *def_attrs[] = { fp@792: &attr_info, fp@792: NULL, fp@792: }; fp@792: fp@792: static struct sysfs_ops sysfs_ops = { fp@792: .show = ec_show_slave_config_attribute fp@792: }; fp@792: fp@792: static struct kobj_type ktype_ec_slave_config = { fp@792: .release = ec_slave_config_clear, fp@792: .sysfs_ops = &sysfs_ops, fp@792: .default_attrs = def_attrs fp@792: }; fp@792: fp@792: /** \endcond */ fp@792: fp@792: /*****************************************************************************/ fp@792: fp@792: /** Slave configuration constructor. fp@792: * fp@792: * See ecrt_master_slave_config() for the usage of the \a alias and \a fp@792: * position parameters. fp@792: * fp@792: * \retval 0 Success. fp@792: * \retval <0 Failure. fp@792: */ fp@792: int ec_slave_config_init(ec_slave_config_t *sc, /**< Slave configuration. */ fp@792: ec_master_t *master, /**< EtherCAT master. */ fp@792: uint16_t alias, /**< Slave alias. */ fp@792: uint16_t position, /**< Slave position. */ fp@792: uint32_t vendor_id, /**< Expected vendor ID. */ fp@792: uint32_t product_code /**< Expected product code. */ fp@792: ) fp@792: { fp@792: ec_direction_t dir; fp@792: fp@792: sc->master = master; fp@792: sc->alias = alias; fp@792: sc->position = position; fp@792: sc->vendor_id = vendor_id; fp@792: sc->product_code = product_code; fp@792: sc->slave = NULL; fp@792: fp@792: for (dir = EC_DIR_OUTPUT; dir <= EC_DIR_INPUT; dir++) fp@792: ec_pdo_mapping_init(&sc->mapping[dir]); fp@792: fp@792: INIT_LIST_HEAD(&sc->sdo_configs); fp@858: INIT_LIST_HEAD(&sc->sdo_requests); fp@792: fp@792: sc->used_fmmus = 0; fp@792: fp@792: // init kobject and add it to the hierarchy fp@792: memset(&sc->kobj, 0x00, sizeof(struct kobject)); fp@792: kobject_init(&sc->kobj); fp@792: sc->kobj.ktype = &ktype_ec_slave_config; fp@792: sc->kobj.parent = &master->kobj; fp@792: if (kobject_set_name(&sc->kobj, "config-%u-%u", sc->alias, sc->position)) { fp@792: EC_ERR("Failed to set kobject name for slave config %u:%u.\n", fp@792: sc->alias, sc->position); fp@792: goto out_put; fp@792: } fp@792: if (kobject_add(&sc->kobj)) { fp@792: EC_ERR("Failed to add kobject for slave config %u:%u.\n", fp@792: sc->alias, sc->position); fp@792: goto out_put; fp@792: } fp@792: fp@792: return 0; fp@792: fp@792: out_put: fp@792: kobject_put(&sc->kobj); fp@792: return -1; fp@792: } fp@792: fp@792: /*****************************************************************************/ fp@792: fp@792: /** Slave configuration destructor. fp@792: * fp@792: * Clears and frees a slave configuration object. fp@792: */ fp@792: void ec_slave_config_destroy( fp@792: ec_slave_config_t *sc /**< Slave configuration. */ fp@792: ) fp@792: { fp@792: ec_slave_config_detach(sc); fp@792: fp@792: // destroy self fp@792: kobject_del(&sc->kobj); fp@792: kobject_put(&sc->kobj); fp@792: } fp@792: fp@792: /*****************************************************************************/ fp@792: fp@792: /** Clear and free the slave configuration. fp@792: * fp@792: * This method is called by the kobject, once there are no more references to fp@792: * it. fp@792: */ fp@792: void ec_slave_config_clear(struct kobject *kobj /**< kobject of the config. */) fp@792: { fp@792: ec_slave_config_t *sc; fp@792: ec_direction_t dir; fp@854: ec_sdo_request_t *req, *next_req; fp@792: fp@792: sc = container_of(kobj, ec_slave_config_t, kobj); fp@792: fp@792: // Free Pdo mappings fp@792: for (dir = EC_DIR_OUTPUT; dir <= EC_DIR_INPUT; dir++) fp@792: ec_pdo_mapping_clear(&sc->mapping[dir]); fp@792: fp@814: // free all Sdo configurations fp@854: list_for_each_entry_safe(req, next_req, &sc->sdo_configs, list) { fp@854: list_del(&req->list); fp@854: ec_sdo_request_clear(req); fp@854: kfree(req); fp@854: } fp@792: fp@858: // free all Sdo requests fp@858: list_for_each_entry_safe(req, next_req, &sc->sdo_requests, list) { fp@858: list_del(&req->list); fp@858: ec_sdo_request_clear(req); fp@858: kfree(req); fp@858: } fp@858: fp@792: kfree(sc); fp@792: } fp@792: fp@792: /*****************************************************************************/ fp@792: fp@792: /** Prepares an FMMU configuration. fp@792: * fp@792: * Configuration data for the FMMU is saved in the slave config structure and fp@792: * is written to the slave during the configuration. The FMMU configuration fp@792: * is done in a way, that the complete data range of the corresponding sync fp@792: * manager is covered. Seperate FMMUs are configured for each domain. If the fp@792: * FMMU configuration is already prepared, the function returns with success. fp@792: * fp@792: * \retval >=0 Logical offset address. fp@792: * \retval -1 FMMU limit reached. fp@792: */ fp@792: int ec_slave_config_prepare_fmmu( fp@792: ec_slave_config_t *sc, /**< Slave configuration. */ fp@792: ec_domain_t *domain, /**< Domain. */ fp@814: ec_direction_t dir /**< Pdo direction. */ fp@792: ) fp@792: { fp@792: unsigned int i; fp@792: ec_fmmu_config_t *fmmu; fp@792: fp@792: // FMMU configuration already prepared? fp@792: for (i = 0; i < sc->used_fmmus; i++) { fp@792: fmmu = &sc->fmmu_configs[i]; fp@792: if (fmmu->domain == domain && fmmu->dir == dir) fp@792: return fmmu->logical_start_address; fp@792: } fp@792: fp@792: if (sc->used_fmmus == EC_MAX_FMMUS) { fp@792: EC_ERR("FMMU limit reached for slave configuration %u:%u!\n", fp@792: sc->alias, sc->position); fp@792: return -1; fp@792: } fp@792: fp@792: fmmu = &sc->fmmu_configs[sc->used_fmmus++]; fp@792: ec_fmmu_config_init(fmmu, sc, domain, dir); fp@792: return fmmu->logical_start_address; fp@792: } fp@792: fp@792: /*****************************************************************************/ fp@792: fp@792: /** Outputs all information about a certain slave configuration. fp@792: */ fp@792: ssize_t ec_slave_config_info( fp@792: const ec_slave_config_t *sc, /**< Slave configuration. */ fp@792: char *buffer /**< Output buffer */ fp@792: ) fp@792: { fp@792: char *buf = buffer; fp@792: ec_direction_t dir; fp@792: const ec_pdo_mapping_t *map; fp@792: const ec_pdo_t *pdo; fp@792: const ec_pdo_entry_t *entry; fp@792: char str[20]; fp@854: const ec_sdo_request_t *req; fp@792: fp@792: buf += sprintf(buf, "Alias: 0x%04X (%u)\n", sc->alias, sc->alias); fp@792: buf += sprintf(buf, "Position: %u\n", sc->position); fp@792: fp@792: for (dir = EC_DIR_OUTPUT; dir <= EC_DIR_INPUT; dir++) { fp@792: map = &sc->mapping[dir]; fp@792: fp@792: if (!list_empty(&map->pdos)) { fp@792: buf += sprintf(buf, "%s mapping:\n", fp@792: dir == EC_DIR_OUTPUT ? "Output" : "Input"); fp@792: fp@792: list_for_each_entry(pdo, &map->pdos, list) { fp@792: buf += sprintf(buf, " %s 0x%04X \"%s\"\n", fp@792: pdo->dir == EC_DIR_OUTPUT ? "RxPdo" : "TxPdo", fp@792: pdo->index, pdo->name ? pdo->name : "???"); fp@792: fp@792: list_for_each_entry(entry, &pdo->entries, list) { fp@792: buf += sprintf(buf, " 0x%04X:%X \"%s\", %u bit\n", fp@792: entry->index, entry->subindex, fp@792: entry->name ? entry->name : "???", fp@792: entry->bit_length); fp@792: } fp@792: } fp@792: } fp@792: } fp@792: fp@792: // type-cast to avoid warnings on some compilers fp@792: if (!list_empty((struct list_head *) &sc->sdo_configs)) { fp@814: buf += sprintf(buf, "\nSdo configurations:\n"); fp@792: fp@854: list_for_each_entry(req, &sc->sdo_configs, list) { fp@854: switch (req->data_size) { fp@854: case 1: sprintf(str, "%u", EC_READ_U8(req->data)); break; fp@854: case 2: sprintf(str, "%u", EC_READ_U16(req->data)); break; fp@854: case 4: sprintf(str, "%u", EC_READ_U32(req->data)); break; fp@792: default: sprintf(str, "(invalid size)"); break; fp@792: } fp@792: buf += sprintf(buf, " 0x%04X:%-3i -> %s\n", fp@854: req->index, req->subindex, str); fp@792: } fp@792: buf += sprintf(buf, "\n"); fp@792: } fp@792: fp@858: // type-cast to avoid warnings on some compilers fp@858: if (!list_empty((struct list_head *) &sc->sdo_requests)) { fp@858: buf += sprintf(buf, "\nSdo requests:\n"); fp@858: fp@858: list_for_each_entry(req, &sc->sdo_requests, list) { fp@858: buf += sprintf(buf, " 0x%04X:%u\n", req->index, req->subindex); fp@858: } fp@858: buf += sprintf(buf, "\n"); fp@858: } fp@858: fp@792: return buf - buffer; fp@792: } fp@792: fp@792: /*****************************************************************************/ fp@792: fp@792: /** Formats attribute data for SysFS read access. fp@792: * fp@792: * \return number of bytes to read fp@792: */ fp@792: ssize_t ec_show_slave_config_attribute( fp@792: struct kobject *kobj, /**< Slave configuration's kobject */ fp@792: struct attribute *attr, /**< Requested attribute. */ fp@792: char *buffer /**< Memory to store data. */ fp@792: ) fp@792: { fp@792: ec_slave_config_t *sc = container_of(kobj, ec_slave_config_t, kobj); fp@792: fp@792: if (attr == &attr_info) { fp@792: return ec_slave_config_info(sc, buffer); fp@792: } fp@792: fp@792: return 0; fp@792: } fp@792: fp@792: /*****************************************************************************/ fp@792: fp@814: /** Adds an Sdo configuration. fp@792: */ fp@792: int ec_slave_config_sdo(ec_slave_config_t *sc, uint16_t index, fp@792: uint8_t subindex, const uint8_t *data, size_t size) fp@792: { fp@792: ec_slave_t *slave = sc->slave; fp@854: ec_sdo_request_t *req; fp@792: fp@834: if (slave && !(slave->sii.mailbox_protocols & EC_MBOX_COE)) { fp@792: EC_ERR("Slave %u does not support CoE!\n", slave->ring_position); fp@792: return -1; fp@792: } fp@792: fp@854: if (!(req = (ec_sdo_request_t *) fp@854: kmalloc(sizeof(ec_sdo_request_t), GFP_KERNEL))) { fp@854: EC_ERR("Failed to allocate memory for Sdo configuration!\n"); fp@792: return -1; fp@792: } fp@792: fp@854: ec_sdo_request_init(req); fp@854: ec_sdo_request_address(req, index, subindex); fp@854: fp@854: if (ec_sdo_request_copy_data(req, data, size)) { fp@854: ec_sdo_request_clear(req); fp@854: kfree(req); fp@792: return -1; fp@792: } fp@854: fp@854: list_add_tail(&req->list, &sc->sdo_configs); fp@792: return 0; fp@792: } fp@792: fp@792: /*****************************************************************************/ fp@792: fp@792: /** Attaches the configuration to the addressed slave object. fp@792: * fp@792: * \retval 0 Success. fp@792: * \retval -1 Slave not found. fp@792: * \retval -2 Slave already configured. fp@792: * \retval -3 Invalid slave type found at the given position. fp@792: */ fp@792: int ec_slave_config_attach( fp@792: ec_slave_config_t *sc /**< Slave configuration. */ fp@792: ) fp@792: { fp@792: ec_slave_t *slave; fp@792: unsigned int alias_found = 0, relative_position = 0; fp@792: fp@792: if (sc->slave) fp@792: return 0; // already attached fp@792: fp@792: list_for_each_entry(slave, &sc->master->slaves, list) { fp@792: if (!alias_found) { fp@834: if (sc->alias && slave->sii.alias != sc->alias) fp@792: continue; fp@792: alias_found = 1; fp@792: relative_position = 0; fp@792: } fp@792: if (relative_position == sc->position) fp@792: goto found; fp@792: relative_position++; fp@792: } fp@792: fp@797: EC_WARN("Failed to find slave for configuration %u:%u.\n", fp@792: sc->alias, sc->position); fp@792: return -1; fp@792: fp@792: found: fp@792: if (slave->config) { fp@792: EC_ERR("Failed to attach slave configuration %u:%u. Slave %u" fp@792: " already has a configuration!\n", sc->alias, fp@792: sc->position, slave->ring_position); fp@792: return -2; fp@792: } fp@834: if (slave->sii.vendor_id != sc->vendor_id fp@834: || slave->sii.product_code != sc->product_code) { fp@792: EC_ERR("Slave %u has an invalid type (0x%08X/0x%08X) for" fp@792: " configuration %u:%u (0x%08X/0x%08X).\n", fp@834: slave->ring_position, slave->sii.vendor_id, fp@834: slave->sii.product_code, sc->alias, sc->position, fp@792: sc->vendor_id, sc->product_code); fp@792: return -3; fp@792: } fp@792: fp@792: // attach slave fp@792: slave->config = sc; fp@792: sc->slave = slave; fp@792: fp@792: ec_slave_request_state(slave, EC_SLAVE_STATE_OP); fp@792: fp@792: return 0; fp@792: } fp@792: fp@792: /*****************************************************************************/ fp@792: fp@792: /** Detaches the configuration from a slave object. fp@792: */ fp@792: void ec_slave_config_detach( fp@792: ec_slave_config_t *sc /**< Slave configuration. */ fp@792: ) fp@792: { fp@792: if (sc->slave) { fp@792: sc->slave->config = NULL; fp@792: sc->slave = NULL; fp@792: } fp@792: } fp@792: fp@792: /*****************************************************************************/ fp@792: fp@792: /** Loads the default mapping from the slave object. fp@792: */ fp@792: void ec_slave_config_load_default_mapping(ec_slave_config_t *sc) fp@792: { fp@792: ec_direction_t dir; fp@792: ec_pdo_mapping_t *map; fp@792: ec_sync_t *sync; fp@792: fp@792: if (!sc->slave) fp@792: return; fp@792: fp@792: for (dir = EC_DIR_OUTPUT; dir <= EC_DIR_INPUT; dir++) { fp@792: map = &sc->mapping[dir]; fp@792: if (!(sync = ec_slave_get_pdo_sync(sc->slave, dir))) fp@792: continue; fp@792: ec_pdo_mapping_copy(map, &sync->mapping); fp@842: map->default_mapping = 1; fp@842: } fp@842: } fp@842: fp@842: /*****************************************************************************/ fp@842: fp@842: /** Loads the default configuration for a Pdo from the slave object. fp@842: */ fp@842: void ec_slave_config_load_default_pdo_config( fp@842: const ec_slave_config_t *sc, fp@842: ec_pdo_t *pdo fp@842: ) fp@842: { fp@842: const ec_sync_t *sync; fp@842: const ec_pdo_t *default_pdo; fp@842: fp@843: if (sc->master->debug_level) fp@843: EC_DBG("Loading default configuration for Pdo 0x%04X in" fp@843: " config %u:%u.\n", pdo->index, sc->alias, sc->position); fp@843: fp@842: pdo->default_config = 1; fp@842: fp@842: if (!sc->slave) { fp@842: EC_WARN("Failed to load default Pdo configuration for %u:%u:" fp@842: " Slave not found.\n", sc->alias, sc->position); fp@842: return; fp@842: } fp@842: fp@842: if (!(sync = ec_slave_get_pdo_sync(sc->slave, pdo->dir))) { fp@842: EC_WARN("Slave %u does not provide a default Pdo" fp@842: " configuration!\n", sc->slave->ring_position); fp@842: return; fp@842: } fp@842: fp@842: list_for_each_entry(default_pdo, &sync->mapping.pdos, list) { fp@842: if (default_pdo->index != pdo->index) fp@842: continue; fp@842: fp@842: if (sc->master->debug_level) fp@842: EC_DBG(" Found Pdo name \"%s\".\n", fp@842: default_pdo->name); fp@842: fp@842: // try to take Pdo name from mapped one fp@842: ec_pdo_set_name(pdo, default_pdo->name); fp@842: fp@842: // copy entries (= default Pdo configuration) fp@842: if (ec_pdo_copy_entries(pdo, default_pdo)) fp@842: return; fp@842: fp@842: if (sc->master->debug_level) { fp@842: const ec_pdo_entry_t *entry; fp@842: list_for_each_entry(entry, &pdo->entries, list) { fp@842: EC_DBG(" Entry 0x%04X:%u.\n", fp@842: entry->index, entry->subindex); fp@842: } fp@842: } fp@792: } fp@792: } fp@792: fp@792: /****************************************************************************** fp@792: * Realtime interface fp@792: *****************************************************************************/ fp@792: fp@842: int ecrt_slave_config_pdo(ec_slave_config_t *sc, ec_direction_t dir, fp@842: uint16_t index) fp@842: { fp@842: ec_pdo_mapping_t *pm = &sc->mapping[dir]; fp@842: ec_pdo_t *pdo; fp@842: fp@842: if (pm->default_mapping) { fp@843: if (sc->master->debug_level) fp@843: EC_DBG("Clearing default mapping for dir %u, config %u:%u.\n", fp@843: dir, sc->alias, sc->position); fp@842: pm->default_mapping = 0; fp@842: ec_pdo_mapping_clear_pdos(pm); fp@842: } fp@842: fp@843: if (sc->master->debug_level) fp@843: EC_DBG("Adding Pdo 0x%04X to mapping for dir %u, config %u:%u.\n", fp@843: index, dir, sc->alias, sc->position); fp@843: fp@844: if (!(pdo = ec_pdo_mapping_add_pdo(pm, dir, index))) fp@842: return -1; fp@842: fp@842: ec_slave_config_load_default_pdo_config(sc, pdo); fp@842: return 0; fp@842: } fp@842: fp@842: /*****************************************************************************/ fp@842: fp@842: int ecrt_slave_config_pdo_entry(ec_slave_config_t *sc, uint16_t pdo_index, fp@842: uint16_t entry_index, uint8_t entry_subindex, fp@842: uint8_t entry_bit_length) fp@842: { fp@842: ec_direction_t dir; fp@842: ec_pdo_t *pdo; fp@842: fp@843: if (sc->master->debug_level) fp@843: EC_DBG("Adding Pdo entry 0x%04X:%u (%u bit) to configuration of Pdo" fp@843: " 0x%04X, config %u:%u.\n", entry_index, entry_subindex, fp@843: entry_bit_length, pdo_index, sc->alias, sc->position); fp@843: fp@842: for (dir = EC_DIR_OUTPUT; dir <= EC_DIR_INPUT; dir++) fp@842: if ((pdo = ec_pdo_mapping_find_pdo(&sc->mapping[dir], pdo_index))) fp@842: break; fp@842: fp@843: if (!pdo) { fp@843: EC_ERR("Pdo 0x%04X was not found in the mapping of config %u:%u.\n", fp@843: pdo_index, sc->alias, sc->position); fp@843: return -1; fp@843: } fp@843: fp@842: if (pdo->default_config) { fp@843: if (sc->master->debug_level) fp@843: EC_DBG("Clearing default configuration of Pdo 0x%04X," fp@843: " config %u:%u.\n", pdo->index, sc->alias, sc->position); fp@842: pdo->default_config = 0; fp@842: ec_pdo_clear_entries(pdo); fp@842: } fp@842: fp@842: return ec_pdo_add_entry(pdo, entry_index, entry_subindex, fp@842: entry_bit_length) ? 0 : -1; fp@842: } fp@842: fp@842: /*****************************************************************************/ fp@842: fp@844: int ecrt_slave_config_mapping(ec_slave_config_t *sc, unsigned int n_infos, fp@792: const ec_pdo_info_t pdo_infos[]) fp@792: { fp@844: unsigned int i, j; fp@842: const ec_pdo_info_t *pi; fp@842: ec_pdo_mapping_t *pm; fp@842: ec_pdo_t *pdo; fp@842: const ec_pdo_entry_info_t *ei; fp@842: fp@844: for (i = 0; i < n_infos; i++) { fp@842: pi = &pdo_infos[i]; fp@842: pm = &sc->mapping[pi->dir]; fp@842: fp@842: if (pm->default_mapping) { fp@843: if (sc->master->debug_level) fp@843: EC_DBG("Clearing default mapping for dir %u, config %u:%u.\n", fp@843: pi->dir, sc->alias, sc->position); fp@842: pm->default_mapping = 0; fp@842: ec_pdo_mapping_clear_pdos(pm); fp@842: } fp@842: fp@842: if (sc->master->debug_level) fp@844: EC_DBG("Adding Pdo 0x%04X to mapping for dir %u, config %u:%u.\n", fp@844: pi->index, pi->dir, sc->alias, sc->position); fp@842: fp@842: if (!(pdo = ec_pdo_mapping_add_pdo(pm, pi->dir, pi->index))) fp@792: return -1; fp@792: fp@842: if (pi->n_entries && pi->entries) { // configuration provided fp@842: if (sc->master->debug_level) fp@842: EC_DBG(" Pdo configuration information provided.\n"); fp@842: fp@844: for (j = 0; j < pi->n_entries; j++) { fp@844: ei = &pi->entries[j]; fp@842: if (!ec_pdo_add_entry(pdo, ei->index, ei->subindex, fp@842: ei->bit_length)) fp@842: return -1; fp@842: } fp@842: } else { // use default Pdo configuration fp@842: ec_slave_config_load_default_pdo_config(sc, pdo); fp@842: } fp@842: } fp@842: fp@792: return 0; fp@792: } fp@792: fp@792: /*****************************************************************************/ fp@792: fp@807: int ecrt_slave_config_reg_pdo_entry( fp@807: ec_slave_config_t *sc, /**< Slave configuration. */ fp@807: uint16_t index, /**< Index of Pdo entry to register. */ fp@807: uint8_t subindex, /**< Subindex of Pdo entry to register. */ fp@807: ec_domain_t *domain /**< Domain. */ fp@807: ) fp@807: { fp@807: ec_direction_t dir; fp@807: ec_pdo_mapping_t *map; fp@807: unsigned int bit_offset, byte_offset; fp@807: ec_pdo_t *pdo; fp@807: ec_pdo_entry_t *entry; fp@807: int ret; fp@807: fp@807: for (dir = EC_DIR_OUTPUT; dir <= EC_DIR_INPUT; dir++) { fp@807: map = &sc->mapping[dir]; fp@807: bit_offset = 0; fp@807: list_for_each_entry(pdo, &map->pdos, list) { fp@807: list_for_each_entry(entry, &pdo->entries, list) { fp@807: if (entry->index != index || entry->subindex != subindex) { fp@807: bit_offset += entry->bit_length; fp@807: } else { fp@807: goto found; fp@807: } fp@807: } fp@807: } fp@807: } fp@807: fp@814: EC_ERR("Pdo entry 0x%04X:%u is not mapped in slave config %u:%u.\n", fp@807: index, subindex, sc->alias, sc->position); fp@807: return -1; fp@807: fp@807: found: fp@807: byte_offset = bit_offset / 8; fp@807: if ((ret = ec_slave_config_prepare_fmmu(sc, domain, dir)) < 0) fp@807: return -2; fp@807: return ret + byte_offset; fp@807: } fp@807: fp@807: /*****************************************************************************/ fp@807: fp@792: int ecrt_slave_config_sdo8(ec_slave_config_t *slave, uint16_t index, fp@792: uint8_t subindex, uint8_t value) fp@792: { fp@792: uint8_t data[1]; fp@792: EC_WRITE_U8(data, value); fp@792: return ec_slave_config_sdo(slave, index, subindex, data, 1); fp@792: } fp@792: fp@792: /*****************************************************************************/ fp@792: fp@792: int ecrt_slave_config_sdo16(ec_slave_config_t *slave, uint16_t index, fp@792: uint8_t subindex, uint16_t value) fp@792: { fp@792: uint8_t data[2]; fp@792: EC_WRITE_U16(data, value); fp@792: return ec_slave_config_sdo(slave, index, subindex, data, 2); fp@792: } fp@792: fp@792: /*****************************************************************************/ fp@792: fp@792: int ecrt_slave_config_sdo32(ec_slave_config_t *slave, uint16_t index, fp@792: uint8_t subindex, uint32_t value) fp@792: { fp@792: uint8_t data[4]; fp@792: EC_WRITE_U32(data, value); fp@792: return ec_slave_config_sdo(slave, index, subindex, data, 4); fp@792: } fp@792: fp@792: /*****************************************************************************/ fp@792: fp@858: ec_sdo_request_t *ecrt_slave_config_create_sdo_request(ec_slave_config_t *sc, fp@858: uint16_t index, uint8_t subindex, size_t size) fp@858: { fp@858: ec_sdo_request_t *req; fp@858: fp@858: if (!(req = (ec_sdo_request_t *) fp@858: kmalloc(sizeof(ec_sdo_request_t), GFP_KERNEL))) { fp@858: EC_ERR("Failed to allocate Sdo request memory!\n"); fp@858: return NULL; fp@858: } fp@858: fp@858: ec_sdo_request_init(req); fp@858: ec_sdo_request_address(req, index, subindex); fp@858: fp@858: if (ec_sdo_request_alloc(req, size)) { fp@858: ec_sdo_request_clear(req); fp@858: kfree(req); fp@858: return NULL; fp@858: } fp@859: fp@859: // prepare data for optional writing fp@859: memset(req->data, 0x00, size); fp@859: req->data_size = size; fp@858: fp@858: list_add_tail(&req->list, &sc->sdo_requests); fp@858: return req; fp@858: } fp@858: fp@858: /*****************************************************************************/ fp@858: fp@792: /** \cond */ fp@792: fp@842: EXPORT_SYMBOL(ecrt_slave_config_pdo); fp@842: EXPORT_SYMBOL(ecrt_slave_config_pdo_entry); fp@792: EXPORT_SYMBOL(ecrt_slave_config_mapping); fp@807: EXPORT_SYMBOL(ecrt_slave_config_reg_pdo_entry); fp@792: EXPORT_SYMBOL(ecrt_slave_config_sdo8); fp@792: EXPORT_SYMBOL(ecrt_slave_config_sdo16); fp@792: EXPORT_SYMBOL(ecrt_slave_config_sdo32); fp@858: EXPORT_SYMBOL(ecrt_slave_config_create_sdo_request); fp@792: fp@792: /** \endcond */ fp@792: fp@792: /*****************************************************************************/