125 kobject_put(&slave->kobj); |
112 kobject_put(&slave->kobj); |
126 return -1; |
113 return -1; |
127 } |
114 } |
128 |
115 |
129 slave->master = master; |
116 slave->master = master; |
|
117 |
|
118 slave->requested_state = EC_SLAVE_STATE_UNKNOWN; |
|
119 slave->current_state = EC_SLAVE_STATE_UNKNOWN; |
|
120 slave->error_flag = 0; |
|
121 slave->online = 1; |
|
122 slave->fmmu_count = 0; |
|
123 slave->registered = 0; |
|
124 |
130 slave->coupler_index = 0; |
125 slave->coupler_index = 0; |
131 slave->coupler_subindex = 0xFFFF; |
126 slave->coupler_subindex = 0xFFFF; |
|
127 |
132 slave->base_type = 0; |
128 slave->base_type = 0; |
133 slave->base_revision = 0; |
129 slave->base_revision = 0; |
134 slave->base_build = 0; |
130 slave->base_build = 0; |
135 slave->base_fmmu_count = 0; |
131 slave->base_fmmu_count = 0; |
136 slave->base_sync_count = 0; |
132 slave->base_sync_count = 0; |
|
133 |
|
134 slave->eeprom_data = NULL; |
|
135 slave->eeprom_size = 0; |
|
136 slave->new_eeprom_data = NULL; |
|
137 slave->new_eeprom_size = 0; |
|
138 |
137 slave->sii_alias = 0; |
139 slave->sii_alias = 0; |
138 slave->sii_vendor_id = 0; |
140 slave->sii_vendor_id = 0; |
139 slave->sii_product_code = 0; |
141 slave->sii_product_code = 0; |
140 slave->sii_revision_number = 0; |
142 slave->sii_revision_number = 0; |
141 slave->sii_serial_number = 0; |
143 slave->sii_serial_number = 0; |
142 slave->sii_rx_mailbox_offset = 0; |
144 slave->sii_rx_mailbox_offset = 0; |
143 slave->sii_rx_mailbox_size = 0; |
145 slave->sii_rx_mailbox_size = 0; |
144 slave->sii_tx_mailbox_offset = 0; |
146 slave->sii_tx_mailbox_offset = 0; |
145 slave->sii_tx_mailbox_size = 0; |
147 slave->sii_tx_mailbox_size = 0; |
146 slave->sii_mailbox_protocols = 0; |
148 slave->sii_mailbox_protocols = 0; |
147 slave->type = NULL; |
149 slave->sii_group = NULL; |
148 slave->registered = 0; |
150 slave->sii_image = NULL; |
149 slave->fmmu_count = 0; |
151 slave->sii_order = NULL; |
150 slave->eeprom_data = NULL; |
152 slave->sii_name = NULL; |
151 slave->eeprom_size = 0; |
153 |
152 slave->eeprom_group = NULL; |
154 INIT_LIST_HEAD(&slave->sii_strings); |
153 slave->eeprom_image = NULL; |
155 INIT_LIST_HEAD(&slave->sii_syncs); |
154 slave->eeprom_order = NULL; |
156 INIT_LIST_HEAD(&slave->sii_pdos); |
155 slave->eeprom_name = NULL; |
|
156 slave->requested_state = EC_SLAVE_STATE_UNKNOWN; |
|
157 slave->current_state = EC_SLAVE_STATE_UNKNOWN; |
|
158 slave->error_flag = 0; |
|
159 slave->online = 1; |
|
160 slave->new_eeprom_data = NULL; |
|
161 slave->new_eeprom_size = 0; |
|
162 |
|
163 INIT_LIST_HEAD(&slave->eeprom_strings); |
|
164 INIT_LIST_HEAD(&slave->eeprom_syncs); |
|
165 INIT_LIST_HEAD(&slave->eeprom_pdos); |
|
166 INIT_LIST_HEAD(&slave->sdo_dictionary); |
157 INIT_LIST_HEAD(&slave->sdo_dictionary); |
167 INIT_LIST_HEAD(&slave->varsize_fields); |
158 INIT_LIST_HEAD(&slave->varsize_fields); |
168 |
159 |
169 for (i = 0; i < 4; i++) { |
160 for (i = 0; i < 4; i++) { |
170 slave->dl_link[i] = 0; |
161 slave->dl_link[i] = 0; |
183 */ |
174 */ |
184 |
175 |
185 void ec_slave_clear(struct kobject *kobj /**< kobject of the slave */) |
176 void ec_slave_clear(struct kobject *kobj /**< kobject of the slave */) |
186 { |
177 { |
187 ec_slave_t *slave; |
178 ec_slave_t *slave; |
188 ec_eeprom_string_t *string, *next_str; |
179 ec_sii_string_t *string, *next_str; |
189 ec_eeprom_sync_t *sync, *next_sync; |
180 ec_sii_sync_t *sync, *next_sync; |
190 ec_eeprom_pdo_t *pdo, *next_pdo; |
181 ec_sii_pdo_t *pdo, *next_pdo; |
191 ec_eeprom_pdo_entry_t *entry, *next_ent; |
182 ec_sii_pdo_entry_t *entry, *next_ent; |
192 ec_sdo_t *sdo, *next_sdo; |
183 ec_sdo_t *sdo, *next_sdo; |
193 ec_sdo_entry_t *en, *next_en; |
184 ec_sdo_entry_t *en, *next_en; |
194 ec_varsize_t *var, *next_var; |
185 ec_varsize_t *var, *next_var; |
195 |
186 |
196 slave = container_of(kobj, ec_slave_t, kobj); |
187 slave = container_of(kobj, ec_slave_t, kobj); |
197 |
188 |
198 // free all string objects |
189 // free all string objects |
199 list_for_each_entry_safe(string, next_str, &slave->eeprom_strings, list) { |
190 list_for_each_entry_safe(string, next_str, &slave->sii_strings, list) { |
200 list_del(&string->list); |
191 list_del(&string->list); |
201 kfree(string); |
192 kfree(string); |
202 } |
193 } |
203 |
194 |
204 // free all sync managers |
195 // free all sync managers |
205 list_for_each_entry_safe(sync, next_sync, &slave->eeprom_syncs, list) { |
196 list_for_each_entry_safe(sync, next_sync, &slave->sii_syncs, list) { |
206 list_del(&sync->list); |
197 list_del(&sync->list); |
207 kfree(sync); |
198 kfree(sync); |
208 } |
199 } |
209 |
200 |
210 // free all PDOs |
201 // free all PDOs |
211 list_for_each_entry_safe(pdo, next_pdo, &slave->eeprom_pdos, list) { |
202 list_for_each_entry_safe(pdo, next_pdo, &slave->sii_pdos, list) { |
212 list_del(&pdo->list); |
203 list_del(&pdo->list); |
213 if (pdo->name) kfree(pdo->name); |
204 if (pdo->name) kfree(pdo->name); |
214 |
205 |
215 // free all PDO entries |
206 // free all PDO entries |
216 list_for_each_entry_safe(entry, next_ent, &pdo->entries, list) { |
207 list_for_each_entry_safe(entry, next_ent, &pdo->entries, list) { |
251 } |
242 } |
252 |
243 |
253 /*****************************************************************************/ |
244 /*****************************************************************************/ |
254 |
245 |
255 /** |
246 /** |
256 Reads all necessary information from a slave. |
|
257 \return 0 in case of success, else < 0 |
|
258 */ |
|
259 |
|
260 int ec_slave_fetch(ec_slave_t *slave /**< EtherCAT slave */) |
|
261 { |
|
262 ec_datagram_t *datagram; |
|
263 unsigned int i; |
|
264 uint16_t dl_status; |
|
265 |
|
266 datagram = &slave->master->simple_datagram; |
|
267 |
|
268 // read base data |
|
269 if (ec_datagram_nprd(datagram, slave->station_address, 0x0000, 6)) |
|
270 return -1; |
|
271 if (unlikely(ec_master_simple_io(slave->master, datagram))) { |
|
272 EC_ERR("Reading base data from slave %i failed!\n", |
|
273 slave->ring_position); |
|
274 return -1; |
|
275 } |
|
276 |
|
277 slave->base_type = EC_READ_U8 (datagram->data); |
|
278 slave->base_revision = EC_READ_U8 (datagram->data + 1); |
|
279 slave->base_build = EC_READ_U16(datagram->data + 2); |
|
280 slave->base_fmmu_count = EC_READ_U8 (datagram->data + 4); |
|
281 slave->base_sync_count = EC_READ_U8 (datagram->data + 5); |
|
282 |
|
283 if (slave->base_fmmu_count > EC_MAX_FMMUS) |
|
284 slave->base_fmmu_count = EC_MAX_FMMUS; |
|
285 |
|
286 // read data link status |
|
287 if (ec_datagram_nprd(datagram, slave->station_address, 0x0110, 2)) |
|
288 return -1; |
|
289 if (unlikely(ec_master_simple_io(slave->master, datagram))) { |
|
290 EC_ERR("Reading DL status from slave %i failed!\n", |
|
291 slave->ring_position); |
|
292 return -1; |
|
293 } |
|
294 |
|
295 dl_status = EC_READ_U16(datagram->data); |
|
296 for (i = 0; i < 4; i++) { |
|
297 slave->dl_link[i] = dl_status & (1 << (4 + i)) ? 1 : 0; |
|
298 slave->dl_loop[i] = dl_status & (1 << (8 + i * 2)) ? 1 : 0; |
|
299 slave->dl_signal[i] = dl_status & (1 << (9 + i * 2)) ? 1 : 0; |
|
300 } |
|
301 |
|
302 // read EEPROM data |
|
303 if (ec_slave_sii_read16(slave, 0x0004, &slave->sii_alias)) |
|
304 return -1; |
|
305 if (ec_slave_sii_read32(slave, 0x0008, &slave->sii_vendor_id)) |
|
306 return -1; |
|
307 if (ec_slave_sii_read32(slave, 0x000A, &slave->sii_product_code)) |
|
308 return -1; |
|
309 if (ec_slave_sii_read32(slave, 0x000C, &slave->sii_revision_number)) |
|
310 return -1; |
|
311 if (ec_slave_sii_read32(slave, 0x000E, &slave->sii_serial_number)) |
|
312 return -1; |
|
313 if (ec_slave_sii_read16(slave, 0x0018, &slave->sii_rx_mailbox_offset)) |
|
314 return -1; |
|
315 if (ec_slave_sii_read16(slave, 0x0019, &slave->sii_rx_mailbox_size)) |
|
316 return -1; |
|
317 if (ec_slave_sii_read16(slave, 0x001A, &slave->sii_tx_mailbox_offset)) |
|
318 return -1; |
|
319 if (ec_slave_sii_read16(slave, 0x001B, &slave->sii_tx_mailbox_size)) |
|
320 return -1; |
|
321 if (ec_slave_sii_read16(slave, 0x001C, &slave->sii_mailbox_protocols)) |
|
322 return -1; |
|
323 |
|
324 if (unlikely(ec_slave_fetch_categories(slave))) { |
|
325 EC_ERR("Failed to fetch category data!\n"); |
|
326 return -1; |
|
327 } |
|
328 |
|
329 return 0; |
|
330 } |
|
331 |
|
332 /*****************************************************************************/ |
|
333 |
|
334 /** |
|
335 Reads 16 bit from the slave information interface (SII). |
|
336 \return 0 in case of success, else < 0 |
|
337 */ |
|
338 |
|
339 int ec_slave_sii_read16(ec_slave_t *slave, |
|
340 /**< EtherCAT slave */ |
|
341 uint16_t offset, |
|
342 /**< address of the SII register to read */ |
|
343 uint16_t *target |
|
344 /**< target memory */ |
|
345 ) |
|
346 { |
|
347 ec_datagram_t *datagram; |
|
348 cycles_t start, end, timeout; |
|
349 |
|
350 datagram = &slave->master->simple_datagram; |
|
351 |
|
352 // initiate read operation |
|
353 if (ec_datagram_npwr(datagram, slave->station_address, 0x502, 6)) |
|
354 return -1; |
|
355 EC_WRITE_U8 (datagram->data, 0x00); // read-only access |
|
356 EC_WRITE_U8 (datagram->data + 1, 0x01); // request read operation |
|
357 EC_WRITE_U32(datagram->data + 2, offset); |
|
358 if (unlikely(ec_master_simple_io(slave->master, datagram))) { |
|
359 EC_ERR("SII-read failed on slave %i!\n", slave->ring_position); |
|
360 return -1; |
|
361 } |
|
362 |
|
363 start = get_cycles(); |
|
364 timeout = (cycles_t) 100 * cpu_khz; // 100ms |
|
365 |
|
366 while (1) |
|
367 { |
|
368 udelay(10); |
|
369 |
|
370 if (ec_datagram_nprd(datagram, slave->station_address, 0x502, 10)) |
|
371 return -1; |
|
372 if (unlikely(ec_master_simple_io(slave->master, datagram))) { |
|
373 EC_ERR("Getting SII-read status failed on slave %i!\n", |
|
374 slave->ring_position); |
|
375 return -1; |
|
376 } |
|
377 |
|
378 end = get_cycles(); |
|
379 |
|
380 // check for "busy bit" |
|
381 if (likely((EC_READ_U8(datagram->data + 1) & 0x81) == 0)) { |
|
382 *target = EC_READ_U16(datagram->data + 6); |
|
383 return 0; |
|
384 } |
|
385 |
|
386 if (unlikely((end - start) >= timeout)) { |
|
387 EC_ERR("SII-read. Slave %i timed out!\n", slave->ring_position); |
|
388 return -1; |
|
389 } |
|
390 } |
|
391 } |
|
392 |
|
393 /*****************************************************************************/ |
|
394 |
|
395 /** |
|
396 Reads 32 bit from the slave information interface (SII). |
|
397 \return 0 in case of success, else < 0 |
|
398 */ |
|
399 |
|
400 int ec_slave_sii_read32(ec_slave_t *slave, |
|
401 /**< EtherCAT slave */ |
|
402 uint16_t offset, |
|
403 /**< address of the SII register to read */ |
|
404 uint32_t *target |
|
405 /**< target memory */ |
|
406 ) |
|
407 { |
|
408 ec_datagram_t *datagram; |
|
409 cycles_t start, end, timeout; |
|
410 |
|
411 datagram = &slave->master->simple_datagram; |
|
412 |
|
413 // initiate read operation |
|
414 if (ec_datagram_npwr(datagram, slave->station_address, 0x502, 6)) |
|
415 return -1; |
|
416 EC_WRITE_U8 (datagram->data, 0x00); // read-only access |
|
417 EC_WRITE_U8 (datagram->data + 1, 0x01); // request read operation |
|
418 EC_WRITE_U32(datagram->data + 2, offset); |
|
419 if (unlikely(ec_master_simple_io(slave->master, datagram))) { |
|
420 EC_ERR("SII-read failed on slave %i!\n", slave->ring_position); |
|
421 return -1; |
|
422 } |
|
423 |
|
424 start = get_cycles(); |
|
425 timeout = (cycles_t) 100 * cpu_khz; // 100ms |
|
426 |
|
427 while (1) |
|
428 { |
|
429 udelay(10); |
|
430 |
|
431 if (ec_datagram_nprd(datagram, slave->station_address, 0x502, 10)) |
|
432 return -1; |
|
433 if (unlikely(ec_master_simple_io(slave->master, datagram))) { |
|
434 EC_ERR("Getting SII-read status failed on slave %i!\n", |
|
435 slave->ring_position); |
|
436 return -1; |
|
437 } |
|
438 |
|
439 end = get_cycles(); |
|
440 |
|
441 // check "busy bit" |
|
442 if (likely((EC_READ_U8(datagram->data + 1) & 0x81) == 0)) { |
|
443 *target = EC_READ_U32(datagram->data + 6); |
|
444 return 0; |
|
445 } |
|
446 |
|
447 if (unlikely((end - start) >= timeout)) { |
|
448 EC_ERR("SII-read. Slave %i timed out!\n", slave->ring_position); |
|
449 return -1; |
|
450 } |
|
451 } |
|
452 } |
|
453 |
|
454 /*****************************************************************************/ |
|
455 |
|
456 /** |
|
457 Writes 16 bit of data to the slave information interface (SII). |
|
458 \return 0 in case of success, else < 0 |
|
459 */ |
|
460 |
|
461 int ec_slave_sii_write16(ec_slave_t *slave, |
|
462 /**< EtherCAT slave */ |
|
463 uint16_t offset, |
|
464 /**< address of the SII register to write */ |
|
465 uint16_t value |
|
466 /**< new value */ |
|
467 ) |
|
468 { |
|
469 ec_datagram_t *datagram; |
|
470 cycles_t start, end, timeout; |
|
471 |
|
472 datagram = &slave->master->simple_datagram; |
|
473 |
|
474 EC_INFO("SII-write (slave %i, offset 0x%04X, value 0x%04X)\n", |
|
475 slave->ring_position, offset, value); |
|
476 |
|
477 // initiate write operation |
|
478 if (ec_datagram_npwr(datagram, slave->station_address, 0x502, 8)) |
|
479 return -1; |
|
480 EC_WRITE_U8 (datagram->data, 0x01); // enable write access |
|
481 EC_WRITE_U8 (datagram->data + 1, 0x02); // request write operation |
|
482 EC_WRITE_U32(datagram->data + 2, offset); |
|
483 EC_WRITE_U16(datagram->data + 6, value); |
|
484 if (unlikely(ec_master_simple_io(slave->master, datagram))) { |
|
485 EC_ERR("SII-write failed on slave %i!\n", slave->ring_position); |
|
486 return -1; |
|
487 } |
|
488 |
|
489 start = get_cycles(); |
|
490 timeout = (cycles_t) 100 * cpu_khz; // 100ms |
|
491 |
|
492 while (1) |
|
493 { |
|
494 udelay(10); |
|
495 |
|
496 if (ec_datagram_nprd(datagram, slave->station_address, 0x502, 2)) |
|
497 return -1; |
|
498 if (unlikely(ec_master_simple_io(slave->master, datagram))) { |
|
499 EC_ERR("Getting SII-write status failed on slave %i!\n", |
|
500 slave->ring_position); |
|
501 return -1; |
|
502 } |
|
503 |
|
504 end = get_cycles(); |
|
505 |
|
506 // check "busy bit" |
|
507 if (likely((EC_READ_U8(datagram->data + 1) & 0x82) == 0)) { |
|
508 if (EC_READ_U8(datagram->data + 1) & 0x40) { |
|
509 EC_ERR("SII-write failed!\n"); |
|
510 return -1; |
|
511 } |
|
512 else { |
|
513 EC_INFO("SII-write succeeded!\n"); |
|
514 return 0; |
|
515 } |
|
516 } |
|
517 |
|
518 if (unlikely((end - start) >= timeout)) { |
|
519 EC_ERR("SII-write: Slave %i timed out!\n", slave->ring_position); |
|
520 return -1; |
|
521 } |
|
522 } |
|
523 } |
|
524 |
|
525 /*****************************************************************************/ |
|
526 |
|
527 /** |
|
528 Fetches data from slave's EEPROM. |
|
529 \return 0 in case of success, else < 0 |
|
530 \todo memory allocation |
|
531 */ |
|
532 |
|
533 int ec_slave_fetch_categories(ec_slave_t *slave /**< EtherCAT slave */) |
|
534 { |
|
535 uint16_t word_offset, cat_type, word_count; |
|
536 uint32_t value; |
|
537 uint8_t *cat_data; |
|
538 unsigned int i; |
|
539 |
|
540 word_offset = 0x0040; |
|
541 |
|
542 if (!(cat_data = (uint8_t *) kmalloc(0x10000, GFP_ATOMIC))) { |
|
543 EC_ERR("Failed to allocate 64k bytes for category data.\n"); |
|
544 return -1; |
|
545 } |
|
546 |
|
547 while (1) { |
|
548 // read category type |
|
549 if (ec_slave_sii_read32(slave, word_offset, &value)) { |
|
550 EC_ERR("Unable to read category header.\n"); |
|
551 goto out_free; |
|
552 } |
|
553 |
|
554 // last category? |
|
555 if ((value & 0xFFFF) == 0xFFFF) break; |
|
556 |
|
557 cat_type = value & 0x7FFF; |
|
558 word_count = (value >> 16) & 0xFFFF; |
|
559 |
|
560 // fetch category data |
|
561 for (i = 0; i < word_count; i++) { |
|
562 if (ec_slave_sii_read32(slave, word_offset + 2 + i, &value)) { |
|
563 EC_ERR("Unable to read category data word %i.\n", i); |
|
564 goto out_free; |
|
565 } |
|
566 |
|
567 cat_data[i * 2] = (value >> 0) & 0xFF; |
|
568 cat_data[i * 2 + 1] = (value >> 8) & 0xFF; |
|
569 |
|
570 // read second word "on the fly" |
|
571 if (i + 1 < word_count) { |
|
572 i++; |
|
573 cat_data[i * 2] = (value >> 16) & 0xFF; |
|
574 cat_data[i * 2 + 1] = (value >> 24) & 0xFF; |
|
575 } |
|
576 } |
|
577 |
|
578 switch (cat_type) |
|
579 { |
|
580 case 0x000A: |
|
581 if (ec_slave_fetch_strings(slave, cat_data)) |
|
582 goto out_free; |
|
583 break; |
|
584 case 0x001E: |
|
585 if (ec_slave_fetch_general(slave, cat_data)) |
|
586 goto out_free; |
|
587 break; |
|
588 case 0x0028: |
|
589 break; |
|
590 case 0x0029: |
|
591 if (ec_slave_fetch_sync(slave, cat_data, word_count)) |
|
592 goto out_free; |
|
593 break; |
|
594 case 0x0032: |
|
595 if (ec_slave_fetch_pdo(slave, cat_data, word_count, EC_TX_PDO)) |
|
596 goto out_free; |
|
597 break; |
|
598 case 0x0033: |
|
599 if (ec_slave_fetch_pdo(slave, cat_data, word_count, EC_RX_PDO)) |
|
600 goto out_free; |
|
601 break; |
|
602 default: |
|
603 EC_WARN("Unknown category type 0x%04X in slave %i.\n", |
|
604 cat_type, slave->ring_position); |
|
605 } |
|
606 |
|
607 word_offset += 2 + word_count; |
|
608 } |
|
609 |
|
610 kfree(cat_data); |
|
611 return 0; |
|
612 |
|
613 out_free: |
|
614 kfree(cat_data); |
|
615 return -1; |
|
616 } |
|
617 |
|
618 /*****************************************************************************/ |
|
619 |
|
620 /** |
|
621 Fetches data from a STRING category. |
247 Fetches data from a STRING category. |
622 \return 0 in case of success, else < 0 |
248 \return 0 in case of success, else < 0 |
623 */ |
249 */ |
624 |
250 |
625 int ec_slave_fetch_strings(ec_slave_t *slave, /**< EtherCAT slave */ |
251 int ec_slave_fetch_strings(ec_slave_t *slave, /**< EtherCAT slave */ |
726 */ |
346 */ |
727 |
347 |
728 int ec_slave_fetch_pdo(ec_slave_t *slave, /**< EtherCAT slave */ |
348 int ec_slave_fetch_pdo(ec_slave_t *slave, /**< EtherCAT slave */ |
729 const uint8_t *data, /**< category data */ |
349 const uint8_t *data, /**< category data */ |
730 size_t word_count, /**< number of words */ |
350 size_t word_count, /**< number of words */ |
731 ec_pdo_type_t pdo_type /**< PDO type */ |
351 ec_sii_pdo_type_t pdo_type /**< PDO type */ |
732 ) |
352 ) |
733 { |
353 { |
734 ec_eeprom_pdo_t *pdo; |
354 ec_sii_pdo_t *pdo; |
735 ec_eeprom_pdo_entry_t *entry; |
355 ec_sii_pdo_entry_t *entry; |
736 unsigned int entry_count, i; |
356 unsigned int entry_count, i; |
737 |
357 |
738 while (word_count >= 4) { |
358 while (word_count >= 4) { |
739 if (!(pdo = (ec_eeprom_pdo_t *) |
359 if (!(pdo = (ec_sii_pdo_t *) |
740 kmalloc(sizeof(ec_eeprom_pdo_t), GFP_ATOMIC))) { |
360 kmalloc(sizeof(ec_sii_pdo_t), GFP_ATOMIC))) { |
741 EC_ERR("Failed to allocate PDO memory.\n"); |
361 EC_ERR("Failed to allocate PDO memory.\n"); |
742 return -1; |
362 return -1; |
743 } |
363 } |
744 |
364 |
745 INIT_LIST_HEAD(&pdo->entries); |
365 INIT_LIST_HEAD(&pdo->entries); |
746 pdo->type = pdo_type; |
366 pdo->type = pdo_type; |
747 |
367 |
748 pdo->index = *((uint16_t *) data); |
368 pdo->index = EC_READ_U16(data); |
749 entry_count = data[2]; |
369 entry_count = EC_READ_U8(data + 2); |
750 pdo->sync_manager = data[3]; |
370 pdo->sync_index = EC_READ_U8(data + 3); |
751 pdo->name = NULL; |
371 pdo->name = NULL; |
752 ec_slave_locate_string(slave, data[5], &pdo->name); |
372 ec_slave_locate_string(slave, EC_READ_U8(data + 5), &pdo->name); |
753 |
373 |
754 list_add_tail(&pdo->list, &slave->eeprom_pdos); |
374 list_add_tail(&pdo->list, &slave->sii_pdos); |
755 |
375 |
756 word_count -= 4; |
376 word_count -= 4; |
757 data += 8; |
377 data += 8; |
758 |
378 |
759 for (i = 0; i < entry_count; i++) { |
379 for (i = 0; i < entry_count; i++) { |
760 if (!(entry = (ec_eeprom_pdo_entry_t *) |
380 if (!(entry = (ec_sii_pdo_entry_t *) |
761 kmalloc(sizeof(ec_eeprom_pdo_entry_t), GFP_ATOMIC))) { |
381 kmalloc(sizeof(ec_sii_pdo_entry_t), GFP_ATOMIC))) { |
762 EC_ERR("Failed to allocate PDO entry memory.\n"); |
382 EC_ERR("Failed to allocate PDO entry memory.\n"); |
763 return -1; |
383 return -1; |
764 } |
384 } |
765 |
385 |
766 entry->index = *((uint16_t *) data); |
386 entry->index = EC_READ_U16(data); |
767 entry->subindex = data[2]; |
387 entry->subindex = EC_READ_U8(data + 2); |
768 entry->name = NULL; |
388 entry->name = NULL; |
769 ec_slave_locate_string(slave, data[3], &entry->name); |
389 ec_slave_locate_string(slave, EC_READ_U8(data + 3), &entry->name); |
770 entry->bit_length = data[5]; |
390 entry->bit_length = EC_READ_U8(data + 5); |
771 |
391 |
772 list_add_tail(&entry->list, &pdo->entries); |
392 list_add_tail(&entry->list, &pdo->entries); |
773 |
393 |
774 word_count -= 4; |
394 word_count -= 4; |
775 data += 8; |
395 data += 8; |
819 EC_WARN("String %i not found in slave %i.\n", index, slave->ring_position); |
439 EC_WARN("String %i not found in slave %i.\n", index, slave->ring_position); |
820 |
440 |
821 err_string = "(string not found)"; |
441 err_string = "(string not found)"; |
822 |
442 |
823 if (!(*ptr = (char *) kmalloc(strlen(err_string) + 1, GFP_ATOMIC))) { |
443 if (!(*ptr = (char *) kmalloc(strlen(err_string) + 1, GFP_ATOMIC))) { |
824 EC_ERR("Unable to allocate string memory.\n"); |
444 EC_WARN("Unable to allocate string memory.\n"); |
825 return -1; |
445 return -1; |
826 } |
446 } |
827 |
447 |
828 memcpy(*ptr, err_string, strlen(err_string) + 1); |
448 memcpy(*ptr, err_string, strlen(err_string) + 1); |
829 return 0; |
449 return 0; |
830 } |
|
831 |
|
832 /*****************************************************************************/ |
|
833 |
|
834 /** |
|
835 Acknowledges an error after a state transition. |
|
836 */ |
|
837 |
|
838 void ec_slave_state_ack(ec_slave_t *slave, /**< EtherCAT slave */ |
|
839 uint8_t state /**< previous state */ |
|
840 ) |
|
841 { |
|
842 ec_datagram_t *datagram; |
|
843 cycles_t start, end, timeout; |
|
844 |
|
845 datagram = &slave->master->simple_datagram; |
|
846 |
|
847 if (ec_datagram_npwr(datagram, slave->station_address, 0x0120, 2)) return; |
|
848 EC_WRITE_U16(datagram->data, state | EC_ACK); |
|
849 if (unlikely(ec_master_simple_io(slave->master, datagram))) { |
|
850 EC_WARN("Acknowledge sending failed on slave %i!\n", |
|
851 slave->ring_position); |
|
852 return; |
|
853 } |
|
854 |
|
855 start = get_cycles(); |
|
856 timeout = (cycles_t) 10 * cpu_khz; // 10ms |
|
857 |
|
858 while (1) |
|
859 { |
|
860 udelay(100); // wait a little bit... |
|
861 |
|
862 if (ec_datagram_nprd(datagram, slave->station_address, 0x0130, 2)) |
|
863 return; |
|
864 if (unlikely(ec_master_simple_io(slave->master, datagram))) { |
|
865 slave->current_state = EC_SLAVE_STATE_UNKNOWN; |
|
866 EC_WARN("Acknowledge checking failed on slave %i!\n", |
|
867 slave->ring_position); |
|
868 return; |
|
869 } |
|
870 |
|
871 end = get_cycles(); |
|
872 |
|
873 if (likely(EC_READ_U8(datagram->data) == state)) { |
|
874 slave->current_state = state; |
|
875 EC_INFO("Acknowleged state 0x%02X on slave %i.\n", state, |
|
876 slave->ring_position); |
|
877 return; |
|
878 } |
|
879 |
|
880 if (unlikely((end - start) >= timeout)) { |
|
881 slave->current_state = EC_SLAVE_STATE_UNKNOWN; |
|
882 EC_WARN("Failed to acknowledge state 0x%02X on slave %i" |
|
883 " - Timeout!\n", state, slave->ring_position); |
|
884 return; |
|
885 } |
|
886 } |
|
887 } |
|
888 |
|
889 /*****************************************************************************/ |
|
890 |
|
891 /** |
|
892 Reads the AL status code of a slave and displays it. |
|
893 If the AL status code is not supported, or if no error occurred (both |
|
894 resulting in code = 0), nothing is displayed. |
|
895 */ |
|
896 |
|
897 void ec_slave_read_al_status_code(ec_slave_t *slave /**< EtherCAT slave */) |
|
898 { |
|
899 ec_datagram_t *datagram; |
|
900 uint16_t code; |
|
901 const ec_code_msg_t *al_msg; |
|
902 |
|
903 datagram = &slave->master->simple_datagram; |
|
904 |
|
905 if (ec_datagram_nprd(datagram, slave->station_address, 0x0134, 2)) return; |
|
906 if (unlikely(ec_master_simple_io(slave->master, datagram))) { |
|
907 EC_WARN("Failed to read AL status code on slave %i!\n", |
|
908 slave->ring_position); |
|
909 return; |
|
910 } |
|
911 |
|
912 if (!(code = EC_READ_U16(datagram->data))) return; |
|
913 |
|
914 for (al_msg = al_status_messages; al_msg->code; al_msg++) { |
|
915 if (al_msg->code == code) { |
|
916 EC_ERR("AL status message 0x%04X: \"%s\".\n", |
|
917 al_msg->code, al_msg->message); |
|
918 return; |
|
919 } |
|
920 } |
|
921 |
|
922 EC_ERR("Unknown AL status code 0x%04X.\n", code); |
|
923 } |
|
924 |
|
925 /*****************************************************************************/ |
|
926 |
|
927 /** |
|
928 Does a state transition. |
|
929 \return 0 in case of success, else < 0 |
|
930 */ |
|
931 |
|
932 int ec_slave_state_change(ec_slave_t *slave, /**< EtherCAT slave */ |
|
933 uint8_t state /**< new state */ |
|
934 ) |
|
935 { |
|
936 ec_datagram_t *datagram; |
|
937 cycles_t start, end, timeout; |
|
938 |
|
939 datagram = &slave->master->simple_datagram; |
|
940 |
|
941 slave->requested_state = state; |
|
942 |
|
943 if (ec_datagram_npwr(datagram, slave->station_address, 0x0120, 2)) |
|
944 return -1; |
|
945 EC_WRITE_U16(datagram->data, state); |
|
946 if (unlikely(ec_master_simple_io(slave->master, datagram))) { |
|
947 EC_ERR("Failed to set state 0x%02X on slave %i!\n", |
|
948 state, slave->ring_position); |
|
949 return -1; |
|
950 } |
|
951 |
|
952 start = get_cycles(); |
|
953 timeout = (cycles_t) 10 * cpu_khz; // 10ms |
|
954 |
|
955 while (1) |
|
956 { |
|
957 udelay(100); // wait a little bit |
|
958 |
|
959 if (ec_datagram_nprd(datagram, slave->station_address, 0x0130, 2)) |
|
960 return -1; |
|
961 if (unlikely(ec_master_simple_io(slave->master, datagram))) { |
|
962 slave->current_state = EC_SLAVE_STATE_UNKNOWN; |
|
963 EC_ERR("Failed to check state 0x%02X on slave %i!\n", |
|
964 state, slave->ring_position); |
|
965 return -1; |
|
966 } |
|
967 |
|
968 end = get_cycles(); |
|
969 |
|
970 if (unlikely(EC_READ_U8(datagram->data) & 0x10)) { |
|
971 // state change error |
|
972 EC_ERR("Failed to set state 0x%02X - Slave %i refused state change" |
|
973 " (code 0x%02X)!\n", state, slave->ring_position, |
|
974 EC_READ_U8(datagram->data)); |
|
975 slave->current_state = EC_READ_U8(datagram->data); |
|
976 state = slave->current_state & 0x0F; |
|
977 ec_slave_read_al_status_code(slave); |
|
978 ec_slave_state_ack(slave, state); |
|
979 return -1; |
|
980 } |
|
981 |
|
982 if (likely(EC_READ_U8(datagram->data) == (state & 0x0F))) { |
|
983 slave->current_state = state; |
|
984 return 0; // state change successful |
|
985 } |
|
986 |
|
987 if (unlikely((end - start) >= timeout)) { |
|
988 slave->current_state = EC_SLAVE_STATE_UNKNOWN; |
|
989 EC_ERR("Failed to check state 0x%02X of slave %i - Timeout!\n", |
|
990 state, slave->ring_position); |
|
991 return -1; |
|
992 } |
|
993 } |
|
994 } |
450 } |
995 |
451 |
996 /*****************************************************************************/ |
452 /*****************************************************************************/ |
997 |
453 |
998 /** |
454 /** |
999 Prepares an FMMU configuration. |
455 Prepares an FMMU configuration. |
1000 Configuration data for the FMMU is saved in the slave structure and is |
456 Configuration data for the FMMU is saved in the slave structure and is |
1001 written to the slave in ecrt_master_activate(). |
457 written to the slave in ecrt_master_activate(). |
1002 The FMMU configuration is done in a way, that the complete data range |
458 The FMMU configuration is done in a way, that the complete data range |
1003 of the corresponding sync manager is covered. Seperate FMMUs arce configured |
459 of the corresponding sync manager is covered. Seperate FMMUs are configured |
1004 for each domain. |
460 for each domain. |
1005 If the FMMU configuration is already prepared, the function returns with |
461 If the FMMU configuration is already prepared, the function returns with |
1006 success. |
462 success. |
1007 \return 0 in case of success, else < 0 |
463 \return 0 in case of success, else < 0 |
1008 */ |
464 */ |
1009 |
465 |
1010 int ec_slave_prepare_fmmu(ec_slave_t *slave, /**< EtherCAT slave */ |
466 int ec_slave_prepare_fmmu(ec_slave_t *slave, /**< EtherCAT slave */ |
1011 const ec_domain_t *domain, /**< domain */ |
467 const ec_domain_t *domain, /**< domain */ |
1012 const ec_sync_t *sync /**< sync manager */ |
468 const ec_sii_sync_t *sync /**< sync manager */ |
1013 ) |
469 ) |
1014 { |
470 { |
1015 unsigned int i; |
471 unsigned int i; |
1016 |
472 |
1017 // FMMU configuration already prepared? |
473 // FMMU configuration already prepared? |
1037 |
493 |
1038 /*****************************************************************************/ |
494 /*****************************************************************************/ |
1039 |
495 |
1040 /** |
496 /** |
1041 Outputs all information about a certain slave. |
497 Outputs all information about a certain slave. |
1042 Verbosity: |
498 */ |
1043 - 0: Only slave types and addresses |
499 |
1044 - 1: with EEPROM information |
500 size_t ec_slave_info(const ec_slave_t *slave, /**< EtherCAT slave */ |
1045 - >1: with SDO dictionaries |
501 char *buffer /**< Output buffer */ |
1046 */ |
502 ) |
1047 |
503 { |
1048 void ec_slave_print(const ec_slave_t *slave, /**< EtherCAT slave */ |
504 off_t off = 0; |
1049 unsigned int verbosity /**< verbosity level */ |
505 ec_sii_sync_t *sync; |
1050 ) |
506 ec_sii_pdo_t *pdo; |
1051 { |
507 ec_sii_pdo_entry_t *pdo_entry; |
1052 ec_eeprom_sync_t *sync; |
|
1053 ec_eeprom_pdo_t *pdo; |
|
1054 ec_eeprom_pdo_entry_t *pdo_entry; |
|
1055 ec_sdo_t *sdo; |
|
1056 ec_sdo_entry_t *sdo_entry; |
|
1057 int first, i; |
508 int first, i; |
1058 |
509 |
1059 if (slave->type) { |
510 off += sprintf(buffer + off, "\nName: "); |
1060 EC_INFO("%i) %s %s: %s\n", slave->ring_position, |
511 |
1061 slave->type->vendor_name, slave->type->product_name, |
512 if (slave->sii_name) |
1062 slave->type->description); |
513 off += sprintf(buffer + off, "%s", slave->sii_name); |
1063 } |
514 |
1064 else { |
515 off += sprintf(buffer + off, "\n\nVendor ID: 0x%08X\n", |
1065 EC_INFO("%i) UNKNOWN SLAVE: vendor 0x%08X, product 0x%08X\n", |
516 slave->sii_vendor_id); |
1066 slave->ring_position, slave->sii_vendor_id, |
517 off += sprintf(buffer + off, "Product code: 0x%08X\n\n", |
1067 slave->sii_product_code); |
518 slave->sii_product_code); |
1068 } |
519 |
1069 |
520 off += sprintf(buffer + off, "Ring position: %i\n", slave->ring_position); |
1070 if (!verbosity) return; |
521 off += sprintf(buffer + off, "Advanced position: %i:%i\n\n", |
1071 |
522 slave->coupler_index, slave->coupler_subindex); |
1072 EC_INFO(" Station address: 0x%04X\n", slave->station_address); |
523 |
1073 |
524 off += sprintf(buffer + off, "State: "); |
1074 EC_INFO(" Data link status:\n"); |
525 off += ec_state_string(slave->current_state, buffer + off); |
|
526 off += sprintf(buffer + off, "\n\n"); |
|
527 |
|
528 off += sprintf(buffer + off, "Data link status:\n"); |
1075 for (i = 0; i < 4; i++) { |
529 for (i = 0; i < 4; i++) { |
1076 EC_INFO(" Port %i (", i); |
530 off += sprintf(buffer + off, " Port %i (", i); |
1077 switch (slave->sii_physical_layer[i]) { |
531 switch (slave->sii_physical_layer[i]) { |
1078 case 0x00: |
532 case 0x00: |
1079 printk("EBUS"); |
533 off += sprintf(buffer + off, "EBUS"); |
1080 break; |
534 break; |
1081 case 0x01: |
535 case 0x01: |
1082 printk("100BASE-TX"); |
536 off += sprintf(buffer + off, "100BASE-TX"); |
1083 break; |
537 break; |
1084 case 0x02: |
538 case 0x02: |
1085 printk("100BASE-FX"); |
539 off += sprintf(buffer + off, "100BASE-FX"); |
1086 break; |
540 break; |
1087 default: |
541 default: |
1088 printk("unknown"); |
542 off += sprintf(buffer + off, "unknown (%i)", |
1089 } |
543 slave->sii_physical_layer[i]); |
1090 printk(")\n"); |
544 } |
1091 EC_INFO(" link %s, loop %s, %s\n", |
545 off += sprintf(buffer + off, ") Link %s, Loop %s, %s\n", |
1092 slave->dl_link[i] ? "up" : "down", |
546 slave->dl_link[i] ? "up" : "down", |
1093 slave->dl_loop[i] ? "closed" : "open", |
547 slave->dl_loop[i] ? "closed" : "open", |
1094 slave->dl_signal[i] ? "signal detected" : "no signal"); |
548 slave->dl_signal[i] ? "Signal detected" : "No signal"); |
1095 } |
549 } |
1096 |
|
1097 EC_INFO(" Base information:\n"); |
|
1098 EC_INFO(" Type %u, revision %i, build %i\n", |
|
1099 slave->base_type, slave->base_revision, slave->base_build); |
|
1100 EC_INFO(" Supported FMMUs: %i, sync managers: %i\n", |
|
1101 slave->base_fmmu_count, slave->base_sync_count); |
|
1102 |
550 |
1103 if (slave->sii_mailbox_protocols) { |
551 if (slave->sii_mailbox_protocols) { |
1104 EC_INFO(" Mailbox communication:\n"); |
552 off += sprintf(buffer + off, "\nMailboxes:\n"); |
1105 EC_INFO(" RX mailbox: 0x%04X/%i, TX mailbox: 0x%04X/%i\n", |
553 off += sprintf(buffer + off, " RX mailbox: 0x%04X/%i," |
1106 slave->sii_rx_mailbox_offset, slave->sii_rx_mailbox_size, |
554 " TX mailbox: 0x%04X/%i\n", |
1107 slave->sii_tx_mailbox_offset, slave->sii_tx_mailbox_size); |
555 slave->sii_rx_mailbox_offset, |
1108 EC_INFO(" Supported protocols: "); |
556 slave->sii_rx_mailbox_size, |
|
557 slave->sii_tx_mailbox_offset, |
|
558 slave->sii_tx_mailbox_size); |
|
559 off += sprintf(buffer + off, " Supported protocols: "); |
1109 |
560 |
1110 first = 1; |
561 first = 1; |
1111 if (slave->sii_mailbox_protocols & EC_MBOX_AOE) { |
562 if (slave->sii_mailbox_protocols & EC_MBOX_AOE) { |
1112 printk("AoE"); |
563 off += sprintf(buffer + off, "AoE"); |
1113 first = 0; |
564 first = 0; |
1114 } |
565 } |
1115 if (slave->sii_mailbox_protocols & EC_MBOX_EOE) { |
566 if (slave->sii_mailbox_protocols & EC_MBOX_EOE) { |
1116 if (!first) printk(", "); |
567 if (!first) off += sprintf(buffer + off, ", "); |
1117 printk("EoE"); |
568 off += sprintf(buffer + off, "EoE"); |
1118 first = 0; |
569 first = 0; |
1119 } |
570 } |
1120 if (slave->sii_mailbox_protocols & EC_MBOX_COE) { |
571 if (slave->sii_mailbox_protocols & EC_MBOX_COE) { |
1121 if (!first) printk(", "); |
572 if (!first) off += sprintf(buffer + off, ", "); |
1122 printk("CoE"); |
573 off += sprintf(buffer + off, "CoE"); |
1123 first = 0; |
574 first = 0; |
1124 } |
575 } |
1125 if (slave->sii_mailbox_protocols & EC_MBOX_FOE) { |
576 if (slave->sii_mailbox_protocols & EC_MBOX_FOE) { |
1126 if (!first) printk(", "); |
577 if (!first) off += sprintf(buffer + off, ", "); |
1127 printk("FoE"); |
578 off += sprintf(buffer + off, "FoE"); |
1128 first = 0; |
579 first = 0; |
1129 } |
580 } |
1130 if (slave->sii_mailbox_protocols & EC_MBOX_SOE) { |
581 if (slave->sii_mailbox_protocols & EC_MBOX_SOE) { |
1131 if (!first) printk(", "); |
582 if (!first) off += sprintf(buffer + off, ", "); |
1132 printk("SoE"); |
583 off += sprintf(buffer + off, "SoE"); |
1133 first = 0; |
584 first = 0; |
1134 } |
585 } |
1135 if (slave->sii_mailbox_protocols & EC_MBOX_VOE) { |
586 if (slave->sii_mailbox_protocols & EC_MBOX_VOE) { |
1136 if (!first) printk(", "); |
587 if (!first) off += sprintf(buffer + off, ", "); |
1137 printk("VoE"); |
588 off += sprintf(buffer + off, "VoE"); |
1138 } |
589 } |
1139 printk("\n"); |
590 off += sprintf(buffer + off, "\n"); |
1140 } |
591 } |
1141 |
592 |
1142 EC_INFO(" EEPROM data:\n"); |
593 if (slave->sii_alias || slave->sii_group |
1143 |
594 || slave->sii_image || slave->sii_order) |
1144 EC_INFO(" EEPROM content size: %i Bytes\n", slave->eeprom_size); |
595 off += sprintf(buffer + off, "\nSII data:\n"); |
1145 |
596 |
1146 if (slave->sii_alias) |
597 if (slave->sii_alias) |
1147 EC_INFO(" Configured station alias: 0x%04X (%i)\n", |
598 off += sprintf(buffer + off, " Configured station alias:" |
1148 slave->sii_alias, slave->sii_alias); |
599 " 0x%04X (%i)\n", slave->sii_alias, slave->sii_alias); |
1149 |
600 if (slave->sii_group) |
1150 EC_INFO(" Vendor-ID: 0x%08X, Product code: 0x%08X\n", |
601 off += sprintf(buffer + off, " Group: %s\n", slave->sii_group); |
1151 slave->sii_vendor_id, slave->sii_product_code); |
602 if (slave->sii_image) |
1152 EC_INFO(" Revision number: 0x%08X, Serial number: 0x%08X\n", |
603 off += sprintf(buffer + off, " Image: %s\n", slave->sii_image); |
1153 slave->sii_revision_number, slave->sii_serial_number); |
604 if (slave->sii_order) |
1154 |
605 off += sprintf(buffer + off, " Order#: %s\n", slave->sii_order); |
1155 if (slave->eeprom_group) |
606 |
1156 EC_INFO(" Group: %s\n", slave->eeprom_group); |
607 if (!list_empty(&slave->sii_syncs)) |
1157 if (slave->eeprom_image) |
608 off += sprintf(buffer + off, "\nSync-Managers:\n"); |
1158 EC_INFO(" Image: %s\n", slave->eeprom_image); |
609 |
1159 if (slave->eeprom_order) |
610 list_for_each_entry(sync, &slave->sii_syncs, list) { |
1160 EC_INFO(" Order#: %s\n", slave->eeprom_order); |
611 off += sprintf(buffer + off, " %i: 0x%04X, length %i," |
1161 if (slave->eeprom_name) |
612 " control 0x%02X, %s\n", |
1162 EC_INFO(" Name: %s\n", slave->eeprom_name); |
613 sync->index, sync->physical_start_address, |
1163 |
614 sync->length, sync->control_register, |
1164 if (!list_empty(&slave->eeprom_syncs)) { |
615 sync->enable ? "enable" : "disable"); |
1165 EC_INFO(" Sync-Managers:\n"); |
616 } |
1166 list_for_each_entry(sync, &slave->eeprom_syncs, list) { |
617 |
1167 EC_INFO(" %i: 0x%04X, length %i, control 0x%02X, %s\n", |
618 if (!list_empty(&slave->sii_pdos)) |
1168 sync->index, sync->physical_start_address, |
619 off += sprintf(buffer + off, "\nPDOs:\n"); |
1169 sync->length, sync->control_register, |
620 |
1170 sync->enable ? "enable" : "disable"); |
621 list_for_each_entry(pdo, &slave->sii_pdos, list) { |
1171 } |
622 off += sprintf(buffer + off, |
1172 } |
623 " %s \"%s\" (0x%04X), -> Sync-Manager %i\n", |
1173 |
624 pdo->type == EC_RX_PDO ? "RXPDO" : "TXPDO", |
1174 list_for_each_entry(pdo, &slave->eeprom_pdos, list) { |
625 pdo->name ? pdo->name : "???", |
1175 EC_INFO(" %s \"%s\" (0x%04X), -> Sync-Manager %i\n", |
626 pdo->index, pdo->sync_index); |
1176 pdo->type == EC_RX_PDO ? "RXPDO" : "TXPDO", |
|
1177 pdo->name ? pdo->name : "???", |
|
1178 pdo->index, pdo->sync_manager); |
|
1179 |
627 |
1180 list_for_each_entry(pdo_entry, &pdo->entries, list) { |
628 list_for_each_entry(pdo_entry, &pdo->entries, list) { |
1181 EC_INFO(" \"%s\" 0x%04X:%X, %i Bit\n", |
629 off += sprintf(buffer + off, " \"%s\" 0x%04X:%X, %i Bit\n", |
1182 pdo_entry->name ? pdo_entry->name : "???", |
630 pdo_entry->name ? pdo_entry->name : "???", |
1183 pdo_entry->index, pdo_entry->subindex, |
631 pdo_entry->index, pdo_entry->subindex, |
1184 pdo_entry->bit_length); |
632 pdo_entry->bit_length); |
1185 } |
633 } |
1186 } |
634 } |
1187 |
635 |
1188 if (verbosity < 2) return; |
636 off += sprintf(buffer + off, "\n"); |
1189 |
637 |
1190 if (!list_empty(&slave->sdo_dictionary)) { |
638 return off; |
1191 EC_INFO(" SDO-Dictionary:\n"); |
639 } |
1192 list_for_each_entry(sdo, &slave->sdo_dictionary, list) { |
640 |
1193 EC_INFO(" 0x%04X \"%s\"\n", sdo->index, |
641 /*****************************************************************************/ |
1194 sdo->name ? sdo->name : ""); |
642 |
1195 EC_INFO(" Object code: 0x%02X\n", sdo->object_code); |
643 #if 0 |
1196 list_for_each_entry(sdo_entry, &sdo->entries, list) { |
|
1197 EC_INFO(" 0x%04X:%i \"%s\", type 0x%04X, %i bits\n", |
|
1198 sdo->index, sdo_entry->subindex, |
|
1199 sdo_entry->name ? sdo_entry->name : "", |
|
1200 sdo_entry->data_type, sdo_entry->bit_length); |
|
1201 } |
|
1202 } |
|
1203 } |
|
1204 } |
|
1205 |
|
1206 /*****************************************************************************/ |
|
1207 |
644 |
1208 /** |
645 /** |
1209 Outputs the values of the CRC faoult counters and resets them. |
646 Outputs the values of the CRC faoult counters and resets them. |
1210 \return 0 in case of success, else < 0 |
647 \return 0 in case of success, else < 0 |
1211 */ |
648 */ |
1458 } |
867 } |
1459 |
868 |
1460 /*****************************************************************************/ |
869 /*****************************************************************************/ |
1461 |
870 |
1462 /** |
871 /** |
1463 \return size of sync manager contents |
872 Calculates the size of a sync manager by evaluating PDO sizes. |
1464 */ |
873 \return sync manager size |
1465 |
874 */ |
1466 size_t ec_slave_calc_sync_size(const ec_slave_t *slave, /**< EtherCAT slave */ |
875 |
1467 const ec_sync_t *sync /**< sync manager */ |
876 uint16_t ec_slave_calc_sync_size(const ec_slave_t *slave, |
1468 ) |
877 /**< EtherCAT slave */ |
1469 { |
878 const ec_sii_sync_t *sync |
1470 unsigned int i, found; |
879 /**< sync manager */ |
1471 const ec_field_t *field; |
880 ) |
1472 const ec_varsize_t *var; |
881 { |
1473 size_t size; |
882 ec_sii_pdo_t *pdo; |
1474 |
883 ec_sii_pdo_entry_t *pdo_entry; |
1475 // if size is specified, return size |
884 unsigned int bit_size; |
1476 if (sync->size) return sync->size; |
885 |
1477 |
886 if (sync->length) return sync->length; |
1478 // sync manager has variable size (size == 0). |
887 |
1479 |
888 bit_size = 0; |
1480 size = 0; |
889 list_for_each_entry(pdo, &slave->sii_pdos, list) { |
1481 for (i = 0; (field = sync->fields[i]); i++) { |
890 if (pdo->sync_index != sync->index) continue; |
1482 found = 0; |
891 |
1483 list_for_each_entry(var, &slave->varsize_fields, list) { |
892 list_for_each_entry(pdo_entry, &pdo->entries, list) { |
1484 if (var->field != field) continue; |
893 bit_size += pdo_entry->bit_length; |
1485 size += var->size; |
894 } |
1486 found = 1; |
895 } |
1487 } |
896 |
1488 |
897 if (bit_size % 8) // round up to full bytes |
1489 if (!found) { |
898 return bit_size / 8 + 1; |
1490 EC_WARN("Variable data field \"%s\" of slave %i has no size" |
899 else |
1491 " information!\n", field->name, slave->ring_position); |
900 return bit_size / 8; |
1492 } |
901 } |
1493 } |
902 |
1494 return size; |
903 /*****************************************************************************/ |
|
904 |
|
905 /** |
|
906 \return non-zero if slave is a bus coupler |
|
907 */ |
|
908 |
|
909 int ec_slave_is_coupler(const ec_slave_t *slave) |
|
910 { |
|
911 // TODO: Better bus coupler criterion |
|
912 return slave->sii_vendor_id == 0x00000002 |
|
913 && slave->sii_product_code == 0x044C2C52; |
1495 } |
914 } |
1496 |
915 |
1497 /****************************************************************************** |
916 /****************************************************************************** |
1498 * Realtime interface |
917 * Realtime interface |
1499 *****************************************************************************/ |
918 *****************************************************************************/ |
1500 |
919 |
1501 /** |
920 /** |
1502 Writes the "configured station alias" to the slave's EEPROM. |
|
1503 \return 0 in case of success, else < 0 |
921 \return 0 in case of success, else < 0 |
1504 \ingroup RealtimeInterface |
922 \ingroup RealtimeInterface |
1505 */ |
923 */ |
1506 |
924 |
1507 int ecrt_slave_write_alias(ec_slave_t *slave, /**< EtherCAT slave */ |
925 int ecrt_slave_pdo_size(ec_slave_t *slave, /**< EtherCAT slave */ |
1508 uint16_t alias /**< new alias */ |
926 uint16_t pdo_index, /**< PDO index */ |
1509 ) |
927 uint8_t pdo_subindex, /**< PDO subindex */ |
1510 { |
928 size_t size /**< new PDO size */ |
1511 return ec_slave_sii_write16(slave, 0x0004, alias); |
929 ) |
1512 } |
930 { |
1513 |
931 EC_WARN("ecrt_slave_pdo_size() currently not available.\n"); |
1514 /*****************************************************************************/ |
932 return -1; |
1515 |
933 |
1516 /** |
934 #if 0 |
1517 \return 0 in case of success, else < 0 |
|
1518 \ingroup RealtimeInterface |
|
1519 */ |
|
1520 |
|
1521 int ecrt_slave_field_size(ec_slave_t *slave, /**< EtherCAT slave */ |
|
1522 const char *field_name, /**< data field name */ |
|
1523 unsigned int field_index, /**< data field index */ |
|
1524 size_t size /**< new data field size */ |
|
1525 ) |
|
1526 { |
|
1527 unsigned int i, j, field_counter; |
935 unsigned int i, j, field_counter; |
1528 const ec_sync_t *sync; |
936 const ec_sii_sync_t *sync; |
1529 const ec_field_t *field; |
937 const ec_pdo_t *pdo; |
1530 ec_varsize_t *var; |
938 ec_varsize_t *var; |
1531 |
939 |
1532 if (!slave->type) { |
940 if (!slave->type) { |
1533 EC_ERR("Slave %i has no type information!\n", slave->ring_position); |
941 EC_ERR("Slave %i has no type information!\n", slave->ring_position); |
1534 return -1; |
942 return -1; |