slave.c

Go to the documentation of this file.
00001 /******************************************************************************
00002  *
00003  *  $Id: slave.c 533 2006-09-01 12:35:41Z fp $
00004  *
00005  *  Copyright (C) 2006  Florian Pose, Ingenieurgemeinschaft IgH
00006  *
00007  *  This file is part of the IgH EtherCAT Master.
00008  *
00009  *  The IgH EtherCAT Master is free software; you can redistribute it
00010  *  and/or modify it under the terms of the GNU General Public License
00011  *  as published by the Free Software Foundation; either version 2 of the
00012  *  License, or (at your option) any later version.
00013  *
00014  *  The IgH EtherCAT Master is distributed in the hope that it will be
00015  *  useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017  *  GNU General Public License for more details.
00018  *
00019  *  You should have received a copy of the GNU General Public License
00020  *  along with the IgH EtherCAT Master; if not, write to the Free Software
00021  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00022  *
00023  *  The right to use EtherCAT Technology is granted and comes free of
00024  *  charge under condition of compatibility of product made by
00025  *  Licensee. People intending to distribute/sell products based on the
00026  *  code, have to sign an agreement to guarantee that products using
00027  *  software based on IgH EtherCAT master stay compatible with the actual
00028  *  EtherCAT specification (which are released themselves as an open
00029  *  standard) as the (only) precondition to have the right to use EtherCAT
00030  *  Technology, IP and trade marks.
00031  *
00032  *****************************************************************************/
00033 
00039 /*****************************************************************************/
00040 
00041 #include <linux/module.h>
00042 #include <linux/delay.h>
00043 
00044 #include "globals.h"
00045 #include "slave.h"
00046 #include "datagram.h"
00047 #include "master.h"
00048 
00049 /*****************************************************************************/
00050 
00051 extern const ec_code_msg_t al_status_messages[];
00052 
00053 /*****************************************************************************/
00054 
00055 ssize_t ec_show_slave_attribute(struct kobject *, struct attribute *, char *);
00056 ssize_t ec_store_slave_attribute(struct kobject *, struct attribute *,
00057                                  const char *, size_t);
00058 
00059 /*****************************************************************************/
00060 
00063 EC_SYSFS_READ_ATTR(info);
00064 EC_SYSFS_READ_WRITE_ATTR(state);
00065 EC_SYSFS_READ_WRITE_ATTR(eeprom);
00066 
00067 static struct attribute *def_attrs[] = {
00068     &attr_info,
00069     &attr_state,
00070     &attr_eeprom,
00071     NULL,
00072 };
00073 
00074 static struct sysfs_ops sysfs_ops = {
00075     .show = ec_show_slave_attribute,
00076     .store = ec_store_slave_attribute
00077 };
00078 
00079 static struct kobj_type ktype_ec_slave = {
00080     .release = ec_slave_clear,
00081     .sysfs_ops = &sysfs_ops,
00082     .default_attrs = def_attrs
00083 };
00084 
00087 /*****************************************************************************/
00088 
00094 int ec_slave_init(ec_slave_t *slave, 
00095                   ec_master_t *master, 
00096                   uint16_t ring_position, 
00097                   uint16_t station_address 
00098                   )
00099 {
00100     unsigned int i;
00101 
00102     slave->ring_position = ring_position;
00103     slave->station_address = station_address;
00104 
00105     // init kobject and add it to the hierarchy
00106     memset(&slave->kobj, 0x00, sizeof(struct kobject));
00107     kobject_init(&slave->kobj);
00108     slave->kobj.ktype = &ktype_ec_slave;
00109     slave->kobj.parent = &master->kobj;
00110     if (kobject_set_name(&slave->kobj, "slave%03i", slave->ring_position)) {
00111         EC_ERR("Failed to set kobject name.\n");
00112         kobject_put(&slave->kobj);
00113         return -1;
00114     }
00115 
00116     slave->master = master;
00117 
00118     slave->requested_state = EC_SLAVE_STATE_UNKNOWN;
00119     slave->current_state = EC_SLAVE_STATE_UNKNOWN;
00120     slave->error_flag = 0;
00121     slave->online = 1;
00122     slave->fmmu_count = 0;
00123     slave->registered = 0;
00124 
00125     slave->coupler_index = 0;
00126     slave->coupler_subindex = 0xFFFF;
00127 
00128     slave->base_type = 0;
00129     slave->base_revision = 0;
00130     slave->base_build = 0;
00131     slave->base_fmmu_count = 0;
00132     slave->base_sync_count = 0;
00133 
00134     slave->eeprom_data = NULL;
00135     slave->eeprom_size = 0;
00136     slave->new_eeprom_data = NULL;
00137     slave->new_eeprom_size = 0;
00138 
00139     slave->sii_alias = 0;
00140     slave->sii_vendor_id = 0;
00141     slave->sii_product_code = 0;
00142     slave->sii_revision_number = 0;
00143     slave->sii_serial_number = 0;
00144     slave->sii_rx_mailbox_offset = 0;
00145     slave->sii_rx_mailbox_size = 0;
00146     slave->sii_tx_mailbox_offset = 0;
00147     slave->sii_tx_mailbox_size = 0;
00148     slave->sii_mailbox_protocols = 0;
00149     slave->sii_group = NULL;
00150     slave->sii_image = NULL;
00151     slave->sii_order = NULL;
00152     slave->sii_name = NULL;
00153 
00154     INIT_LIST_HEAD(&slave->sii_strings);
00155     INIT_LIST_HEAD(&slave->sii_syncs);
00156     INIT_LIST_HEAD(&slave->sii_pdos);
00157     INIT_LIST_HEAD(&slave->sdo_dictionary);
00158     INIT_LIST_HEAD(&slave->sdo_confs);
00159     INIT_LIST_HEAD(&slave->varsize_fields);
00160 
00161     for (i = 0; i < 4; i++) {
00162         slave->dl_link[i] = 0;
00163         slave->dl_loop[i] = 0;
00164         slave->dl_signal[i] = 0;
00165         slave->sii_physical_layer[i] = 0xFF;
00166     }
00167 
00168     return 0;
00169 }
00170 
00171 /*****************************************************************************/
00172 
00177 void ec_slave_clear(struct kobject *kobj )
00178 {
00179     ec_slave_t *slave;
00180     ec_sii_string_t *string, *next_str;
00181     ec_sii_sync_t *sync, *next_sync;
00182     ec_sii_pdo_t *pdo, *next_pdo;
00183     ec_sii_pdo_entry_t *entry, *next_ent;
00184     ec_sdo_t *sdo, *next_sdo;
00185     ec_sdo_entry_t *en, *next_en;
00186     ec_sdo_data_t *sdodata, *next_sdodata;
00187     ec_varsize_t *var, *next_var;
00188 
00189     slave = container_of(kobj, ec_slave_t, kobj);
00190 
00191     // free all string objects
00192     list_for_each_entry_safe(string, next_str, &slave->sii_strings, list) {
00193         list_del(&string->list);
00194         kfree(string);
00195     }
00196 
00197     // free all sync managers
00198     list_for_each_entry_safe(sync, next_sync, &slave->sii_syncs, list) {
00199         list_del(&sync->list);
00200         kfree(sync);
00201     }
00202 
00203     // free all PDOs
00204     list_for_each_entry_safe(pdo, next_pdo, &slave->sii_pdos, list) {
00205         list_del(&pdo->list);
00206         if (pdo->name) kfree(pdo->name);
00207 
00208         // free all PDO entries
00209         list_for_each_entry_safe(entry, next_ent, &pdo->entries, list) {
00210             list_del(&entry->list);
00211             if (entry->name) kfree(entry->name);
00212             kfree(entry);
00213         }
00214 
00215         kfree(pdo);
00216     }
00217 
00218     if (slave->sii_group) kfree(slave->sii_group);
00219     if (slave->sii_image) kfree(slave->sii_image);
00220     if (slave->sii_order) kfree(slave->sii_order);
00221     if (slave->sii_name) kfree(slave->sii_name);
00222 
00223     // free all SDOs
00224     list_for_each_entry_safe(sdo, next_sdo, &slave->sdo_dictionary, list) {
00225         list_del(&sdo->list);
00226         if (sdo->name) kfree(sdo->name);
00227 
00228         // free all SDO entries
00229         list_for_each_entry_safe(en, next_en, &sdo->entries, list) {
00230             list_del(&en->list);
00231             kfree(en);
00232         }
00233         kfree(sdo);
00234     }
00235 
00236     // free all SDO configurations
00237     list_for_each_entry_safe(sdodata, next_sdodata, &slave->sdo_confs, list) {
00238         list_del(&sdodata->list);
00239         kfree(sdodata->data);
00240         kfree(sdodata);
00241     }
00242 
00243     // free information about variable sized data fields
00244     list_for_each_entry_safe(var, next_var, &slave->varsize_fields, list) {
00245         list_del(&var->list);
00246         kfree(var);
00247     }
00248 
00249     if (slave->eeprom_data) kfree(slave->eeprom_data);
00250     if (slave->new_eeprom_data) kfree(slave->new_eeprom_data);
00251 }
00252 
00253 /*****************************************************************************/
00254 
00260 int ec_slave_fetch_strings(ec_slave_t *slave, 
00261                            const uint8_t *data 
00262                            )
00263 {
00264     unsigned int string_count, i;
00265     size_t size;
00266     off_t offset;
00267     ec_sii_string_t *string;
00268 
00269     string_count = data[0];
00270     offset = 1;
00271     for (i = 0; i < string_count; i++) {
00272         size = data[offset];
00273         // allocate memory for string structure and data at a single blow
00274         if (!(string = (ec_sii_string_t *)
00275               kmalloc(sizeof(ec_sii_string_t) + size + 1, GFP_ATOMIC))) {
00276             EC_ERR("Failed to allocate string memory.\n");
00277             return -1;
00278         }
00279         string->size = size;
00280         // string memory appended to string structure
00281         string->data = (char *) string + sizeof(ec_sii_string_t);
00282         memcpy(string->data, data + offset + 1, size);
00283         string->data[size] = 0x00;
00284         list_add_tail(&string->list, &slave->sii_strings);
00285         offset += 1 + size;
00286     }
00287 
00288     return 0;
00289 }
00290 
00291 /*****************************************************************************/
00292 
00298 void ec_slave_fetch_general(ec_slave_t *slave, 
00299                             const uint8_t *data 
00300                             )
00301 {
00302     unsigned int i;
00303 
00304     ec_slave_locate_string(slave, data[0], &slave->sii_group);
00305     ec_slave_locate_string(slave, data[1], &slave->sii_image);
00306     ec_slave_locate_string(slave, data[2], &slave->sii_order);
00307     ec_slave_locate_string(slave, data[3], &slave->sii_name);
00308 
00309     for (i = 0; i < 4; i++)
00310         slave->sii_physical_layer[i] =
00311             (data[4] & (0x03 << (i * 2))) >> (i * 2);
00312 }
00313 
00314 /*****************************************************************************/
00315 
00321 int ec_slave_fetch_sync(ec_slave_t *slave, 
00322                         const uint8_t *data, 
00323                         size_t word_count 
00324                         )
00325 {
00326     unsigned int sync_count, i;
00327     ec_sii_sync_t *sync;
00328 
00329     sync_count = word_count / 4; // sync manager struct is 4 words long
00330 
00331     for (i = 0; i < sync_count; i++, data += 8) {
00332         if (!(sync = (ec_sii_sync_t *)
00333               kmalloc(sizeof(ec_sii_sync_t), GFP_ATOMIC))) {
00334             EC_ERR("Failed to allocate Sync-Manager memory.\n");
00335             return -1;
00336         }
00337 
00338         sync->index = i;
00339         sync->physical_start_address = EC_READ_U16(data);
00340         sync->length                 = EC_READ_U16(data + 2);
00341         sync->control_register       = EC_READ_U8 (data + 4);
00342         sync->enable                 = EC_READ_U8 (data + 6);
00343 
00344         list_add_tail(&sync->list, &slave->sii_syncs);
00345     }
00346 
00347     return 0;
00348 }
00349 
00350 /*****************************************************************************/
00351 
00357 int ec_slave_fetch_pdo(ec_slave_t *slave, 
00358                        const uint8_t *data, 
00359                        size_t word_count, 
00360                        ec_sii_pdo_type_t pdo_type 
00361                        )
00362 {
00363     ec_sii_pdo_t *pdo;
00364     ec_sii_pdo_entry_t *entry;
00365     unsigned int entry_count, i;
00366 
00367     while (word_count >= 4) {
00368         if (!(pdo = (ec_sii_pdo_t *)
00369               kmalloc(sizeof(ec_sii_pdo_t), GFP_ATOMIC))) {
00370             EC_ERR("Failed to allocate PDO memory.\n");
00371             return -1;
00372         }
00373 
00374         INIT_LIST_HEAD(&pdo->entries);
00375         pdo->type = pdo_type;
00376 
00377         pdo->index = EC_READ_U16(data);
00378         entry_count = EC_READ_U8(data + 2);
00379         pdo->sync_index = EC_READ_U8(data + 3);
00380         pdo->name = NULL;
00381         ec_slave_locate_string(slave, EC_READ_U8(data + 5), &pdo->name);
00382 
00383         list_add_tail(&pdo->list, &slave->sii_pdos);
00384 
00385         word_count -= 4;
00386         data += 8;
00387 
00388         for (i = 0; i < entry_count; i++) {
00389             if (!(entry = (ec_sii_pdo_entry_t *)
00390                   kmalloc(sizeof(ec_sii_pdo_entry_t), GFP_ATOMIC))) {
00391                 EC_ERR("Failed to allocate PDO entry memory.\n");
00392                 return -1;
00393             }
00394 
00395             entry->index = EC_READ_U16(data);
00396             entry->subindex = EC_READ_U8(data + 2);
00397             entry->name = NULL;
00398             ec_slave_locate_string(slave, EC_READ_U8(data + 3), &entry->name);
00399             entry->bit_length = EC_READ_U8(data + 5);
00400 
00401             list_add_tail(&entry->list, &pdo->entries);
00402 
00403             word_count -= 4;
00404             data += 8;
00405         }
00406     }
00407 
00408     return 0;
00409 }
00410 
00411 /*****************************************************************************/
00412 
00419 int ec_slave_locate_string(ec_slave_t *slave, 
00420                            unsigned int index, 
00421                            char **ptr 
00422                            )
00423 {
00424     ec_sii_string_t *string;
00425     char *err_string;
00426 
00427     // Erst alten Speicher freigeben
00428     if (*ptr) {
00429         kfree(*ptr);
00430         *ptr = NULL;
00431     }
00432 
00433     // Index 0 bedeutet "nicht belegt"
00434     if (!index) return 0;
00435 
00436     // EEPROM-String mit Index finden und kopieren
00437     list_for_each_entry(string, &slave->sii_strings, list) {
00438         if (--index) continue;
00439 
00440         if (!(*ptr = (char *) kmalloc(string->size + 1, GFP_ATOMIC))) {
00441             EC_ERR("Unable to allocate string memory.\n");
00442             return -1;
00443         }
00444         memcpy(*ptr, string->data, string->size + 1);
00445         return 0;
00446     }
00447 
00448     EC_WARN("String %i not found in slave %i.\n", index, slave->ring_position);
00449 
00450     err_string = "(string not found)";
00451 
00452     if (!(*ptr = (char *) kmalloc(strlen(err_string) + 1, GFP_ATOMIC))) {
00453         EC_WARN("Unable to allocate string memory.\n");
00454         return -1;
00455     }
00456 
00457     memcpy(*ptr, err_string, strlen(err_string) + 1);
00458     return 0;
00459 }
00460 
00461 /*****************************************************************************/
00462 
00475 int ec_slave_prepare_fmmu(ec_slave_t *slave, 
00476                           const ec_domain_t *domain, 
00477                           const ec_sii_sync_t *sync  
00478                           )
00479 {
00480     unsigned int i;
00481 
00482     // FMMU configuration already prepared?
00483     for (i = 0; i < slave->fmmu_count; i++)
00484         if (slave->fmmus[i].domain == domain && slave->fmmus[i].sync == sync)
00485             return 0;
00486 
00487     // reserve new FMMU...
00488 
00489     if (slave->fmmu_count >= slave->base_fmmu_count) {
00490         EC_ERR("Slave %i FMMU limit reached!\n", slave->ring_position);
00491         return -1;
00492     }
00493 
00494     slave->fmmus[slave->fmmu_count].domain = domain;
00495     slave->fmmus[slave->fmmu_count].sync = sync;
00496     slave->fmmus[slave->fmmu_count].logical_start_address = 0;
00497     slave->fmmu_count++;
00498     slave->registered = 1;
00499 
00500     return 0;
00501 }
00502 
00503 /*****************************************************************************/
00504 
00509 size_t ec_slave_info(const ec_slave_t *slave, 
00510                      char *buffer 
00511                      )
00512 {
00513     off_t off = 0;
00514     ec_sii_sync_t *sync;
00515     ec_sii_pdo_t *pdo;
00516     ec_sii_pdo_entry_t *pdo_entry;
00517     int first, i;
00518 
00519     off += sprintf(buffer + off, "\nName: ");
00520 
00521     if (slave->sii_name)
00522         off += sprintf(buffer + off, "%s", slave->sii_name);
00523 
00524     off += sprintf(buffer + off, "\nVendor ID: 0x%08X\n",
00525                    slave->sii_vendor_id);
00526     off += sprintf(buffer + off, "Product code: 0x%08X\n\n",
00527                    slave->sii_product_code);
00528 
00529     off += sprintf(buffer + off, "State: ");
00530     off += ec_state_string(slave->current_state, buffer + off);
00531     off += sprintf(buffer + off, "\nRing position: %i\n",
00532                    slave->ring_position);
00533     off += sprintf(buffer + off, "Advanced position: %i:%i\n\n",
00534                    slave->coupler_index, slave->coupler_subindex);
00535 
00536     off += sprintf(buffer + off, "Data link status:\n");
00537     for (i = 0; i < 4; i++) {
00538         off += sprintf(buffer + off, "  Port %i (", i);
00539         switch (slave->sii_physical_layer[i]) {
00540             case 0x00:
00541                 off += sprintf(buffer + off, "EBUS");
00542                 break;
00543             case 0x01:
00544                 off += sprintf(buffer + off, "100BASE-TX");
00545                 break;
00546             case 0x02:
00547                 off += sprintf(buffer + off, "100BASE-FX");
00548                 break;
00549             default:
00550                 off += sprintf(buffer + off, "unknown (%i)",
00551                                slave->sii_physical_layer[i]);
00552         }
00553         off += sprintf(buffer + off, ") Link %s, Loop %s, %s\n",
00554                        slave->dl_link[i] ? "up" : "down",
00555                        slave->dl_loop[i] ? "closed" : "open",
00556                        slave->dl_signal[i] ? "Signal detected" : "No signal");
00557     }
00558 
00559     if (slave->sii_mailbox_protocols) {
00560         off += sprintf(buffer + off, "\nMailboxes:\n");
00561         off += sprintf(buffer + off, "  RX mailbox: 0x%04X/%i,"
00562                        " TX mailbox: 0x%04X/%i\n",
00563                        slave->sii_rx_mailbox_offset,
00564                        slave->sii_rx_mailbox_size,
00565                        slave->sii_tx_mailbox_offset,
00566                        slave->sii_tx_mailbox_size);
00567         off += sprintf(buffer + off, "  Supported protocols: ");
00568 
00569         first = 1;
00570         if (slave->sii_mailbox_protocols & EC_MBOX_AOE) {
00571             off += sprintf(buffer + off, "AoE");
00572             first = 0;
00573         }
00574         if (slave->sii_mailbox_protocols & EC_MBOX_EOE) {
00575             if (!first) off += sprintf(buffer + off, ", ");
00576             off += sprintf(buffer + off, "EoE");
00577             first = 0;
00578         }
00579         if (slave->sii_mailbox_protocols & EC_MBOX_COE) {
00580             if (!first) off += sprintf(buffer + off, ", ");
00581             off += sprintf(buffer + off, "CoE");
00582             first = 0;
00583         }
00584         if (slave->sii_mailbox_protocols & EC_MBOX_FOE) {
00585             if (!first) off += sprintf(buffer + off, ", ");
00586             off += sprintf(buffer + off, "FoE");
00587             first = 0;
00588         }
00589         if (slave->sii_mailbox_protocols & EC_MBOX_SOE) {
00590             if (!first) off += sprintf(buffer + off, ", ");
00591             off += sprintf(buffer + off, "SoE");
00592             first = 0;
00593         }
00594         if (slave->sii_mailbox_protocols & EC_MBOX_VOE) {
00595             if (!first) off += sprintf(buffer + off, ", ");
00596             off += sprintf(buffer + off, "VoE");
00597         }
00598         off += sprintf(buffer + off, "\n");
00599     }
00600 
00601     if (slave->sii_alias || slave->sii_group
00602         || slave->sii_image || slave->sii_order)
00603         off += sprintf(buffer + off, "\nSII data:\n");
00604 
00605     if (slave->sii_alias)
00606         off += sprintf(buffer + off, "  Configured station alias:"
00607                        " 0x%04X (%i)\n", slave->sii_alias, slave->sii_alias);
00608     if (slave->sii_group)
00609         off += sprintf(buffer + off, "  Group: %s\n", slave->sii_group);
00610     if (slave->sii_image)
00611         off += sprintf(buffer + off, "  Image: %s\n", slave->sii_image);
00612     if (slave->sii_order)
00613         off += sprintf(buffer + off, "  Order number: %s\n", slave->sii_order);
00614 
00615     if (!list_empty(&slave->sii_syncs))
00616         off += sprintf(buffer + off, "\nSync-Managers:\n");
00617 
00618     list_for_each_entry(sync, &slave->sii_syncs, list) {
00619         off += sprintf(buffer + off, "  %i: 0x%04X, length %i,"
00620                        " control 0x%02X, %s\n",
00621                        sync->index, sync->physical_start_address,
00622                        sync->length, sync->control_register,
00623                        sync->enable ? "enable" : "disable");
00624     }
00625 
00626     if (!list_empty(&slave->sii_pdos))
00627         off += sprintf(buffer + off, "\nPDOs:\n");
00628 
00629     list_for_each_entry(pdo, &slave->sii_pdos, list) {
00630         off += sprintf(buffer + off,
00631                        "  %s \"%s\" (0x%04X), Sync-Manager %i\n",
00632                        pdo->type == EC_RX_PDO ? "RXPDO" : "TXPDO",
00633                        pdo->name ? pdo->name : "???",
00634                        pdo->index, pdo->sync_index);
00635 
00636         list_for_each_entry(pdo_entry, &pdo->entries, list) {
00637             off += sprintf(buffer + off, "    \"%s\" 0x%04X:%X, %i bit\n",
00638                            pdo_entry->name ? pdo_entry->name : "???",
00639                            pdo_entry->index, pdo_entry->subindex,
00640                            pdo_entry->bit_length);
00641         }
00642     }
00643 
00644     off += sprintf(buffer + off, "\n");
00645 
00646     return off;
00647 }
00648 
00649 /*****************************************************************************/
00650 
00656 ssize_t ec_slave_write_eeprom(ec_slave_t *slave, 
00657                               const uint8_t *data, 
00658                               size_t size 
00659                               )
00660 {
00661     uint16_t word_size, cat_type, cat_size;
00662     const uint16_t *data_words, *next_header;
00663     uint16_t *new_data;
00664 
00665     if (!slave->master->eeprom_write_enable) {
00666         EC_ERR("Writing EEPROMs not allowed! Enable via"
00667                " eeprom_write_enable SysFS entry.\n");
00668         return -1;
00669     }
00670 
00671     if (slave->master->mode != EC_MASTER_MODE_IDLE) {
00672         EC_ERR("Writing EEPROMs only allowed in idle mode!\n");
00673         return -1;
00674     }
00675 
00676     if (slave->new_eeprom_data) {
00677         EC_ERR("Slave %i already has a pending EEPROM write operation!\n",
00678                slave->ring_position);
00679         return -1;
00680     }
00681 
00682     // coarse check of the data
00683 
00684     if (size % 2) {
00685         EC_ERR("EEPROM size is odd! Dropping.\n");
00686         return -1;
00687     }
00688 
00689     data_words = (const uint16_t *) data;
00690     word_size = size / 2;
00691 
00692     if (word_size < 0x0041) {
00693         EC_ERR("EEPROM data too short! Dropping.\n");
00694         return -1;
00695     }
00696 
00697     next_header = data_words + 0x0040;
00698     cat_type = EC_READ_U16(next_header);
00699     while (cat_type != 0xFFFF) {
00700         cat_type = EC_READ_U16(next_header);
00701         cat_size = EC_READ_U16(next_header + 1);
00702         if ((next_header + cat_size + 2) - data_words >= word_size) {
00703             EC_ERR("EEPROM data seems to be corrupted! Dropping.\n");
00704             return -1;
00705         }
00706         next_header += cat_size + 2;
00707         cat_type = EC_READ_U16(next_header);
00708     }
00709 
00710     // data ok!
00711 
00712     if (!(new_data = (uint16_t *) kmalloc(word_size * 2, GFP_KERNEL))) {
00713         EC_ERR("Unable to allocate memory for new EEPROM data!\n");
00714         return -1;
00715     }
00716     memcpy(new_data, data, size);
00717 
00718     slave->new_eeprom_size = word_size;
00719     slave->new_eeprom_data = new_data;
00720 
00721     EC_INFO("EEPROM writing scheduled for slave %i, %i words.\n",
00722             slave->ring_position, word_size);
00723     return 0;
00724 }
00725 
00726 /*****************************************************************************/
00727 
00733 ssize_t ec_show_slave_attribute(struct kobject *kobj, 
00734                                 struct attribute *attr, 
00735                                 char *buffer 
00736                                 )
00737 {
00738     ec_slave_t *slave = container_of(kobj, ec_slave_t, kobj);
00739 
00740     if (attr == &attr_info) {
00741         return ec_slave_info(slave, buffer);
00742     }
00743     else if (attr == &attr_state) {
00744         switch (slave->current_state) {
00745             case EC_SLAVE_STATE_INIT:
00746                 return sprintf(buffer, "INIT\n");
00747             case EC_SLAVE_STATE_PREOP:
00748                 return sprintf(buffer, "PREOP\n");
00749             case EC_SLAVE_STATE_SAVEOP:
00750                 return sprintf(buffer, "SAVEOP\n");
00751             case EC_SLAVE_STATE_OP:
00752                 return sprintf(buffer, "OP\n");
00753             default:
00754                 return sprintf(buffer, "UNKNOWN\n");
00755         }
00756     }
00757     else if (attr == &attr_eeprom) {
00758         if (slave->eeprom_data) {
00759             if (slave->eeprom_size > PAGE_SIZE) {
00760                 EC_ERR("EEPROM contents of slave %i exceed 1 page (%i/%i).\n",
00761                        slave->ring_position, slave->eeprom_size,
00762                        (int) PAGE_SIZE);
00763             }
00764             else {
00765                 memcpy(buffer, slave->eeprom_data, slave->eeprom_size);
00766                 return slave->eeprom_size;
00767             }
00768         }
00769     }
00770 
00771     return 0;
00772 }
00773 
00774 /*****************************************************************************/
00775 
00781 ssize_t ec_store_slave_attribute(struct kobject *kobj, 
00782                                  struct attribute *attr, 
00783                                  const char *buffer, 
00784                                  size_t size 
00785                                  )
00786 {
00787     ec_slave_t *slave = container_of(kobj, ec_slave_t, kobj);
00788 
00789     if (attr == &attr_state) {
00790         char state[25];
00791         if (!strcmp(buffer, "INIT\n"))
00792             slave->requested_state = EC_SLAVE_STATE_INIT;
00793         else if (!strcmp(buffer, "PREOP\n"))
00794             slave->requested_state = EC_SLAVE_STATE_PREOP;
00795         else if (!strcmp(buffer, "SAVEOP\n"))
00796             slave->requested_state = EC_SLAVE_STATE_SAVEOP;
00797         else if (!strcmp(buffer, "OP\n"))
00798             slave->requested_state = EC_SLAVE_STATE_OP;
00799         else {
00800             EC_ERR("Invalid slave state \"%s\"!\n", buffer);
00801             return -EINVAL;
00802         }
00803 
00804         ec_state_string(slave->requested_state, state);
00805         EC_INFO("Accepted new state %s for slave %i.\n",
00806                 state, slave->ring_position);
00807         slave->error_flag = 0;
00808         return size;
00809     }
00810     else if (attr == &attr_eeprom) {
00811         if (!ec_slave_write_eeprom(slave, buffer, size))
00812             return size;
00813     }
00814 
00815     return -EINVAL;
00816 }
00817 
00818 /*****************************************************************************/
00819 
00825 uint16_t ec_slave_calc_sync_size(const ec_slave_t *slave,
00827                                  const ec_sii_sync_t *sync
00829                                  )
00830 {
00831     ec_sii_pdo_t *pdo;
00832     ec_sii_pdo_entry_t *pdo_entry;
00833     unsigned int bit_size;
00834 
00835     if (sync->length) return sync->length;
00836 
00837     bit_size = 0;
00838     list_for_each_entry(pdo, &slave->sii_pdos, list) {
00839         if (pdo->sync_index != sync->index) continue;
00840 
00841         list_for_each_entry(pdo_entry, &pdo->entries, list) {
00842             bit_size += pdo_entry->bit_length;
00843         }
00844     }
00845 
00846     if (bit_size % 8) // round up to full bytes
00847         return bit_size / 8 + 1;
00848     else
00849         return bit_size / 8;
00850 }
00851 
00852 /*****************************************************************************/
00853 
00858 int ec_slave_is_coupler(const ec_slave_t *slave )
00859 {
00860     // TODO: Better bus coupler criterion
00861     return slave->sii_vendor_id == 0x00000002
00862         && slave->sii_product_code == 0x044C2C52;
00863 }
00864 
00865 /*****************************************************************************/
00866 
00871 int ec_slave_conf_sdo(ec_slave_t *slave, 
00872                       uint16_t sdo_index, 
00873                       uint8_t sdo_subindex, 
00874                       const uint8_t *data, 
00875                       size_t size 
00876                       )
00877 {
00878     ec_sdo_data_t *sdodata;
00879 
00880     if (!(slave->sii_mailbox_protocols & EC_MBOX_COE)) {
00881         EC_ERR("Slave %i does not support CoE!\n", slave->ring_position);
00882         return -1;
00883     }
00884 
00885     if (!(sdodata = (ec_sdo_data_t *)
00886           kmalloc(sizeof(ec_sdo_data_t), GFP_KERNEL))) {
00887         EC_ERR("Failed to allocate memory for SDO configuration object!\n");
00888         return -1;
00889     }
00890 
00891     if (!(sdodata->data = (uint8_t *) kmalloc(size, GFP_KERNEL))) {
00892         EC_ERR("Failed to allocate memory for SDO configuration data!\n");
00893         kfree(sdodata);
00894         return -1;
00895     }
00896 
00897     sdodata->index = sdo_index;
00898     sdodata->subindex = sdo_subindex;
00899     memcpy(sdodata->data, data, size);
00900     sdodata->size = size;
00901 
00902     list_add_tail(&sdodata->list, &slave->sdo_confs);
00903     return 0;
00904 }
00905 
00906 /******************************************************************************
00907  *  Realtime interface
00908  *****************************************************************************/
00909 
00915 int ecrt_slave_conf_sdo8(ec_slave_t *slave, 
00916                          uint16_t sdo_index, 
00917                          uint8_t sdo_subindex, 
00918                          uint8_t value 
00919                          )
00920 {
00921     uint8_t data[1];
00922     EC_WRITE_U8(data, value);
00923     return ec_slave_conf_sdo(slave, sdo_index, sdo_subindex, data, 1);
00924 }
00925 
00926 /*****************************************************************************/
00927 
00933 int ecrt_slave_conf_sdo16(ec_slave_t *slave, 
00934                           uint16_t sdo_index, 
00935                           uint8_t sdo_subindex, 
00936                           uint16_t value 
00937                           )
00938 {
00939     uint8_t data[2];
00940     EC_WRITE_U16(data, value);
00941     return ec_slave_conf_sdo(slave, sdo_index, sdo_subindex, data, 2);
00942 }
00943 
00944 /*****************************************************************************/
00945 
00951 int ecrt_slave_conf_sdo32(ec_slave_t *slave, 
00952                           uint16_t sdo_index, 
00953                           uint8_t sdo_subindex, 
00954                           uint32_t value 
00955                           )
00956 {
00957     uint8_t data[4];
00958     EC_WRITE_U32(data, value);
00959     return ec_slave_conf_sdo(slave, sdo_index, sdo_subindex, data, 4);
00960 }
00961 
00962 /*****************************************************************************/
00963 
00969 int ecrt_slave_pdo_size(ec_slave_t *slave, 
00970                         uint16_t pdo_index, 
00971                         uint8_t pdo_subindex, 
00972                         size_t size 
00973                         )
00974 {
00975     EC_WARN("ecrt_slave_pdo_size() currently not available.\n");
00976     return -1;
00977 
00978 #if 0
00979     unsigned int i, j, field_counter;
00980     const ec_sii_sync_t *sync;
00981     const ec_pdo_t *pdo;
00982     ec_varsize_t *var;
00983 
00984     if (!slave->type) {
00985         EC_ERR("Slave %i has no type information!\n", slave->ring_position);
00986         return -1;
00987     }
00988 
00989     field_counter = 0;
00990     for (i = 0; (sync = slave->type->sync_managers[i]); i++) {
00991         for (j = 0; (field = sync->fields[j]); j++) {
00992             if (!strcmp(field->name, field_name)) {
00993                 if (field_counter++ == field_index) {
00994                     // is the size of this field variable?
00995                     if (field->size) {
00996                         EC_ERR("Field \"%s\"[%i] of slave %i has no variable"
00997                                " size!\n", field->name, field_index,
00998                                slave->ring_position);
00999                         return -1;
01000                     }
01001                     // does a size specification already exist?
01002                     list_for_each_entry(var, &slave->varsize_fields, list) {
01003                         if (var->field == field) {
01004                             EC_WARN("Resizing field \"%s\"[%i] of slave %i.\n",
01005                                     field->name, field_index,
01006                                     slave->ring_position);
01007                             var->size = size;
01008                             return 0;
01009                         }
01010                     }
01011                     // create a new size specification...
01012                     if (!(var = kmalloc(sizeof(ec_varsize_t), GFP_KERNEL))) {
01013                         EC_ERR("Failed to allocate memory for varsize_t!\n");
01014                         return -1;
01015                     }
01016                     var->field = field;
01017                     var->size = size;
01018                     list_add_tail(&var->list, &slave->varsize_fields);
01019                     return 0;
01020                 }
01021             }
01022         }
01023     }
01024 
01025     EC_ERR("Slave %i (\"%s %s\") has no field \"%s\"[%i]!\n",
01026            slave->ring_position, slave->type->vendor_name,
01027            slave->type->product_name, field_name, field_index);
01028     return -1;
01029 #endif
01030 }
01031 
01032 /*****************************************************************************/
01033 
01036 EXPORT_SYMBOL(ecrt_slave_conf_sdo8);
01037 EXPORT_SYMBOL(ecrt_slave_conf_sdo16);
01038 EXPORT_SYMBOL(ecrt_slave_conf_sdo32);
01039 EXPORT_SYMBOL(ecrt_slave_pdo_size);
01040 
01043 /*****************************************************************************/

Generated on Fri Sep 1 14:56:56 2006 for IgH EtherCAT master by  doxygen 1.4.6