slave.c

Go to the documentation of this file.
00001 /******************************************************************************
00002  *
00003  *  $Id: slave.c 490 2006-08-02 12:25:25Z 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 int ec_slave_fetch_categories(ec_slave_t *);
00056 ssize_t ec_show_slave_attribute(struct kobject *, struct attribute *, char *);
00057 ssize_t ec_store_slave_attribute(struct kobject *, struct attribute *,
00058                                  const char *, size_t);
00059 
00060 /*****************************************************************************/
00061 
00064 EC_SYSFS_READ_ATTR(ring_position);
00065 EC_SYSFS_READ_ATTR(advanced_position);
00066 EC_SYSFS_READ_ATTR(vendor_name); // deprecated
00067 EC_SYSFS_READ_ATTR(product_name); // deprecated
00068 EC_SYSFS_READ_ATTR(product_desc); // deprecated
00069 EC_SYSFS_READ_ATTR(name);
00070 EC_SYSFS_READ_ATTR(type); // deprecated
00071 EC_SYSFS_READ_WRITE_ATTR(state);
00072 EC_SYSFS_READ_WRITE_ATTR(eeprom);
00073 
00074 static struct attribute *def_attrs[] = {
00075     &attr_ring_position,
00076     &attr_advanced_position,
00077     &attr_vendor_name,
00078     &attr_product_name,
00079     &attr_product_desc,
00080     &attr_name,
00081     &attr_type,
00082     &attr_state,
00083     &attr_eeprom,
00084     NULL,
00085 };
00086 
00087 static struct sysfs_ops sysfs_ops = {
00088     .show = ec_show_slave_attribute,
00089     .store = ec_store_slave_attribute
00090 };
00091 
00092 static struct kobj_type ktype_ec_slave = {
00093     .release = ec_slave_clear,
00094     .sysfs_ops = &sysfs_ops,
00095     .default_attrs = def_attrs
00096 };
00097 
00100 /*****************************************************************************/
00101 
00107 int ec_slave_init(ec_slave_t *slave, 
00108                   ec_master_t *master, 
00109                   uint16_t ring_position, 
00110                   uint16_t station_address 
00111                   )
00112 {
00113     unsigned int i;
00114 
00115     slave->ring_position = ring_position;
00116     slave->station_address = station_address;
00117 
00118     // init kobject and add it to the hierarchy
00119     memset(&slave->kobj, 0x00, sizeof(struct kobject));
00120     kobject_init(&slave->kobj);
00121     slave->kobj.ktype = &ktype_ec_slave;
00122     slave->kobj.parent = &master->kobj;
00123     if (kobject_set_name(&slave->kobj, "slave%03i", slave->ring_position)) {
00124         EC_ERR("Failed to set kobject name.\n");
00125         kobject_put(&slave->kobj);
00126         return -1;
00127     }
00128 
00129     slave->master = master;
00130     slave->coupler_index = 0;
00131     slave->coupler_subindex = 0xFFFF;
00132     slave->base_type = 0;
00133     slave->base_revision = 0;
00134     slave->base_build = 0;
00135     slave->base_fmmu_count = 0;
00136     slave->base_sync_count = 0;
00137     slave->sii_alias = 0;
00138     slave->sii_vendor_id = 0;
00139     slave->sii_product_code = 0;
00140     slave->sii_revision_number = 0;
00141     slave->sii_serial_number = 0;
00142     slave->sii_rx_mailbox_offset = 0;
00143     slave->sii_rx_mailbox_size = 0;
00144     slave->sii_tx_mailbox_offset = 0;
00145     slave->sii_tx_mailbox_size = 0;
00146     slave->sii_mailbox_protocols = 0;
00147     slave->type = NULL;
00148     slave->registered = 0;
00149     slave->fmmu_count = 0;
00150     slave->eeprom_data = NULL;
00151     slave->eeprom_size = 0;
00152     slave->eeprom_group = NULL;
00153     slave->eeprom_image = NULL;
00154     slave->eeprom_order = NULL;
00155     slave->eeprom_name = NULL;
00156     slave->requested_state = EC_SLAVE_STATE_UNKNOWN;
00157     slave->current_state = EC_SLAVE_STATE_UNKNOWN;
00158     slave->error_flag = 0;
00159     slave->online = 1;
00160     slave->new_eeprom_data = NULL;
00161     slave->new_eeprom_size = 0;
00162 
00163     INIT_LIST_HEAD(&slave->eeprom_strings);
00164     INIT_LIST_HEAD(&slave->eeprom_syncs);
00165     INIT_LIST_HEAD(&slave->eeprom_pdos);
00166     INIT_LIST_HEAD(&slave->sdo_dictionary);
00167     INIT_LIST_HEAD(&slave->varsize_fields);
00168 
00169     for (i = 0; i < 4; i++) {
00170         slave->dl_link[i] = 0;
00171         slave->dl_loop[i] = 0;
00172         slave->dl_signal[i] = 0;
00173         slave->sii_physical_layer[i] = 0xFF;
00174     }
00175 
00176     return 0;
00177 }
00178 
00179 /*****************************************************************************/
00180 
00185 void ec_slave_clear(struct kobject *kobj )
00186 {
00187     ec_slave_t *slave;
00188     ec_eeprom_string_t *string, *next_str;
00189     ec_eeprom_sync_t *sync, *next_sync;
00190     ec_eeprom_pdo_t *pdo, *next_pdo;
00191     ec_eeprom_pdo_entry_t *entry, *next_ent;
00192     ec_sdo_t *sdo, *next_sdo;
00193     ec_sdo_entry_t *en, *next_en;
00194     ec_varsize_t *var, *next_var;
00195 
00196     slave = container_of(kobj, ec_slave_t, kobj);
00197 
00198     // free all string objects
00199     list_for_each_entry_safe(string, next_str, &slave->eeprom_strings, list) {
00200         list_del(&string->list);
00201         kfree(string);
00202     }
00203 
00204     // free all sync managers
00205     list_for_each_entry_safe(sync, next_sync, &slave->eeprom_syncs, list) {
00206         list_del(&sync->list);
00207         kfree(sync);
00208     }
00209 
00210     // free all PDOs
00211     list_for_each_entry_safe(pdo, next_pdo, &slave->eeprom_pdos, list) {
00212         list_del(&pdo->list);
00213         if (pdo->name) kfree(pdo->name);
00214 
00215         // free all PDO entries
00216         list_for_each_entry_safe(entry, next_ent, &pdo->entries, list) {
00217             list_del(&entry->list);
00218             if (entry->name) kfree(entry->name);
00219             kfree(entry);
00220         }
00221 
00222         kfree(pdo);
00223     }
00224 
00225     if (slave->eeprom_group) kfree(slave->eeprom_group);
00226     if (slave->eeprom_image) kfree(slave->eeprom_image);
00227     if (slave->eeprom_order) kfree(slave->eeprom_order);
00228     if (slave->eeprom_name) kfree(slave->eeprom_name);
00229 
00230     // free all SDOs
00231     list_for_each_entry_safe(sdo, next_sdo, &slave->sdo_dictionary, list) {
00232         list_del(&sdo->list);
00233         if (sdo->name) kfree(sdo->name);
00234 
00235         // free all SDO entries
00236         list_for_each_entry_safe(en, next_en, &sdo->entries, list) {
00237             list_del(&en->list);
00238             kfree(en);
00239         }
00240         kfree(sdo);
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(ec_slave_t *slave )
00261 {
00262     ec_datagram_t *datagram;
00263     unsigned int i;
00264     uint16_t dl_status;
00265 
00266     datagram = &slave->master->simple_datagram;
00267 
00268     // read base data
00269     if (ec_datagram_nprd(datagram, slave->station_address, 0x0000, 6))
00270         return -1;
00271     if (unlikely(ec_master_simple_io(slave->master, datagram))) {
00272         EC_ERR("Reading base data from slave %i failed!\n",
00273                slave->ring_position);
00274         return -1;
00275     }
00276 
00277     slave->base_type =       EC_READ_U8 (datagram->data);
00278     slave->base_revision =   EC_READ_U8 (datagram->data + 1);
00279     slave->base_build =      EC_READ_U16(datagram->data + 2);
00280     slave->base_fmmu_count = EC_READ_U8 (datagram->data + 4);
00281     slave->base_sync_count = EC_READ_U8 (datagram->data + 5);
00282 
00283     if (slave->base_fmmu_count > EC_MAX_FMMUS)
00284         slave->base_fmmu_count = EC_MAX_FMMUS;
00285 
00286     // read data link status
00287     if (ec_datagram_nprd(datagram, slave->station_address, 0x0110, 2))
00288         return -1;
00289     if (unlikely(ec_master_simple_io(slave->master, datagram))) {
00290         EC_ERR("Reading DL status from slave %i failed!\n",
00291                slave->ring_position);
00292         return -1;
00293     }
00294 
00295     dl_status = EC_READ_U16(datagram->data);
00296     for (i = 0; i < 4; i++) {
00297         slave->dl_link[i] = dl_status & (1 << (4 + i)) ? 1 : 0;
00298         slave->dl_loop[i] = dl_status & (1 << (8 + i * 2)) ? 1 : 0;
00299         slave->dl_signal[i] = dl_status & (1 << (9 + i * 2)) ? 1 : 0;
00300     }
00301 
00302     // read EEPROM data
00303     if (ec_slave_sii_read16(slave, 0x0004, &slave->sii_alias))
00304         return -1;
00305     if (ec_slave_sii_read32(slave, 0x0008, &slave->sii_vendor_id))
00306         return -1;
00307     if (ec_slave_sii_read32(slave, 0x000A, &slave->sii_product_code))
00308         return -1;
00309     if (ec_slave_sii_read32(slave, 0x000C, &slave->sii_revision_number))
00310         return -1;
00311     if (ec_slave_sii_read32(slave, 0x000E, &slave->sii_serial_number))
00312         return -1;
00313     if (ec_slave_sii_read16(slave, 0x0018, &slave->sii_rx_mailbox_offset))
00314         return -1;
00315     if (ec_slave_sii_read16(slave, 0x0019, &slave->sii_rx_mailbox_size))
00316         return -1;
00317     if (ec_slave_sii_read16(slave, 0x001A, &slave->sii_tx_mailbox_offset))
00318         return -1;
00319     if (ec_slave_sii_read16(slave, 0x001B, &slave->sii_tx_mailbox_size))
00320         return -1;
00321     if (ec_slave_sii_read16(slave, 0x001C, &slave->sii_mailbox_protocols))
00322         return -1;
00323 
00324     if (unlikely(ec_slave_fetch_categories(slave))) {
00325         EC_ERR("Failed to fetch category data!\n");
00326         return -1;
00327     }
00328 
00329     return 0;
00330 }
00331 
00332 /*****************************************************************************/
00333 
00339 int ec_slave_sii_read16(ec_slave_t *slave,
00341                         uint16_t offset,
00343                         uint16_t *target
00345                         )
00346 {
00347     ec_datagram_t *datagram;
00348     cycles_t start, end, timeout;
00349 
00350     datagram = &slave->master->simple_datagram;
00351 
00352     // initiate read operation
00353     if (ec_datagram_npwr(datagram, slave->station_address, 0x502, 6))
00354         return -1;
00355     EC_WRITE_U8 (datagram->data,     0x00); // read-only access
00356     EC_WRITE_U8 (datagram->data + 1, 0x01); // request read operation
00357     EC_WRITE_U32(datagram->data + 2, offset);
00358     if (unlikely(ec_master_simple_io(slave->master, datagram))) {
00359         EC_ERR("SII-read failed on slave %i!\n", slave->ring_position);
00360         return -1;
00361     }
00362 
00363     start = get_cycles();
00364     timeout = (cycles_t) 100 * cpu_khz; // 100ms
00365 
00366     while (1)
00367     {
00368         udelay(10);
00369 
00370         if (ec_datagram_nprd(datagram, slave->station_address, 0x502, 10))
00371             return -1;
00372         if (unlikely(ec_master_simple_io(slave->master, datagram))) {
00373             EC_ERR("Getting SII-read status failed on slave %i!\n",
00374                    slave->ring_position);
00375             return -1;
00376         }
00377 
00378         end = get_cycles();
00379 
00380         // check for "busy bit"
00381         if (likely((EC_READ_U8(datagram->data + 1) & 0x81) == 0)) {
00382             *target = EC_READ_U16(datagram->data + 6);
00383             return 0;
00384         }
00385 
00386         if (unlikely((end - start) >= timeout)) {
00387             EC_ERR("SII-read. Slave %i timed out!\n", slave->ring_position);
00388             return -1;
00389         }
00390     }
00391 }
00392 
00393 /*****************************************************************************/
00394 
00400 int ec_slave_sii_read32(ec_slave_t *slave,
00402                         uint16_t offset,
00404                         uint32_t *target
00406                         )
00407 {
00408     ec_datagram_t *datagram;
00409     cycles_t start, end, timeout;
00410 
00411     datagram = &slave->master->simple_datagram;
00412 
00413     // initiate read operation
00414     if (ec_datagram_npwr(datagram, slave->station_address, 0x502, 6))
00415         return -1;
00416     EC_WRITE_U8 (datagram->data,     0x00); // read-only access
00417     EC_WRITE_U8 (datagram->data + 1, 0x01); // request read operation
00418     EC_WRITE_U32(datagram->data + 2, offset);
00419     if (unlikely(ec_master_simple_io(slave->master, datagram))) {
00420         EC_ERR("SII-read failed on slave %i!\n", slave->ring_position);
00421         return -1;
00422     }
00423 
00424     start = get_cycles();
00425     timeout = (cycles_t) 100 * cpu_khz; // 100ms
00426 
00427     while (1)
00428     {
00429         udelay(10);
00430 
00431         if (ec_datagram_nprd(datagram, slave->station_address, 0x502, 10))
00432             return -1;
00433         if (unlikely(ec_master_simple_io(slave->master, datagram))) {
00434             EC_ERR("Getting SII-read status failed on slave %i!\n",
00435                    slave->ring_position);
00436             return -1;
00437         }
00438 
00439         end = get_cycles();
00440 
00441         // check "busy bit"
00442         if (likely((EC_READ_U8(datagram->data + 1) & 0x81) == 0)) {
00443             *target = EC_READ_U32(datagram->data + 6);
00444             return 0;
00445         }
00446 
00447         if (unlikely((end - start) >= timeout)) {
00448             EC_ERR("SII-read. Slave %i timed out!\n", slave->ring_position);
00449             return -1;
00450         }
00451     }
00452 }
00453 
00454 /*****************************************************************************/
00455 
00461 int ec_slave_sii_write16(ec_slave_t *slave,
00463                          uint16_t offset,
00465                          uint16_t value
00467                          )
00468 {
00469     ec_datagram_t *datagram;
00470     cycles_t start, end, timeout;
00471 
00472     datagram = &slave->master->simple_datagram;
00473 
00474     EC_INFO("SII-write (slave %i, offset 0x%04X, value 0x%04X)\n",
00475             slave->ring_position, offset, value);
00476 
00477     // initiate write operation
00478     if (ec_datagram_npwr(datagram, slave->station_address, 0x502, 8))
00479         return -1;
00480     EC_WRITE_U8 (datagram->data,     0x01); // enable write access
00481     EC_WRITE_U8 (datagram->data + 1, 0x02); // request write operation
00482     EC_WRITE_U32(datagram->data + 2, offset);
00483     EC_WRITE_U16(datagram->data + 6, value);
00484     if (unlikely(ec_master_simple_io(slave->master, datagram))) {
00485         EC_ERR("SII-write failed on slave %i!\n", slave->ring_position);
00486         return -1;
00487     }
00488 
00489     start = get_cycles();
00490     timeout = (cycles_t) 100 * cpu_khz; // 100ms
00491 
00492     while (1)
00493     {
00494         udelay(10);
00495 
00496         if (ec_datagram_nprd(datagram, slave->station_address, 0x502, 2))
00497             return -1;
00498         if (unlikely(ec_master_simple_io(slave->master, datagram))) {
00499             EC_ERR("Getting SII-write status failed on slave %i!\n",
00500                    slave->ring_position);
00501             return -1;
00502         }
00503 
00504         end = get_cycles();
00505 
00506         // check "busy bit"
00507         if (likely((EC_READ_U8(datagram->data + 1) & 0x82) == 0)) {
00508             if (EC_READ_U8(datagram->data + 1) & 0x40) {
00509                 EC_ERR("SII-write failed!\n");
00510                 return -1;
00511             }
00512             else {
00513                 EC_INFO("SII-write succeeded!\n");
00514                 return 0;
00515             }
00516         }
00517 
00518         if (unlikely((end - start) >= timeout)) {
00519             EC_ERR("SII-write: Slave %i timed out!\n", slave->ring_position);
00520             return -1;
00521         }
00522     }
00523 }
00524 
00525 /*****************************************************************************/
00526 
00533 int ec_slave_fetch_categories(ec_slave_t *slave )
00534 {
00535     uint16_t word_offset, cat_type, word_count;
00536     uint32_t value;
00537     uint8_t *cat_data;
00538     unsigned int i;
00539 
00540     word_offset = 0x0040;
00541 
00542     if (!(cat_data = (uint8_t *) kmalloc(0x10000, GFP_ATOMIC))) {
00543         EC_ERR("Failed to allocate 64k bytes for category data.\n");
00544         return -1;
00545     }
00546 
00547     while (1) {
00548         // read category type
00549         if (ec_slave_sii_read32(slave, word_offset, &value)) {
00550             EC_ERR("Unable to read category header.\n");
00551             goto out_free;
00552         }
00553 
00554         // last category?
00555         if ((value & 0xFFFF) == 0xFFFF) break;
00556 
00557         cat_type = value & 0x7FFF;
00558         word_count = (value >> 16) & 0xFFFF;
00559 
00560         // fetch category data
00561         for (i = 0; i < word_count; i++) {
00562             if (ec_slave_sii_read32(slave, word_offset + 2 + i, &value)) {
00563                 EC_ERR("Unable to read category data word %i.\n", i);
00564                 goto out_free;
00565             }
00566 
00567             cat_data[i * 2]     = (value >> 0) & 0xFF;
00568             cat_data[i * 2 + 1] = (value >> 8) & 0xFF;
00569 
00570             // read second word "on the fly"
00571             if (i + 1 < word_count) {
00572                 i++;
00573                 cat_data[i * 2]     = (value >> 16) & 0xFF;
00574                 cat_data[i * 2 + 1] = (value >> 24) & 0xFF;
00575             }
00576         }
00577 
00578         switch (cat_type)
00579         {
00580             case 0x000A:
00581                 if (ec_slave_fetch_strings(slave, cat_data))
00582                     goto out_free;
00583                 break;
00584             case 0x001E:
00585                 if (ec_slave_fetch_general(slave, cat_data))
00586                     goto out_free;
00587                 break;
00588             case 0x0028:
00589                 break;
00590             case 0x0029:
00591                 if (ec_slave_fetch_sync(slave, cat_data, word_count))
00592                     goto out_free;
00593                 break;
00594             case 0x0032:
00595                 if (ec_slave_fetch_pdo(slave, cat_data, word_count, EC_TX_PDO))
00596                     goto out_free;
00597                 break;
00598             case 0x0033:
00599                 if (ec_slave_fetch_pdo(slave, cat_data, word_count, EC_RX_PDO))
00600                     goto out_free;
00601                 break;
00602             default:
00603                 EC_WARN("Unknown category type 0x%04X in slave %i.\n",
00604                         cat_type, slave->ring_position);
00605         }
00606 
00607         word_offset += 2 + word_count;
00608     }
00609 
00610     kfree(cat_data);
00611     return 0;
00612 
00613  out_free:
00614     kfree(cat_data);
00615     return -1;
00616 }
00617 
00618 /*****************************************************************************/
00619 
00625 int ec_slave_fetch_strings(ec_slave_t *slave, 
00626                            const uint8_t *data 
00627                            )
00628 {
00629     unsigned int string_count, i;
00630     size_t size;
00631     off_t offset;
00632     ec_eeprom_string_t *string;
00633 
00634     string_count = data[0];
00635     offset = 1;
00636     for (i = 0; i < string_count; i++) {
00637         size = data[offset];
00638         // allocate memory for string structure and data at a single blow
00639         if (!(string = (ec_eeprom_string_t *)
00640               kmalloc(sizeof(ec_eeprom_string_t) + size + 1, GFP_ATOMIC))) {
00641             EC_ERR("Failed to allocate string memory.\n");
00642             return -1;
00643         }
00644         string->size = size;
00645         // string memory appended to string structure
00646         string->data = (char *) string + sizeof(ec_eeprom_string_t);
00647         memcpy(string->data, data + offset + 1, size);
00648         string->data[size] = 0x00;
00649         list_add_tail(&string->list, &slave->eeprom_strings);
00650         offset += 1 + size;
00651     }
00652 
00653     return 0;
00654 }
00655 
00656 /*****************************************************************************/
00657 
00663 int ec_slave_fetch_general(ec_slave_t *slave, 
00664                            const uint8_t *data 
00665                            )
00666 {
00667     unsigned int i;
00668 
00669     if (ec_slave_locate_string(slave, data[0], &slave->eeprom_group))
00670         return -1;
00671     if (ec_slave_locate_string(slave, data[1], &slave->eeprom_image))
00672         return -1;
00673     if (ec_slave_locate_string(slave, data[2], &slave->eeprom_order))
00674         return -1;
00675     if (ec_slave_locate_string(slave, data[3], &slave->eeprom_name))
00676         return -1;
00677 
00678     for (i = 0; i < 4; i++)
00679         slave->sii_physical_layer[i] =
00680             (data[4] & (0x03 << (i * 2))) >> (i * 2);
00681 
00682     return 0;
00683 }
00684 
00685 /*****************************************************************************/
00686 
00692 int ec_slave_fetch_sync(ec_slave_t *slave, 
00693                         const uint8_t *data, 
00694                         size_t word_count 
00695                         )
00696 {
00697     unsigned int sync_count, i;
00698     ec_eeprom_sync_t *sync;
00699 
00700     sync_count = word_count / 4; // sync manager struct is 4 words long
00701 
00702     for (i = 0; i < sync_count; i++, data += 8) {
00703         if (!(sync = (ec_eeprom_sync_t *)
00704               kmalloc(sizeof(ec_eeprom_sync_t), GFP_ATOMIC))) {
00705             EC_ERR("Failed to allocate Sync-Manager memory.\n");
00706             return -1;
00707         }
00708 
00709         sync->index = i;
00710         sync->physical_start_address = *((uint16_t *) (data + 0));
00711         sync->length                 = *((uint16_t *) (data + 2));
00712         sync->control_register       = data[4];
00713         sync->enable                 = data[6];
00714 
00715         list_add_tail(&sync->list, &slave->eeprom_syncs);
00716     }
00717 
00718     return 0;
00719 }
00720 
00721 /*****************************************************************************/
00722 
00728 int ec_slave_fetch_pdo(ec_slave_t *slave, 
00729                        const uint8_t *data, 
00730                        size_t word_count, 
00731                        ec_pdo_type_t pdo_type 
00732                        )
00733 {
00734     ec_eeprom_pdo_t *pdo;
00735     ec_eeprom_pdo_entry_t *entry;
00736     unsigned int entry_count, i;
00737 
00738     while (word_count >= 4) {
00739         if (!(pdo = (ec_eeprom_pdo_t *)
00740               kmalloc(sizeof(ec_eeprom_pdo_t), GFP_ATOMIC))) {
00741             EC_ERR("Failed to allocate PDO memory.\n");
00742             return -1;
00743         }
00744 
00745         INIT_LIST_HEAD(&pdo->entries);
00746         pdo->type = pdo_type;
00747 
00748         pdo->index = *((uint16_t *) data);
00749         entry_count = data[2];
00750         pdo->sync_manager = data[3];
00751         pdo->name = NULL;
00752         ec_slave_locate_string(slave, data[5], &pdo->name);
00753 
00754         list_add_tail(&pdo->list, &slave->eeprom_pdos);
00755 
00756         word_count -= 4;
00757         data += 8;
00758 
00759         for (i = 0; i < entry_count; i++) {
00760             if (!(entry = (ec_eeprom_pdo_entry_t *)
00761                   kmalloc(sizeof(ec_eeprom_pdo_entry_t), GFP_ATOMIC))) {
00762                 EC_ERR("Failed to allocate PDO entry memory.\n");
00763                 return -1;
00764             }
00765 
00766             entry->index = *((uint16_t *) data);
00767             entry->subindex = data[2];
00768             entry->name = NULL;
00769             ec_slave_locate_string(slave, data[3], &entry->name);
00770             entry->bit_length = data[5];
00771 
00772             list_add_tail(&entry->list, &pdo->entries);
00773 
00774             word_count -= 4;
00775             data += 8;
00776         }
00777     }
00778 
00779     return 0;
00780 }
00781 
00782 /*****************************************************************************/
00783 
00790 int ec_slave_locate_string(ec_slave_t *slave, 
00791                            unsigned int index, 
00792                            char **ptr 
00793                            )
00794 {
00795     ec_eeprom_string_t *string;
00796     char *err_string;
00797 
00798     // Erst alten Speicher freigeben
00799     if (*ptr) {
00800         kfree(*ptr);
00801         *ptr = NULL;
00802     }
00803 
00804     // Index 0 bedeutet "nicht belegt"
00805     if (!index) return 0;
00806 
00807     // EEPROM-String mit Index finden und kopieren
00808     list_for_each_entry(string, &slave->eeprom_strings, list) {
00809         if (--index) continue;
00810 
00811         if (!(*ptr = (char *) kmalloc(string->size + 1, GFP_ATOMIC))) {
00812             EC_ERR("Unable to allocate string memory.\n");
00813             return -1;
00814         }
00815         memcpy(*ptr, string->data, string->size + 1);
00816         return 0;
00817     }
00818 
00819     EC_WARN("String %i not found in slave %i.\n", index, slave->ring_position);
00820 
00821     err_string = "(string not found)";
00822 
00823     if (!(*ptr = (char *) kmalloc(strlen(err_string) + 1, GFP_ATOMIC))) {
00824         EC_ERR("Unable to allocate string memory.\n");
00825         return -1;
00826     }
00827 
00828     memcpy(*ptr, err_string, strlen(err_string) + 1);
00829     return 0;
00830 }
00831 
00832 /*****************************************************************************/
00833 
00838 void ec_slave_state_ack(ec_slave_t *slave, 
00839                         uint8_t state 
00840                         )
00841 {
00842     ec_datagram_t *datagram;
00843     cycles_t start, end, timeout;
00844 
00845     datagram = &slave->master->simple_datagram;
00846 
00847     if (ec_datagram_npwr(datagram, slave->station_address, 0x0120, 2)) return;
00848     EC_WRITE_U16(datagram->data, state | EC_ACK);
00849     if (unlikely(ec_master_simple_io(slave->master, datagram))) {
00850         EC_WARN("Acknowledge sending failed on slave %i!\n",
00851                 slave->ring_position);
00852         return;
00853     }
00854 
00855     start = get_cycles();
00856     timeout = (cycles_t) 100 * cpu_khz; // 100ms
00857 
00858     while (1) {
00859         udelay(100); // wait a little bit...
00860 
00861         if (ec_datagram_nprd(datagram, slave->station_address, 0x0130, 2))
00862             return;
00863         if (unlikely(ec_master_simple_io(slave->master, datagram))) {
00864             slave->current_state = EC_SLAVE_STATE_UNKNOWN;
00865             EC_WARN("Acknowledge checking failed on slave %i!\n",
00866                     slave->ring_position);
00867             return;
00868         }
00869 
00870         end = get_cycles();
00871 
00872         if (EC_READ_U8(datagram->data) == state) {
00873             slave->current_state = state;
00874             EC_INFO("Acknowleged state 0x%02X on slave %i.\n", state,
00875                     slave->ring_position);
00876             return;
00877         }
00878 
00879         if (end - start >= timeout) {
00880             slave->current_state = EC_SLAVE_STATE_UNKNOWN;
00881             EC_WARN("Failed to acknowledge state 0x%02X on slave %i"
00882                     " - Timeout!\n", state, slave->ring_position);
00883             return;
00884         }
00885     }
00886 }
00887 
00888 /*****************************************************************************/
00889 
00896 void ec_slave_read_al_status_code(ec_slave_t *slave )
00897 {
00898     ec_datagram_t *datagram;
00899     uint16_t code;
00900     const ec_code_msg_t *al_msg;
00901 
00902     datagram = &slave->master->simple_datagram;
00903 
00904     if (ec_datagram_nprd(datagram, slave->station_address, 0x0134, 2)) return;
00905     if (unlikely(ec_master_simple_io(slave->master, datagram))) {
00906         EC_WARN("Failed to read AL status code on slave %i!\n",
00907                 slave->ring_position);
00908         return;
00909     }
00910 
00911     if (!(code = EC_READ_U16(datagram->data))) return;
00912 
00913     for (al_msg = al_status_messages; al_msg->code; al_msg++) {
00914         if (al_msg->code == code) {
00915             EC_ERR("AL status message 0x%04X: \"%s\".\n",
00916                    al_msg->code, al_msg->message);
00917             return;
00918         }
00919     }
00920 
00921     EC_ERR("Unknown AL status code 0x%04X.\n", code);
00922 }
00923 
00924 /*****************************************************************************/
00925 
00931 int ec_slave_state_change(ec_slave_t *slave, 
00932                           uint8_t state 
00933                           )
00934 {
00935     ec_datagram_t *datagram;
00936     cycles_t start, end, timeout;
00937 
00938     datagram = &slave->master->simple_datagram;
00939 
00940     slave->requested_state = state;
00941 
00942     if (ec_datagram_npwr(datagram, slave->station_address, 0x0120, 2))
00943         return -1;
00944     EC_WRITE_U16(datagram->data, state);
00945     if (unlikely(ec_master_simple_io(slave->master, datagram))) {
00946         EC_ERR("Failed to set state 0x%02X on slave %i!\n",
00947                state, slave->ring_position);
00948         return -1;
00949     }
00950 
00951     start = get_cycles();
00952     timeout = (cycles_t) 10 * cpu_khz; // 10ms
00953 
00954     while (1)
00955     {
00956         udelay(100); // wait a little bit
00957 
00958         if (ec_datagram_nprd(datagram, slave->station_address, 0x0130, 2))
00959             return -1;
00960         if (unlikely(ec_master_simple_io(slave->master, datagram))) {
00961             slave->current_state = EC_SLAVE_STATE_UNKNOWN;
00962             EC_ERR("Failed to check state 0x%02X on slave %i!\n",
00963                    state, slave->ring_position);
00964             return -1;
00965         }
00966 
00967         end = get_cycles();
00968 
00969         if (unlikely(EC_READ_U8(datagram->data) & 0x10)) {
00970             // state change error
00971             EC_ERR("Failed to set state 0x%02X - Slave %i refused state change"
00972                    " (code 0x%02X)!\n", state, slave->ring_position,
00973                    EC_READ_U8(datagram->data));
00974             slave->current_state = EC_READ_U8(datagram->data);
00975             state = slave->current_state & 0x0F;
00976             ec_slave_read_al_status_code(slave);
00977             ec_slave_state_ack(slave, state);
00978             return -1;
00979         }
00980 
00981         if (likely(EC_READ_U8(datagram->data) == (state & 0x0F))) {
00982             slave->current_state = state;
00983             return 0; // state change successful
00984         }
00985 
00986         if (unlikely((end - start) >= timeout)) {
00987             slave->current_state = EC_SLAVE_STATE_UNKNOWN;
00988             EC_ERR("Failed to check state 0x%02X of slave %i - Timeout!\n",
00989                    state, slave->ring_position);
00990             return -1;
00991         }
00992     }
00993 }
00994 
00995 /*****************************************************************************/
00996 
01009 int ec_slave_prepare_fmmu(ec_slave_t *slave, 
01010                           const ec_domain_t *domain, 
01011                           const ec_sync_t *sync  
01012                           )
01013 {
01014     unsigned int i;
01015 
01016     // FMMU configuration already prepared?
01017     for (i = 0; i < slave->fmmu_count; i++)
01018         if (slave->fmmus[i].domain == domain && slave->fmmus[i].sync == sync)
01019             return 0;
01020 
01021     // reserve new FMMU...
01022 
01023     if (slave->fmmu_count >= slave->base_fmmu_count) {
01024         EC_ERR("Slave %i FMMU limit reached!\n", slave->ring_position);
01025         return -1;
01026     }
01027 
01028     slave->fmmus[slave->fmmu_count].domain = domain;
01029     slave->fmmus[slave->fmmu_count].sync = sync;
01030     slave->fmmus[slave->fmmu_count].logical_start_address = 0;
01031     slave->fmmu_count++;
01032     slave->registered = 1;
01033 
01034     return 0;
01035 }
01036 
01037 /*****************************************************************************/
01038 
01047 void ec_slave_print(const ec_slave_t *slave, 
01048                     unsigned int verbosity 
01049                     )
01050 {
01051     ec_eeprom_sync_t *sync;
01052     ec_eeprom_pdo_t *pdo;
01053     ec_eeprom_pdo_entry_t *pdo_entry;
01054     ec_sdo_t *sdo;
01055     ec_sdo_entry_t *sdo_entry;
01056     int first, i;
01057 
01058     if (slave->type) {
01059         EC_INFO("%i) %s %s: %s\n", slave->ring_position,
01060                 slave->type->vendor_name, slave->type->product_name,
01061                 slave->type->description);
01062     }
01063     else {
01064         EC_INFO("%i) UNKNOWN SLAVE: vendor 0x%08X, product 0x%08X\n",
01065                 slave->ring_position, slave->sii_vendor_id,
01066                 slave->sii_product_code);
01067     }
01068 
01069     if (!verbosity) return;
01070 
01071     EC_INFO("  Station address: 0x%04X\n", slave->station_address);
01072 
01073     EC_INFO("  Data link status:\n");
01074     for (i = 0; i < 4; i++) {
01075         EC_INFO("    Port %i (", i);
01076         switch (slave->sii_physical_layer[i]) {
01077             case 0x00:
01078                 printk("EBUS");
01079                 break;
01080             case 0x01:
01081                 printk("100BASE-TX");
01082                 break;
01083             case 0x02:
01084                 printk("100BASE-FX");
01085                 break;
01086             default:
01087                 printk("unknown");
01088         }
01089         printk(")\n");
01090         EC_INFO("      link %s, loop %s, %s\n",
01091                 slave->dl_link[i] ? "up" : "down",
01092                 slave->dl_loop[i] ? "closed" : "open",
01093                 slave->dl_signal[i] ? "signal detected" : "no signal");
01094     }
01095 
01096     EC_INFO("  Base information:\n");
01097     EC_INFO("    Type %u, revision %i, build %i\n",
01098             slave->base_type, slave->base_revision, slave->base_build);
01099     EC_INFO("    Supported FMMUs: %i, sync managers: %i\n",
01100             slave->base_fmmu_count, slave->base_sync_count);
01101 
01102     if (slave->sii_mailbox_protocols) {
01103         EC_INFO("  Mailbox communication:\n");
01104         EC_INFO("    RX mailbox: 0x%04X/%i, TX mailbox: 0x%04X/%i\n",
01105                 slave->sii_rx_mailbox_offset, slave->sii_rx_mailbox_size,
01106                 slave->sii_tx_mailbox_offset, slave->sii_tx_mailbox_size);
01107         EC_INFO("    Supported protocols: ");
01108 
01109         first = 1;
01110         if (slave->sii_mailbox_protocols & EC_MBOX_AOE) {
01111             printk("AoE");
01112             first = 0;
01113         }
01114         if (slave->sii_mailbox_protocols & EC_MBOX_EOE) {
01115             if (!first) printk(", ");
01116             printk("EoE");
01117             first = 0;
01118         }
01119         if (slave->sii_mailbox_protocols & EC_MBOX_COE) {
01120             if (!first) printk(", ");
01121             printk("CoE");
01122             first = 0;
01123         }
01124         if (slave->sii_mailbox_protocols & EC_MBOX_FOE) {
01125             if (!first) printk(", ");
01126             printk("FoE");
01127             first = 0;
01128         }
01129         if (slave->sii_mailbox_protocols & EC_MBOX_SOE) {
01130             if (!first) printk(", ");
01131             printk("SoE");
01132             first = 0;
01133         }
01134         if (slave->sii_mailbox_protocols & EC_MBOX_VOE) {
01135             if (!first) printk(", ");
01136             printk("VoE");
01137         }
01138         printk("\n");
01139     }
01140 
01141     EC_INFO("  EEPROM data:\n");
01142 
01143     EC_INFO("    EEPROM content size: %i Bytes\n", slave->eeprom_size);
01144 
01145     if (slave->sii_alias)
01146         EC_INFO("    Configured station alias: 0x%04X (%i)\n",
01147                 slave->sii_alias, slave->sii_alias);
01148 
01149     EC_INFO("    Vendor-ID: 0x%08X, Product code: 0x%08X\n",
01150             slave->sii_vendor_id, slave->sii_product_code);
01151     EC_INFO("    Revision number: 0x%08X, Serial number: 0x%08X\n",
01152             slave->sii_revision_number, slave->sii_serial_number);
01153 
01154     if (slave->eeprom_group)
01155         EC_INFO("    Group: %s\n", slave->eeprom_group);
01156     if (slave->eeprom_image)
01157         EC_INFO("    Image: %s\n", slave->eeprom_image);
01158     if (slave->eeprom_order)
01159         EC_INFO("    Order#: %s\n", slave->eeprom_order);
01160     if (slave->eeprom_name)
01161         EC_INFO("    Name: %s\n", slave->eeprom_name);
01162 
01163     if (!list_empty(&slave->eeprom_syncs)) {
01164         EC_INFO("    Sync-Managers:\n");
01165         list_for_each_entry(sync, &slave->eeprom_syncs, list) {
01166             EC_INFO("      %i: 0x%04X, length %i, control 0x%02X, %s\n",
01167                     sync->index, sync->physical_start_address,
01168                     sync->length, sync->control_register,
01169                     sync->enable ? "enable" : "disable");
01170         }
01171     }
01172 
01173     list_for_each_entry(pdo, &slave->eeprom_pdos, list) {
01174         EC_INFO("    %s \"%s\" (0x%04X), -> Sync-Manager %i\n",
01175                 pdo->type == EC_RX_PDO ? "RXPDO" : "TXPDO",
01176                 pdo->name ? pdo->name : "???",
01177                 pdo->index, pdo->sync_manager);
01178 
01179         list_for_each_entry(pdo_entry, &pdo->entries, list) {
01180             EC_INFO("      \"%s\" 0x%04X:%X, %i Bit\n",
01181                     pdo_entry->name ? pdo_entry->name : "???",
01182                     pdo_entry->index, pdo_entry->subindex,
01183                     pdo_entry->bit_length);
01184         }
01185     }
01186 
01187     if (verbosity < 2) return;
01188 
01189     if (!list_empty(&slave->sdo_dictionary)) {
01190         EC_INFO("    SDO-Dictionary:\n");
01191         list_for_each_entry(sdo, &slave->sdo_dictionary, list) {
01192             EC_INFO("      0x%04X \"%s\"\n", sdo->index,
01193                     sdo->name ? sdo->name : "");
01194             EC_INFO("        Object code: 0x%02X\n", sdo->object_code);
01195             list_for_each_entry(sdo_entry, &sdo->entries, list) {
01196                 EC_INFO("        0x%04X:%i \"%s\", type 0x%04X, %i bits\n",
01197                         sdo->index, sdo_entry->subindex,
01198                         sdo_entry->name ? sdo_entry->name : "",
01199                         sdo_entry->data_type, sdo_entry->bit_length);
01200             }
01201         }
01202     }
01203 }
01204 
01205 /*****************************************************************************/
01206 
01212 int ec_slave_check_crc(ec_slave_t *slave )
01213 {
01214     ec_datagram_t *datagram;
01215 
01216     datagram = &slave->master->simple_datagram;
01217 
01218     if (ec_datagram_nprd(datagram, slave->station_address, 0x0300, 4))
01219         return -1;
01220     if (unlikely(ec_master_simple_io(slave->master, datagram))) {
01221         EC_WARN("Reading CRC fault counters failed on slave %i!\n",
01222                 slave->ring_position);
01223         return -1;
01224     }
01225 
01226     if (!EC_READ_U32(datagram->data)) return 0; // no CRC faults
01227 
01228     if (EC_READ_U8(datagram->data))
01229         EC_WARN("%3i RX-error%s on slave %i, channel A.\n",
01230                 EC_READ_U8(datagram->data),
01231                 EC_READ_U8(datagram->data) == 1 ? "" : "s",
01232                 slave->ring_position);
01233     if (EC_READ_U8(datagram->data + 1))
01234         EC_WARN("%3i invalid frame%s on slave %i, channel A.\n",
01235                 EC_READ_U8(datagram->data + 1),
01236                 EC_READ_U8(datagram->data + 1) == 1 ? "" : "s",
01237                 slave->ring_position);
01238     if (EC_READ_U8(datagram->data + 2))
01239         EC_WARN("%3i RX-error%s on slave %i, channel B.\n",
01240                 EC_READ_U8(datagram->data + 2),
01241                 EC_READ_U8(datagram->data + 2) == 1 ? "" : "s",
01242                 slave->ring_position);
01243     if (EC_READ_U8(datagram->data + 3))
01244         EC_WARN("%3i invalid frame%s on slave %i, channel B.\n",
01245                 EC_READ_U8(datagram->data + 3),
01246                 EC_READ_U8(datagram->data + 3) == 1 ? "" : "s",
01247                 slave->ring_position);
01248 
01249     // reset CRC counters
01250     if (ec_datagram_npwr(datagram, slave->station_address, 0x0300, 4))
01251         return -1;
01252     EC_WRITE_U32(datagram->data, 0x00000000);
01253     if (unlikely(ec_master_simple_io(slave->master, datagram))) {
01254         EC_WARN("Resetting CRC fault counters failed on slave %i!\n",
01255                 slave->ring_position);
01256         return -1;
01257     }
01258 
01259     return 0;
01260 }
01261 
01262 /*****************************************************************************/
01263 
01269 ssize_t ec_slave_write_eeprom(ec_slave_t *slave, 
01270                               const uint8_t *data, 
01271                               size_t size 
01272                               )
01273 {
01274     uint16_t word_size, cat_type, cat_size;
01275     const uint16_t *data_words, *next_header;
01276     uint16_t *new_data;
01277 
01278     if (!slave->master->eeprom_write_enable) {
01279         EC_ERR("Writing EEPROMs not allowed! Enable via"
01280                " eeprom_write_enable SysFS entry.\n");
01281         return -1;
01282     }
01283 
01284     if (slave->master->mode != EC_MASTER_MODE_IDLE) {
01285         EC_ERR("Writing EEPROMs only allowed in idle mode!\n");
01286         return -1;
01287     }
01288 
01289     if (slave->new_eeprom_data) {
01290         EC_ERR("Slave %i already has a pending EEPROM write operation!\n",
01291                slave->ring_position);
01292         return -1;
01293     }
01294 
01295     // coarse check of the data
01296 
01297     if (size % 2) {
01298         EC_ERR("EEPROM size is odd! Dropping.\n");
01299         return -1;
01300     }
01301 
01302     data_words = (const uint16_t *) data;
01303     word_size = size / 2;
01304 
01305     if (word_size < 0x0041) {
01306         EC_ERR("EEPROM data too short! Dropping.\n");
01307         return -1;
01308     }
01309 
01310     next_header = data_words + 0x0040;
01311     cat_type = EC_READ_U16(next_header);
01312     while (cat_type != 0xFFFF) {
01313         cat_type = EC_READ_U16(next_header);
01314         cat_size = EC_READ_U16(next_header + 1);
01315         if ((next_header + cat_size + 2) - data_words >= word_size) {
01316             EC_ERR("EEPROM data seems to be corrupted! Dropping.\n");
01317             return -1;
01318         }
01319         next_header += cat_size + 2;
01320         cat_type = EC_READ_U16(next_header);
01321     }
01322 
01323     // data ok!
01324 
01325     if (!(new_data = (uint16_t *) kmalloc(word_size * 2, GFP_KERNEL))) {
01326         EC_ERR("Unable to allocate memory for new EEPROM data!\n");
01327         return -1;
01328     }
01329     memcpy(new_data, data, size);
01330 
01331     slave->new_eeprom_size = word_size;
01332     slave->new_eeprom_data = new_data;
01333 
01334     EC_INFO("EEPROM writing scheduled for slave %i, %i words.\n",
01335             slave->ring_position, word_size);
01336     return 0;
01337 }
01338 
01339 /*****************************************************************************/
01340 
01346 ssize_t ec_show_slave_attribute(struct kobject *kobj, 
01347                                 struct attribute *attr, 
01348                                 char *buffer 
01349                                 )
01350 {
01351     ec_slave_t *slave = container_of(kobj, ec_slave_t, kobj);
01352 
01353     if (attr == &attr_ring_position) {
01354         return sprintf(buffer, "%i\n", slave->ring_position);
01355     }
01356     else if (attr == &attr_advanced_position) {
01357         return sprintf(buffer, "%i:%i\n", slave->coupler_index,
01358                        slave->coupler_subindex);
01359     }
01360     else if (attr == &attr_vendor_name) {
01361         if (slave->type)
01362             return sprintf(buffer, "%s\n", slave->type->vendor_name);
01363     }
01364     else if (attr == &attr_product_name) {
01365         if (slave->type)
01366             return sprintf(buffer, "%s\n", slave->type->product_name);
01367     }
01368     else if (attr == &attr_product_desc) {
01369         if (slave->type)
01370             return sprintf(buffer, "%s\n", slave->type->description);
01371     }
01372     else if (attr == &attr_name) {
01373         if (slave->eeprom_name)
01374             return sprintf(buffer, "%s\n", slave->eeprom_name);
01375     }
01376     else if (attr == &attr_type) {
01377         if (slave->type) {
01378             if (slave->type->special == EC_TYPE_BUS_COUPLER)
01379                 return sprintf(buffer, "coupler\n");
01380         else if (slave->type->special == EC_TYPE_INFRA)
01381                 return sprintf(buffer, "infrastructure\n");
01382             else
01383                 return sprintf(buffer, "normal\n");
01384         }
01385     }
01386     else if (attr == &attr_state) {
01387         switch (slave->current_state) {
01388             case EC_SLAVE_STATE_INIT:
01389                 return sprintf(buffer, "INIT\n");
01390             case EC_SLAVE_STATE_PREOP:
01391                 return sprintf(buffer, "PREOP\n");
01392             case EC_SLAVE_STATE_SAVEOP:
01393                 return sprintf(buffer, "SAVEOP\n");
01394             case EC_SLAVE_STATE_OP:
01395                 return sprintf(buffer, "OP\n");
01396             default:
01397                 return sprintf(buffer, "UNKNOWN\n");
01398         }
01399     }
01400     else if (attr == &attr_eeprom) {
01401         if (slave->eeprom_data) {
01402             if (slave->eeprom_size > PAGE_SIZE) {
01403                 EC_ERR("EEPROM contents of slave %i exceed 1 page (%i/%i).\n",
01404                        slave->ring_position, slave->eeprom_size,
01405                        (int) PAGE_SIZE);
01406             }
01407             else {
01408                 memcpy(buffer, slave->eeprom_data, slave->eeprom_size);
01409                 return slave->eeprom_size;
01410             }
01411         }
01412     }
01413 
01414     return 0;
01415 }
01416 
01417 /*****************************************************************************/
01418 
01424 ssize_t ec_store_slave_attribute(struct kobject *kobj, 
01425                                  struct attribute *attr, 
01426                                  const char *buffer, 
01427                                  size_t size 
01428                                  )
01429 {
01430     ec_slave_t *slave = container_of(kobj, ec_slave_t, kobj);
01431 
01432     if (attr == &attr_state) {
01433         if (!strcmp(buffer, "INIT\n"))
01434             slave->requested_state = EC_SLAVE_STATE_INIT;
01435         else if (!strcmp(buffer, "PREOP\n"))
01436             slave->requested_state = EC_SLAVE_STATE_PREOP;
01437         else if (!strcmp(buffer, "SAVEOP\n"))
01438             slave->requested_state = EC_SLAVE_STATE_SAVEOP;
01439         else if (!strcmp(buffer, "OP\n"))
01440             slave->requested_state = EC_SLAVE_STATE_OP;
01441         else {
01442             EC_ERR("Invalid slave state \"%s\"!\n", buffer);
01443             return -EINVAL;
01444         }
01445 
01446         EC_INFO("Accepted new state %s for slave %i.\n",
01447                 buffer, slave->ring_position);
01448         slave->error_flag = 0;
01449         return size;
01450     }
01451     else if (attr == &attr_eeprom) {
01452         if (!ec_slave_write_eeprom(slave, buffer, size))
01453             return size;
01454     }
01455 
01456     return -EINVAL;
01457 }
01458 
01459 /*****************************************************************************/
01460 
01465 size_t ec_slave_calc_sync_size(const ec_slave_t *slave, 
01466                                const ec_sync_t *sync 
01467                                )
01468 {
01469     unsigned int i, found;
01470     const ec_field_t *field;
01471     const ec_varsize_t *var;
01472     size_t size;
01473 
01474     // if size is specified, return size
01475     if (sync->size) return sync->size;
01476 
01477     // sync manager has variable size (size == 0).
01478 
01479     size = 0;
01480     for (i = 0; (field = sync->fields[i]); i++) {
01481         found = 0;
01482         list_for_each_entry(var, &slave->varsize_fields, list) {
01483             if (var->field != field) continue;
01484             size += var->size;
01485             found = 1;
01486         }
01487 
01488         if (!found) {
01489             EC_WARN("Variable data field \"%s\" of slave %i has no size"
01490                     " information!\n", field->name, slave->ring_position);
01491         }
01492     }
01493     return size;
01494 }
01495 
01496 /*****************************************************************************/
01497 
01503 uint16_t ec_slave_calc_eeprom_sync_size(const ec_slave_t *slave,
01505                                         const ec_eeprom_sync_t *sync
01507                                         )
01508 {
01509     ec_eeprom_pdo_t *pdo;
01510     ec_eeprom_pdo_entry_t *pdo_entry;
01511     unsigned int bit_size;
01512 
01513     if (sync->length) return sync->length;
01514 
01515     bit_size = 0;
01516     list_for_each_entry(pdo, &slave->eeprom_pdos, list) {
01517         if (pdo->sync_manager != sync->index) continue;
01518 
01519         list_for_each_entry(pdo_entry, &pdo->entries, list) {
01520             bit_size += pdo_entry->bit_length;
01521         }
01522     }
01523 
01524     if (bit_size % 8) // round up to full bytes
01525         return bit_size / 8 + 1;
01526     else
01527         return bit_size / 8;
01528 }
01529 
01530 /******************************************************************************
01531  *  Realtime interface
01532  *****************************************************************************/
01533 
01540 int ecrt_slave_write_alias(ec_slave_t *slave, 
01541                            uint16_t alias 
01542                            )
01543 {
01544     return ec_slave_sii_write16(slave, 0x0004, alias);
01545 }
01546 
01547 /*****************************************************************************/
01548 
01554 int ecrt_slave_field_size(ec_slave_t *slave, 
01555                           const char *field_name, 
01556                           unsigned int field_index, 
01557                           size_t size 
01558                           )
01559 {
01560     unsigned int i, j, field_counter;
01561     const ec_sync_t *sync;
01562     const ec_field_t *field;
01563     ec_varsize_t *var;
01564 
01565     if (!slave->type) {
01566         EC_ERR("Slave %i has no type information!\n", slave->ring_position);
01567         return -1;
01568     }
01569 
01570     field_counter = 0;
01571     for (i = 0; (sync = slave->type->sync_managers[i]); i++) {
01572         for (j = 0; (field = sync->fields[j]); j++) {
01573             if (!strcmp(field->name, field_name)) {
01574                 if (field_counter++ == field_index) {
01575                     // is the size of this field variable?
01576                     if (field->size) {
01577                         EC_ERR("Field \"%s\"[%i] of slave %i has no variable"
01578                                " size!\n", field->name, field_index,
01579                                slave->ring_position);
01580                         return -1;
01581                     }
01582                     // does a size specification already exist?
01583                     list_for_each_entry(var, &slave->varsize_fields, list) {
01584                         if (var->field == field) {
01585                             EC_WARN("Resizing field \"%s\"[%i] of slave %i.\n",
01586                                     field->name, field_index,
01587                                     slave->ring_position);
01588                             var->size = size;
01589                             return 0;
01590                         }
01591                     }
01592                     // create a new size specification...
01593                     if (!(var = kmalloc(sizeof(ec_varsize_t), GFP_KERNEL))) {
01594                         EC_ERR("Failed to allocate memory for varsize_t!\n");
01595                         return -1;
01596                     }
01597                     var->field = field;
01598                     var->size = size;
01599                     list_add_tail(&var->list, &slave->varsize_fields);
01600                     return 0;
01601                 }
01602             }
01603         }
01604     }
01605 
01606     EC_ERR("Slave %i (\"%s %s\") has no field \"%s\"[%i]!\n",
01607            slave->ring_position, slave->type->vendor_name,
01608            slave->type->product_name, field_name, field_index);
01609     return -1;
01610 }
01611 
01612 /*****************************************************************************/
01613 
01616 EXPORT_SYMBOL(ecrt_slave_write_alias);
01617 EXPORT_SYMBOL(ecrt_slave_field_size);
01618 
01621 /*****************************************************************************/

Generated on Wed Aug 2 18:41:43 2006 for IgH EtherCAT master by  doxygen 1.4.6