686 |
686 |
687 /** |
687 /** |
688 Outputs all information about a certain slave. |
688 Outputs all information about a certain slave. |
689 */ |
689 */ |
690 |
690 |
691 size_t ec_slave_info(const ec_slave_t *slave, /**< EtherCAT slave */ |
691 ssize_t ec_slave_info(const ec_slave_t *slave, /**< EtherCAT slave */ |
692 char *buffer /**< Output buffer */ |
692 char *buffer /**< Output buffer */ |
693 ) |
693 ) |
694 { |
694 { |
695 off_t off = 0; |
|
696 ec_sync_t *sync; |
695 ec_sync_t *sync; |
697 ec_pdo_t *pdo; |
696 ec_pdo_t *pdo; |
698 ec_pdo_entry_t *pdo_entry; |
697 ec_pdo_entry_t *pdo_entry; |
699 int first, i; |
698 int first, i; |
700 ec_sdo_data_t *sdodata; |
699 ec_sdo_data_t *sdodata; |
701 char str[20]; |
700 char str[20]; |
702 |
701 char *large_buffer, *buf; |
703 off += sprintf(buffer + off, "Ring position: %i\n", |
702 unsigned int size; |
|
703 |
|
704 if (!(large_buffer = (char *) kmalloc(PAGE_SIZE * 2, GFP_KERNEL))) { |
|
705 return -ENOMEM; |
|
706 } |
|
707 |
|
708 buf = large_buffer; |
|
709 |
|
710 buf += sprintf(buf, "Ring position: %i\n", |
704 slave->ring_position); |
711 slave->ring_position); |
705 off += sprintf(buffer + off, "State: "); |
712 buf += sprintf(buf, "State: "); |
706 off += ec_state_string(slave->current_state, buffer + off); |
713 buf += ec_state_string(slave->current_state, buf); |
707 off += sprintf(buffer + off, " ("); |
714 buf += sprintf(buf, " ("); |
708 off += ec_state_string(slave->requested_state, buffer + off); |
715 buf += ec_state_string(slave->requested_state, buf); |
709 off += sprintf(buffer + off, ")\n"); |
716 buf += sprintf(buf, ")\n"); |
710 off += sprintf(buffer + off, "Flags: %s, %s\n\n", |
717 buf += sprintf(buf, "Flags: %s, %s\n\n", |
711 slave->online_state == EC_SLAVE_ONLINE ? "online" : "OFFLINE", |
718 slave->online_state == EC_SLAVE_ONLINE ? "online" : "OFFLINE", |
712 slave->error_flag ? "ERROR" : "ok"); |
719 slave->error_flag ? "ERROR" : "ok"); |
713 |
720 |
714 off += sprintf(buffer + off, "Data link status:\n"); |
721 buf += sprintf(buf, "Data link status:\n"); |
715 for (i = 0; i < 4; i++) { |
722 for (i = 0; i < 4; i++) { |
716 off += sprintf(buffer + off, " Port %u: Phy %u (", |
723 buf += sprintf(buf, " Port %u: Phy %u (", |
717 i, slave->sii_physical_layer[i]); |
724 i, slave->sii_physical_layer[i]); |
718 switch (slave->sii_physical_layer[i]) { |
725 switch (slave->sii_physical_layer[i]) { |
719 case 0x00: |
726 case 0x00: |
720 off += sprintf(buffer + off, "EBUS"); |
727 buf += sprintf(buf, "EBUS"); |
721 break; |
728 break; |
722 case 0x01: |
729 case 0x01: |
723 off += sprintf(buffer + off, "100BASE-TX"); |
730 buf += sprintf(buf, "100BASE-TX"); |
724 break; |
731 break; |
725 case 0x02: |
732 case 0x02: |
726 off += sprintf(buffer + off, "100BASE-FX"); |
733 buf += sprintf(buf, "100BASE-FX"); |
727 break; |
734 break; |
728 default: |
735 default: |
729 off += sprintf(buffer + off, "unknown"); |
736 buf += sprintf(buf, "unknown"); |
730 } |
737 } |
731 off += sprintf(buffer + off, "), Link %s, Loop %s, %s\n", |
738 buf += sprintf(buf, "), Link %s, Loop %s, %s\n", |
732 slave->dl_link[i] ? "up" : "down", |
739 slave->dl_link[i] ? "up" : "down", |
733 slave->dl_loop[i] ? "closed" : "open", |
740 slave->dl_loop[i] ? "closed" : "open", |
734 slave->dl_signal[i] ? "Signal detected" : "No signal"); |
741 slave->dl_signal[i] ? "Signal detected" : "No signal"); |
735 } |
742 } |
736 off += sprintf(buffer + off, "\n"); |
743 buf += sprintf(buf, "\n"); |
737 |
744 |
738 if (slave->sii_alias) |
745 if (slave->sii_alias) |
739 off += sprintf(buffer + off, "Configured station alias:" |
746 buf += sprintf(buf, "Configured station alias:" |
740 " 0x%04X (%i)\n\n", slave->sii_alias, slave->sii_alias); |
747 " 0x%04X (%i)\n\n", slave->sii_alias, slave->sii_alias); |
741 |
748 |
742 off += sprintf(buffer + off, "Identity:\n"); |
749 buf += sprintf(buf, "Identity:\n"); |
743 off += sprintf(buffer + off, " Vendor ID: 0x%08X (%u)\n", |
750 buf += sprintf(buf, " Vendor ID: 0x%08X (%u)\n", |
744 slave->sii_vendor_id, slave->sii_vendor_id); |
751 slave->sii_vendor_id, slave->sii_vendor_id); |
745 off += sprintf(buffer + off, " Product code: 0x%08X (%u)\n", |
752 buf += sprintf(buf, " Product code: 0x%08X (%u)\n", |
746 slave->sii_product_code, slave->sii_product_code); |
753 slave->sii_product_code, slave->sii_product_code); |
747 off += sprintf(buffer + off, " Revision number: 0x%08X (%u)\n", |
754 buf += sprintf(buf, " Revision number: 0x%08X (%u)\n", |
748 slave->sii_revision_number, slave->sii_revision_number); |
755 slave->sii_revision_number, slave->sii_revision_number); |
749 off += sprintf(buffer + off, " Serial number: 0x%08X (%u)\n\n", |
756 buf += sprintf(buf, " Serial number: 0x%08X (%u)\n\n", |
750 slave->sii_serial_number, slave->sii_serial_number); |
757 slave->sii_serial_number, slave->sii_serial_number); |
751 |
758 |
752 if (slave->sii_mailbox_protocols) { |
759 if (slave->sii_mailbox_protocols) { |
753 off += sprintf(buffer + off, "Mailboxes:\n"); |
760 buf += sprintf(buf, "Mailboxes:\n"); |
754 off += sprintf(buffer + off, " RX: 0x%04X/%u, TX: 0x%04X/%u\n", |
761 buf += sprintf(buf, " RX: 0x%04X/%u, TX: 0x%04X/%u\n", |
755 slave->sii_rx_mailbox_offset, slave->sii_rx_mailbox_size, |
762 slave->sii_rx_mailbox_offset, slave->sii_rx_mailbox_size, |
756 slave->sii_tx_mailbox_offset, slave->sii_tx_mailbox_size); |
763 slave->sii_tx_mailbox_offset, slave->sii_tx_mailbox_size); |
757 off += sprintf(buffer + off, " Supported protocols: "); |
764 buf += sprintf(buf, " Supported protocols: "); |
758 |
765 |
759 first = 1; |
766 first = 1; |
760 if (slave->sii_mailbox_protocols & EC_MBOX_AOE) { |
767 if (slave->sii_mailbox_protocols & EC_MBOX_AOE) { |
761 off += sprintf(buffer + off, "AoE"); |
768 buf += sprintf(buf, "AoE"); |
762 first = 0; |
769 first = 0; |
763 } |
770 } |
764 if (slave->sii_mailbox_protocols & EC_MBOX_EOE) { |
771 if (slave->sii_mailbox_protocols & EC_MBOX_EOE) { |
765 if (!first) off += sprintf(buffer + off, ", "); |
772 if (!first) buf += sprintf(buf, ", "); |
766 off += sprintf(buffer + off, "EoE"); |
773 buf += sprintf(buf, "EoE"); |
767 first = 0; |
774 first = 0; |
768 } |
775 } |
769 if (slave->sii_mailbox_protocols & EC_MBOX_COE) { |
776 if (slave->sii_mailbox_protocols & EC_MBOX_COE) { |
770 if (!first) off += sprintf(buffer + off, ", "); |
777 if (!first) buf += sprintf(buf, ", "); |
771 off += sprintf(buffer + off, "CoE"); |
778 buf += sprintf(buf, "CoE"); |
772 first = 0; |
779 first = 0; |
773 } |
780 } |
774 if (slave->sii_mailbox_protocols & EC_MBOX_FOE) { |
781 if (slave->sii_mailbox_protocols & EC_MBOX_FOE) { |
775 if (!first) off += sprintf(buffer + off, ", "); |
782 if (!first) buf += sprintf(buf, ", "); |
776 off += sprintf(buffer + off, "FoE"); |
783 buf += sprintf(buf, "FoE"); |
777 first = 0; |
784 first = 0; |
778 } |
785 } |
779 if (slave->sii_mailbox_protocols & EC_MBOX_SOE) { |
786 if (slave->sii_mailbox_protocols & EC_MBOX_SOE) { |
780 if (!first) off += sprintf(buffer + off, ", "); |
787 if (!first) buf += sprintf(buf, ", "); |
781 off += sprintf(buffer + off, "SoE"); |
788 buf += sprintf(buf, "SoE"); |
782 first = 0; |
789 first = 0; |
783 } |
790 } |
784 if (slave->sii_mailbox_protocols & EC_MBOX_VOE) { |
791 if (slave->sii_mailbox_protocols & EC_MBOX_VOE) { |
785 if (!first) off += sprintf(buffer + off, ", "); |
792 if (!first) buf += sprintf(buf, ", "); |
786 off += sprintf(buffer + off, "VoE"); |
793 buf += sprintf(buf, "VoE"); |
787 } |
794 } |
788 off += sprintf(buffer + off, "\n\n"); |
795 buf += sprintf(buf, "\n\n"); |
789 } |
796 } |
790 |
797 |
791 off += sprintf(buffer + off, "Current consumption: %i mA\n\n", |
798 buf += sprintf(buf, "Current consumption: %i mA\n\n", |
792 slave->sii_current_on_ebus); |
799 slave->sii_current_on_ebus); |
793 |
800 |
794 if (slave->sii_group || slave->sii_image || slave->sii_order |
801 if (slave->sii_group || slave->sii_image || slave->sii_order |
795 || slave->sii_name) { |
802 || slave->sii_name) { |
796 off += sprintf(buffer + off, "General:\n"); |
803 buf += sprintf(buf, "General:\n"); |
797 |
804 |
798 if (slave->sii_group) |
805 if (slave->sii_group) |
799 off += sprintf(buffer + off, " Group: %s\n", slave->sii_group); |
806 buf += sprintf(buf, " Group: %s\n", slave->sii_group); |
800 if (slave->sii_image) |
807 if (slave->sii_image) |
801 off += sprintf(buffer + off, " Image: %s\n", slave->sii_image); |
808 buf += sprintf(buf, " Image: %s\n", slave->sii_image); |
802 if (slave->sii_order) |
809 if (slave->sii_order) |
803 off += sprintf(buffer + off, " Order number: %s\n", |
810 buf += sprintf(buf, " Order number: %s\n", |
804 slave->sii_order); |
811 slave->sii_order); |
805 if (slave->sii_name) |
812 if (slave->sii_name) |
806 off += sprintf(buffer + off, " Name: %s\n", slave->sii_name); |
813 buf += sprintf(buf, " Name: %s\n", slave->sii_name); |
807 off += sprintf(buffer + off, "\n"); |
814 buf += sprintf(buf, "\n"); |
808 } |
815 } |
809 |
816 |
810 if (slave->sii_sync_count) { |
817 if (slave->sii_sync_count) { |
811 off += sprintf(buffer + off, "Sync managers / PDO mapping:\n"); |
818 buf += sprintf(buf, "Sync managers / PDO mapping:\n"); |
812 |
819 |
813 for (i = 0; i < slave->sii_sync_count; i++) { |
820 for (i = 0; i < slave->sii_sync_count; i++) { |
814 sync = &slave->sii_syncs[i]; |
821 sync = &slave->sii_syncs[i]; |
815 off += sprintf(buffer + off, |
822 buf += sprintf(buf, |
816 " SM%u: addr 0x%04X, size %i, control 0x%02X, %s\n", |
823 " SM%u: addr 0x%04X, size %i, control 0x%02X, %s\n", |
817 sync->index, sync->physical_start_address, |
824 sync->index, sync->physical_start_address, |
818 ec_sync_size(sync), sync->control_register, |
825 ec_sync_size(sync), sync->control_register, |
819 sync->enable ? "enable" : "disable"); |
826 sync->enable ? "enable" : "disable"); |
820 |
827 |
821 if (list_empty(&sync->pdos)) { |
828 if (list_empty(&sync->pdos)) { |
822 off += sprintf(buffer + off, " No PDOs mapped.\n"); |
829 buf += sprintf(buf, " No PDOs mapped.\n"); |
823 } else if (sync->mapping_source != EC_SYNC_MAPPING_NONE) { |
830 } else if (sync->mapping_source != EC_SYNC_MAPPING_NONE) { |
824 off += sprintf(buffer + off, |
831 buf += sprintf(buf, |
825 " PDO mapping information from %s.\n", |
832 " PDO mapping information from %s.\n", |
826 sync->mapping_source == EC_SYNC_MAPPING_SII |
833 sync->mapping_source == EC_SYNC_MAPPING_SII |
827 ? "SII" : "CoE"); |
834 ? "SII" : "CoE"); |
828 } |
835 } |
829 |
836 |
830 list_for_each_entry(pdo, &sync->pdos, list) { |
837 list_for_each_entry(pdo, &sync->pdos, list) { |
831 off += sprintf(buffer + off, " %s 0x%04X \"%s\"\n", |
838 buf += sprintf(buf, " %s 0x%04X \"%s\"\n", |
832 pdo->type == EC_RX_PDO ? "RxPdo" : "TxPdo", |
839 pdo->type == EC_RX_PDO ? "RxPdo" : "TxPdo", |
833 pdo->index, pdo->name ? pdo->name : "???"); |
840 pdo->index, pdo->name ? pdo->name : "???"); |
834 |
841 |
835 list_for_each_entry(pdo_entry, &pdo->entries, list) { |
842 list_for_each_entry(pdo_entry, &pdo->entries, list) { |
836 off += sprintf(buffer + off, |
843 buf += sprintf(buf, |
837 " 0x%04X:%X \"%s\", %i bit\n", |
844 " 0x%04X:%X \"%s\", %i bit\n", |
838 pdo_entry->index, pdo_entry->subindex, |
845 pdo_entry->index, pdo_entry->subindex, |
839 pdo_entry->name ? pdo_entry->name : "???", |
846 pdo_entry->name ? pdo_entry->name : "???", |
840 pdo_entry->bit_length); |
847 pdo_entry->bit_length); |
841 } |
848 } |
842 } |
849 } |
843 } |
850 } |
844 off += sprintf(buffer + off, "\n"); |
851 buf += sprintf(buf, "\n"); |
845 } |
852 } |
846 |
853 |
847 // type-cast to avoid warnings on some compilers |
854 // type-cast to avoid warnings on some compilers |
848 if (!list_empty((struct list_head *) &slave->sii_pdos)) { |
855 if (!list_empty((struct list_head *) &slave->sii_pdos)) { |
849 off += sprintf(buffer + off, "Available PDOs from SII:\n"); |
856 buf += sprintf(buf, "Available PDOs from SII:\n"); |
850 |
857 |
851 list_for_each_entry(pdo, &slave->sii_pdos, list) { |
858 list_for_each_entry(pdo, &slave->sii_pdos, list) { |
852 off += sprintf(buffer + off, " %s 0x%04X \"%s\"", |
859 buf += sprintf(buf, " %s 0x%04X \"%s\"", |
853 pdo->type == EC_RX_PDO ? "RxPdo" : "TxPdo", |
860 pdo->type == EC_RX_PDO ? "RxPdo" : "TxPdo", |
854 pdo->index, pdo->name ? pdo->name : "???"); |
861 pdo->index, pdo->name ? pdo->name : "???"); |
855 if (pdo->sync_index >= 0) |
862 if (pdo->sync_index >= 0) |
856 off += sprintf(buffer + off, ", default mapping: SM%u.\n", |
863 buf += sprintf(buf, ", default mapping: SM%u.\n", |
857 pdo->sync_index); |
864 pdo->sync_index); |
858 else |
865 else |
859 off += sprintf(buffer + off, ", no default mapping.\n"); |
866 buf += sprintf(buf, ", no default mapping.\n"); |
860 |
867 |
861 list_for_each_entry(pdo_entry, &pdo->entries, list) { |
868 list_for_each_entry(pdo_entry, &pdo->entries, list) { |
862 off += sprintf(buffer + off, " 0x%04X:%X \"%s\", %i bit\n", |
869 buf += sprintf(buf, " 0x%04X:%X \"%s\", %i bit\n", |
863 pdo_entry->index, pdo_entry->subindex, |
870 pdo_entry->index, pdo_entry->subindex, |
864 pdo_entry->name ? pdo_entry->name : "???", |
871 pdo_entry->name ? pdo_entry->name : "???", |
865 pdo_entry->bit_length); |
872 pdo_entry->bit_length); |
866 } |
873 } |
867 } |
874 } |
868 off += sprintf(buffer + off, "\n"); |
875 buf += sprintf(buf, "\n"); |
869 } |
876 } |
870 |
877 |
871 // type-cast to avoid warnings on some compilers |
878 // type-cast to avoid warnings on some compilers |
872 if (!list_empty((struct list_head *) &slave->sdo_confs)) { |
879 if (!list_empty((struct list_head *) &slave->sdo_confs)) { |
873 off += sprintf(buffer + off, "SDO configurations:\n"); |
880 buf += sprintf(buf, "SDO configurations:\n"); |
874 |
881 |
875 list_for_each_entry(sdodata, &slave->sdo_confs, list) { |
882 list_for_each_entry(sdodata, &slave->sdo_confs, list) { |
876 switch (sdodata->size) { |
883 switch (sdodata->size) { |
877 case 1: sprintf(str, "%i", EC_READ_U8(sdodata->data)); break; |
884 case 1: sprintf(str, "%i", EC_READ_U8(sdodata->data)); break; |
878 case 2: sprintf(str, "%i", EC_READ_U16(sdodata->data)); break; |
885 case 2: sprintf(str, "%i", EC_READ_U16(sdodata->data)); break; |
879 case 4: sprintf(str, "%i", EC_READ_U32(sdodata->data)); break; |
886 case 4: sprintf(str, "%i", EC_READ_U32(sdodata->data)); break; |
880 default: sprintf(str, "(invalid size)"); break; |
887 default: sprintf(str, "(invalid size)"); break; |
881 } |
888 } |
882 off += sprintf(buffer + off, " 0x%04X:%-3i -> %s\n", |
889 buf += sprintf(buf, " 0x%04X:%-3i -> %s\n", |
883 sdodata->index, sdodata->subindex, str); |
890 sdodata->index, sdodata->subindex, str); |
884 } |
891 } |
885 off += sprintf(buffer + off, "\n"); |
892 buf += sprintf(buf, "\n"); |
886 } |
893 } |
887 |
894 |
888 return off; |
895 size = buf - large_buffer; |
|
896 if (size >= PAGE_SIZE) { |
|
897 const char trunc[] = "\n---TRUNCATED---\n"; |
|
898 unsigned int len = strlen(trunc); |
|
899 memcpy(large_buffer + PAGE_SIZE - len, trunc, len); |
|
900 } |
|
901 |
|
902 size = min(size, (unsigned int) PAGE_SIZE); |
|
903 memcpy(buffer, large_buffer, size); |
|
904 kfree(large_buffer); |
|
905 return size; |
889 } |
906 } |
890 |
907 |
891 /*****************************************************************************/ |
908 /*****************************************************************************/ |
892 |
909 |
893 /** |
910 /** |