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