Main Page | Modules | Data Structures | Directories | File List | Data Fields | Globals | Related Pages

slave.c

Go to the documentation of this file.
00001 /******************************************************************************
00002  *
00003  *  $Id: slave.c 682 2006-11-07 12:13:30Z 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 void ec_slave_clear(struct kobject *);
00056 void ec_slave_sdos_clear(struct kobject *);
00057 ssize_t ec_show_slave_attribute(struct kobject *, struct attribute *, char *);
00058 ssize_t ec_store_slave_attribute(struct kobject *, struct attribute *,
00059                                  const char *, size_t);
00060 
00061 /*****************************************************************************/
00062 
00065 EC_SYSFS_READ_ATTR(info);
00066 EC_SYSFS_READ_WRITE_ATTR(state);
00067 EC_SYSFS_READ_WRITE_ATTR(eeprom);
00068 
00069 static struct attribute *def_attrs[] = {
00070     &attr_info,
00071     &attr_state,
00072     &attr_eeprom,
00073     NULL,
00074 };
00075 
00076 static struct sysfs_ops sysfs_ops = {
00077     .show = ec_show_slave_attribute,
00078     .store = ec_store_slave_attribute
00079 };
00080 
00081 static struct kobj_type ktype_ec_slave = {
00082     .release = ec_slave_clear,
00083     .sysfs_ops = &sysfs_ops,
00084     .default_attrs = def_attrs
00085 };
00086 
00087 static struct kobj_type ktype_ec_slave_sdos = {
00088     .release = ec_slave_sdos_clear
00089 };
00090 
00093 /*****************************************************************************/
00094 
00100 int ec_slave_init(ec_slave_t *slave, 
00101                   ec_master_t *master, 
00102                   uint16_t ring_position, 
00103                   uint16_t station_address 
00104                   )
00105 {
00106     unsigned int i;
00107 
00108     slave->ring_position = ring_position;
00109     slave->station_address = station_address;
00110 
00111     slave->master = master;
00112 
00113     slave->requested_state = EC_SLAVE_STATE_UNKNOWN;
00114     slave->current_state = EC_SLAVE_STATE_UNKNOWN;
00115     slave->configured = 0;
00116     slave->error_flag = 0;
00117     slave->online = 1;
00118     slave->fmmu_count = 0;
00119 
00120     slave->coupler_index = 0;
00121     slave->coupler_subindex = 0xFFFF;
00122 
00123     slave->base_type = 0;
00124     slave->base_revision = 0;
00125     slave->base_build = 0;
00126     slave->base_fmmu_count = 0;
00127     slave->base_sync_count = 0;
00128 
00129     slave->eeprom_data = NULL;
00130     slave->eeprom_size = 0;
00131     slave->new_eeprom_data = NULL;
00132     slave->new_eeprom_size = 0;
00133 
00134     slave->sii_alias = 0;
00135     slave->sii_vendor_id = 0;
00136     slave->sii_product_code = 0;
00137     slave->sii_revision_number = 0;
00138     slave->sii_serial_number = 0;
00139     slave->sii_rx_mailbox_offset = 0;
00140     slave->sii_rx_mailbox_size = 0;
00141     slave->sii_tx_mailbox_offset = 0;
00142     slave->sii_tx_mailbox_size = 0;
00143     slave->sii_mailbox_protocols = 0;
00144     slave->sii_group = NULL;
00145     slave->sii_image = NULL;
00146     slave->sii_order = NULL;
00147     slave->sii_name = NULL;
00148 
00149     INIT_LIST_HEAD(&slave->sii_strings);
00150     INIT_LIST_HEAD(&slave->sii_syncs);
00151     INIT_LIST_HEAD(&slave->sii_pdos);
00152     INIT_LIST_HEAD(&slave->sdo_dictionary);
00153     INIT_LIST_HEAD(&slave->sdo_confs);
00154 
00155     slave->sdo_dictionary_fetched = 0;
00156     slave->jiffies_preop = 0;
00157 
00158     for (i = 0; i < 4; i++) {
00159         slave->dl_link[i] = 0;
00160         slave->dl_loop[i] = 0;
00161         slave->dl_signal[i] = 0;
00162         slave->sii_physical_layer[i] = 0xFF;
00163     }
00164 
00165     // init kobject and add it to the hierarchy
00166     memset(&slave->kobj, 0x00, sizeof(struct kobject));
00167     kobject_init(&slave->kobj);
00168     slave->kobj.ktype = &ktype_ec_slave;
00169     slave->kobj.parent = &master->kobj;
00170     if (kobject_set_name(&slave->kobj, "slave%03i", slave->ring_position)) {
00171         EC_ERR("Failed to set kobject name.\n");
00172         goto out_slave_put;
00173     }
00174     if (kobject_add(&slave->kobj)) {
00175         EC_ERR("Failed to add slave's kobject.\n");
00176         goto out_slave_put;
00177     }
00178 
00179     // init SDO kobject and add it to the hierarchy
00180     memset(&slave->sdo_kobj, 0x00, sizeof(struct kobject));
00181     kobject_init(&slave->sdo_kobj);
00182     slave->sdo_kobj.ktype = &ktype_ec_slave_sdos;
00183     slave->sdo_kobj.parent = &slave->kobj;
00184     if (kobject_set_name(&slave->sdo_kobj, "sdos")) {
00185         EC_ERR("Failed to set kobject name.\n");
00186         goto out_sdo_put;
00187     }
00188     if (kobject_add(&slave->sdo_kobj)) {
00189         EC_ERR("Failed to add SDOs kobject.\n");
00190         goto out_sdo_put;
00191     }
00192 
00193     return 0;
00194 
00195  out_sdo_put:
00196     kobject_put(&slave->sdo_kobj);
00197     kobject_del(&slave->kobj);
00198  out_slave_put:
00199     kobject_put(&slave->kobj);
00200     return -1;
00201 }
00202 
00203 /*****************************************************************************/
00204 
00210 void ec_slave_destroy(ec_slave_t *slave )
00211 {
00212     ec_sdo_t *sdo, *next_sdo;
00213 
00214     // free all SDOs
00215     list_for_each_entry_safe(sdo, next_sdo, &slave->sdo_dictionary, list) {
00216         list_del(&sdo->list);
00217         ec_sdo_destroy(sdo);
00218     }
00219 
00220     // free SDO kobject
00221     kobject_del(&slave->sdo_kobj);
00222     kobject_put(&slave->sdo_kobj);
00223 
00224     // destroy self
00225     kobject_del(&slave->kobj);
00226     kobject_put(&slave->kobj);
00227 }
00228 
00229 /*****************************************************************************/
00230 
00237 void ec_slave_clear(struct kobject *kobj )
00238 {
00239     ec_slave_t *slave;
00240     ec_sii_string_t *string, *next_str;
00241     ec_sii_sync_t *sync, *next_sync;
00242     ec_sii_pdo_t *pdo, *next_pdo;
00243     ec_sii_pdo_entry_t *entry, *next_ent;
00244     ec_sdo_data_t *sdodata, *next_sdodata;
00245 
00246     slave = container_of(kobj, ec_slave_t, kobj);
00247 
00248     // free all string objects
00249     list_for_each_entry_safe(string, next_str, &slave->sii_strings, list) {
00250         list_del(&string->list);
00251         kfree(string);
00252     }
00253 
00254     // free all sync managers
00255     list_for_each_entry_safe(sync, next_sync, &slave->sii_syncs, list) {
00256         list_del(&sync->list);
00257         kfree(sync);
00258     }
00259 
00260     // free all PDOs
00261     list_for_each_entry_safe(pdo, next_pdo, &slave->sii_pdos, list) {
00262         list_del(&pdo->list);
00263         if (pdo->name) kfree(pdo->name);
00264 
00265         // free all PDO entries
00266         list_for_each_entry_safe(entry, next_ent, &pdo->entries, list) {
00267             list_del(&entry->list);
00268             if (entry->name) kfree(entry->name);
00269             kfree(entry);
00270         }
00271 
00272         kfree(pdo);
00273     }
00274 
00275     if (slave->sii_group) kfree(slave->sii_group);
00276     if (slave->sii_image) kfree(slave->sii_image);
00277     if (slave->sii_order) kfree(slave->sii_order);
00278     if (slave->sii_name) kfree(slave->sii_name);
00279 
00280     // free all SDO configurations
00281     list_for_each_entry_safe(sdodata, next_sdodata, &slave->sdo_confs, list) {
00282         list_del(&sdodata->list);
00283         kfree(sdodata->data);
00284         kfree(sdodata);
00285     }
00286 
00287     if (slave->eeprom_data) kfree(slave->eeprom_data);
00288     if (slave->new_eeprom_data) kfree(slave->new_eeprom_data);
00289 
00290     kfree(slave);
00291 }
00292 
00293 /*****************************************************************************/
00294 
00298 void ec_slave_sdos_clear(struct kobject *kobj )
00299 {
00300 }
00301 
00302 /*****************************************************************************/
00303 
00308 void ec_slave_reset(ec_slave_t *slave )
00309 {
00310     ec_sdo_data_t *sdodata, *next_sdodata;
00311     ec_sii_sync_t *sync;
00312 
00313     // remove FMMU configurations
00314     slave->fmmu_count = 0;
00315 
00316     // free all SDO configurations
00317     list_for_each_entry_safe(sdodata, next_sdodata, &slave->sdo_confs, list) {
00318         list_del(&sdodata->list);
00319         kfree(sdodata->data);
00320         kfree(sdodata);
00321     }
00322 
00323     // remove estimated sync manager sizes
00324     list_for_each_entry(sync, &slave->sii_syncs, list) {
00325         sync->est_length = 0;
00326     }
00327 }
00328 
00329 /*****************************************************************************/
00330 
00334 void ec_slave_request_state(ec_slave_t *slave, 
00335                             ec_slave_state_t state 
00336                             )
00337 {
00338     slave->requested_state = state;
00339     slave->error_flag = 0;
00340 }
00341 
00342 /*****************************************************************************/
00343 
00349 int ec_slave_fetch_strings(ec_slave_t *slave, 
00350                            const uint8_t *data 
00351                            )
00352 {
00353     unsigned int string_count, i;
00354     size_t size;
00355     off_t offset;
00356     ec_sii_string_t *string;
00357 
00358     string_count = data[0];
00359     offset = 1;
00360     for (i = 0; i < string_count; i++) {
00361         size = data[offset];
00362         // allocate memory for string structure and data at a single blow
00363         if (!(string = (ec_sii_string_t *)
00364               kmalloc(sizeof(ec_sii_string_t) + size + 1, GFP_ATOMIC))) {
00365             EC_ERR("Failed to allocate string memory.\n");
00366             return -1;
00367         }
00368         string->size = size;
00369         // string memory appended to string structure
00370         string->data = (char *) string + sizeof(ec_sii_string_t);
00371         memcpy(string->data, data + offset + 1, size);
00372         string->data[size] = 0x00;
00373         list_add_tail(&string->list, &slave->sii_strings);
00374         offset += 1 + size;
00375     }
00376 
00377     return 0;
00378 }
00379 
00380 /*****************************************************************************/
00381 
00387 void ec_slave_fetch_general(ec_slave_t *slave, 
00388                             const uint8_t *data 
00389                             )
00390 {
00391     unsigned int i;
00392 
00393     ec_slave_locate_string(slave, data[0], &slave->sii_group);
00394     ec_slave_locate_string(slave, data[1], &slave->sii_image);
00395     ec_slave_locate_string(slave, data[2], &slave->sii_order);
00396     ec_slave_locate_string(slave, data[3], &slave->sii_name);
00397 
00398     for (i = 0; i < 4; i++)
00399         slave->sii_physical_layer[i] =
00400             (data[4] & (0x03 << (i * 2))) >> (i * 2);
00401 }
00402 
00403 /*****************************************************************************/
00404 
00410 int ec_slave_fetch_sync(ec_slave_t *slave, 
00411                         const uint8_t *data, 
00412                         size_t word_count 
00413                         )
00414 {
00415     unsigned int sync_count, i;
00416     ec_sii_sync_t *sync;
00417 
00418     sync_count = word_count / 4; // sync manager struct is 4 words long
00419 
00420     for (i = 0; i < sync_count; i++, data += 8) {
00421         if (!(sync = (ec_sii_sync_t *)
00422               kmalloc(sizeof(ec_sii_sync_t), GFP_ATOMIC))) {
00423             EC_ERR("Failed to allocate Sync-Manager memory.\n");
00424             return -1;
00425         }
00426 
00427         sync->index = i;
00428         sync->physical_start_address = EC_READ_U16(data);
00429         sync->length                 = EC_READ_U16(data + 2);
00430         sync->control_register       = EC_READ_U8 (data + 4);
00431         sync->enable                 = EC_READ_U8 (data + 6);
00432 
00433         sync->est_length = 0;
00434 
00435         list_add_tail(&sync->list, &slave->sii_syncs);
00436     }
00437 
00438     return 0;
00439 }
00440 
00441 /*****************************************************************************/
00442 
00448 int ec_slave_fetch_pdo(ec_slave_t *slave, 
00449                        const uint8_t *data, 
00450                        size_t word_count, 
00451                        ec_sii_pdo_type_t pdo_type 
00452                        )
00453 {
00454     ec_sii_pdo_t *pdo;
00455     ec_sii_pdo_entry_t *entry;
00456     unsigned int entry_count, i;
00457 
00458     while (word_count >= 4) {
00459         if (!(pdo = (ec_sii_pdo_t *)
00460               kmalloc(sizeof(ec_sii_pdo_t), GFP_ATOMIC))) {
00461             EC_ERR("Failed to allocate PDO memory.\n");
00462             return -1;
00463         }
00464 
00465         INIT_LIST_HEAD(&pdo->entries);
00466         pdo->type = pdo_type;
00467 
00468         pdo->index = EC_READ_U16(data);
00469         entry_count = EC_READ_U8(data + 2);
00470         pdo->sync_index = EC_READ_U8(data + 3);
00471         pdo->name = NULL;
00472         ec_slave_locate_string(slave, EC_READ_U8(data + 5), &pdo->name);
00473 
00474         list_add_tail(&pdo->list, &slave->sii_pdos);
00475 
00476         word_count -= 4;
00477         data += 8;
00478 
00479         for (i = 0; i < entry_count; i++) {
00480             if (!(entry = (ec_sii_pdo_entry_t *)
00481                   kmalloc(sizeof(ec_sii_pdo_entry_t), GFP_ATOMIC))) {
00482                 EC_ERR("Failed to allocate PDO entry memory.\n");
00483                 return -1;
00484             }
00485 
00486             entry->index = EC_READ_U16(data);
00487             entry->subindex = EC_READ_U8(data + 2);
00488             entry->name = NULL;
00489             ec_slave_locate_string(slave, EC_READ_U8(data + 3), &entry->name);
00490             entry->bit_length = EC_READ_U8(data + 5);
00491 
00492             list_add_tail(&entry->list, &pdo->entries);
00493 
00494             word_count -= 4;
00495             data += 8;
00496         }
00497     }
00498 
00499     return 0;
00500 }
00501 
00502 /*****************************************************************************/
00503 
00510 int ec_slave_locate_string(ec_slave_t *slave, 
00511                            unsigned int index, 
00512                            char **ptr 
00513                            )
00514 {
00515     ec_sii_string_t *string;
00516     char *err_string;
00517 
00518     // Erst alten Speicher freigeben
00519     if (*ptr) {
00520         kfree(*ptr);
00521         *ptr = NULL;
00522     }
00523 
00524     // Index 0 bedeutet "nicht belegt"
00525     if (!index) return 0;
00526 
00527     // EEPROM-String mit Index finden und kopieren
00528     list_for_each_entry(string, &slave->sii_strings, list) {
00529         if (--index) continue;
00530 
00531         if (!(*ptr = (char *) kmalloc(string->size + 1, GFP_ATOMIC))) {
00532             EC_ERR("Unable to allocate string memory.\n");
00533             return -1;
00534         }
00535         memcpy(*ptr, string->data, string->size + 1);
00536         return 0;
00537     }
00538 
00539     if (slave->master->debug_level)
00540         EC_WARN("String %i not found in slave %i.\n",
00541                 index, slave->ring_position);
00542 
00543     err_string = "(string not found)";
00544 
00545     if (!(*ptr = (char *) kmalloc(strlen(err_string) + 1, GFP_ATOMIC))) {
00546         EC_WARN("Unable to allocate string memory.\n");
00547         return -1;
00548     }
00549 
00550     memcpy(*ptr, err_string, strlen(err_string) + 1);
00551     return 0;
00552 }
00553 
00554 /*****************************************************************************/
00555 
00568 int ec_slave_prepare_fmmu(ec_slave_t *slave, 
00569                           const ec_domain_t *domain, 
00570                           const ec_sii_sync_t *sync  
00571                           )
00572 {
00573     unsigned int i;
00574     ec_fmmu_t *fmmu;
00575 
00576     // FMMU configuration already prepared?
00577     for (i = 0; i < slave->fmmu_count; i++) {
00578         fmmu = &slave->fmmus[i];
00579         if (fmmu->domain == domain && fmmu->sync == sync)
00580             return 0;
00581     }
00582 
00583     // reserve new FMMU...
00584 
00585     if (slave->fmmu_count >= slave->base_fmmu_count) {
00586         EC_ERR("Slave %i FMMU limit reached!\n", slave->ring_position);
00587         return -1;
00588     }
00589 
00590     fmmu = &slave->fmmus[slave->fmmu_count];
00591 
00592     fmmu->index = slave->fmmu_count;
00593     fmmu->domain = domain;
00594     fmmu->sync = sync;
00595     fmmu->logical_start_address = 0;
00596 
00597     slave->fmmu_count++;
00598 
00599     return 0;
00600 }
00601 
00602 /*****************************************************************************/
00603 
00608 size_t ec_slave_info(const ec_slave_t *slave, 
00609                      char *buffer 
00610                      )
00611 {
00612     off_t off = 0;
00613     ec_sii_sync_t *sync;
00614     ec_sii_pdo_t *pdo;
00615     ec_sii_pdo_entry_t *pdo_entry;
00616     int first, i;
00617     ec_sdo_data_t *sdodata;
00618     char str[20];
00619 
00620     off += sprintf(buffer + off, "\nName: ");
00621 
00622     if (slave->sii_name)
00623         off += sprintf(buffer + off, "%s", slave->sii_name);
00624 
00625     off += sprintf(buffer + off, "\nVendor ID: 0x%08X\n",
00626                    slave->sii_vendor_id);
00627     off += sprintf(buffer + off, "Product code: 0x%08X\n\n",
00628                    slave->sii_product_code);
00629 
00630     off += sprintf(buffer + off, "State: ");
00631     off += ec_state_string(slave->current_state, buffer + off);
00632     off += sprintf(buffer + off, "\nFlags: %s, %s\n",
00633                    slave->online ? "online" : "OFFLINE",
00634                    slave->error_flag ? "ERROR" : "ok");
00635     off += sprintf(buffer + off, "Ring position: %i\n",
00636                    slave->ring_position);
00637     off += sprintf(buffer + off, "Advanced position: %i:%i\n",
00638                    slave->coupler_index, slave->coupler_subindex);
00639     off += sprintf(buffer + off, "Coupler: %s\n\n",
00640                    ec_slave_is_coupler(slave) ? "yes" : "no");
00641 
00642     off += sprintf(buffer + off, "Data link status:\n");
00643     for (i = 0; i < 4; i++) {
00644         off += sprintf(buffer + off, "  Port %i (", i);
00645         switch (slave->sii_physical_layer[i]) {
00646             case 0x00:
00647                 off += sprintf(buffer + off, "EBUS");
00648                 break;
00649             case 0x01:
00650                 off += sprintf(buffer + off, "100BASE-TX");
00651                 break;
00652             case 0x02:
00653                 off += sprintf(buffer + off, "100BASE-FX");
00654                 break;
00655             default:
00656                 off += sprintf(buffer + off, "unknown (%i)",
00657                                slave->sii_physical_layer[i]);
00658         }
00659         off += sprintf(buffer + off, ") Link %s, Loop %s, %s\n",
00660                        slave->dl_link[i] ? "up" : "down",
00661                        slave->dl_loop[i] ? "closed" : "open",
00662                        slave->dl_signal[i] ? "Signal detected" : "No signal");
00663     }
00664 
00665     if (slave->sii_mailbox_protocols) {
00666         off += sprintf(buffer + off, "\nMailboxes:\n");
00667         off += sprintf(buffer + off, "  RX mailbox: 0x%04X/%i,"
00668                        " TX mailbox: 0x%04X/%i\n",
00669                        slave->sii_rx_mailbox_offset,
00670                        slave->sii_rx_mailbox_size,
00671                        slave->sii_tx_mailbox_offset,
00672                        slave->sii_tx_mailbox_size);
00673         off += sprintf(buffer + off, "  Supported protocols: ");
00674 
00675         first = 1;
00676         if (slave->sii_mailbox_protocols & EC_MBOX_AOE) {
00677             off += sprintf(buffer + off, "AoE");
00678             first = 0;
00679         }
00680         if (slave->sii_mailbox_protocols & EC_MBOX_EOE) {
00681             if (!first) off += sprintf(buffer + off, ", ");
00682             off += sprintf(buffer + off, "EoE");
00683             first = 0;
00684         }
00685         if (slave->sii_mailbox_protocols & EC_MBOX_COE) {
00686             if (!first) off += sprintf(buffer + off, ", ");
00687             off += sprintf(buffer + off, "CoE");
00688             first = 0;
00689         }
00690         if (slave->sii_mailbox_protocols & EC_MBOX_FOE) {
00691             if (!first) off += sprintf(buffer + off, ", ");
00692             off += sprintf(buffer + off, "FoE");
00693             first = 0;
00694         }
00695         if (slave->sii_mailbox_protocols & EC_MBOX_SOE) {
00696             if (!first) off += sprintf(buffer + off, ", ");
00697             off += sprintf(buffer + off, "SoE");
00698             first = 0;
00699         }
00700         if (slave->sii_mailbox_protocols & EC_MBOX_VOE) {
00701             if (!first) off += sprintf(buffer + off, ", ");
00702             off += sprintf(buffer + off, "VoE");
00703         }
00704         off += sprintf(buffer + off, "\n");
00705     }
00706 
00707     if (slave->sii_alias || slave->sii_group
00708         || slave->sii_image || slave->sii_order)
00709         off += sprintf(buffer + off, "\nSII data:\n");
00710 
00711     if (slave->sii_alias)
00712         off += sprintf(buffer + off, "  Configured station alias:"
00713                        " 0x%04X (%i)\n", slave->sii_alias, slave->sii_alias);
00714     if (slave->sii_group)
00715         off += sprintf(buffer + off, "  Group: %s\n", slave->sii_group);
00716     if (slave->sii_image)
00717         off += sprintf(buffer + off, "  Image: %s\n", slave->sii_image);
00718     if (slave->sii_order)
00719         off += sprintf(buffer + off, "  Order number: %s\n", slave->sii_order);
00720 
00721     if (!list_empty(&slave->sii_syncs))
00722         off += sprintf(buffer + off, "\nSync-Managers:\n");
00723 
00724     list_for_each_entry(sync, &slave->sii_syncs, list) {
00725         off += sprintf(buffer + off, "  %i: 0x%04X, length %i,"
00726                        " control 0x%02X, %s\n",
00727                        sync->index, sync->physical_start_address,
00728                        sync->length, sync->control_register,
00729                        sync->enable ? "enable" : "disable");
00730     }
00731 
00732     if (!list_empty(&slave->sii_pdos))
00733         off += sprintf(buffer + off, "\nPDOs:\n");
00734 
00735     list_for_each_entry(pdo, &slave->sii_pdos, list) {
00736         off += sprintf(buffer + off,
00737                        "  %s \"%s\" (0x%04X), Sync-Manager %i\n",
00738                        pdo->type == EC_RX_PDO ? "RXPDO" : "TXPDO",
00739                        pdo->name ? pdo->name : "???",
00740                        pdo->index, pdo->sync_index);
00741 
00742         list_for_each_entry(pdo_entry, &pdo->entries, list) {
00743             off += sprintf(buffer + off, "    \"%s\" 0x%04X:%X, %i bit\n",
00744                            pdo_entry->name ? pdo_entry->name : "???",
00745                            pdo_entry->index, pdo_entry->subindex,
00746                            pdo_entry->bit_length);
00747         }
00748     }
00749 
00750     if (!list_empty(&slave->sdo_confs))
00751         off += sprintf(buffer + off, "\nSDO configurations:\n");
00752 
00753     list_for_each_entry(sdodata, &slave->sdo_confs, list) {
00754         switch (sdodata->size) {
00755             case 1: sprintf(str, "%i", EC_READ_U8(sdodata->data)); break;
00756             case 2: sprintf(str, "%i", EC_READ_U16(sdodata->data)); break;
00757             case 4: sprintf(str, "%i", EC_READ_U32(sdodata->data)); break;
00758             default: sprintf(str, "(invalid size)"); break;
00759         }
00760         off += sprintf(buffer + off, "  0x%04X:%-3i -> %s\n",
00761                        sdodata->index, sdodata->subindex, str);
00762     }
00763 
00764     off += sprintf(buffer + off, "\n");
00765 
00766     return off;
00767 }
00768 
00769 /*****************************************************************************/
00770 
00776 ssize_t ec_slave_write_eeprom(ec_slave_t *slave, 
00777                               const uint8_t *data, 
00778                               size_t size 
00779                               )
00780 {
00781     uint16_t word_size, cat_type, cat_size;
00782     const uint16_t *data_words, *next_header;
00783     uint16_t *new_data;
00784 
00785     if (!slave->master->eeprom_write_enable) {
00786         EC_ERR("Writing EEPROMs not allowed! Enable via"
00787                " eeprom_write_enable SysFS entry.\n");
00788         return -1;
00789     }
00790 
00791     if (slave->master->mode != EC_MASTER_MODE_IDLE) {
00792         EC_ERR("Writing EEPROMs only allowed in idle mode!\n");
00793         return -1;
00794     }
00795 
00796     if (slave->new_eeprom_data) {
00797         EC_ERR("Slave %i already has a pending EEPROM write operation!\n",
00798                slave->ring_position);
00799         return -1;
00800     }
00801 
00802     // coarse check of the data
00803 
00804     if (size % 2) {
00805         EC_ERR("EEPROM size is odd! Dropping.\n");
00806         return -1;
00807     }
00808 
00809     data_words = (const uint16_t *) data;
00810     word_size = size / 2;
00811 
00812     if (word_size < 0x0041) {
00813         EC_ERR("EEPROM data too short! Dropping.\n");
00814         return -1;
00815     }
00816 
00817     next_header = data_words + 0x0040;
00818     cat_type = EC_READ_U16(next_header);
00819     while (cat_type != 0xFFFF) {
00820         cat_type = EC_READ_U16(next_header);
00821         cat_size = EC_READ_U16(next_header + 1);
00822         if ((next_header + cat_size + 2) - data_words >= word_size) {
00823             EC_ERR("EEPROM data seems to be corrupted! Dropping.\n");
00824             return -1;
00825         }
00826         next_header += cat_size + 2;
00827         cat_type = EC_READ_U16(next_header);
00828     }
00829 
00830     // data ok!
00831 
00832     if (!(new_data = (uint16_t *) kmalloc(word_size * 2, GFP_KERNEL))) {
00833         EC_ERR("Unable to allocate memory for new EEPROM data!\n");
00834         return -1;
00835     }
00836     memcpy(new_data, data, size);
00837 
00838     slave->new_eeprom_size = word_size;
00839     slave->new_eeprom_data = new_data;
00840 
00841     EC_INFO("EEPROM writing scheduled for slave %i, %i words.\n",
00842             slave->ring_position, word_size);
00843     return 0;
00844 }
00845 
00846 /*****************************************************************************/
00847 
00853 ssize_t ec_show_slave_attribute(struct kobject *kobj, 
00854                                 struct attribute *attr, 
00855                                 char *buffer 
00856                                 )
00857 {
00858     ec_slave_t *slave = container_of(kobj, ec_slave_t, kobj);
00859 
00860     if (attr == &attr_info) {
00861         return ec_slave_info(slave, buffer);
00862     }
00863     else if (attr == &attr_state) {
00864         switch (slave->current_state) {
00865             case EC_SLAVE_STATE_INIT:
00866                 return sprintf(buffer, "INIT\n");
00867             case EC_SLAVE_STATE_PREOP:
00868                 return sprintf(buffer, "PREOP\n");
00869             case EC_SLAVE_STATE_SAVEOP:
00870                 return sprintf(buffer, "SAVEOP\n");
00871             case EC_SLAVE_STATE_OP:
00872                 return sprintf(buffer, "OP\n");
00873             default:
00874                 return sprintf(buffer, "UNKNOWN\n");
00875         }
00876     }
00877     else if (attr == &attr_eeprom) {
00878         if (slave->eeprom_data) {
00879             if (slave->eeprom_size > PAGE_SIZE) {
00880                 EC_ERR("EEPROM contents of slave %i exceed 1 page (%i/%i).\n",
00881                        slave->ring_position, slave->eeprom_size,
00882                        (int) PAGE_SIZE);
00883             }
00884             else {
00885                 memcpy(buffer, slave->eeprom_data, slave->eeprom_size);
00886                 return slave->eeprom_size;
00887             }
00888         }
00889     }
00890 
00891     return 0;
00892 }
00893 
00894 /*****************************************************************************/
00895 
00901 ssize_t ec_store_slave_attribute(struct kobject *kobj, 
00902                                  struct attribute *attr, 
00903                                  const char *buffer, 
00904                                  size_t size 
00905                                  )
00906 {
00907     ec_slave_t *slave = container_of(kobj, ec_slave_t, kobj);
00908 
00909     if (attr == &attr_state) {
00910         char state[EC_STATE_STRING_SIZE];
00911         if (!strcmp(buffer, "INIT\n"))
00912             ec_slave_request_state(slave, EC_SLAVE_STATE_INIT);
00913         else if (!strcmp(buffer, "PREOP\n"))
00914             ec_slave_request_state(slave, EC_SLAVE_STATE_PREOP);
00915         else if (!strcmp(buffer, "SAVEOP\n"))
00916             ec_slave_request_state(slave, EC_SLAVE_STATE_SAVEOP);
00917         else if (!strcmp(buffer, "OP\n"))
00918             ec_slave_request_state(slave, EC_SLAVE_STATE_OP);
00919         else {
00920             EC_ERR("Invalid slave state \"%s\"!\n", buffer);
00921             return -EINVAL;
00922         }
00923 
00924         ec_state_string(slave->requested_state, state);
00925         EC_INFO("Accepted new state %s for slave %i.\n",
00926                 state, slave->ring_position);
00927         return size;
00928     }
00929     else if (attr == &attr_eeprom) {
00930         if (!ec_slave_write_eeprom(slave, buffer, size))
00931             return size;
00932     }
00933 
00934     return -EINVAL;
00935 }
00936 
00937 /*****************************************************************************/
00938 
00944 uint16_t ec_slave_calc_sync_size(const ec_slave_t *slave,
00946                                  const ec_sii_sync_t *sync
00948                                  )
00949 {
00950     ec_sii_pdo_t *pdo;
00951     ec_sii_pdo_entry_t *pdo_entry;
00952     unsigned int bit_size, byte_size;
00953 
00954     if (sync->length) return sync->length;
00955     if (sync->est_length) return sync->est_length;
00956 
00957     bit_size = 0;
00958     list_for_each_entry(pdo, &slave->sii_pdos, list) {
00959         if (pdo->sync_index != sync->index) continue;
00960 
00961         list_for_each_entry(pdo_entry, &pdo->entries, list) {
00962             bit_size += pdo_entry->bit_length;
00963         }
00964     }
00965 
00966     if (bit_size % 8) // round up to full bytes
00967         byte_size = bit_size / 8 + 1;
00968     else
00969         byte_size = bit_size / 8;
00970 
00971     return byte_size;
00972 }
00973 
00974 /*****************************************************************************/
00975 
00980 int ec_slave_is_coupler(const ec_slave_t *slave )
00981 {
00982     // TODO: Better bus coupler criterion
00983     return slave->sii_vendor_id == 0x00000002
00984         && slave->sii_product_code == 0x044C2C52;
00985 }
00986 
00987 /*****************************************************************************/
00988 
00993 int ec_slave_has_subbus(const ec_slave_t *slave )
00994 {
00995     return slave->sii_vendor_id == 0x00000002
00996         && slave->sii_product_code == 0x04602c22;
00997 }
00998 
00999 /*****************************************************************************/
01000 
01005 int ec_slave_conf_sdo(ec_slave_t *slave, 
01006                       uint16_t sdo_index, 
01007                       uint8_t sdo_subindex, 
01008                       const uint8_t *data, 
01009                       size_t size 
01010                       )
01011 {
01012     ec_sdo_data_t *sdodata;
01013 
01014     if (!(slave->sii_mailbox_protocols & EC_MBOX_COE)) {
01015         EC_ERR("Slave %i does not support CoE!\n", slave->ring_position);
01016         return -1;
01017     }
01018 
01019     if (!(sdodata = (ec_sdo_data_t *)
01020           kmalloc(sizeof(ec_sdo_data_t), GFP_KERNEL))) {
01021         EC_ERR("Failed to allocate memory for SDO configuration object!\n");
01022         return -1;
01023     }
01024 
01025     if (!(sdodata->data = (uint8_t *) kmalloc(size, GFP_KERNEL))) {
01026         EC_ERR("Failed to allocate memory for SDO configuration data!\n");
01027         kfree(sdodata);
01028         return -1;
01029     }
01030 
01031     sdodata->index = sdo_index;
01032     sdodata->subindex = sdo_subindex;
01033     memcpy(sdodata->data, data, size);
01034     sdodata->size = size;
01035 
01036     list_add_tail(&sdodata->list, &slave->sdo_confs);
01037     return 0;
01038 }
01039 
01040 /*****************************************************************************/
01041 
01046 int ec_slave_validate(const ec_slave_t *slave, 
01047                       uint32_t vendor_id, 
01048                       uint32_t product_code 
01049                       )
01050 {
01051     if (vendor_id != slave->sii_vendor_id ||
01052         product_code != slave->sii_product_code) {
01053         EC_ERR("Invalid slave type at position %i - Requested: 0x%08X 0x%08X,"
01054                " found: 0x%08X 0x%08X\".\n", slave->ring_position, vendor_id,
01055                product_code, slave->sii_vendor_id, slave->sii_product_code);
01056         return -1;
01057     }
01058     return 0;
01059 }
01060 
01061 /*****************************************************************************/
01062 
01067 void ec_slave_sdo_dict_info(const ec_slave_t *slave, 
01068                             unsigned int *sdo_count, 
01069                             unsigned int *entry_count 
01071                             )
01072 {
01073     unsigned int sdos = 0, entries = 0;
01074     ec_sdo_t *sdo;
01075     ec_sdo_entry_t *entry;
01076 
01077     list_for_each_entry(sdo, &slave->sdo_dictionary, list) {
01078         sdos++;
01079         list_for_each_entry(entry, &sdo->entries, list) {
01080             entries++;
01081         }
01082     }
01083 
01084     *sdo_count = sdos;
01085     *entry_count = entries;
01086 }
01087 
01088 /******************************************************************************
01089  *  Realtime interface
01090  *****************************************************************************/
01091 
01097 int ecrt_slave_conf_sdo8(ec_slave_t *slave, 
01098                          uint16_t sdo_index, 
01099                          uint8_t sdo_subindex, 
01100                          uint8_t value 
01101                          )
01102 {
01103     uint8_t data[1];
01104     EC_WRITE_U8(data, value);
01105     return ec_slave_conf_sdo(slave, sdo_index, sdo_subindex, data, 1);
01106 }
01107 
01108 /*****************************************************************************/
01109 
01115 int ecrt_slave_conf_sdo16(ec_slave_t *slave, 
01116                           uint16_t sdo_index, 
01117                           uint8_t sdo_subindex, 
01118                           uint16_t value 
01119                           )
01120 {
01121     uint8_t data[2];
01122     EC_WRITE_U16(data, value);
01123     return ec_slave_conf_sdo(slave, sdo_index, sdo_subindex, data, 2);
01124 }
01125 
01126 /*****************************************************************************/
01127 
01133 int ecrt_slave_conf_sdo32(ec_slave_t *slave, 
01134                           uint16_t sdo_index, 
01135                           uint8_t sdo_subindex, 
01136                           uint32_t value 
01137                           )
01138 {
01139     uint8_t data[4];
01140     EC_WRITE_U32(data, value);
01141     return ec_slave_conf_sdo(slave, sdo_index, sdo_subindex, data, 4);
01142 }
01143 
01144 /*****************************************************************************/
01145 
01151 int ecrt_slave_pdo_size(ec_slave_t *slave, 
01152                         uint16_t pdo_index, 
01153                         uint8_t pdo_subindex, 
01154                         size_t size 
01155                         )
01156 {
01157     EC_WARN("ecrt_slave_pdo_size() currently not available.\n");
01158     return -1;
01159 
01160 #if 0
01161     unsigned int i, j, field_counter;
01162     const ec_sii_sync_t *sync;
01163     const ec_pdo_t *pdo;
01164     ec_varsize_t *var;
01165 
01166     if (!slave->type) {
01167         EC_ERR("Slave %i has no type information!\n", slave->ring_position);
01168         return -1;
01169     }
01170 
01171     field_counter = 0;
01172     for (i = 0; (sync = slave->type->sync_managers[i]); i++) {
01173         for (j = 0; (field = sync->fields[j]); j++) {
01174             if (!strcmp(field->name, field_name)) {
01175                 if (field_counter++ == field_index) {
01176                     // is the size of this field variable?
01177                     if (field->size) {
01178                         EC_ERR("Field \"%s\"[%i] of slave %i has no variable"
01179                                " size!\n", field->name, field_index,
01180                                slave->ring_position);
01181                         return -1;
01182                     }
01183                     // does a size specification already exist?
01184                     list_for_each_entry(var, &slave->varsize_fields, list) {
01185                         if (var->field == field) {
01186                             EC_WARN("Resizing field \"%s\"[%i] of slave %i.\n",
01187                                     field->name, field_index,
01188                                     slave->ring_position);
01189                             var->size = size;
01190                             return 0;
01191                         }
01192                     }
01193                     // create a new size specification...
01194                     if (!(var = kmalloc(sizeof(ec_varsize_t), GFP_KERNEL))) {
01195                         EC_ERR("Failed to allocate memory for varsize_t!\n");
01196                         return -1;
01197                     }
01198                     var->field = field;
01199                     var->size = size;
01200                     list_add_tail(&var->list, &slave->varsize_fields);
01201                     return 0;
01202                 }
01203             }
01204         }
01205     }
01206 
01207     EC_ERR("Slave %i (\"%s %s\") has no field \"%s\"[%i]!\n",
01208            slave->ring_position, slave->type->vendor_name,
01209            slave->type->product_name, field_name, field_index);
01210     return -1;
01211 #endif
01212 }
01213 
01214 /*****************************************************************************/
01215 
01218 EXPORT_SYMBOL(ecrt_slave_conf_sdo8);
01219 EXPORT_SYMBOL(ecrt_slave_conf_sdo16);
01220 EXPORT_SYMBOL(ecrt_slave_conf_sdo32);
01221 EXPORT_SYMBOL(ecrt_slave_pdo_size);
01222 
01225 /*****************************************************************************/

Generated on Tue Nov 7 15:03:36 2006 for IgH EtherCAT master by  doxygen 1.4.4