master/slave.c
branchstable-1.3
changeset 1744 7bc131b92039
parent 1739 5fcbd29151d2
child 1746 72e7507b3f1b
equal deleted inserted replaced
1743:1a7067207637 1744:7bc131b92039
    55 void ec_slave_clear(struct kobject *);
    55 void ec_slave_clear(struct kobject *);
    56 void ec_slave_sdos_clear(struct kobject *);
    56 void ec_slave_sdos_clear(struct kobject *);
    57 ssize_t ec_show_slave_attribute(struct kobject *, struct attribute *, char *);
    57 ssize_t ec_show_slave_attribute(struct kobject *, struct attribute *, char *);
    58 ssize_t ec_store_slave_attribute(struct kobject *, struct attribute *,
    58 ssize_t ec_store_slave_attribute(struct kobject *, struct attribute *,
    59                                  const char *, size_t);
    59                                  const char *, size_t);
       
    60 char *ec_slave_sii_string(ec_slave_t *, unsigned int);
    60 
    61 
    61 /*****************************************************************************/
    62 /*****************************************************************************/
    62 
    63 
    63 /** \cond */
    64 /** \cond */
    64 
    65 
    65 EC_SYSFS_READ_ATTR(info);
    66 EC_SYSFS_READ_ATTR(info);
    66 EC_SYSFS_READ_WRITE_ATTR(state);
    67 EC_SYSFS_READ_WRITE_ATTR(state);
    67 EC_SYSFS_READ_WRITE_ATTR(eeprom);
    68 EC_SYSFS_READ_WRITE_ATTR(eeprom);
       
    69 EC_SYSFS_READ_WRITE_ATTR(alias);
    68 
    70 
    69 static struct attribute *def_attrs[] = {
    71 static struct attribute *def_attrs[] = {
    70     &attr_info,
    72     &attr_info,
    71     &attr_state,
    73     &attr_state,
    72     &attr_eeprom,
    74     &attr_eeprom,
       
    75     &attr_alias,
    73     NULL,
    76     NULL,
    74 };
    77 };
    75 
    78 
    76 static struct sysfs_ops sysfs_ops = {
    79 static struct sysfs_ops sysfs_ops = {
    77     .show = ec_show_slave_attribute,
    80     .show = ec_show_slave_attribute,
   108     slave->ring_position = ring_position;
   111     slave->ring_position = ring_position;
   109     slave->station_address = station_address;
   112     slave->station_address = station_address;
   110 
   113 
   111     slave->master = master;
   114     slave->master = master;
   112 
   115 
   113     slave->requested_state = EC_SLAVE_STATE_UNKNOWN;
   116     slave->requested_state = EC_SLAVE_STATE_PREOP;
   114     slave->current_state = EC_SLAVE_STATE_UNKNOWN;
   117     slave->current_state = EC_SLAVE_STATE_UNKNOWN;
   115     slave->self_configured = 0;
   118     slave->self_configured = 0;
   116     slave->error_flag = 0;
   119     slave->error_flag = 0;
   117     slave->online = 1;
   120     slave->online_state = EC_SLAVE_ONLINE;
   118     slave->fmmu_count = 0;
   121     slave->fmmu_count = 0;
   119 
   122     slave->pdos_registered = 0;
   120     slave->coupler_index = 0;
       
   121     slave->coupler_subindex = 0xFFFF;
       
   122 
   123 
   123     slave->base_type = 0;
   124     slave->base_type = 0;
   124     slave->base_revision = 0;
   125     slave->base_revision = 0;
   125     slave->base_build = 0;
   126     slave->base_build = 0;
   126     slave->base_fmmu_count = 0;
   127     slave->base_fmmu_count = 0;
   127     slave->base_sync_count = 0;
       
   128 
   128 
   129     slave->eeprom_data = NULL;
   129     slave->eeprom_data = NULL;
   130     slave->eeprom_size = 0;
   130     slave->eeprom_size = 0;
   131     slave->new_eeprom_data = NULL;
       
   132     slave->new_eeprom_size = 0;
       
   133 
   131 
   134     slave->sii_alias = 0;
   132     slave->sii_alias = 0;
   135     slave->sii_vendor_id = 0;
   133     slave->sii_vendor_id = 0;
   136     slave->sii_product_code = 0;
   134     slave->sii_product_code = 0;
   137     slave->sii_revision_number = 0;
   135     slave->sii_revision_number = 0;
   145     slave->sii_image = NULL;
   143     slave->sii_image = NULL;
   146     slave->sii_order = NULL;
   144     slave->sii_order = NULL;
   147     slave->sii_name = NULL;
   145     slave->sii_name = NULL;
   148     slave->sii_current_on_ebus = 0;
   146     slave->sii_current_on_ebus = 0;
   149 
   147 
   150     INIT_LIST_HEAD(&slave->sii_strings);
   148     slave->sii_strings = NULL;
   151     INIT_LIST_HEAD(&slave->sii_syncs);
   149     slave->sii_string_count = 0;
       
   150     slave->sii_syncs = NULL;
       
   151     slave->sii_sync_count = 0;
   152     INIT_LIST_HEAD(&slave->sii_pdos);
   152     INIT_LIST_HEAD(&slave->sii_pdos);
   153     INIT_LIST_HEAD(&slave->sdo_dictionary);
   153     INIT_LIST_HEAD(&slave->sdo_dictionary);
   154     INIT_LIST_HEAD(&slave->sdo_confs);
   154     INIT_LIST_HEAD(&slave->sdo_confs);
   155 
   155 
   156     slave->sdo_dictionary_fetched = 0;
   156     slave->sdo_dictionary_fetched = 0;
   236 */
   236 */
   237 
   237 
   238 void ec_slave_clear(struct kobject *kobj /**< kobject of the slave */)
   238 void ec_slave_clear(struct kobject *kobj /**< kobject of the slave */)
   239 {
   239 {
   240     ec_slave_t *slave;
   240     ec_slave_t *slave;
   241     ec_sii_string_t *string, *next_str;
   241     ec_pdo_t *pdo, *next_pdo;
   242     ec_sii_sync_t *sync, *next_sync;
       
   243     ec_sii_pdo_t *pdo, *next_pdo;
       
   244     ec_sii_pdo_entry_t *entry, *next_ent;
       
   245     ec_sdo_data_t *sdodata, *next_sdodata;
   242     ec_sdo_data_t *sdodata, *next_sdodata;
       
   243     unsigned int i;
   246 
   244 
   247     slave = container_of(kobj, ec_slave_t, kobj);
   245     slave = container_of(kobj, ec_slave_t, kobj);
   248 
   246 
   249     // free all string objects
   247     // free all strings
   250     list_for_each_entry_safe(string, next_str, &slave->sii_strings, list) {
   248     if (slave->sii_strings) {
   251         list_del(&string->list);
   249         for (i = 0; i < slave->sii_string_count; i++)
   252         kfree(string);
   250             kfree(slave->sii_strings[i]);
       
   251         kfree(slave->sii_strings);
   253     }
   252     }
   254 
   253 
   255     // free all sync managers
   254     // free all sync managers
   256     list_for_each_entry_safe(sync, next_sync, &slave->sii_syncs, list) {
   255     if (slave->sii_syncs) {
   257         list_del(&sync->list);
   256         for (i = 0; i < slave->sii_sync_count; i++) {
   258         kfree(sync);
   257             ec_sync_clear(&slave->sii_syncs[i]);
   259     }
   258         }
   260 
   259         kfree(slave->sii_syncs);
   261     // free all PDOs
   260     }
       
   261 
       
   262     // free all SII PDOs
   262     list_for_each_entry_safe(pdo, next_pdo, &slave->sii_pdos, list) {
   263     list_for_each_entry_safe(pdo, next_pdo, &slave->sii_pdos, list) {
   263         list_del(&pdo->list);
   264         list_del(&pdo->list);
   264         if (pdo->name) kfree(pdo->name);
   265         ec_pdo_clear(pdo);
   265 
       
   266         // free all PDO entries
       
   267         list_for_each_entry_safe(entry, next_ent, &pdo->entries, list) {
       
   268             list_del(&entry->list);
       
   269             if (entry->name) kfree(entry->name);
       
   270             kfree(entry);
       
   271         }
       
   272 
       
   273         kfree(pdo);
   266         kfree(pdo);
   274     }
   267     }
   275 
       
   276     if (slave->sii_group) kfree(slave->sii_group);
       
   277     if (slave->sii_image) kfree(slave->sii_image);
       
   278     if (slave->sii_order) kfree(slave->sii_order);
       
   279     if (slave->sii_name) kfree(slave->sii_name);
       
   280 
   268 
   281     // free all SDO configurations
   269     // free all SDO configurations
   282     list_for_each_entry_safe(sdodata, next_sdodata, &slave->sdo_confs, list) {
   270     list_for_each_entry_safe(sdodata, next_sdodata, &slave->sdo_confs, list) {
   283         list_del(&sdodata->list);
   271         list_del(&sdodata->list);
   284         kfree(sdodata->data);
   272         kfree(sdodata->data);
   285         kfree(sdodata);
   273         kfree(sdodata);
   286     }
   274     }
   287 
   275 
   288     if (slave->eeprom_data) kfree(slave->eeprom_data);
   276     if (slave->eeprom_data) kfree(slave->eeprom_data);
   289     if (slave->new_eeprom_data) kfree(slave->new_eeprom_data);
       
   290 
   277 
   291     kfree(slave);
   278     kfree(slave);
   292 }
   279 }
   293 
   280 
   294 /*****************************************************************************/
   281 /*****************************************************************************/
   307 */
   294 */
   308 
   295 
   309 void ec_slave_reset(ec_slave_t *slave /**< EtherCAT slave */)
   296 void ec_slave_reset(ec_slave_t *slave /**< EtherCAT slave */)
   310 {
   297 {
   311     ec_sdo_data_t *sdodata, *next_sdodata;
   298     ec_sdo_data_t *sdodata, *next_sdodata;
   312     ec_sii_sync_t *sync;
   299     unsigned int i;
   313 
   300 
   314     // remove FMMU configurations
       
   315     slave->fmmu_count = 0;
   301     slave->fmmu_count = 0;
       
   302     slave->pdos_registered = 0;
   316 
   303 
   317     // free all SDO configurations
   304     // free all SDO configurations
   318     list_for_each_entry_safe(sdodata, next_sdodata, &slave->sdo_confs, list) {
   305     list_for_each_entry_safe(sdodata, next_sdodata, &slave->sdo_confs, list) {
   319         list_del(&sdodata->list);
   306         list_del(&sdodata->list);
   320         kfree(sdodata->data);
   307         kfree(sdodata->data);
   321         kfree(sdodata);
   308         kfree(sdodata);
   322     }
   309     }
   323 
   310 
   324     // remove estimated sync manager sizes
   311     // remove estimated sync manager sizes
   325     list_for_each_entry(sync, &slave->sii_syncs, list) {
   312     for (i = 0; i < slave->sii_sync_count; i++) {
   326         sync->est_length = 0;
   313         slave->sii_syncs[i].est_length = 0;
   327     }
   314     }
   328 }
   315 }
   329 
   316 
   330 /*****************************************************************************/
   317 /*****************************************************************************/
   331 
   318 
   332 /**
   319 /**
       
   320  * Sets the application state of a slave.
   333  */
   321  */
   334 
   322 
   335 void ec_slave_request_state(ec_slave_t *slave, /**< ETherCAT slave */
   323 void ec_slave_set_state(ec_slave_t *slave, /**< EtherCAT slave */
       
   324         ec_slave_state_t new_state /**< new application state */
       
   325         )
       
   326 {
       
   327     if (new_state != slave->current_state) {
       
   328         if (slave->master->debug_level) {
       
   329             char old_state[EC_STATE_STRING_SIZE],
       
   330                 cur_state[EC_STATE_STRING_SIZE];
       
   331             ec_state_string(slave->current_state, old_state);
       
   332             ec_state_string(new_state, cur_state);
       
   333             EC_DBG("Slave %i: %s -> %s.\n",
       
   334                    slave->ring_position, old_state, cur_state);
       
   335         }
       
   336         slave->current_state = new_state;
       
   337     }
       
   338 }
       
   339 
       
   340 /*****************************************************************************/
       
   341 
       
   342 /**
       
   343  * Sets the online state of a slave.
       
   344  */
       
   345 
       
   346 void ec_slave_set_online_state(ec_slave_t *slave, /**< EtherCAT slave */
       
   347         ec_slave_online_state_t new_state /**< new online state */
       
   348         )
       
   349 {
       
   350     if (new_state == EC_SLAVE_OFFLINE &&
       
   351             slave->online_state == EC_SLAVE_ONLINE) {
       
   352         if (slave->pdos_registered)
       
   353             slave->master->pdo_slaves_offline++;
       
   354         if (slave->master->debug_level)
       
   355             EC_DBG("Slave %i: offline.\n", slave->ring_position);
       
   356     }
       
   357     else if (new_state == EC_SLAVE_ONLINE &&
       
   358             slave->online_state == EC_SLAVE_OFFLINE) {
       
   359         slave->error_flag = 0; // clear error flag
       
   360         if (slave->pdos_registered)
       
   361             slave->master->pdo_slaves_offline--;
       
   362         if (slave->master->debug_level) {
       
   363             char cur_state[EC_STATE_STRING_SIZE];
       
   364             ec_state_string(slave->current_state, cur_state);
       
   365             EC_DBG("Slave %i: online (%s).\n",
       
   366                    slave->ring_position, cur_state);
       
   367         }
       
   368     }
       
   369 
       
   370     slave->online_state = new_state;
       
   371 }
       
   372 
       
   373 /*****************************************************************************/
       
   374 
       
   375 /**
       
   376  */
       
   377 
       
   378 void ec_slave_request_state(ec_slave_t *slave, /**< EtherCAT slave */
   336                             ec_slave_state_t state /**< new state */
   379                             ec_slave_state_t state /**< new state */
   337                             )
   380                             )
   338 {
   381 {
   339     slave->requested_state = state;
   382     slave->requested_state = state;
   340     slave->error_flag = 0;
   383     slave->error_flag = 0;
   345 /**
   388 /**
   346    Fetches data from a STRING category.
   389    Fetches data from a STRING category.
   347    \return 0 in case of success, else < 0
   390    \return 0 in case of success, else < 0
   348 */
   391 */
   349 
   392 
   350 int ec_slave_fetch_strings(ec_slave_t *slave, /**< EtherCAT slave */
   393 int ec_slave_fetch_sii_strings(
   351                            const uint8_t *data /**< category data */
   394         ec_slave_t *slave, /**< EtherCAT slave */
   352                            )
   395         const uint8_t *data /**< category data */
   353 {
   396         )
   354     unsigned int string_count, i;
   397 {
       
   398     int i;
   355     size_t size;
   399     size_t size;
   356     off_t offset;
   400     off_t offset;
   357     ec_sii_string_t *string;
   401 
   358 
   402     slave->sii_string_count = data[0];
   359     string_count = data[0];
   403 
       
   404     if (!slave->sii_string_count)
       
   405         return 0;
       
   406 
       
   407     if (!(slave->sii_strings =
       
   408                 kmalloc(sizeof(char *) * slave->sii_string_count,
       
   409                     GFP_KERNEL))) {
       
   410         EC_ERR("Failed to allocate string array memory.\n");
       
   411         goto out_zero;
       
   412     }
       
   413 
   360     offset = 1;
   414     offset = 1;
   361     for (i = 0; i < string_count; i++) {
   415     for (i = 0; i < slave->sii_string_count; i++) {
   362         size = data[offset];
   416         size = data[offset];
   363         // allocate memory for string structure and data at a single blow
   417         // allocate memory for string structure and data at a single blow
   364         if (!(string = (ec_sii_string_t *)
   418         if (!(slave->sii_strings[i] =
   365               kmalloc(sizeof(ec_sii_string_t) + size + 1, GFP_ATOMIC))) {
   419                     kmalloc(sizeof(char) * size + 1, GFP_KERNEL))) {
   366             EC_ERR("Failed to allocate string memory.\n");
   420             EC_ERR("Failed to allocate string memory.\n");
   367             return -1;
   421             goto out_free;
   368         }
   422         }
   369         string->size = size;
   423         memcpy(slave->sii_strings[i], data + offset + 1, size);
   370         // string memory appended to string structure
   424         slave->sii_strings[i][size] = 0x00; // append binary zero
   371         string->data = (char *) string + sizeof(ec_sii_string_t);
       
   372         memcpy(string->data, data + offset + 1, size);
       
   373         string->data[size] = 0x00;
       
   374         list_add_tail(&string->list, &slave->sii_strings);
       
   375         offset += 1 + size;
   425         offset += 1 + size;
   376     }
   426     }
   377 
   427 
   378     return 0;
   428     return 0;
       
   429 
       
   430 out_free:
       
   431     for (i--; i >= 0; i--) kfree(slave->sii_strings[i]);
       
   432     kfree(slave->sii_strings);
       
   433     slave->sii_strings = NULL;
       
   434 out_zero:
       
   435     slave->sii_string_count = 0;
       
   436     return -1;
   379 }
   437 }
   380 
   438 
   381 /*****************************************************************************/
   439 /*****************************************************************************/
   382 
   440 
   383 /**
   441 /**
   384    Fetches data from a GENERAL category.
   442    Fetches data from a GENERAL category.
   385    \return 0 in case of success, else < 0
   443    \return 0 in case of success, else < 0
   386 */
   444 */
   387 
   445 
   388 void ec_slave_fetch_general(ec_slave_t *slave, /**< EtherCAT slave */
   446 void ec_slave_fetch_sii_general(
   389                             const uint8_t *data /**< category data */
   447         ec_slave_t *slave, /**< EtherCAT slave */
   390                             )
   448         const uint8_t *data /**< category data */
       
   449         )
   391 {
   450 {
   392     unsigned int i;
   451     unsigned int i;
   393 
   452 
   394     ec_slave_locate_string(slave, data[0], &slave->sii_group);
   453     slave->sii_group = ec_slave_sii_string(slave, data[0]);
   395     ec_slave_locate_string(slave, data[1], &slave->sii_image);
   454     slave->sii_image = ec_slave_sii_string(slave, data[1]);
   396     ec_slave_locate_string(slave, data[2], &slave->sii_order);
   455     slave->sii_order = ec_slave_sii_string(slave, data[2]);
   397     ec_slave_locate_string(slave, data[3], &slave->sii_name);
   456     slave->sii_name = ec_slave_sii_string(slave, data[3]);
   398 
   457 
   399     for (i = 0; i < 4; i++)
   458     for (i = 0; i < 4; i++)
   400         slave->sii_physical_layer[i] =
   459         slave->sii_physical_layer[i] =
   401             (data[4] & (0x03 << (i * 2))) >> (i * 2);
   460             (data[4] & (0x03 << (i * 2))) >> (i * 2);
   402 
   461 
   408 /**
   467 /**
   409    Fetches data from a SYNC MANAGER category.
   468    Fetches data from a SYNC MANAGER category.
   410    \return 0 in case of success, else < 0
   469    \return 0 in case of success, else < 0
   411 */
   470 */
   412 
   471 
   413 int ec_slave_fetch_sync(ec_slave_t *slave, /**< EtherCAT slave */
   472 int ec_slave_fetch_sii_syncs(
   414                         const uint8_t *data, /**< category data */
   473         ec_slave_t *slave, /**< EtherCAT slave */
   415                         size_t word_count /**< number of words */
   474         const uint8_t *data, /**< category data */
   416                         )
   475         size_t word_count /**< number of words */
   417 {
   476         )
   418     unsigned int sync_count, i;
   477 {
   419     ec_sii_sync_t *sync;
   478     unsigned int i;
   420 
   479     ec_sync_t *sync;
   421     sync_count = word_count / 4; // sync manager struct is 4 words long
   480 
   422 
   481     // sync manager struct is 4 words long
   423     for (i = 0; i < sync_count; i++, data += 8) {
   482     slave->sii_sync_count = word_count / 4;
   424         if (!(sync = (ec_sii_sync_t *)
   483 
   425               kmalloc(sizeof(ec_sii_sync_t), GFP_ATOMIC))) {
   484     if (!(slave->sii_syncs =
   426             EC_ERR("Failed to allocate Sync-Manager memory.\n");
   485                 kmalloc(sizeof(ec_sync_t) * slave->sii_sync_count,
   427             return -1;
   486                     GFP_KERNEL))) {
   428         }
   487         EC_ERR("Failed to allocate memory for sync managers.\n");
   429 
   488         slave->sii_sync_count = 0;
   430         sync->index = i;
   489         return -1;
       
   490     }
       
   491     
       
   492     for (i = 0; i < slave->sii_sync_count; i++, data += 8) {
       
   493         sync = &slave->sii_syncs[i];
       
   494 
       
   495         ec_sync_init(sync, slave, i);
   431         sync->physical_start_address = EC_READ_U16(data);
   496         sync->physical_start_address = EC_READ_U16(data);
   432         sync->length                 = EC_READ_U16(data + 2);
   497         sync->length = EC_READ_U16(data + 2);
   433         sync->control_register       = EC_READ_U8 (data + 4);
   498         sync->control_register = EC_READ_U8 (data + 4);
   434         sync->enable                 = EC_READ_U8 (data + 6);
   499         sync->enable = EC_READ_U8 (data + 6);
   435 
       
   436         sync->est_length = 0;
       
   437 
       
   438         list_add_tail(&sync->list, &slave->sii_syncs);
       
   439     }
   500     }
   440 
   501 
   441     return 0;
   502     return 0;
   442 }
   503 }
   443 
   504 
   446 /**
   507 /**
   447    Fetches data from a [RT]XPDO category.
   508    Fetches data from a [RT]XPDO category.
   448    \return 0 in case of success, else < 0
   509    \return 0 in case of success, else < 0
   449 */
   510 */
   450 
   511 
   451 int ec_slave_fetch_pdo(ec_slave_t *slave, /**< EtherCAT slave */
   512 int ec_slave_fetch_sii_pdos(
   452                        const uint8_t *data, /**< category data */
   513         ec_slave_t *slave, /**< EtherCAT slave */
   453                        size_t word_count, /**< number of words */
   514         const uint8_t *data, /**< category data */
   454                        ec_sii_pdo_type_t pdo_type /**< PDO type */
   515         size_t word_count, /**< number of words */
   455                        )
   516         ec_pdo_type_t pdo_type /**< PDO type */
   456 {
   517         )
   457     ec_sii_pdo_t *pdo;
   518 {
   458     ec_sii_pdo_entry_t *entry;
   519     ec_pdo_t *pdo;
       
   520     ec_pdo_entry_t *entry;
   459     unsigned int entry_count, i;
   521     unsigned int entry_count, i;
   460 
   522 
   461     while (word_count >= 4) {
   523     while (word_count >= 4) {
   462         if (!(pdo = (ec_sii_pdo_t *)
   524         if (!(pdo = kmalloc(sizeof(ec_pdo_t), GFP_KERNEL))) {
   463               kmalloc(sizeof(ec_sii_pdo_t), GFP_ATOMIC))) {
       
   464             EC_ERR("Failed to allocate PDO memory.\n");
   525             EC_ERR("Failed to allocate PDO memory.\n");
   465             return -1;
   526             return -1;
   466         }
   527         }
   467 
   528 
   468         INIT_LIST_HEAD(&pdo->entries);
   529         ec_pdo_init(pdo);
   469         pdo->type = pdo_type;
   530         pdo->type = pdo_type;
   470 
       
   471         pdo->index = EC_READ_U16(data);
   531         pdo->index = EC_READ_U16(data);
   472         entry_count = EC_READ_U8(data + 2);
   532         entry_count = EC_READ_U8(data + 2);
   473         pdo->sync_index = EC_READ_U8(data + 3);
   533         pdo->sync_index = EC_READ_U8(data + 3);
   474         pdo->name = NULL;
   534         pdo->name = ec_slave_sii_string(slave, EC_READ_U8(data + 5));
   475         ec_slave_locate_string(slave, EC_READ_U8(data + 5), &pdo->name);
       
   476 
       
   477         list_add_tail(&pdo->list, &slave->sii_pdos);
   535         list_add_tail(&pdo->list, &slave->sii_pdos);
   478 
   536 
   479         word_count -= 4;
   537         word_count -= 4;
   480         data += 8;
   538         data += 8;
   481 
   539 
   482         for (i = 0; i < entry_count; i++) {
   540         for (i = 0; i < entry_count; i++) {
   483             if (!(entry = (ec_sii_pdo_entry_t *)
   541             if (!(entry = kmalloc(sizeof(ec_pdo_entry_t), GFP_KERNEL))) {
   484                   kmalloc(sizeof(ec_sii_pdo_entry_t), GFP_ATOMIC))) {
       
   485                 EC_ERR("Failed to allocate PDO entry memory.\n");
   542                 EC_ERR("Failed to allocate PDO entry memory.\n");
   486                 return -1;
   543                 return -1;
   487             }
   544             }
   488 
   545 
   489             entry->index = EC_READ_U16(data);
   546             entry->index = EC_READ_U16(data);
   490             entry->subindex = EC_READ_U8(data + 2);
   547             entry->subindex = EC_READ_U8(data + 2);
   491             entry->name = NULL;
   548             entry->name = ec_slave_sii_string(slave, EC_READ_U8(data + 3));
   492             ec_slave_locate_string(slave, EC_READ_U8(data + 3), &entry->name);
       
   493             entry->bit_length = EC_READ_U8(data + 5);
   549             entry->bit_length = EC_READ_U8(data + 5);
   494 
       
   495             list_add_tail(&entry->list, &pdo->entries);
   550             list_add_tail(&entry->list, &pdo->entries);
   496 
   551 
   497             word_count -= 4;
   552             word_count -= 4;
   498             data += 8;
   553             data += 8;
       
   554         }
       
   555 
       
   556         // if sync manager index is positive, the PDO is mapped by default
       
   557         if (pdo->sync_index >= 0) {
       
   558             ec_pdo_t *mapped_pdo;
       
   559 
       
   560             if (pdo->sync_index >= slave->sii_sync_count) {
       
   561                 EC_ERR("Invalid SM index %i for PDO 0x%04X in slave %u.",
       
   562                         pdo->sync_index, pdo->index, slave->ring_position);
       
   563                 return -1;
       
   564             }
       
   565 
       
   566             if (!(mapped_pdo = kmalloc(sizeof(ec_pdo_t), GFP_KERNEL))) {
       
   567                 EC_ERR("Failed to allocate PDO memory.\n");
       
   568                 return -1;
       
   569             }
       
   570 
       
   571             if (ec_pdo_copy(mapped_pdo, pdo)) {
       
   572                 EC_ERR("Failed to copy PDO.\n");
       
   573                 kfree(mapped_pdo);
       
   574                 return -1;
       
   575             }
       
   576 
       
   577             list_add_tail(&mapped_pdo->list,
       
   578                     &slave->sii_syncs[pdo->sync_index].pdos);
   499         }
   579         }
   500     }
   580     }
   501 
   581 
   502     return 0;
   582     return 0;
   503 }
   583 }
   508    Searches the string list for an index and allocates a new string.
   588    Searches the string list for an index and allocates a new string.
   509    \return 0 in case of success, else < 0
   589    \return 0 in case of success, else < 0
   510    \todo documentation
   590    \todo documentation
   511 */
   591 */
   512 
   592 
   513 int ec_slave_locate_string(ec_slave_t *slave, /**< EtherCAT slave */
   593 char *ec_slave_sii_string(
   514                            unsigned int index, /**< string index */
   594         ec_slave_t *slave, /**< EtherCAT slave */
   515                            char **ptr /**< Address of the string pointer */
   595         unsigned int index /**< string index */
   516                            )
   596         )
   517 {
   597 {
   518     ec_sii_string_t *string;
   598     if (!index--) 
   519     char *err_string;
   599         return NULL;
   520 
   600 
   521     // Erst alten Speicher freigeben
   601     if (index >= slave->sii_string_count) {
   522     if (*ptr) {
   602         if (slave->master->debug_level)
   523         kfree(*ptr);
   603             EC_WARN("String %i not found in slave %i.\n",
   524         *ptr = NULL;
   604                     index, slave->ring_position);
   525     }
   605         return NULL;
   526 
   606     }
   527     // Index 0 bedeutet "nicht belegt"
   607 
   528     if (!index) return 0;
   608     return slave->sii_strings[index];
   529 
   609 }
   530     // EEPROM-String mit Index finden und kopieren
   610 
   531     list_for_each_entry(string, &slave->sii_strings, list) {
   611 /*****************************************************************************/
   532         if (--index) continue;
   612 
   533 
   613 /**
   534         if (!(*ptr = (char *) kmalloc(string->size + 1, GFP_ATOMIC))) {
   614  * Prepares an FMMU configuration.
   535             EC_ERR("Unable to allocate string memory.\n");
   615  * Configuration data for the FMMU is saved in the slave structure and is
   536             return -1;
   616  * written to the slave in ecrt_master_activate().
   537         }
   617  * The FMMU configuration is done in a way, that the complete data range
   538         memcpy(*ptr, string->data, string->size + 1);
   618  * of the corresponding sync manager is covered. Seperate FMMUs are configured
   539         return 0;
   619  * for each domain.
   540     }
   620  * If the FMMU configuration is already prepared, the function returns with
   541 
   621  * success.
   542     if (slave->master->debug_level)
   622  * \return 0 in case of success, else < 0
   543         EC_WARN("String %i not found in slave %i.\n",
   623  */
   544                 index, slave->ring_position);
   624 
   545 
   625 int ec_slave_prepare_fmmu(
   546     err_string = "(string not found)";
   626         ec_slave_t *slave, /**< EtherCAT slave */
   547 
   627         const ec_domain_t *domain, /**< domain */
   548     if (!(*ptr = (char *) kmalloc(strlen(err_string) + 1, GFP_ATOMIC))) {
   628         const ec_sync_t *sync  /**< sync manager */
   549         EC_WARN("Unable to allocate string memory.\n");
   629         )
   550         return -1;
       
   551     }
       
   552 
       
   553     memcpy(*ptr, err_string, strlen(err_string) + 1);
       
   554     return 0;
       
   555 }
       
   556 
       
   557 /*****************************************************************************/
       
   558 
       
   559 /**
       
   560    Prepares an FMMU configuration.
       
   561    Configuration data for the FMMU is saved in the slave structure and is
       
   562    written to the slave in ecrt_master_activate().
       
   563    The FMMU configuration is done in a way, that the complete data range
       
   564    of the corresponding sync manager is covered. Seperate FMMUs are configured
       
   565    for each domain.
       
   566    If the FMMU configuration is already prepared, the function returns with
       
   567    success.
       
   568    \return 0 in case of success, else < 0
       
   569 */
       
   570 
       
   571 int ec_slave_prepare_fmmu(ec_slave_t *slave, /**< EtherCAT slave */
       
   572                           const ec_domain_t *domain, /**< domain */
       
   573                           const ec_sii_sync_t *sync  /**< sync manager */
       
   574                           )
       
   575 {
   630 {
   576     unsigned int i;
   631     unsigned int i;
   577     ec_fmmu_t *fmmu;
   632     ec_fmmu_t *fmmu;
   578 
   633 
   579     // FMMU configuration already prepared?
   634     // FMMU configuration already prepared?
   590         return -1;
   645         return -1;
   591     }
   646     }
   592 
   647 
   593     fmmu = &slave->fmmus[slave->fmmu_count];
   648     fmmu = &slave->fmmus[slave->fmmu_count];
   594 
   649 
   595     fmmu->index = slave->fmmu_count;
   650     ec_fmmu_init(fmmu, slave, slave->fmmu_count++);
   596     fmmu->domain = domain;
   651     fmmu->domain = domain;
   597     fmmu->sync = sync;
   652     fmmu->sync = sync;
   598     fmmu->logical_start_address = 0;
   653     fmmu->logical_start_address = 0;
   599 
   654 
   600     slave->fmmu_count++;
   655     slave->pdos_registered = 1;
       
   656     
       
   657     ec_slave_request_state(slave, EC_SLAVE_STATE_OP);
   601 
   658 
   602     return 0;
   659     return 0;
   603 }
   660 }
   604 
   661 
   605 /*****************************************************************************/
   662 /*****************************************************************************/
   611 size_t ec_slave_info(const ec_slave_t *slave, /**< EtherCAT slave */
   668 size_t ec_slave_info(const ec_slave_t *slave, /**< EtherCAT slave */
   612                      char *buffer /**< Output buffer */
   669                      char *buffer /**< Output buffer */
   613                      )
   670                      )
   614 {
   671 {
   615     off_t off = 0;
   672     off_t off = 0;
   616     ec_sii_sync_t *sync;
   673     ec_sync_t *sync;
   617     ec_sii_pdo_t *pdo;
   674     ec_pdo_t *pdo;
   618     ec_sii_pdo_entry_t *pdo_entry;
   675     ec_pdo_entry_t *pdo_entry;
   619     int first, i;
   676     int first, i;
   620     ec_sdo_data_t *sdodata;
   677     ec_sdo_data_t *sdodata;
   621     char str[20];
   678     char str[20];
   622 
   679 
   623     off += sprintf(buffer + off, "\nName: ");
   680     off += sprintf(buffer + off, "\nName: ");
   633     off += sprintf(buffer + off, "State: ");
   690     off += sprintf(buffer + off, "State: ");
   634     off += ec_state_string(slave->current_state, buffer + off);
   691     off += ec_state_string(slave->current_state, buffer + off);
   635     off += sprintf(buffer + off, " (");
   692     off += sprintf(buffer + off, " (");
   636     off += ec_state_string(slave->requested_state, buffer + off);
   693     off += ec_state_string(slave->requested_state, buffer + off);
   637     off += sprintf(buffer + off, ")\nFlags: %s, %s\n",
   694     off += sprintf(buffer + off, ")\nFlags: %s, %s\n",
   638                    slave->online ? "online" : "OFFLINE",
   695             slave->online_state == EC_SLAVE_ONLINE ? "online" : "OFFLINE",
   639                    slave->error_flag ? "ERROR" : "ok");
   696             slave->error_flag ? "ERROR" : "ok");
   640     off += sprintf(buffer + off, "Ring position: %i\n",
   697     off += sprintf(buffer + off, "Ring position: %i\n",
   641                    slave->ring_position);
   698                    slave->ring_position);
   642     off += sprintf(buffer + off, "Advanced position: %i:%i\n",
       
   643                    slave->coupler_index, slave->coupler_subindex);
       
   644     off += sprintf(buffer + off, "Coupler: %s\n",
       
   645                    ec_slave_is_coupler(slave) ? "yes" : "no");
       
   646     off += sprintf(buffer + off, "Current consumption: %i mA\n\n",
   699     off += sprintf(buffer + off, "Current consumption: %i mA\n\n",
   647                    slave->sii_current_on_ebus);
   700                    slave->sii_current_on_ebus);
   648 
   701 
   649     off += sprintf(buffer + off, "Data link status:\n");
   702     off += sprintf(buffer + off, "Data link status:\n");
   650     for (i = 0; i < 4; i++) {
   703     for (i = 0; i < 4; i++) {
   723     if (slave->sii_image)
   776     if (slave->sii_image)
   724         off += sprintf(buffer + off, "  Image: %s\n", slave->sii_image);
   777         off += sprintf(buffer + off, "  Image: %s\n", slave->sii_image);
   725     if (slave->sii_order)
   778     if (slave->sii_order)
   726         off += sprintf(buffer + off, "  Order number: %s\n", slave->sii_order);
   779         off += sprintf(buffer + off, "  Order number: %s\n", slave->sii_order);
   727 
   780 
   728     if (!list_empty(&slave->sii_syncs))
   781     if (slave->sii_sync_count)
   729         off += sprintf(buffer + off, "\nSync-Managers:\n");
   782         off += sprintf(buffer + off, "\nSync managers / PDO mapping:\n");
   730 
   783 
   731     list_for_each_entry(sync, &slave->sii_syncs, list) {
   784     for (i = 0; i < slave->sii_sync_count; i++) {
   732         off += sprintf(buffer + off, "  %i: 0x%04X, length %i,"
   785         sync = &slave->sii_syncs[i];
   733                        " control 0x%02X, %s\n",
   786         off += sprintf(buffer + off,
   734                        sync->index, sync->physical_start_address,
   787                 "  SM%u: addr 0x%04X, size %i, control 0x%02X, %s\n",
   735                        sync->length, sync->control_register,
   788                 sync->index, sync->physical_start_address,
   736                        sync->enable ? "enable" : "disable");
   789                 ec_sync_size(sync), sync->control_register,
       
   790                 sync->enable ? "enable" : "disable");
       
   791 
       
   792         if (list_empty(&sync->pdos))
       
   793             off += sprintf(buffer + off, "    No PDOs mapped.\n");
       
   794 
       
   795         list_for_each_entry(pdo, &sync->pdos, list) {
       
   796             off += sprintf(buffer + off, "    %s 0x%04X \"%s\"\n",
       
   797                     pdo->type == EC_RX_PDO ? "RXPDO" : "TXPDO",
       
   798                     pdo->index, pdo->name ? pdo->name : "???");
       
   799 
       
   800             list_for_each_entry(pdo_entry, &pdo->entries, list) {
       
   801                 off += sprintf(buffer + off,
       
   802                         "      0x%04X:%X \"%s\", %i bit\n",
       
   803                         pdo_entry->index, pdo_entry->subindex,
       
   804                         pdo_entry->name ? pdo_entry->name : "???",
       
   805                         pdo_entry->bit_length);
       
   806             }
       
   807         }
   737     }
   808     }
   738 
   809 
   739     if (!list_empty(&slave->sii_pdos))
   810     if (!list_empty(&slave->sii_pdos))
   740         off += sprintf(buffer + off, "\nPDOs:\n");
   811         off += sprintf(buffer + off, "\nAvailable PDOs:\n");
   741 
   812 
   742     list_for_each_entry(pdo, &slave->sii_pdos, list) {
   813     list_for_each_entry(pdo, &slave->sii_pdos, list) {
   743         off += sprintf(buffer + off,
   814         off += sprintf(buffer + off, "  %s 0x%04X \"%s\"",
   744                        "  %s \"%s\" (0x%04X), Sync-Manager %i\n",
       
   745                        pdo->type == EC_RX_PDO ? "RXPDO" : "TXPDO",
   815                        pdo->type == EC_RX_PDO ? "RXPDO" : "TXPDO",
   746                        pdo->name ? pdo->name : "???",
   816                        pdo->index, pdo->name ? pdo->name : "???");
   747                        pdo->index, pdo->sync_index);
   817         if (pdo->sync_index >= 0)
       
   818             off += sprintf(buffer + off, ", default mapping: SM%u.\n",
       
   819                     pdo->sync_index);
       
   820         else
       
   821             off += sprintf(buffer + off, ", no default mapping.\n");
   748 
   822 
   749         list_for_each_entry(pdo_entry, &pdo->entries, list) {
   823         list_for_each_entry(pdo_entry, &pdo->entries, list) {
   750             off += sprintf(buffer + off, "    \"%s\" 0x%04X:%X, %i bit\n",
   824             off += sprintf(buffer + off, "    0x%04X:%X \"%s\", %i bit\n",
       
   825                            pdo_entry->index, pdo_entry->subindex,
   751                            pdo_entry->name ? pdo_entry->name : "???",
   826                            pdo_entry->name ? pdo_entry->name : "???",
   752                            pdo_entry->index, pdo_entry->subindex,
       
   753                            pdo_entry->bit_length);
   827                            pdo_entry->bit_length);
   754         }
   828         }
   755     }
   829     }
   756 
   830 
   757     if (!list_empty(&slave->sdo_confs))
   831     if (!list_empty(&slave->sdo_confs))
   774 }
   848 }
   775 
   849 
   776 /*****************************************************************************/
   850 /*****************************************************************************/
   777 
   851 
   778 /**
   852 /**
   779    Schedules an EEPROM write operation.
   853  * Schedules an EEPROM write request.
   780    \return 0 in case of success, else < 0
   854  * \return 0 case of success, otherwise error code.
   781 */
   855  */
       
   856 
       
   857 int ec_slave_schedule_eeprom_writing(ec_eeprom_write_request_t *request)
       
   858 {
       
   859     ec_master_t *master = request->slave->master;
       
   860 
       
   861     request->state = EC_REQUEST_QUEUED;
       
   862 
       
   863     // schedule EEPROM write request.
       
   864     down(&master->eeprom_sem);
       
   865     list_add_tail(&request->list, &master->eeprom_requests);
       
   866     up(&master->eeprom_sem);
       
   867 
       
   868     // wait for processing through FSM
       
   869     if (wait_event_interruptible(master->eeprom_queue,
       
   870                 request->state != EC_REQUEST_QUEUED)) {
       
   871         // interrupted by signal
       
   872         down(&master->eeprom_sem);
       
   873         if (request->state == EC_REQUEST_QUEUED) {
       
   874             list_del(&request->list);
       
   875             up(&master->eeprom_sem);
       
   876             return -EINTR;
       
   877         }
       
   878         // request already processing: interrupt not possible.
       
   879         up(&master->eeprom_sem);
       
   880     }
       
   881 
       
   882     // wait until master FSM has finished processing
       
   883     wait_event(master->eeprom_queue,
       
   884             request->state != EC_REQUEST_IN_PROGRESS);
       
   885 
       
   886     return request->state == EC_REQUEST_COMPLETE ? 0 : -EIO;
       
   887 }
       
   888 
       
   889 /*****************************************************************************/
       
   890 
       
   891 /**
       
   892  * Writes complete EEPROM contents to a slave.
       
   893  * \return data size written in case of success, otherwise error code.
       
   894  */
   782 
   895 
   783 ssize_t ec_slave_write_eeprom(ec_slave_t *slave, /**< EtherCAT slave */
   896 ssize_t ec_slave_write_eeprom(ec_slave_t *slave, /**< EtherCAT slave */
   784                               const uint8_t *data, /**< new EEPROM data */
   897         const uint8_t *data, /**< new EEPROM data */
   785                               size_t size /**< size of data in bytes */
   898         size_t size /**< size of data in bytes */
   786                               )
   899         )
   787 {
   900 {
   788     uint16_t word_size, cat_type, cat_size;
   901     ec_eeprom_write_request_t request;
   789     const uint16_t *data_words, *next_header;
   902     const uint16_t *cat_header;
   790     uint16_t *new_data;
   903     uint16_t cat_type, cat_size;
   791 
   904     int ret;
   792     if (!slave->master->eeprom_write_enable) {
   905 
   793         EC_ERR("Writing EEPROMs not allowed! Enable via"
   906     if (slave->master->mode != EC_MASTER_MODE_IDLE) { // FIXME
   794                " eeprom_write_enable SysFS entry.\n");
       
   795         return -1;
       
   796     }
       
   797 
       
   798     if (slave->master->mode != EC_MASTER_MODE_IDLE) {
       
   799         EC_ERR("Writing EEPROMs only allowed in idle mode!\n");
   907         EC_ERR("Writing EEPROMs only allowed in idle mode!\n");
   800         return -1;
   908         return -EBUSY;
   801     }
   909     }
   802 
       
   803     if (slave->new_eeprom_data) {
       
   804         EC_ERR("Slave %i already has a pending EEPROM write operation!\n",
       
   805                slave->ring_position);
       
   806         return -1;
       
   807     }
       
   808 
       
   809     // coarse check of the data
       
   810 
   910 
   811     if (size % 2) {
   911     if (size % 2) {
   812         EC_ERR("EEPROM size is odd! Dropping.\n");
   912         EC_ERR("EEPROM data size is odd! Dropping.\n");
   813         return -1;
   913         return -EINVAL;
   814     }
   914     }
   815 
   915 
   816     data_words = (const uint16_t *) data;
   916     // init EEPROM write request
   817     word_size = size / 2;
   917     INIT_LIST_HEAD(&request.list);
   818 
   918     request.slave = slave;
   819     if (word_size < 0x0041) {
   919     request.words = (const uint16_t *) data;
       
   920     request.offset = 0;
       
   921     request.size = size / 2;
       
   922 
       
   923     if (request.size < 0x0041) {
   820         EC_ERR("EEPROM data too short! Dropping.\n");
   924         EC_ERR("EEPROM data too short! Dropping.\n");
   821         return -1;
   925         return -EINVAL;
   822     }
   926     }
   823 
   927 
   824     next_header = data_words + 0x0040;
   928     cat_header = request.words + EC_FIRST_EEPROM_CATEGORY_OFFSET;
   825     cat_type = EC_READ_U16(next_header);
   929     cat_type = EC_READ_U16(cat_header);
   826     while (cat_type != 0xFFFF) {
   930     while (cat_type != 0xFFFF) { // cycle through categories
   827         cat_type = EC_READ_U16(next_header);
   931         if (cat_header + 1 > request.words + request.size) {
   828         cat_size = EC_READ_U16(next_header + 1);
   932             EC_ERR("EEPROM data corrupted! Dropping.\n");
   829         if ((next_header + cat_size + 2) - data_words >= word_size) {
   933             return -EINVAL;
   830             EC_ERR("EEPROM data seems to be corrupted! Dropping.\n");
   934         }
   831             return -1;
   935         cat_size = EC_READ_U16(cat_header + 1);
   832         }
   936         if (cat_header + cat_size + 2 > request.words + request.size) {
   833         next_header += cat_size + 2;
   937             EC_ERR("EEPROM data corrupted! Dropping.\n");
   834         cat_type = EC_READ_U16(next_header);
   938             return -EINVAL;
   835     }
   939         }
   836 
   940         cat_header += cat_size + 2;
   837     // data ok!
   941         cat_type = EC_READ_U16(cat_header);
   838 
   942     }
   839     if (!(new_data = (uint16_t *) kmalloc(word_size * 2, GFP_KERNEL))) {
   943 
   840         EC_ERR("Unable to allocate memory for new EEPROM data!\n");
   944     // EEPROM data ok. schedule writing.
   841         return -1;
   945     if ((ret = ec_slave_schedule_eeprom_writing(&request)))
   842     }
   946         return ret; // error code
   843     memcpy(new_data, data, size);
   947 
   844 
   948     return size; // success
   845     slave->new_eeprom_size = word_size;
   949 }
   846     slave->new_eeprom_data = new_data;
   950 
   847 
   951 /*****************************************************************************/
   848     EC_INFO("EEPROM writing scheduled for slave %i, %i words.\n",
   952 
   849             slave->ring_position, word_size);
   953 /**
   850     return 0;
   954  * Writes the Secondary slave address (alias) to the slave's EEPROM.
   851 }
   955  * \return data size written in case of success, otherwise error code.
       
   956  */
       
   957 
       
   958 ssize_t ec_slave_write_alias(ec_slave_t *slave, /**< EtherCAT slave */
       
   959         const uint8_t *data, /**< alias string */
       
   960         size_t size /**< size of data in bytes */
       
   961         )
       
   962 {
       
   963     ec_eeprom_write_request_t request;
       
   964     char *remainder;
       
   965     uint16_t alias, word;
       
   966     int ret;
       
   967 
       
   968     if (slave->master->mode != EC_MASTER_MODE_IDLE) { // FIXME
       
   969         EC_ERR("Writing EEPROMs only allowed in idle mode!\n");
       
   970         return -EBUSY;
       
   971     }
       
   972 
       
   973     alias = simple_strtoul(data, &remainder, 0);
       
   974     if (remainder == (char *) data || (*remainder && *remainder != '\n')) {
       
   975         EC_ERR("Invalid alias value! Dropping.\n");
       
   976         return -EINVAL;
       
   977     }
       
   978     
       
   979     // correct endianess
       
   980     EC_WRITE_U16(&word, alias);
       
   981 
       
   982     // init EEPROM write request
       
   983     INIT_LIST_HEAD(&request.list);
       
   984     request.slave = slave;
       
   985     request.words = &word;
       
   986     request.offset = 0x0004;
       
   987     request.size = 1;
       
   988 
       
   989     if ((ret = ec_slave_schedule_eeprom_writing(&request)))
       
   990         return ret; // error code
       
   991 
       
   992     slave->sii_alias = alias; // FIXME: do this in state machine
       
   993 
       
   994     return size; // success
       
   995 }
       
   996 
   852 
   997 
   853 /*****************************************************************************/
   998 /*****************************************************************************/
   854 
   999 
   855 /**
  1000 /**
   856    Formats attribute data for SysFS read access.
  1001    Formats attribute data for SysFS read access.
   891             else {
  1036             else {
   892                 memcpy(buffer, slave->eeprom_data, slave->eeprom_size);
  1037                 memcpy(buffer, slave->eeprom_data, slave->eeprom_size);
   893                 return slave->eeprom_size;
  1038                 return slave->eeprom_size;
   894             }
  1039             }
   895         }
  1040         }
       
  1041     }
       
  1042     else if (attr == &attr_alias) {
       
  1043         return sprintf(buffer, "%u\n", slave->sii_alias);
   896     }
  1044     }
   897 
  1045 
   898     return 0;
  1046     return 0;
   899 }
  1047 }
   900 
  1048 
   932         EC_INFO("Accepted new state %s for slave %i.\n",
  1080         EC_INFO("Accepted new state %s for slave %i.\n",
   933                 state, slave->ring_position);
  1081                 state, slave->ring_position);
   934         return size;
  1082         return size;
   935     }
  1083     }
   936     else if (attr == &attr_eeprom) {
  1084     else if (attr == &attr_eeprom) {
   937         if (!ec_slave_write_eeprom(slave, buffer, size))
  1085         return ec_slave_write_eeprom(slave, buffer, size);
   938             return size;
  1086     }
   939     }
  1087     else if (attr == &attr_alias) {
   940 
  1088         return ec_slave_write_alias(slave, buffer, size);
   941     return -EINVAL;
  1089     }
   942 }
  1090 
   943 
  1091     return -EIO;
   944 /*****************************************************************************/
  1092 }
   945 
  1093 
   946 /**
  1094 /*****************************************************************************/
   947    Calculates the size of a sync manager by evaluating PDO sizes.
  1095 
   948    \return sync manager size
  1096 /**
   949 */
  1097  */
   950 
  1098 
   951 uint16_t ec_slave_calc_sync_size(const ec_slave_t *slave,
  1099 ec_sync_t *ec_slave_get_pdo_sync(
   952                                  /**< EtherCAT slave */
  1100         ec_slave_t *slave, /**< EtherCAT slave */
   953                                  const ec_sii_sync_t *sync
  1101         ec_direction_t dir /**< input or output */
   954                                  /**< sync manager */
       
   955                                  )
       
   956 {
       
   957     ec_sii_pdo_t *pdo;
       
   958     ec_sii_pdo_entry_t *pdo_entry;
       
   959     unsigned int bit_size, byte_size;
       
   960 
       
   961     if (sync->length) return sync->length;
       
   962     if (sync->est_length) return sync->est_length;
       
   963 
       
   964     bit_size = 0;
       
   965     list_for_each_entry(pdo, &slave->sii_pdos, list) {
       
   966         if (pdo->sync_index != sync->index) continue;
       
   967 
       
   968         list_for_each_entry(pdo_entry, &pdo->entries, list) {
       
   969             bit_size += pdo_entry->bit_length;
       
   970         }
       
   971     }
       
   972 
       
   973     if (bit_size % 8) // round up to full bytes
       
   974         byte_size = bit_size / 8 + 1;
       
   975     else
       
   976         byte_size = bit_size / 8;
       
   977 
       
   978     return byte_size;
       
   979 }
       
   980 
       
   981 /*****************************************************************************/
       
   982 
       
   983 /**
       
   984    Initializes a sync manager configuration page with EEPROM data.
       
   985    The referenced memory (\a data) must be at least EC_SYNC_SIZE bytes.
       
   986 */
       
   987 
       
   988 void ec_slave_sync_config(const ec_slave_t *slave, /**< EtherCAT slave */
       
   989         const ec_sii_sync_t *sync, /**< sync manager */
       
   990         uint8_t *data /**> configuration memory */
       
   991         )
  1102         )
   992 {
  1103 {
   993     size_t sync_size;
  1104     unsigned int sync_index;
   994 
  1105 
   995     sync_size = ec_slave_calc_sync_size(slave, sync);
  1106     if (dir != EC_DIR_INPUT && dir != EC_DIR_OUTPUT) {
   996 
  1107         EC_ERR("Invalid direction!\n");
   997     if (slave->master->debug_level) {
  1108         return NULL;
   998         EC_DBG("Slave %3i, SM %i: Addr 0x%04X, Size %3i, Ctrl 0x%02X, En %i\n",
  1109     }
   999                slave->ring_position, sync->index, sync->physical_start_address,
  1110 
  1000                sync_size, sync->control_register, sync->enable);
  1111     sync_index = (unsigned int) dir;
  1001     }
  1112     if (slave->sii_mailbox_protocols) sync_index += 2;
  1002 
  1113 
  1003     EC_WRITE_U16(data,     sync->physical_start_address);
  1114     if (sync_index >= slave->sii_sync_count)
  1004     EC_WRITE_U16(data + 2, sync_size);
  1115         return NULL;
  1005     EC_WRITE_U8 (data + 4, sync->control_register);
  1116 
  1006     EC_WRITE_U8 (data + 5, 0x00); // status byte (read only)
  1117     return &slave->sii_syncs[sync_index];
  1007     EC_WRITE_U16(data + 6, sync->enable ? 0x0001 : 0x0000); // enable
       
  1008 }
       
  1009 
       
  1010 /*****************************************************************************/
       
  1011 
       
  1012 /**
       
  1013    Initializes an FMMU configuration page.
       
  1014    The referenced memory (\a data) must be at least EC_FMMU_SIZE bytes.
       
  1015 */
       
  1016 
       
  1017 void ec_slave_fmmu_config(const ec_slave_t *slave, /**< EtherCAT slave */
       
  1018         const ec_fmmu_t *fmmu, /**< FMMU */
       
  1019         uint8_t *data /**> configuration memory */
       
  1020         )
       
  1021 {
       
  1022     size_t sync_size;
       
  1023 
       
  1024     sync_size = ec_slave_calc_sync_size(slave, fmmu->sync);
       
  1025 
       
  1026     if (slave->master->debug_level) {
       
  1027         EC_DBG("Slave %3i, FMMU %2i:"
       
  1028                " LogAddr 0x%08X, Size %3i, PhysAddr 0x%04X, Dir %s\n",
       
  1029                slave->ring_position, fmmu->index, fmmu->logical_start_address,
       
  1030                sync_size, fmmu->sync->physical_start_address,
       
  1031                ((fmmu->sync->control_register & 0x04) ? "out" : "in"));
       
  1032     }
       
  1033 
       
  1034     EC_WRITE_U32(data,      fmmu->logical_start_address);
       
  1035     EC_WRITE_U16(data + 4,  sync_size); // size of fmmu
       
  1036     EC_WRITE_U8 (data + 6,  0x00); // logical start bit
       
  1037     EC_WRITE_U8 (data + 7,  0x07); // logical end bit
       
  1038     EC_WRITE_U16(data + 8,  fmmu->sync->physical_start_address);
       
  1039     EC_WRITE_U8 (data + 10, 0x00); // physical start bit
       
  1040     EC_WRITE_U8 (data + 11, ((fmmu->sync->control_register & 0x04)
       
  1041                              ? 0x02 : 0x01));
       
  1042     EC_WRITE_U16(data + 12, 0x0001); // enable
       
  1043     EC_WRITE_U16(data + 14, 0x0000); // reserved
       
  1044 }
       
  1045 
       
  1046 /*****************************************************************************/
       
  1047 
       
  1048 /**
       
  1049    \return non-zero if slave is a bus coupler
       
  1050 */
       
  1051 
       
  1052 int ec_slave_is_coupler(const ec_slave_t *slave /**< EtherCAT slave */)
       
  1053 {
       
  1054     // TODO: Better bus coupler criterion
       
  1055     return slave->sii_vendor_id == 0x00000002
       
  1056         && slave->sii_product_code == 0x044C2C52;
       
  1057 }
       
  1058 
       
  1059 /*****************************************************************************/
       
  1060 
       
  1061 /**
       
  1062    \return non-zero if slave is a bus coupler
       
  1063 */
       
  1064 
       
  1065 int ec_slave_has_subbus(const ec_slave_t *slave /**< EtherCAT slave */)
       
  1066 {
       
  1067     return slave->sii_vendor_id == 0x00000002
       
  1068         && slave->sii_product_code == 0x04602c22;
       
  1069 }
  1118 }
  1070 
  1119 
  1071 /*****************************************************************************/
  1120 /*****************************************************************************/
  1072 
  1121 
  1073 /**
  1122 /**
  1120                       uint32_t product_code /**< product code */
  1169                       uint32_t product_code /**< product code */
  1121                       )
  1170                       )
  1122 {
  1171 {
  1123     if (vendor_id != slave->sii_vendor_id ||
  1172     if (vendor_id != slave->sii_vendor_id ||
  1124         product_code != slave->sii_product_code) {
  1173         product_code != slave->sii_product_code) {
  1125         EC_ERR("Invalid slave type at position %i - Requested: 0x%08X 0x%08X,"
  1174         EC_ERR("Invalid slave type at position %i:\n", slave->ring_position);
  1126                " found: 0x%08X 0x%08X\".\n", slave->ring_position, vendor_id,
  1175         EC_ERR("  Requested: 0x%08X 0x%08X\n", vendor_id, product_code);
  1127                product_code, slave->sii_vendor_id, slave->sii_product_code);
  1176         EC_ERR("      Found: 0x%08X 0x%08X\n",
       
  1177                 slave->sii_vendor_id, slave->sii_product_code);
  1128         return -1;
  1178         return -1;
  1129     }
  1179     }
  1130     return 0;
  1180     return 0;
  1131 }
  1181 }
  1132 
  1182 
  1213     return ec_slave_conf_sdo(slave, sdo_index, sdo_subindex, data, 4);
  1263     return ec_slave_conf_sdo(slave, sdo_index, sdo_subindex, data, 4);
  1214 }
  1264 }
  1215 
  1265 
  1216 /*****************************************************************************/
  1266 /*****************************************************************************/
  1217 
  1267 
  1218 /**
  1268 void ecrt_slave_pdo_mapping_clear(
  1219    \return 0 in case of success, else < 0
  1269         ec_slave_t *slave, /**< EtherCAT slave */
  1220    \ingroup RealtimeInterface
  1270         ec_direction_t dir /**< output/input */
  1221 */
  1271         )
  1222 
  1272 {
  1223 int ecrt_slave_pdo_size(ec_slave_t *slave, /**< EtherCAT slave */
  1273     ec_sync_t *sync;
  1224                         uint16_t pdo_index, /**< PDO index */
  1274 
  1225                         uint8_t pdo_subindex, /**< PDO subindex */
  1275     if (!(slave->sii_mailbox_protocols & EC_MBOX_COE)) {
  1226                         size_t size /**< new PDO size */
  1276         EC_ERR("Slave %i does not support CoE!\n", slave->ring_position);
  1227                         )
  1277         return;
  1228 {
  1278     }
  1229     EC_WARN("ecrt_slave_pdo_size() currently not available.\n");
  1279 
  1230     return -1;
  1280     if (!(sync = ec_slave_get_pdo_sync(slave, dir)))
  1231 
  1281         return;
  1232 #if 0
  1282 
  1233     unsigned int i, j, field_counter;
  1283     ec_sync_clear_pdos(sync);
  1234     const ec_sii_sync_t *sync;
  1284 }
  1235     const ec_pdo_t *pdo;
  1285 
  1236     ec_varsize_t *var;
  1286 /*****************************************************************************/
  1237 
  1287 
  1238     if (!slave->type) {
  1288 int ecrt_slave_pdo_mapping_add(
  1239         EC_ERR("Slave %i has no type information!\n", slave->ring_position);
  1289         ec_slave_t *slave, /**< EtherCAT slave */
       
  1290         ec_direction_t dir, /**< input/output */
       
  1291         uint16_t pdo_index /**< Index of PDO mapping list */)
       
  1292 {
       
  1293     ec_pdo_t *pdo;
       
  1294     ec_sync_t *sync;
       
  1295     unsigned int not_found = 1;
       
  1296 
       
  1297     if (!(slave->sii_mailbox_protocols & EC_MBOX_COE)) {
       
  1298         EC_ERR("Slave %u does not support CoE!\n", slave->ring_position);
  1240         return -1;
  1299         return -1;
  1241     }
  1300     }
  1242 
  1301 
  1243     field_counter = 0;
  1302     // does the slave provide the PDO list?
  1244     for (i = 0; (sync = slave->type->sync_managers[i]); i++) {
  1303     list_for_each_entry(pdo, &slave->sii_pdos, list) {
  1245         for (j = 0; (field = sync->fields[j]); j++) {
  1304         if (pdo->index == pdo_index) {
  1246             if (!strcmp(field->name, field_name)) {
  1305             not_found = 0;
  1247                 if (field_counter++ == field_index) {
  1306             break;
  1248                     // is the size of this field variable?
  1307         }
  1249                     if (field->size) {
  1308     }
  1250                         EC_ERR("Field \"%s\"[%i] of slave %i has no variable"
  1309 
  1251                                " size!\n", field->name, field_index,
  1310     if (not_found) {
  1252                                slave->ring_position);
  1311         EC_ERR("Slave %u does not provide PDO 0x%04X!\n",
  1253                         return -1;
  1312                 slave->ring_position, pdo_index);
  1254                     }
  1313         return -1;
  1255                     // does a size specification already exist?
  1314     }
  1256                     list_for_each_entry(var, &slave->varsize_fields, list) {
  1315 
  1257                         if (var->field == field) {
  1316     // check direction
  1258                             EC_WARN("Resizing field \"%s\"[%i] of slave %i.\n",
  1317     if ((pdo->type == EC_TX_PDO && dir == EC_DIR_OUTPUT) ||
  1259                                     field->name, field_index,
  1318             (pdo->type == EC_RX_PDO && dir == EC_DIR_INPUT)) {
  1260                                     slave->ring_position);
  1319         EC_ERR("Invalid direction for PDO 0x%04X.\n", pdo_index);
  1261                             var->size = size;
  1320         return -1;
  1262                             return 0;
  1321     }
  1263                         }
  1322 
  1264                     }
  1323 
  1265                     // create a new size specification...
  1324     if (!(sync = ec_slave_get_pdo_sync(slave, dir))) {
  1266                     if (!(var = kmalloc(sizeof(ec_varsize_t), GFP_KERNEL))) {
  1325         EC_ERR("Failed to obtain sync manager for PDO mapping of slave %u!\n",
  1267                         EC_ERR("Failed to allocate memory for varsize_t!\n");
  1326                 slave->ring_position);
  1268                         return -1;
  1327         return -1;
  1269                     }
  1328     }
  1270                     var->field = field;
  1329 
  1271                     var->size = size;
  1330     return ec_sync_add_pdo(sync, pdo);
  1272                     list_add_tail(&var->list, &slave->varsize_fields);
  1331 }
  1273                     return 0;
  1332 
  1274                 }
  1333 /*****************************************************************************/
  1275             }
  1334 
  1276         }
  1335 int ecrt_slave_pdo_mapping(ec_slave_t *slave, /**< EtherCAT slave */
  1277     }
  1336         ec_direction_t dir, /**< input/output */
  1278 
  1337         unsigned int num_args, /**< Number of following arguments */
  1279     EC_ERR("Slave %i (\"%s %s\") has no field \"%s\"[%i]!\n",
  1338         ... /**< PDO indices to map */
  1280            slave->ring_position, slave->type->vendor_name,
  1339         )
  1281            slave->type->product_name, field_name, field_index);
  1340 {
  1282     return -1;
  1341     va_list ap;
  1283 #endif
  1342 
  1284 }
  1343     ecrt_slave_pdo_mapping_clear(slave, dir);
       
  1344 
       
  1345     va_start(ap, num_args);
       
  1346 
       
  1347     for (; num_args; num_args--) {
       
  1348         if (ecrt_slave_pdo_mapping_add(
       
  1349                     slave, dir, (uint16_t) va_arg(ap, int))) {
       
  1350             return -1;
       
  1351         }
       
  1352     }
       
  1353 
       
  1354     va_end(ap);
       
  1355     return 0;
       
  1356 }
       
  1357 
  1285 
  1358 
  1286 /*****************************************************************************/
  1359 /*****************************************************************************/
  1287 
  1360 
  1288 /** \cond */
  1361 /** \cond */
  1289 
  1362 
  1290 EXPORT_SYMBOL(ecrt_slave_conf_sdo8);
  1363 EXPORT_SYMBOL(ecrt_slave_conf_sdo8);
  1291 EXPORT_SYMBOL(ecrt_slave_conf_sdo16);
  1364 EXPORT_SYMBOL(ecrt_slave_conf_sdo16);
  1292 EXPORT_SYMBOL(ecrt_slave_conf_sdo32);
  1365 EXPORT_SYMBOL(ecrt_slave_conf_sdo32);
  1293 EXPORT_SYMBOL(ecrt_slave_pdo_size);
  1366 EXPORT_SYMBOL(ecrt_slave_pdo_mapping_clear);
       
  1367 EXPORT_SYMBOL(ecrt_slave_pdo_mapping_add);
       
  1368 EXPORT_SYMBOL(ecrt_slave_pdo_mapping);
  1294 
  1369 
  1295 /** \endcond */
  1370 /** \endcond */
  1296 
  1371 
  1297 /*****************************************************************************/
  1372 /*****************************************************************************/