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