67 EC_SYSFS_READ_ATTR(product_name); |
67 EC_SYSFS_READ_ATTR(product_name); |
68 EC_SYSFS_READ_ATTR(product_desc); |
68 EC_SYSFS_READ_ATTR(product_desc); |
69 EC_SYSFS_READ_ATTR(sii_name); |
69 EC_SYSFS_READ_ATTR(sii_name); |
70 EC_SYSFS_READ_ATTR(type); |
70 EC_SYSFS_READ_ATTR(type); |
71 EC_SYSFS_READ_WRITE_ATTR(state); |
71 EC_SYSFS_READ_WRITE_ATTR(state); |
|
72 EC_SYSFS_READ_WRITE_ATTR(eeprom); |
72 |
73 |
73 static struct attribute *def_attrs[] = { |
74 static struct attribute *def_attrs[] = { |
74 &attr_ring_position, |
75 &attr_ring_position, |
75 &attr_coupler_address, |
76 &attr_coupler_address, |
76 &attr_vendor_name, |
77 &attr_vendor_name, |
77 &attr_product_name, |
78 &attr_product_name, |
78 &attr_product_desc, |
79 &attr_product_desc, |
79 &attr_sii_name, |
80 &attr_sii_name, |
80 &attr_type, |
81 &attr_type, |
81 &attr_state, |
82 &attr_state, |
|
83 &attr_eeprom, |
82 NULL, |
84 NULL, |
83 }; |
85 }; |
84 |
86 |
85 static struct sysfs_ops sysfs_ops = { |
87 static struct sysfs_ops sysfs_ops = { |
86 .show = ec_show_slave_attribute, |
88 .show = ec_show_slave_attribute, |
143 slave->sii_tx_mailbox_size = 0; |
145 slave->sii_tx_mailbox_size = 0; |
144 slave->sii_mailbox_protocols = 0; |
146 slave->sii_mailbox_protocols = 0; |
145 slave->type = NULL; |
147 slave->type = NULL; |
146 slave->registered = 0; |
148 slave->registered = 0; |
147 slave->fmmu_count = 0; |
149 slave->fmmu_count = 0; |
|
150 slave->eeprom_data = NULL; |
|
151 slave->eeprom_size = 0; |
148 slave->eeprom_group = NULL; |
152 slave->eeprom_group = NULL; |
149 slave->eeprom_image = NULL; |
153 slave->eeprom_image = NULL; |
150 slave->eeprom_order = NULL; |
154 slave->eeprom_order = NULL; |
151 slave->eeprom_name = NULL; |
155 slave->eeprom_name = NULL; |
152 slave->requested_state = EC_SLAVE_STATE_UNKNOWN; |
156 slave->requested_state = EC_SLAVE_STATE_UNKNOWN; |
153 slave->current_state = EC_SLAVE_STATE_UNKNOWN; |
157 slave->current_state = EC_SLAVE_STATE_UNKNOWN; |
154 slave->state_error = 0; |
158 slave->state_error = 0; |
155 slave->online = 1; |
159 slave->online = 1; |
156 |
160 slave->new_eeprom_data = NULL; |
157 ec_command_init(&slave->mbox_command); |
161 slave->new_eeprom_size = 0; |
158 |
162 |
159 INIT_LIST_HEAD(&slave->eeprom_strings); |
163 INIT_LIST_HEAD(&slave->eeprom_strings); |
160 INIT_LIST_HEAD(&slave->eeprom_syncs); |
164 INIT_LIST_HEAD(&slave->eeprom_syncs); |
161 INIT_LIST_HEAD(&slave->eeprom_pdos); |
165 INIT_LIST_HEAD(&slave->eeprom_pdos); |
162 INIT_LIST_HEAD(&slave->sdo_dictionary); |
166 INIT_LIST_HEAD(&slave->sdo_dictionary); |
|
167 INIT_LIST_HEAD(&slave->varsize_fields); |
163 |
168 |
164 for (i = 0; i < 4; i++) { |
169 for (i = 0; i < 4; i++) { |
165 slave->dl_link[i] = 0; |
170 slave->dl_link[i] = 0; |
166 slave->dl_loop[i] = 0; |
171 slave->dl_loop[i] = 0; |
167 slave->dl_signal[i] = 0; |
172 slave->dl_signal[i] = 0; |
184 ec_eeprom_sync_t *sync, *next_sync; |
189 ec_eeprom_sync_t *sync, *next_sync; |
185 ec_eeprom_pdo_t *pdo, *next_pdo; |
190 ec_eeprom_pdo_t *pdo, *next_pdo; |
186 ec_eeprom_pdo_entry_t *entry, *next_ent; |
191 ec_eeprom_pdo_entry_t *entry, *next_ent; |
187 ec_sdo_t *sdo, *next_sdo; |
192 ec_sdo_t *sdo, *next_sdo; |
188 ec_sdo_entry_t *en, *next_en; |
193 ec_sdo_entry_t *en, *next_en; |
|
194 ec_varsize_t *var, *next_var; |
189 |
195 |
190 slave = container_of(kobj, ec_slave_t, kobj); |
196 slave = container_of(kobj, ec_slave_t, kobj); |
191 |
197 |
192 // free all string objects |
198 // free all string objects |
193 list_for_each_entry_safe(string, next_str, &slave->eeprom_strings, list) { |
199 list_for_each_entry_safe(string, next_str, &slave->eeprom_strings, list) { |
1119 printk("\n"); |
1132 printk("\n"); |
1120 } |
1133 } |
1121 |
1134 |
1122 EC_INFO(" EEPROM data:\n"); |
1135 EC_INFO(" EEPROM data:\n"); |
1123 |
1136 |
|
1137 EC_INFO(" EEPROM content size: %i Bytes\n", slave->eeprom_size); |
|
1138 |
1124 if (slave->sii_alias) |
1139 if (slave->sii_alias) |
1125 EC_INFO(" Configured station alias: 0x%04X (%i)\n", |
1140 EC_INFO(" Configured station alias: 0x%04X (%i)\n", |
1126 slave->sii_alias, slave->sii_alias); |
1141 slave->sii_alias, slave->sii_alias); |
1127 |
1142 |
1128 EC_INFO(" Vendor-ID: 0x%08X, Product code: 0x%08X\n", |
1143 EC_INFO(" Vendor-ID: 0x%08X, Product code: 0x%08X\n", |
1237 } |
1252 } |
1238 |
1253 |
1239 /*****************************************************************************/ |
1254 /*****************************************************************************/ |
1240 |
1255 |
1241 /** |
1256 /** |
|
1257 Schedules an EEPROM write operation. |
|
1258 \return 0 in case of success, else < 0 |
|
1259 */ |
|
1260 |
|
1261 ssize_t ec_slave_write_eeprom(ec_slave_t *slave, /**< EtherCAT slave */ |
|
1262 const uint8_t *data, /**< new EEPROM data */ |
|
1263 size_t size /**< size of data in bytes */ |
|
1264 ) |
|
1265 { |
|
1266 uint16_t word_size, cat_type, cat_size; |
|
1267 const uint16_t *data_words, *next_header; |
|
1268 uint16_t *new_data; |
|
1269 |
|
1270 if (!slave->master->eeprom_write_enable) { |
|
1271 EC_ERR("Writing EEPROMs not allowed! Enable via" |
|
1272 " eeprom_write_enable SysFS entry.\n"); |
|
1273 return -1; |
|
1274 } |
|
1275 |
|
1276 if (slave->master->mode != EC_MASTER_MODE_FREERUN) { |
|
1277 EC_ERR("Writing EEPROMs only allowed in freerun mode!\n"); |
|
1278 return -1; |
|
1279 } |
|
1280 |
|
1281 if (slave->new_eeprom_data) { |
|
1282 EC_ERR("Slave %i already has a pending EEPROM write operation!\n", |
|
1283 slave->ring_position); |
|
1284 return -1; |
|
1285 } |
|
1286 |
|
1287 // coarse check of the data |
|
1288 |
|
1289 if (size % 2) { |
|
1290 EC_ERR("EEPROM size is odd! Dropping.\n"); |
|
1291 return -1; |
|
1292 } |
|
1293 |
|
1294 data_words = (const uint16_t *) data; |
|
1295 word_size = size / 2; |
|
1296 |
|
1297 if (word_size < 0x0041) { |
|
1298 EC_ERR("EEPROM data too short! Dropping.\n"); |
|
1299 return -1; |
|
1300 } |
|
1301 |
|
1302 next_header = data_words + 0x0040; |
|
1303 cat_type = EC_READ_U16(next_header); |
|
1304 while (cat_type != 0xFFFF) { |
|
1305 cat_type = EC_READ_U16(next_header); |
|
1306 cat_size = EC_READ_U16(next_header + 1); |
|
1307 if ((next_header + cat_size + 2) - data_words >= word_size) { |
|
1308 EC_ERR("EEPROM data seems to be corrupted! Dropping.\n"); |
|
1309 return -1; |
|
1310 } |
|
1311 next_header += cat_size + 2; |
|
1312 cat_type = EC_READ_U16(next_header); |
|
1313 } |
|
1314 |
|
1315 // data ok! |
|
1316 |
|
1317 if (!(new_data = (uint16_t *) kmalloc(word_size * 2, GFP_KERNEL))) { |
|
1318 EC_ERR("Unable to allocate memory for new EEPROM data!\n"); |
|
1319 return -1; |
|
1320 } |
|
1321 memcpy(new_data, data, size); |
|
1322 |
|
1323 slave->new_eeprom_size = word_size; |
|
1324 slave->new_eeprom_data = new_data; |
|
1325 |
|
1326 EC_INFO("EEPROM writing scheduled for slave %i, %i words.\n", |
|
1327 slave->ring_position, word_size); |
|
1328 return 0; |
|
1329 } |
|
1330 |
|
1331 /*****************************************************************************/ |
|
1332 |
|
1333 /** |
1242 Formats attribute data for SysFS read access. |
1334 Formats attribute data for SysFS read access. |
1243 \return number of bytes to read |
1335 \return number of bytes to read |
1244 */ |
1336 */ |
1245 |
1337 |
1246 ssize_t ec_show_slave_attribute(struct kobject *kobj, /**< slave's kobject */ |
1338 ssize_t ec_show_slave_attribute(struct kobject *kobj, /**< slave's kobject */ |
1293 return sprintf(buffer, "OP\n"); |
1385 return sprintf(buffer, "OP\n"); |
1294 default: |
1386 default: |
1295 return sprintf(buffer, "UNKNOWN\n"); |
1387 return sprintf(buffer, "UNKNOWN\n"); |
1296 } |
1388 } |
1297 } |
1389 } |
|
1390 else if (attr == &attr_eeprom) { |
|
1391 if (slave->eeprom_data) { |
|
1392 if (slave->eeprom_size > PAGE_SIZE) { |
|
1393 EC_ERR("EEPROM contents of slave %i exceed 1 page (%i/%i).\n", |
|
1394 slave->ring_position, slave->eeprom_size, |
|
1395 (int) PAGE_SIZE); |
|
1396 } |
|
1397 else { |
|
1398 memcpy(buffer, slave->eeprom_data, slave->eeprom_size); |
|
1399 return slave->eeprom_size; |
|
1400 } |
|
1401 } |
|
1402 } |
1298 |
1403 |
1299 return 0; |
1404 return 0; |
1300 } |
1405 } |
1301 |
1406 |
1302 /*****************************************************************************/ |
1407 /*****************************************************************************/ |
1336 return size; |
1441 return size; |
1337 } |
1442 } |
1338 |
1443 |
1339 EC_ERR("Failed to set slave state!\n"); |
1444 EC_ERR("Failed to set slave state!\n"); |
1340 } |
1445 } |
|
1446 else if (attr == &attr_eeprom) { |
|
1447 if (!ec_slave_write_eeprom(slave, buffer, size)) |
|
1448 return size; |
|
1449 } |
1341 |
1450 |
1342 return -EINVAL; |
1451 return -EINVAL; |
|
1452 } |
|
1453 |
|
1454 /*****************************************************************************/ |
|
1455 |
|
1456 /** |
|
1457 \return size of sync manager contents |
|
1458 */ |
|
1459 |
|
1460 size_t ec_slave_calc_sync_size(const ec_slave_t *slave, /**< EtherCAT slave */ |
|
1461 const ec_sync_t *sync /**< sync manager */ |
|
1462 ) |
|
1463 { |
|
1464 unsigned int i, found; |
|
1465 const ec_field_t *field; |
|
1466 const ec_varsize_t *var; |
|
1467 size_t size; |
|
1468 |
|
1469 // if size is specified, return size |
|
1470 if (sync->size) return sync->size; |
|
1471 |
|
1472 // sync manager has variable size (size == 0). |
|
1473 |
|
1474 size = 0; |
|
1475 for (i = 0; (field = sync->fields[i]); i++) { |
|
1476 found = 0; |
|
1477 list_for_each_entry(var, &slave->varsize_fields, list) { |
|
1478 if (var->field != field) continue; |
|
1479 size += var->size; |
|
1480 found = 1; |
|
1481 } |
|
1482 |
|
1483 if (!found) { |
|
1484 EC_WARN("Variable data field \"%s\" of slave %i has no size" |
|
1485 " information!\n", field->name, slave->ring_position); |
|
1486 } |
|
1487 } |
|
1488 return size; |
1343 } |
1489 } |
1344 |
1490 |
1345 /****************************************************************************** |
1491 /****************************************************************************** |
1346 * Realtime interface |
1492 * Realtime interface |
1347 *****************************************************************************/ |
1493 *****************************************************************************/ |
1359 return ec_slave_sii_write16(slave, 0x0004, alias); |
1505 return ec_slave_sii_write16(slave, 0x0004, alias); |
1360 } |
1506 } |
1361 |
1507 |
1362 /*****************************************************************************/ |
1508 /*****************************************************************************/ |
1363 |
1509 |
|
1510 /** |
|
1511 \return 0 in case of success, else < 0 |
|
1512 \ingroup RealtimeInterface |
|
1513 */ |
|
1514 |
|
1515 int ecrt_slave_field_size(ec_slave_t *slave, /**< EtherCAT slave */ |
|
1516 const char *field_name, /**< data field name */ |
|
1517 unsigned int field_index, /**< data field index */ |
|
1518 size_t size /**< new data field size */ |
|
1519 ) |
|
1520 { |
|
1521 unsigned int i, j, field_counter; |
|
1522 const ec_sync_t *sync; |
|
1523 const ec_field_t *field; |
|
1524 ec_varsize_t *var; |
|
1525 |
|
1526 if (!slave->type) { |
|
1527 EC_ERR("Slave %i has no type information!\n", slave->ring_position); |
|
1528 return -1; |
|
1529 } |
|
1530 |
|
1531 field_counter = 0; |
|
1532 for (i = 0; (sync = slave->type->sync_managers[i]); i++) { |
|
1533 for (j = 0; (field = sync->fields[j]); j++) { |
|
1534 if (!strcmp(field->name, field_name)) { |
|
1535 if (field_counter++ == field_index) { |
|
1536 // is the size of this field variable? |
|
1537 if (field->size) { |
|
1538 EC_ERR("Field \"%s\"[%i] of slave %i has no variable" |
|
1539 " size!\n", field->name, field_index, |
|
1540 slave->ring_position); |
|
1541 return -1; |
|
1542 } |
|
1543 // does a size specification already exist? |
|
1544 list_for_each_entry(var, &slave->varsize_fields, list) { |
|
1545 if (var->field == field) { |
|
1546 EC_WARN("Resizing field \"%s\"[%i] of slave %i.\n", |
|
1547 field->name, field_index, |
|
1548 slave->ring_position); |
|
1549 var->size = size; |
|
1550 return 0; |
|
1551 } |
|
1552 } |
|
1553 // create a new size specification... |
|
1554 if (!(var = kmalloc(sizeof(ec_varsize_t), GFP_KERNEL))) { |
|
1555 EC_ERR("Failed to allocate memory for varsize_t!\n"); |
|
1556 return -1; |
|
1557 } |
|
1558 var->field = field; |
|
1559 var->size = size; |
|
1560 list_add_tail(&var->list, &slave->varsize_fields); |
|
1561 return 0; |
|
1562 } |
|
1563 } |
|
1564 } |
|
1565 } |
|
1566 |
|
1567 EC_ERR("Slave %i (\"%s %s\") has no field \"%s\"[%i]!\n", |
|
1568 slave->ring_position, slave->type->vendor_name, |
|
1569 slave->type->product_name, field_name, field_index); |
|
1570 return -1; |
|
1571 } |
|
1572 |
|
1573 /*****************************************************************************/ |
|
1574 |
1364 /**< \cond */ |
1575 /**< \cond */ |
1365 |
1576 |
1366 EXPORT_SYMBOL(ecrt_slave_write_alias); |
1577 EXPORT_SYMBOL(ecrt_slave_write_alias); |
|
1578 EXPORT_SYMBOL(ecrt_slave_field_size); |
1367 |
1579 |
1368 /**< \endcond */ |
1580 /**< \endcond */ |
1369 |
1581 |
1370 /*****************************************************************************/ |
1582 /*****************************************************************************/ |