19 /*****************************************************************************/ |
19 /*****************************************************************************/ |
20 |
20 |
21 int ec_slave_fetch_categories(ec_slave_t *); |
21 int ec_slave_fetch_categories(ec_slave_t *); |
22 int ec_slave_fetch_strings(ec_slave_t *, const uint8_t *); |
22 int ec_slave_fetch_strings(ec_slave_t *, const uint8_t *); |
23 int ec_slave_fetch_general(ec_slave_t *, const uint8_t *); |
23 int ec_slave_fetch_general(ec_slave_t *, const uint8_t *); |
24 void ec_slave_fetch_fmmu(ec_slave_t *, const uint8_t *); |
24 int ec_slave_fetch_sync(ec_slave_t *, const uint8_t *, size_t); |
25 void ec_slave_fetch_sync(ec_slave_t *, const uint8_t *); |
25 int ec_slave_fetch_pdo(ec_slave_t *, const uint8_t *, size_t, ec_pdo_type_t); |
26 void ec_slave_fetch_txpdo(ec_slave_t *, const uint8_t *); |
|
27 void ec_slave_fetch_rxpdo(ec_slave_t *, const uint8_t *); |
|
28 int ec_slave_locate_string(ec_slave_t *, unsigned int, char **); |
26 int ec_slave_locate_string(ec_slave_t *, unsigned int, char **); |
29 |
27 |
30 /*****************************************************************************/ |
28 /*****************************************************************************/ |
31 |
29 |
32 /** |
30 /** |
51 slave->sii_revision_number = 0; |
49 slave->sii_revision_number = 0; |
52 slave->sii_serial_number = 0; |
50 slave->sii_serial_number = 0; |
53 slave->type = NULL; |
51 slave->type = NULL; |
54 slave->registered = 0; |
52 slave->registered = 0; |
55 slave->fmmu_count = 0; |
53 slave->fmmu_count = 0; |
56 |
|
57 INIT_LIST_HEAD(&slave->eeprom_strings); |
|
58 slave->eeprom_name = NULL; |
54 slave->eeprom_name = NULL; |
59 slave->eeprom_group = NULL; |
55 slave->eeprom_group = NULL; |
60 slave->eeprom_desc = NULL; |
56 slave->eeprom_desc = NULL; |
|
57 INIT_LIST_HEAD(&slave->eeprom_strings); |
|
58 INIT_LIST_HEAD(&slave->eeprom_syncs); |
|
59 INIT_LIST_HEAD(&slave->eeprom_pdos); |
61 } |
60 } |
62 |
61 |
63 /*****************************************************************************/ |
62 /*****************************************************************************/ |
64 |
63 |
65 /** |
64 /** |
66 EtherCAT-Slave-Destruktor. |
65 EtherCAT-Slave-Destruktor. |
67 */ |
66 */ |
68 |
67 |
69 void ec_slave_clear(ec_slave_t *slave /**< EtherCAT-Slave */) |
68 void ec_slave_clear(ec_slave_t *slave /**< EtherCAT-Slave */) |
70 { |
69 { |
71 ec_slave_string_t *string, *next; |
70 ec_eeprom_string_t *string, *next_str; |
|
71 ec_eeprom_sync_t *sync, *next_sync; |
|
72 ec_eeprom_pdo_t *pdo, *next_pdo; |
|
73 ec_eeprom_pdo_entry_t *entry, *next_ent; |
72 |
74 |
73 // Alle Strings freigeben |
75 // Alle Strings freigeben |
74 list_for_each_entry_safe(string, next, &slave->eeprom_strings, list) { |
76 list_for_each_entry_safe(string, next_str, &slave->eeprom_strings, list) { |
75 list_del(&string->list); |
77 list_del(&string->list); |
76 kfree(string); |
78 kfree(string); |
|
79 } |
|
80 |
|
81 // Alle Sync-Manager freigeben |
|
82 list_for_each_entry_safe(sync, next_sync, &slave->eeprom_syncs, list) { |
|
83 list_del(&sync->list); |
|
84 kfree(sync); |
|
85 } |
|
86 |
|
87 // Alle PDOs freigeben |
|
88 list_for_each_entry_safe(pdo, next_pdo, &slave->eeprom_pdos, list) { |
|
89 list_del(&pdo->list); |
|
90 if (pdo->name) kfree(pdo->name); |
|
91 |
|
92 // Alle Entries innerhalb eines PDOs freigeben |
|
93 list_for_each_entry_safe(entry, next_ent, &pdo->entries, list) { |
|
94 list_del(&entry->list); |
|
95 if (entry->name) kfree(entry->name); |
|
96 kfree(entry); |
|
97 } |
|
98 |
|
99 kfree(pdo); |
77 } |
100 } |
78 |
101 |
79 if (slave->eeprom_name) kfree(slave->eeprom_name); |
102 if (slave->eeprom_name) kfree(slave->eeprom_name); |
80 if (slave->eeprom_group) kfree(slave->eeprom_group); |
103 if (slave->eeprom_group) kfree(slave->eeprom_group); |
81 if (slave->eeprom_desc) kfree(slave->eeprom_desc); |
104 if (slave->eeprom_desc) kfree(slave->eeprom_desc); |
312 EC_ERR("Failed to allocate 64k bytes for category data.\n"); |
335 EC_ERR("Failed to allocate 64k bytes for category data.\n"); |
313 return -1; |
336 return -1; |
314 } |
337 } |
315 |
338 |
316 while (1) { |
339 while (1) { |
317 // read category header |
340 // read category type |
318 if (ec_slave_sii_read(slave, word_offset, &value)) { |
341 if (ec_slave_sii_read(slave, word_offset, &value)) { |
319 EC_ERR("Unable to read category header and size.\n"); |
342 EC_ERR("Unable to read category header.\n"); |
320 goto out_free; |
343 goto out_free; |
321 } |
344 } |
322 |
345 |
323 // Last category? |
346 // Last category? |
324 if ((value & 0xFFFF) == 0xFFFF) break; |
347 if ((value & 0xFFFF) == 0xFFFF) break; |
325 |
348 |
326 header = value & 0x7FFF; |
349 cat_type = value & 0x7FFF; |
327 word_count = (value >> 16) & 0xFFFF; |
350 word_count = (value >> 16) & 0xFFFF; |
328 |
351 |
329 // Fetch category data |
352 // Fetch category data |
330 for (i = 0; i < word_count; i++) { |
353 for (i = 0; i < word_count; i++) { |
331 if (ec_slave_sii_read(slave, word_offset + 2 + i, &value)) { |
354 if (ec_slave_sii_read(slave, word_offset + 2 + i, &value)) { |
342 cat_data[i * 2] = (value >> 16) & 0xFF; |
365 cat_data[i * 2] = (value >> 16) & 0xFF; |
343 cat_data[i * 2 + 1] = (value >> 24) & 0xFF; |
366 cat_data[i * 2 + 1] = (value >> 24) & 0xFF; |
344 } |
367 } |
345 } |
368 } |
346 |
369 |
347 switch (header) |
370 switch (cat_type) |
348 { |
371 { |
349 case 0x000A: |
372 case 0x000A: |
350 if (ec_slave_fetch_strings(slave, cat_data)) |
373 if (ec_slave_fetch_strings(slave, cat_data)) |
351 goto out_free; |
374 goto out_free; |
352 break; |
375 break; |
353 case 0x001E: |
376 case 0x001E: |
354 case 0x0001: |
|
355 if (ec_slave_fetch_general(slave, cat_data)) |
377 if (ec_slave_fetch_general(slave, cat_data)) |
356 goto out_free; |
378 goto out_free; |
357 break; |
379 break; |
358 case 0x0028: |
380 case 0x0028: |
359 case 0x0002: |
|
360 ec_slave_fetch_fmmu(slave, cat_data); |
|
361 break; |
381 break; |
362 case 0x0029: |
382 case 0x0029: |
363 case 0x0003: |
383 if (ec_slave_fetch_sync(slave, cat_data, word_count)) |
364 ec_slave_fetch_sync(slave, cat_data); |
384 goto out_free; |
365 break; |
385 break; |
366 case 0x0032: |
386 case 0x0032: |
367 case 0x0004: |
387 if (ec_slave_fetch_pdo(slave, cat_data, word_count, EC_TX_PDO)) |
368 ec_slave_fetch_txpdo(slave, cat_data); |
388 goto out_free; |
369 break; |
389 break; |
370 case 0x0033: |
390 case 0x0033: |
371 case 0x0005: |
391 if (ec_slave_fetch_pdo(slave, cat_data, word_count, EC_RX_PDO)) |
372 ec_slave_fetch_rxpdo(slave, cat_data); |
392 goto out_free; |
373 break; |
393 break; |
374 default: |
394 default: |
375 EC_WARN("Unknown category header 0x%04X in slave %i.\n", |
395 EC_WARN("Unknown category type 0x%04X in slave %i.\n", |
376 header, slave->ring_position); |
396 cat_type, slave->ring_position); |
377 } |
397 } |
378 |
398 |
379 word_offset += 2 + word_count; |
399 word_offset += 2 + word_count; |
380 } |
400 } |
381 |
401 |
400 ) |
420 ) |
401 { |
421 { |
402 unsigned int string_count, i; |
422 unsigned int string_count, i; |
403 size_t size; |
423 size_t size; |
404 off_t offset; |
424 off_t offset; |
405 ec_slave_string_t *string; |
425 ec_eeprom_string_t *string; |
406 |
426 |
407 string_count = data[0]; |
427 string_count = data[0]; |
408 offset = 1; |
428 offset = 1; |
409 for (i = 0; i < string_count; i++) { |
429 for (i = 0; i < string_count; i++) { |
410 size = data[offset]; |
430 size = data[offset]; |
411 // Speicher für String-Objekt und Daten in einem Rutsch allozieren |
431 // Speicher für String-Objekt und Daten in einem Rutsch allozieren |
412 if (!(string = (ec_slave_string_t *) kmalloc(sizeof(ec_slave_string_t) |
432 if (!(string = (ec_eeprom_string_t *) |
413 + size + 1, |
433 kmalloc(sizeof(ec_eeprom_string_t) + size + 1, GFP_KERNEL))) { |
414 GFP_KERNEL))) { |
|
415 EC_ERR("Failed to allocate string memory.\n"); |
434 EC_ERR("Failed to allocate string memory.\n"); |
416 return -1; |
435 return -1; |
417 } |
436 } |
418 string->size = size; |
437 string->size = size; |
419 string->data = (char *) string + sizeof(ec_slave_string_t); |
438 string->data = (char *) string + sizeof(ec_eeprom_string_t); |
420 memcpy(string->data, data + offset + 1, size); |
439 memcpy(string->data, data + offset + 1, size); |
421 string->data[size] = 0x00; |
440 string->data[size] = 0x00; |
422 list_add_tail(&string->list, &slave->eeprom_strings); |
441 list_add_tail(&string->list, &slave->eeprom_strings); |
423 offset += 1 + size; |
442 offset += 1 + size; |
424 } |
443 } |
447 } |
466 } |
448 |
467 |
449 /*****************************************************************************/ |
468 /*****************************************************************************/ |
450 |
469 |
451 /** |
470 /** |
452 Holt die Daten einer FMMU-Kategorie. |
|
453 */ |
|
454 |
|
455 void ec_slave_fetch_fmmu(ec_slave_t *slave, /**< EtherCAT-Slave */ |
|
456 const uint8_t *data /**< Kategorie-Daten */ |
|
457 ) |
|
458 { |
|
459 } |
|
460 |
|
461 /*****************************************************************************/ |
|
462 |
|
463 /** |
|
464 Holt die Daten einer Sync-Manager-Kategorie. |
471 Holt die Daten einer Sync-Manager-Kategorie. |
465 */ |
472 */ |
466 |
473 |
467 void ec_slave_fetch_sync(ec_slave_t *slave, /**< EtherCAT-Slave */ |
474 int ec_slave_fetch_sync(ec_slave_t *slave, /**< EtherCAT-Slave */ |
468 const uint8_t *data /**< Kategorie-Daten */ |
475 const uint8_t *data, /**< Kategorie-Daten */ |
469 ) |
476 size_t word_count /**< Anzahl Words */ |
470 { |
477 ) |
|
478 { |
|
479 unsigned int sync_count, i; |
|
480 ec_eeprom_sync_t *sync; |
|
481 |
|
482 sync_count = word_count / 4; // Sync-Manager-Strunktur ist 4 Worte lang |
|
483 |
|
484 for (i = 0; i < sync_count; i++, data += 8) { |
|
485 if (!(sync = (ec_eeprom_sync_t *) kmalloc(sizeof(ec_eeprom_sync_t), |
|
486 GFP_KERNEL))) { |
|
487 EC_ERR("Failed to allocate Sync-Manager memory.\n"); |
|
488 return -1; |
|
489 } |
|
490 |
|
491 sync->index = i; |
|
492 sync->physical_start_address = *((uint16_t *) (data + 0)); |
|
493 sync->length = *((uint16_t *) (data + 2)); |
|
494 sync->control_register = data[4]; |
|
495 sync->enable = data[6]; |
|
496 |
|
497 list_add_tail(&sync->list, &slave->eeprom_syncs); |
|
498 } |
|
499 |
|
500 return 0; |
471 } |
501 } |
472 |
502 |
473 /*****************************************************************************/ |
503 /*****************************************************************************/ |
474 |
504 |
475 /** |
505 /** |
476 Holt die Daten einer TXPDO-Kategorie. |
506 Holt die Daten einer TXPDO-Kategorie. |
477 */ |
507 */ |
478 |
508 |
479 void ec_slave_fetch_txpdo(ec_slave_t *slave, /**< EtherCAT-Slave */ |
509 int ec_slave_fetch_pdo(ec_slave_t *slave, /**< EtherCAT-Slave */ |
480 const uint8_t *data /**< Kategorie-Daten */ |
510 const uint8_t *data, /**< Kategorie-Daten */ |
481 ) |
511 size_t word_count, /**< Anzahl Worte */ |
482 { |
512 ec_pdo_type_t pdo_type /**< PDO-Typ */ |
483 } |
513 ) |
484 |
514 { |
485 /*****************************************************************************/ |
515 ec_eeprom_pdo_t *pdo; |
486 |
516 ec_eeprom_pdo_entry_t *entry; |
487 /** |
517 unsigned int entry_count, i; |
488 Holt die Daten einer RXPDO-Kategorie. |
518 |
489 */ |
519 while (word_count >= 4) { |
490 |
520 if (!(pdo = (ec_eeprom_pdo_t *) kmalloc(sizeof(ec_eeprom_pdo_t), |
491 void ec_slave_fetch_rxpdo(ec_slave_t *slave, /**< EtherCAT-Slave */ |
521 GFP_KERNEL))) { |
492 const uint8_t *data /**< Kategorie-Daten */ |
522 EC_ERR("Failed to allocate PDO memory.\n"); |
493 ) |
523 return -1; |
494 { |
524 } |
|
525 |
|
526 INIT_LIST_HEAD(&pdo->entries); |
|
527 pdo->type = pdo_type; |
|
528 |
|
529 pdo->index = *((uint16_t *) data); |
|
530 entry_count = data[2]; |
|
531 pdo->sync_manager = data[3]; |
|
532 pdo->name = NULL; |
|
533 ec_slave_locate_string(slave, data[5], &pdo->name); |
|
534 |
|
535 list_add_tail(&pdo->list, &slave->eeprom_pdos); |
|
536 |
|
537 word_count -= 4; |
|
538 data += 8; |
|
539 |
|
540 for (i = 0; i < entry_count; i++) { |
|
541 if (!(entry = (ec_eeprom_pdo_entry_t *) |
|
542 kmalloc(sizeof(ec_eeprom_pdo_entry_t), GFP_KERNEL))) { |
|
543 EC_ERR("Failed to allocate PDO entry memory.\n"); |
|
544 return -1; |
|
545 } |
|
546 |
|
547 entry->index = *((uint16_t *) data); |
|
548 entry->subindex = data[2]; |
|
549 entry->name = NULL; |
|
550 ec_slave_locate_string(slave, data[3], &entry->name); |
|
551 entry->bit_length = data[5]; |
|
552 |
|
553 list_add_tail(&entry->list, &pdo->entries); |
|
554 |
|
555 word_count -= 4; |
|
556 data += 8; |
|
557 } |
|
558 } |
|
559 |
|
560 return 0; |
495 } |
561 } |
496 |
562 |
497 /*****************************************************************************/ |
563 /*****************************************************************************/ |
498 |
564 |
499 /** |
565 /** |
500 Durchsucht die temporären Strings und dupliziert den gefundenen String. |
566 Durchsucht die temporären Strings und dupliziert den gefundenen String. |
501 */ |
567 */ |
502 |
568 |
503 int ec_slave_locate_string(ec_slave_t *slave, unsigned int index, char **ptr) |
569 int ec_slave_locate_string(ec_slave_t *slave, unsigned int index, char **ptr) |
504 { |
570 { |
505 ec_slave_string_t *string; |
571 ec_eeprom_string_t *string; |
506 |
572 char *err_string; |
|
573 |
|
574 // Erst alten Speicher freigeben |
507 if (*ptr) { |
575 if (*ptr) { |
508 kfree(*ptr); |
576 kfree(*ptr); |
509 *ptr = NULL; |
577 *ptr = NULL; |
510 } |
578 } |
511 |
579 |
|
580 // Index 0 bedeutet "nicht belegt" |
512 if (!index) return 0; |
581 if (!index) return 0; |
513 |
582 |
|
583 // EEPROM-String mit Index finden und kopieren |
514 list_for_each_entry(string, &slave->eeprom_strings, list) { |
584 list_for_each_entry(string, &slave->eeprom_strings, list) { |
515 if (!(--index)) { |
585 if (--index) continue; |
516 if (!(*ptr = (char *) kmalloc(string->size + 1, GFP_KERNEL))) { |
586 |
517 EC_ERR("Unable to allocate string memory.\n"); |
587 if (!(*ptr = (char *) kmalloc(string->size + 1, GFP_KERNEL))) { |
518 return -1; |
588 EC_ERR("Unable to allocate string memory.\n"); |
519 } |
589 return -1; |
520 memcpy(*ptr, string->data, string->size + 1); |
590 } |
521 break; |
591 memcpy(*ptr, string->data, string->size + 1); |
522 } |
592 return 0; |
523 } |
593 } |
524 |
594 |
|
595 EC_WARN("String %i not found in slave %i.\n", index, slave->ring_position); |
|
596 |
|
597 err_string = "(string not found)"; |
|
598 |
|
599 if (!(*ptr = (char *) kmalloc(strlen(err_string) + 1, GFP_KERNEL))) { |
|
600 EC_ERR("Unable to allocate string memory.\n"); |
|
601 return -1; |
|
602 } |
|
603 |
|
604 memcpy(*ptr, err_string, strlen(err_string) + 1); |
525 return 0; |
605 return 0; |
526 } |
606 } |
527 |
607 |
528 /*****************************************************************************/ |
608 /*****************************************************************************/ |
529 |
609 |
723 slave->base_type, slave->base_revision, slave->base_build); |
807 slave->base_type, slave->base_revision, slave->base_build); |
724 EC_INFO("| Supported FMMUs: %i, Sync managers: %i\n", |
808 EC_INFO("| Supported FMMUs: %i, Sync managers: %i\n", |
725 slave->base_fmmu_count, slave->base_sync_count); |
809 slave->base_fmmu_count, slave->base_sync_count); |
726 |
810 |
727 EC_INFO("| EEPROM data:\n"); |
811 EC_INFO("| EEPROM data:\n"); |
|
812 |
728 if (slave->sii_alias) |
813 if (slave->sii_alias) |
729 EC_INFO("| Configured station alias: 0x%04X (%i)\n", |
814 EC_INFO("| Configured station alias: 0x%04X (%i)\n", |
730 slave->sii_alias, slave->sii_alias); |
815 slave->sii_alias, slave->sii_alias); |
|
816 |
731 EC_INFO("| Vendor-ID: 0x%08X, Product code: 0x%08X\n", |
817 EC_INFO("| Vendor-ID: 0x%08X, Product code: 0x%08X\n", |
732 slave->sii_vendor_id, slave->sii_product_code); |
818 slave->sii_vendor_id, slave->sii_product_code); |
733 EC_INFO("| Revision number: 0x%08X, Serial number: 0x%08X\n", |
819 EC_INFO("| Revision number: 0x%08X, Serial number: 0x%08X\n", |
734 slave->sii_revision_number, slave->sii_serial_number); |
820 slave->sii_revision_number, slave->sii_serial_number); |
|
821 |
735 if (slave->eeprom_name) |
822 if (slave->eeprom_name) |
736 EC_INFO("| Name: %s\n", slave->eeprom_name); |
823 EC_INFO("| Name: %s\n", slave->eeprom_name); |
737 if (slave->eeprom_group) |
824 if (slave->eeprom_group) |
738 EC_INFO("| Group: %s\n", slave->eeprom_group); |
825 EC_INFO("| Group: %s\n", slave->eeprom_group); |
739 if (slave->eeprom_desc) |
826 if (slave->eeprom_desc) |
740 EC_INFO("| Description: %s\n", slave->eeprom_desc); |
827 EC_INFO("| Description: %s\n", slave->eeprom_desc); |
|
828 |
|
829 if (!list_empty(&slave->eeprom_syncs)) { |
|
830 EC_INFO("| Sync-Managers:\n"); |
|
831 list_for_each_entry(sync, &slave->eeprom_syncs, list) { |
|
832 EC_INFO("| %i: 0x%04X, length %i, control 0x%02X, %s\n", |
|
833 sync->index, sync->physical_start_address, sync->length, |
|
834 sync->control_register, |
|
835 sync->enable ? "enable" : "disable"); |
|
836 } |
|
837 } |
|
838 |
|
839 list_for_each_entry(pdo, &slave->eeprom_pdos, list) { |
|
840 EC_INFO("| %s \"%s\" (0x%04X), -> Sync-Manager %i\n", |
|
841 pdo->type == EC_RX_PDO ? "RXPDO" : "TXPDO", |
|
842 pdo->name ? pdo->name : "???", |
|
843 pdo->index, pdo->sync_manager); |
|
844 |
|
845 list_for_each_entry(entry, &pdo->entries, list) { |
|
846 EC_INFO("| \"%s\" 0x%04X:%X, %i Bit\n", |
|
847 entry->name ? entry->name : "???", |
|
848 entry->index, entry->subindex, entry->bit_length); |
|
849 } |
|
850 } |
|
851 |
741 EC_INFO("x---------------------------------------------\n"); |
852 EC_INFO("x---------------------------------------------\n"); |
742 } |
853 } |
743 |
854 |
744 /*****************************************************************************/ |
855 /*****************************************************************************/ |
745 |
856 |