master/slave.c
branchstable-1.1
changeset 1732 1cc865ba17c2
parent 1731 60b2aad9d40b
child 1739 5fcbd29151d2
equal deleted inserted replaced
1731:60b2aad9d40b 1732:1cc865ba17c2
    50 
    50 
    51 extern const ec_code_msg_t al_status_messages[];
    51 extern const ec_code_msg_t al_status_messages[];
    52 
    52 
    53 /*****************************************************************************/
    53 /*****************************************************************************/
    54 
    54 
       
    55 void ec_slave_clear(struct kobject *);
       
    56 void ec_slave_sdos_clear(struct kobject *);
    55 ssize_t ec_show_slave_attribute(struct kobject *, struct attribute *, char *);
    57 ssize_t ec_show_slave_attribute(struct kobject *, struct attribute *, char *);
    56 ssize_t ec_store_slave_attribute(struct kobject *, struct attribute *,
    58 ssize_t ec_store_slave_attribute(struct kobject *, struct attribute *,
    57                                  const char *, size_t);
    59                                  const char *, size_t);
    58 
    60 
    59 /*****************************************************************************/
    61 /*****************************************************************************/
    80     .release = ec_slave_clear,
    82     .release = ec_slave_clear,
    81     .sysfs_ops = &sysfs_ops,
    83     .sysfs_ops = &sysfs_ops,
    82     .default_attrs = def_attrs
    84     .default_attrs = def_attrs
    83 };
    85 };
    84 
    86 
       
    87 static struct kobj_type ktype_ec_slave_sdos = {
       
    88     .release = ec_slave_sdos_clear
       
    89 };
       
    90 
    85 /** \endcond */
    91 /** \endcond */
    86 
    92 
    87 /*****************************************************************************/
    93 /*****************************************************************************/
    88 
    94 
    89 /**
    95 /**
   100     unsigned int i;
   106     unsigned int i;
   101 
   107 
   102     slave->ring_position = ring_position;
   108     slave->ring_position = ring_position;
   103     slave->station_address = station_address;
   109     slave->station_address = station_address;
   104 
   110 
   105     // init kobject and add it to the hierarchy
       
   106     memset(&slave->kobj, 0x00, sizeof(struct kobject));
       
   107     kobject_init(&slave->kobj);
       
   108     slave->kobj.ktype = &ktype_ec_slave;
       
   109     slave->kobj.parent = &master->kobj;
       
   110     if (kobject_set_name(&slave->kobj, "slave%03i", slave->ring_position)) {
       
   111         EC_ERR("Failed to set kobject name.\n");
       
   112         kobject_put(&slave->kobj);
       
   113         return -1;
       
   114     }
       
   115 
       
   116     slave->master = master;
   111     slave->master = master;
   117 
   112 
   118     slave->requested_state = EC_SLAVE_STATE_UNKNOWN;
   113     slave->requested_state = EC_SLAVE_STATE_UNKNOWN;
   119     slave->current_state = EC_SLAVE_STATE_UNKNOWN;
   114     slave->current_state = EC_SLAVE_STATE_UNKNOWN;
       
   115     slave->configured = 0;
   120     slave->error_flag = 0;
   116     slave->error_flag = 0;
   121     slave->online = 1;
   117     slave->online = 1;
   122     slave->fmmu_count = 0;
   118     slave->fmmu_count = 0;
   123     slave->registered = 0;
       
   124 
   119 
   125     slave->coupler_index = 0;
   120     slave->coupler_index = 0;
   126     slave->coupler_subindex = 0xFFFF;
   121     slave->coupler_subindex = 0xFFFF;
   127 
   122 
   128     slave->base_type = 0;
   123     slave->base_type = 0;
   154     INIT_LIST_HEAD(&slave->sii_strings);
   149     INIT_LIST_HEAD(&slave->sii_strings);
   155     INIT_LIST_HEAD(&slave->sii_syncs);
   150     INIT_LIST_HEAD(&slave->sii_syncs);
   156     INIT_LIST_HEAD(&slave->sii_pdos);
   151     INIT_LIST_HEAD(&slave->sii_pdos);
   157     INIT_LIST_HEAD(&slave->sdo_dictionary);
   152     INIT_LIST_HEAD(&slave->sdo_dictionary);
   158     INIT_LIST_HEAD(&slave->sdo_confs);
   153     INIT_LIST_HEAD(&slave->sdo_confs);
   159     INIT_LIST_HEAD(&slave->varsize_fields);
   154 
       
   155     slave->sdo_dictionary_fetched = 0;
       
   156     slave->jiffies_preop = 0;
   160 
   157 
   161     for (i = 0; i < 4; i++) {
   158     for (i = 0; i < 4; i++) {
   162         slave->dl_link[i] = 0;
   159         slave->dl_link[i] = 0;
   163         slave->dl_loop[i] = 0;
   160         slave->dl_loop[i] = 0;
   164         slave->dl_signal[i] = 0;
   161         slave->dl_signal[i] = 0;
   165         slave->sii_physical_layer[i] = 0xFF;
   162         slave->sii_physical_layer[i] = 0xFF;
   166     }
   163     }
   167 
   164 
       
   165     // init kobject and add it to the hierarchy
       
   166     memset(&slave->kobj, 0x00, sizeof(struct kobject));
       
   167     kobject_init(&slave->kobj);
       
   168     slave->kobj.ktype = &ktype_ec_slave;
       
   169     slave->kobj.parent = &master->kobj;
       
   170     if (kobject_set_name(&slave->kobj, "slave%03i", slave->ring_position)) {
       
   171         EC_ERR("Failed to set kobject name.\n");
       
   172         goto out_slave_put;
       
   173     }
       
   174     if (kobject_add(&slave->kobj)) {
       
   175         EC_ERR("Failed to add slave's kobject.\n");
       
   176         goto out_slave_put;
       
   177     }
       
   178 
       
   179     // init SDO kobject and add it to the hierarchy
       
   180     memset(&slave->sdo_kobj, 0x00, sizeof(struct kobject));
       
   181     kobject_init(&slave->sdo_kobj);
       
   182     slave->sdo_kobj.ktype = &ktype_ec_slave_sdos;
       
   183     slave->sdo_kobj.parent = &slave->kobj;
       
   184     if (kobject_set_name(&slave->sdo_kobj, "sdos")) {
       
   185         EC_ERR("Failed to set kobject name.\n");
       
   186         goto out_sdo_put;
       
   187     }
       
   188     if (kobject_add(&slave->sdo_kobj)) {
       
   189         EC_ERR("Failed to add SDOs kobject.\n");
       
   190         goto out_sdo_put;
       
   191     }
       
   192 
   168     return 0;
   193     return 0;
       
   194 
       
   195  out_sdo_put:
       
   196     kobject_put(&slave->sdo_kobj);
       
   197     kobject_del(&slave->kobj);
       
   198  out_slave_put:
       
   199     kobject_put(&slave->kobj);
       
   200     return -1;
   169 }
   201 }
   170 
   202 
   171 /*****************************************************************************/
   203 /*****************************************************************************/
   172 
   204 
   173 /**
   205 /**
   174    Slave destructor.
   206    Slave destructor.
       
   207    Clears and frees a slave object.
       
   208 */
       
   209 
       
   210 void ec_slave_destroy(ec_slave_t *slave /**< EtherCAT slave */)
       
   211 {
       
   212     ec_sdo_t *sdo, *next_sdo;
       
   213 
       
   214     // free all SDOs
       
   215     list_for_each_entry_safe(sdo, next_sdo, &slave->sdo_dictionary, list) {
       
   216         list_del(&sdo->list);
       
   217         ec_sdo_destroy(sdo);
       
   218     }
       
   219 
       
   220     // free SDO kobject
       
   221     kobject_del(&slave->sdo_kobj);
       
   222     kobject_put(&slave->sdo_kobj);
       
   223 
       
   224     // destroy self
       
   225     kobject_del(&slave->kobj);
       
   226     kobject_put(&slave->kobj);
       
   227 }
       
   228 
       
   229 /*****************************************************************************/
       
   230 
       
   231 /**
       
   232    Clear and free slave.
       
   233    This method is called by the kobject,
       
   234    once there are no more references to it.
   175 */
   235 */
   176 
   236 
   177 void ec_slave_clear(struct kobject *kobj /**< kobject of the slave */)
   237 void ec_slave_clear(struct kobject *kobj /**< kobject of the slave */)
   178 {
   238 {
   179     ec_slave_t *slave;
   239     ec_slave_t *slave;
   180     ec_sii_string_t *string, *next_str;
   240     ec_sii_string_t *string, *next_str;
   181     ec_sii_sync_t *sync, *next_sync;
   241     ec_sii_sync_t *sync, *next_sync;
   182     ec_sii_pdo_t *pdo, *next_pdo;
   242     ec_sii_pdo_t *pdo, *next_pdo;
   183     ec_sii_pdo_entry_t *entry, *next_ent;
   243     ec_sii_pdo_entry_t *entry, *next_ent;
   184     ec_sdo_t *sdo, *next_sdo;
       
   185     ec_sdo_entry_t *en, *next_en;
       
   186     ec_sdo_data_t *sdodata, *next_sdodata;
   244     ec_sdo_data_t *sdodata, *next_sdodata;
   187     ec_varsize_t *var, *next_var;
       
   188 
   245 
   189     slave = container_of(kobj, ec_slave_t, kobj);
   246     slave = container_of(kobj, ec_slave_t, kobj);
   190 
   247 
   191     // free all string objects
   248     // free all string objects
   192     list_for_each_entry_safe(string, next_str, &slave->sii_strings, list) {
   249     list_for_each_entry_safe(string, next_str, &slave->sii_strings, list) {
   218     if (slave->sii_group) kfree(slave->sii_group);
   275     if (slave->sii_group) kfree(slave->sii_group);
   219     if (slave->sii_image) kfree(slave->sii_image);
   276     if (slave->sii_image) kfree(slave->sii_image);
   220     if (slave->sii_order) kfree(slave->sii_order);
   277     if (slave->sii_order) kfree(slave->sii_order);
   221     if (slave->sii_name) kfree(slave->sii_name);
   278     if (slave->sii_name) kfree(slave->sii_name);
   222 
   279 
   223     // free all SDOs
       
   224     list_for_each_entry_safe(sdo, next_sdo, &slave->sdo_dictionary, list) {
       
   225         list_del(&sdo->list);
       
   226         if (sdo->name) kfree(sdo->name);
       
   227 
       
   228         // free all SDO entries
       
   229         list_for_each_entry_safe(en, next_en, &sdo->entries, list) {
       
   230             list_del(&en->list);
       
   231             kfree(en);
       
   232         }
       
   233         kfree(sdo);
       
   234     }
       
   235 
       
   236     // free all SDO configurations
   280     // free all SDO configurations
   237     list_for_each_entry_safe(sdodata, next_sdodata, &slave->sdo_confs, list) {
   281     list_for_each_entry_safe(sdodata, next_sdodata, &slave->sdo_confs, list) {
   238         list_del(&sdodata->list);
   282         list_del(&sdodata->list);
   239         kfree(sdodata->data);
   283         kfree(sdodata->data);
   240         kfree(sdodata);
   284         kfree(sdodata);
   241     }
   285     }
   242 
   286 
   243     // free information about variable sized data fields
       
   244     list_for_each_entry_safe(var, next_var, &slave->varsize_fields, list) {
       
   245         list_del(&var->list);
       
   246         kfree(var);
       
   247     }
       
   248 
       
   249     if (slave->eeprom_data) kfree(slave->eeprom_data);
   287     if (slave->eeprom_data) kfree(slave->eeprom_data);
   250     if (slave->new_eeprom_data) kfree(slave->new_eeprom_data);
   288     if (slave->new_eeprom_data) kfree(slave->new_eeprom_data);
       
   289 
       
   290     kfree(slave);
       
   291 }
       
   292 
       
   293 /*****************************************************************************/
       
   294 
       
   295 /**
       
   296 */
       
   297 
       
   298 void ec_slave_sdos_clear(struct kobject *kobj /**< kobject for SDOs */)
       
   299 {
       
   300 }
       
   301 
       
   302 /*****************************************************************************/
       
   303 
       
   304 /**
       
   305    Reset slave from operation mode.
       
   306 */
       
   307 
       
   308 void ec_slave_reset(ec_slave_t *slave /**< EtherCAT slave */)
       
   309 {
       
   310     ec_sdo_data_t *sdodata, *next_sdodata;
       
   311     ec_sii_sync_t *sync;
       
   312 
       
   313     // remove FMMU configurations
       
   314     slave->fmmu_count = 0;
       
   315 
       
   316     // free all SDO configurations
       
   317     list_for_each_entry_safe(sdodata, next_sdodata, &slave->sdo_confs, list) {
       
   318         list_del(&sdodata->list);
       
   319         kfree(sdodata->data);
       
   320         kfree(sdodata);
       
   321     }
       
   322 
       
   323     // remove estimated sync manager sizes
       
   324     list_for_each_entry(sync, &slave->sii_syncs, list) {
       
   325         sync->est_length = 0;
       
   326     }
       
   327 }
       
   328 
       
   329 /*****************************************************************************/
       
   330 
       
   331 /**
       
   332  */
       
   333 
       
   334 void ec_slave_request_state(ec_slave_t *slave, /**< ETherCAT slave */
       
   335                             ec_slave_state_t state /**< new state */
       
   336                             )
       
   337 {
       
   338     slave->requested_state = state;
       
   339     slave->error_flag = 0;
   251 }
   340 }
   252 
   341 
   253 /*****************************************************************************/
   342 /*****************************************************************************/
   254 
   343 
   255 /**
   344 /**
   339         sync->physical_start_address = EC_READ_U16(data);
   428         sync->physical_start_address = EC_READ_U16(data);
   340         sync->length                 = EC_READ_U16(data + 2);
   429         sync->length                 = EC_READ_U16(data + 2);
   341         sync->control_register       = EC_READ_U8 (data + 4);
   430         sync->control_register       = EC_READ_U8 (data + 4);
   342         sync->enable                 = EC_READ_U8 (data + 6);
   431         sync->enable                 = EC_READ_U8 (data + 6);
   343 
   432 
       
   433         sync->est_length = 0;
       
   434 
   344         list_add_tail(&sync->list, &slave->sii_syncs);
   435         list_add_tail(&sync->list, &slave->sii_syncs);
   345     }
   436     }
   346 
   437 
   347     return 0;
   438     return 0;
   348 }
   439 }
   443         }
   534         }
   444         memcpy(*ptr, string->data, string->size + 1);
   535         memcpy(*ptr, string->data, string->size + 1);
   445         return 0;
   536         return 0;
   446     }
   537     }
   447 
   538 
   448     EC_WARN("String %i not found in slave %i.\n", index, slave->ring_position);
   539     if (slave->master->debug_level)
       
   540         EC_WARN("String %i not found in slave %i.\n",
       
   541                 index, slave->ring_position);
   449 
   542 
   450     err_string = "(string not found)";
   543     err_string = "(string not found)";
   451 
   544 
   452     if (!(*ptr = (char *) kmalloc(strlen(err_string) + 1, GFP_ATOMIC))) {
   545     if (!(*ptr = (char *) kmalloc(strlen(err_string) + 1, GFP_ATOMIC))) {
   453         EC_WARN("Unable to allocate string memory.\n");
   546         EC_WARN("Unable to allocate string memory.\n");
   476                           const ec_domain_t *domain, /**< domain */
   569                           const ec_domain_t *domain, /**< domain */
   477                           const ec_sii_sync_t *sync  /**< sync manager */
   570                           const ec_sii_sync_t *sync  /**< sync manager */
   478                           )
   571                           )
   479 {
   572 {
   480     unsigned int i;
   573     unsigned int i;
       
   574     ec_fmmu_t *fmmu;
   481 
   575 
   482     // FMMU configuration already prepared?
   576     // FMMU configuration already prepared?
   483     for (i = 0; i < slave->fmmu_count; i++)
   577     for (i = 0; i < slave->fmmu_count; i++) {
   484         if (slave->fmmus[i].domain == domain && slave->fmmus[i].sync == sync)
   578         fmmu = &slave->fmmus[i];
       
   579         if (fmmu->domain == domain && fmmu->sync == sync)
   485             return 0;
   580             return 0;
       
   581     }
   486 
   582 
   487     // reserve new FMMU...
   583     // reserve new FMMU...
   488 
   584 
   489     if (slave->fmmu_count >= slave->base_fmmu_count) {
   585     if (slave->fmmu_count >= slave->base_fmmu_count) {
   490         EC_ERR("Slave %i FMMU limit reached!\n", slave->ring_position);
   586         EC_ERR("Slave %i FMMU limit reached!\n", slave->ring_position);
   491         return -1;
   587         return -1;
   492     }
   588     }
   493 
   589 
   494     slave->fmmus[slave->fmmu_count].domain = domain;
   590     fmmu = &slave->fmmus[slave->fmmu_count];
   495     slave->fmmus[slave->fmmu_count].sync = sync;
   591 
   496     slave->fmmus[slave->fmmu_count].logical_start_address = 0;
   592     fmmu->index = slave->fmmu_count;
       
   593     fmmu->domain = domain;
       
   594     fmmu->sync = sync;
       
   595     fmmu->logical_start_address = 0;
       
   596 
   497     slave->fmmu_count++;
   597     slave->fmmu_count++;
   498     slave->registered = 1;
       
   499 
   598 
   500     return 0;
   599     return 0;
   501 }
   600 }
   502 
   601 
   503 /*****************************************************************************/
   602 /*****************************************************************************/
   513     off_t off = 0;
   612     off_t off = 0;
   514     ec_sii_sync_t *sync;
   613     ec_sii_sync_t *sync;
   515     ec_sii_pdo_t *pdo;
   614     ec_sii_pdo_t *pdo;
   516     ec_sii_pdo_entry_t *pdo_entry;
   615     ec_sii_pdo_entry_t *pdo_entry;
   517     int first, i;
   616     int first, i;
       
   617     ec_sdo_data_t *sdodata;
       
   618     char str[20];
   518 
   619 
   519     off += sprintf(buffer + off, "\nName: ");
   620     off += sprintf(buffer + off, "\nName: ");
   520 
   621 
   521     if (slave->sii_name)
   622     if (slave->sii_name)
   522         off += sprintf(buffer + off, "%s", slave->sii_name);
   623         off += sprintf(buffer + off, "%s", slave->sii_name);
   526     off += sprintf(buffer + off, "Product code: 0x%08X\n\n",
   627     off += sprintf(buffer + off, "Product code: 0x%08X\n\n",
   527                    slave->sii_product_code);
   628                    slave->sii_product_code);
   528 
   629 
   529     off += sprintf(buffer + off, "State: ");
   630     off += sprintf(buffer + off, "State: ");
   530     off += ec_state_string(slave->current_state, buffer + off);
   631     off += ec_state_string(slave->current_state, buffer + off);
   531     off += sprintf(buffer + off, "\nRing position: %i\n",
   632     off += sprintf(buffer + off, "\nFlags: %s, %s\n",
       
   633                    slave->online ? "online" : "OFFLINE",
       
   634                    slave->error_flag ? "ERROR" : "ok");
       
   635     off += sprintf(buffer + off, "Ring position: %i\n",
   532                    slave->ring_position);
   636                    slave->ring_position);
   533     off += sprintf(buffer + off, "Advanced position: %i:%i\n",
   637     off += sprintf(buffer + off, "Advanced position: %i:%i\n",
   534                    slave->coupler_index, slave->coupler_subindex);
   638                    slave->coupler_index, slave->coupler_subindex);
   535     off += sprintf(buffer + off, "Coupler: %s\n\n",
   639     off += sprintf(buffer + off, "Coupler: %s\n\n",
   536                    ec_slave_is_coupler(slave) ? "yes" : "no");
   640                    ec_slave_is_coupler(slave) ? "yes" : "no");
   641                            pdo_entry->index, pdo_entry->subindex,
   745                            pdo_entry->index, pdo_entry->subindex,
   642                            pdo_entry->bit_length);
   746                            pdo_entry->bit_length);
   643         }
   747         }
   644     }
   748     }
   645 
   749 
       
   750     if (!list_empty(&slave->sdo_confs))
       
   751         off += sprintf(buffer + off, "\nSDO configurations:\n");
       
   752 
       
   753     list_for_each_entry(sdodata, &slave->sdo_confs, list) {
       
   754         switch (sdodata->size) {
       
   755             case 1: sprintf(str, "%i", EC_READ_U8(sdodata->data)); break;
       
   756             case 2: sprintf(str, "%i", EC_READ_U16(sdodata->data)); break;
       
   757             case 4: sprintf(str, "%i", EC_READ_U32(sdodata->data)); break;
       
   758             default: sprintf(str, "(invalid size)"); break;
       
   759         }
       
   760         off += sprintf(buffer + off, "  0x%04X:%-3i -> %s\n",
       
   761                        sdodata->index, sdodata->subindex, str);
       
   762     }
       
   763 
   646     off += sprintf(buffer + off, "\n");
   764     off += sprintf(buffer + off, "\n");
   647 
   765 
   648     return off;
   766     return off;
   649 }
   767 }
   650 
   768 
   787                                  )
   905                                  )
   788 {
   906 {
   789     ec_slave_t *slave = container_of(kobj, ec_slave_t, kobj);
   907     ec_slave_t *slave = container_of(kobj, ec_slave_t, kobj);
   790 
   908 
   791     if (attr == &attr_state) {
   909     if (attr == &attr_state) {
   792         char state[25];
   910         char state[EC_STATE_STRING_SIZE];
   793         if (!strcmp(buffer, "INIT\n"))
   911         if (!strcmp(buffer, "INIT\n"))
   794             slave->requested_state = EC_SLAVE_STATE_INIT;
   912             ec_slave_request_state(slave, EC_SLAVE_STATE_INIT);
   795         else if (!strcmp(buffer, "PREOP\n"))
   913         else if (!strcmp(buffer, "PREOP\n"))
   796             slave->requested_state = EC_SLAVE_STATE_PREOP;
   914             ec_slave_request_state(slave, EC_SLAVE_STATE_PREOP);
   797         else if (!strcmp(buffer, "SAVEOP\n"))
   915         else if (!strcmp(buffer, "SAVEOP\n"))
   798             slave->requested_state = EC_SLAVE_STATE_SAVEOP;
   916             ec_slave_request_state(slave, EC_SLAVE_STATE_SAVEOP);
   799         else if (!strcmp(buffer, "OP\n"))
   917         else if (!strcmp(buffer, "OP\n"))
   800             slave->requested_state = EC_SLAVE_STATE_OP;
   918             ec_slave_request_state(slave, EC_SLAVE_STATE_OP);
   801         else {
   919         else {
   802             EC_ERR("Invalid slave state \"%s\"!\n", buffer);
   920             EC_ERR("Invalid slave state \"%s\"!\n", buffer);
   803             return -EINVAL;
   921             return -EINVAL;
   804         }
   922         }
   805 
   923 
   806         ec_state_string(slave->requested_state, state);
   924         ec_state_string(slave->requested_state, state);
   807         EC_INFO("Accepted new state %s for slave %i.\n",
   925         EC_INFO("Accepted new state %s for slave %i.\n",
   808                 state, slave->ring_position);
   926                 state, slave->ring_position);
   809         slave->error_flag = 0;
       
   810         return size;
   927         return size;
   811     }
   928     }
   812     else if (attr == &attr_eeprom) {
   929     else if (attr == &attr_eeprom) {
   813         if (!ec_slave_write_eeprom(slave, buffer, size))
   930         if (!ec_slave_write_eeprom(slave, buffer, size))
   814             return size;
   931             return size;
   830                                  /**< sync manager */
   947                                  /**< sync manager */
   831                                  )
   948                                  )
   832 {
   949 {
   833     ec_sii_pdo_t *pdo;
   950     ec_sii_pdo_t *pdo;
   834     ec_sii_pdo_entry_t *pdo_entry;
   951     ec_sii_pdo_entry_t *pdo_entry;
   835     unsigned int bit_size;
   952     unsigned int bit_size, byte_size;
   836 
   953 
   837     if (sync->length) return sync->length;
   954     if (sync->length) return sync->length;
       
   955     if (sync->est_length) return sync->est_length;
   838 
   956 
   839     bit_size = 0;
   957     bit_size = 0;
   840     list_for_each_entry(pdo, &slave->sii_pdos, list) {
   958     list_for_each_entry(pdo, &slave->sii_pdos, list) {
   841         if (pdo->sync_index != sync->index) continue;
   959         if (pdo->sync_index != sync->index) continue;
   842 
   960 
   844             bit_size += pdo_entry->bit_length;
   962             bit_size += pdo_entry->bit_length;
   845         }
   963         }
   846     }
   964     }
   847 
   965 
   848     if (bit_size % 8) // round up to full bytes
   966     if (bit_size % 8) // round up to full bytes
   849         return bit_size / 8 + 1;
   967         byte_size = bit_size / 8 + 1;
   850     else
   968     else
   851         return bit_size / 8;
   969         byte_size = bit_size / 8;
       
   970 
       
   971     return byte_size;
   852 }
   972 }
   853 
   973 
   854 /*****************************************************************************/
   974 /*****************************************************************************/
   855 
   975 
   856 /**
   976 /**
   871 */
   991 */
   872 
   992 
   873 int ec_slave_has_subbus(const ec_slave_t *slave /**< EtherCAT slave */)
   993 int ec_slave_has_subbus(const ec_slave_t *slave /**< EtherCAT slave */)
   874 {
   994 {
   875     return slave->sii_vendor_id == 0x00000002
   995     return slave->sii_vendor_id == 0x00000002
   876         && slave->sii_product_code == 0x13ED3052;
   996         && slave->sii_product_code == 0x04602c22;
   877 }
   997 }
   878 
   998 
   879 /*****************************************************************************/
   999 /*****************************************************************************/
   880 
  1000 
   881 /**
  1001 /**
   913     memcpy(sdodata->data, data, size);
  1033     memcpy(sdodata->data, data, size);
   914     sdodata->size = size;
  1034     sdodata->size = size;
   915 
  1035 
   916     list_add_tail(&sdodata->list, &slave->sdo_confs);
  1036     list_add_tail(&sdodata->list, &slave->sdo_confs);
   917     return 0;
  1037     return 0;
       
  1038 }
       
  1039 
       
  1040 /*****************************************************************************/
       
  1041 
       
  1042 /**
       
  1043    \return 0 in case of success, else < 0
       
  1044 */
       
  1045 
       
  1046 int ec_slave_validate(const ec_slave_t *slave, /**< EtherCAT slave */
       
  1047                       uint32_t vendor_id, /**< vendor ID */
       
  1048                       uint32_t product_code /**< product code */
       
  1049                       )
       
  1050 {
       
  1051     if (vendor_id != slave->sii_vendor_id ||
       
  1052         product_code != slave->sii_product_code) {
       
  1053         EC_ERR("Invalid slave type at position %i - Requested: 0x%08X 0x%08X,"
       
  1054                " found: 0x%08X 0x%08X\".\n", slave->ring_position, vendor_id,
       
  1055                product_code, slave->sii_vendor_id, slave->sii_product_code);
       
  1056         return -1;
       
  1057     }
       
  1058     return 0;
       
  1059 }
       
  1060 
       
  1061 /*****************************************************************************/
       
  1062 
       
  1063 /**
       
  1064    Counts the total number of SDOs and entries in the dictionary.
       
  1065 */
       
  1066 
       
  1067 void ec_slave_sdo_dict_info(const ec_slave_t *slave, /**< EtherCAT slave */
       
  1068                             unsigned int *sdo_count, /**< number of SDOs */
       
  1069                             unsigned int *entry_count /**< total number of
       
  1070                                                          entries */
       
  1071                             )
       
  1072 {
       
  1073     unsigned int sdos = 0, entries = 0;
       
  1074     ec_sdo_t *sdo;
       
  1075     ec_sdo_entry_t *entry;
       
  1076 
       
  1077     list_for_each_entry(sdo, &slave->sdo_dictionary, list) {
       
  1078         sdos++;
       
  1079         list_for_each_entry(entry, &sdo->entries, list) {
       
  1080             entries++;
       
  1081         }
       
  1082     }
       
  1083 
       
  1084     *sdo_count = sdos;
       
  1085     *entry_count = entries;
   918 }
  1086 }
   919 
  1087 
   920 /******************************************************************************
  1088 /******************************************************************************
   921  *  Realtime interface
  1089  *  Realtime interface
   922  *****************************************************************************/
  1090  *****************************************************************************/