190 #ifdef EC_EOE |
225 #ifdef EC_EOE |
191 master->eoe_thread = NULL; |
226 master->eoe_thread = NULL; |
192 INIT_LIST_HEAD(&master->eoe_handlers); |
227 INIT_LIST_HEAD(&master->eoe_handlers); |
193 #endif |
228 #endif |
194 |
229 |
195 ec_mutex_init(&master->io_mutex); |
230 sema_init(&master->io_sem, 1); |
196 master->fsm_queue_lock_cb = NULL; |
231 master->send_cb = NULL; |
197 master->fsm_queue_unlock_cb = NULL; |
232 master->receive_cb = NULL; |
198 master->fsm_queue_locking_data = NULL; |
233 master->cb_data = NULL; |
199 master->app_fsm_queue_lock_cb = NULL; |
234 master->app_send_cb = NULL; |
200 master->app_fsm_queue_unlock_cb = NULL; |
235 master->app_receive_cb = NULL; |
201 master->app_fsm_queue_locking_data = NULL; |
236 master->app_cb_data = NULL; |
202 |
237 |
203 INIT_LIST_HEAD(&master->sii_requests); |
238 INIT_LIST_HEAD(&master->sii_requests); |
204 init_waitqueue_head(&master->sii_queue); |
239 INIT_LIST_HEAD(&master->emerg_reg_requests); |
205 |
240 |
206 INIT_LIST_HEAD(&master->reg_requests); |
241 init_waitqueue_head(&master->request_queue); |
207 init_waitqueue_head(&master->reg_queue); |
|
208 |
242 |
209 // init devices |
243 // init devices |
210 ret = ec_device_init(&master->main_device, master); |
244 for (dev_idx = EC_DEVICE_MAIN; dev_idx < ec_master_num_devices(master); |
211 if (ret < 0) |
245 dev_idx++) { |
212 goto out_return; |
246 ret = ec_device_init(&master->devices[dev_idx], master); |
213 |
247 if (ret < 0) { |
214 ret = ec_device_init(&master->backup_device, master); |
248 goto out_clear_devices; |
215 if (ret < 0) |
249 } |
216 goto out_clear_main; |
250 } |
217 |
251 |
218 // init state machine datagram |
252 // init state machine datagram |
219 ec_datagram_init(&master->fsm_datagram); |
253 ec_datagram_init(&master->fsm_datagram); |
220 snprintf(master->fsm_datagram.name, EC_DATAGRAM_NAME_SIZE, "master-fsm"); |
254 snprintf(master->fsm_datagram.name, EC_DATAGRAM_NAME_SIZE, "master-fsm"); |
221 ret = ec_datagram_prealloc(&master->fsm_datagram, EC_MAX_DATA_SIZE); |
255 ret = ec_datagram_prealloc(&master->fsm_datagram, EC_MAX_DATA_SIZE); |
222 if (ret < 0) { |
256 if (ret < 0) { |
223 ec_datagram_clear(&master->fsm_datagram); |
257 ec_datagram_clear(&master->fsm_datagram); |
224 EC_MASTER_ERR(master, "Failed to allocate FSM datagram.\n"); |
258 EC_MASTER_ERR(master, "Failed to allocate FSM datagram.\n"); |
225 goto out_clear_backup; |
259 goto out_clear_devices; |
226 } |
260 } |
227 |
261 |
228 // create state machine object |
262 // create state machine object |
229 ec_mbox_init(&master->fsm_mbox, &master->fsm_datagram); |
|
230 ec_fsm_master_init(&master->fsm, master, &master->fsm_datagram); |
263 ec_fsm_master_init(&master->fsm, master, &master->fsm_datagram); |
|
264 |
|
265 // alloc external datagram ring |
|
266 for (i = 0; i < EC_EXT_RING_SIZE; i++) { |
|
267 ec_datagram_t *datagram = &master->ext_datagram_ring[i]; |
|
268 ret = ec_datagram_prealloc(datagram, EC_MAX_DATA_SIZE); |
|
269 if (ret) { |
|
270 EC_MASTER_ERR(master, "Failed to allocate external" |
|
271 " datagram %u.\n", i); |
|
272 goto out_clear_ext_datagrams; |
|
273 } |
|
274 } |
231 |
275 |
232 // init reference sync datagram |
276 // init reference sync datagram |
233 ec_datagram_init(&master->ref_sync_datagram); |
277 ec_datagram_init(&master->ref_sync_datagram); |
234 snprintf(master->ref_sync_datagram.name, EC_DATAGRAM_NAME_SIZE, "refsync"); |
278 snprintf(master->ref_sync_datagram.name, EC_DATAGRAM_NAME_SIZE, |
235 ret = ec_datagram_apwr(&master->ref_sync_datagram, 0, 0x0910, 8); |
279 "refsync"); |
|
280 ret = ec_datagram_prealloc(&master->ref_sync_datagram, 4); |
236 if (ret < 0) { |
281 if (ret < 0) { |
237 ec_datagram_clear(&master->ref_sync_datagram); |
282 ec_datagram_clear(&master->ref_sync_datagram); |
238 EC_MASTER_ERR(master, "Failed to allocate reference" |
283 EC_MASTER_ERR(master, "Failed to allocate reference" |
239 " synchronisation datagram.\n"); |
284 " synchronisation datagram.\n"); |
240 goto out_clear_fsm; |
285 goto out_clear_ext_datagrams; |
241 } |
286 } |
242 |
287 |
243 // init sync datagram |
288 // init sync datagram |
244 ec_datagram_init(&master->sync_datagram); |
289 ec_datagram_init(&master->sync_datagram); |
245 snprintf(master->sync_datagram.name, EC_DATAGRAM_NAME_SIZE, "sync"); |
290 snprintf(master->sync_datagram.name, EC_DATAGRAM_NAME_SIZE, "sync"); |
671 master->phase = EC_IDLE; |
779 master->phase = EC_IDLE; |
672 } |
780 } |
673 |
781 |
674 /*****************************************************************************/ |
782 /*****************************************************************************/ |
675 |
783 |
676 /** Injects fsm datagrams that fit into the datagram queue. |
784 /** Injects external datagrams that fit into the datagram queue. |
677 */ |
785 */ |
678 void ec_master_inject_fsm_datagrams( |
786 void ec_master_inject_external_datagrams( |
679 ec_master_t *master /**< EtherCAT master */ |
787 ec_master_t *master /**< EtherCAT master */ |
680 ) |
788 ) |
681 { |
789 { |
682 ec_datagram_t *datagram, *next; |
790 ec_datagram_t *datagram; |
683 size_t queue_size = 0; |
791 size_t queue_size = 0, new_queue_size = 0; |
684 |
792 #if DEBUG_INJECT |
685 if (master->fsm_queue_lock_cb) { |
793 unsigned int datagram_count = 0; |
686 master->fsm_queue_lock_cb(master->fsm_queue_locking_data); |
794 #endif |
687 } |
795 |
688 |
796 if (master->ext_ring_idx_rt == master->ext_ring_idx_fsm) { |
689 if (ec_mutex_trylock(&master->fsm_queue_mutex) == 0) { |
797 // nothing to inject |
690 goto unlock_cb; |
798 return; |
691 } |
|
692 |
|
693 if (list_empty(&master->fsm_datagram_queue)) { |
|
694 goto unlock; |
|
695 } |
799 } |
696 |
800 |
697 list_for_each_entry(datagram, &master->datagram_queue, queue) { |
801 list_for_each_entry(datagram, &master->datagram_queue, queue) { |
698 queue_size += datagram->data_size; |
802 if (datagram->state == EC_DATAGRAM_QUEUED) { |
699 } |
803 queue_size += datagram->data_size; |
700 |
804 } |
701 list_for_each_entry_safe(datagram, next, &master->fsm_datagram_queue, |
805 } |
702 fsm_queue) { |
806 |
703 queue_size += datagram->data_size; |
|
704 if (queue_size <= master->max_queue_size) { |
|
705 list_del_init(&datagram->fsm_queue); |
|
706 #if DEBUG_INJECT |
807 #if DEBUG_INJECT |
707 EC_MASTER_DBG(master, 2, "Injecting fsm datagram %p" |
808 EC_MASTER_DBG(master, 1, "Injecting datagrams, queue_size=%zu\n", |
708 " size=%zu, queue_size=%zu\n", datagram, |
809 queue_size); |
709 datagram->data_size, queue_size); |
810 #endif |
|
811 |
|
812 while (master->ext_ring_idx_rt != master->ext_ring_idx_fsm) { |
|
813 datagram = &master->ext_datagram_ring[master->ext_ring_idx_rt]; |
|
814 |
|
815 if (datagram->state != EC_DATAGRAM_INIT) { |
|
816 // skip datagram |
|
817 master->ext_ring_idx_rt = |
|
818 (master->ext_ring_idx_rt + 1) % EC_EXT_RING_SIZE; |
|
819 continue; |
|
820 } |
|
821 |
|
822 new_queue_size = queue_size + datagram->data_size; |
|
823 if (new_queue_size <= master->max_queue_size) { |
|
824 #if DEBUG_INJECT |
|
825 EC_MASTER_DBG(master, 1, "Injecting datagram %s" |
|
826 " size=%zu, queue_size=%zu\n", datagram->name, |
|
827 datagram->data_size, new_queue_size); |
|
828 datagram_count++; |
710 #endif |
829 #endif |
711 #ifdef EC_HAVE_CYCLES |
830 #ifdef EC_HAVE_CYCLES |
712 datagram->cycles_sent = 0; |
831 datagram->cycles_sent = 0; |
713 #endif |
832 #endif |
714 datagram->jiffies_sent = 0; // FIXME why? |
833 datagram->jiffies_sent = 0; |
715 ec_master_queue_datagram(master, datagram); |
834 ec_master_queue_datagram(master, datagram); |
716 } else { |
835 queue_size = new_queue_size; |
717 if (datagram->data_size > master->max_queue_size) { |
836 } |
718 list_del_init(&datagram->fsm_queue); |
837 else if (datagram->data_size > master->max_queue_size) { |
|
838 datagram->state = EC_DATAGRAM_ERROR; |
|
839 EC_MASTER_ERR(master, "External datagram %s is too large," |
|
840 " size=%zu, max_queue_size=%zu\n", |
|
841 datagram->name, datagram->data_size, |
|
842 master->max_queue_size); |
|
843 } |
|
844 else { // datagram does not fit in the current cycle |
|
845 #ifdef EC_HAVE_CYCLES |
|
846 cycles_t cycles_now = get_cycles(); |
|
847 |
|
848 if (cycles_now - datagram->cycles_sent |
|
849 > ext_injection_timeout_cycles) |
|
850 #else |
|
851 if (jiffies - datagram->jiffies_sent |
|
852 > ext_injection_timeout_jiffies) |
|
853 #endif |
|
854 { |
|
855 #if defined EC_RT_SYSLOG || DEBUG_INJECT |
|
856 unsigned int time_us; |
|
857 #endif |
|
858 |
719 datagram->state = EC_DATAGRAM_ERROR; |
859 datagram->state = EC_DATAGRAM_ERROR; |
720 EC_MASTER_ERR(master, "Fsm datagram %p is too large," |
860 |
721 " size=%zu, max_queue_size=%zu\n", |
861 #if defined EC_RT_SYSLOG || DEBUG_INJECT |
722 datagram, datagram->data_size, |
|
723 master->max_queue_size); |
|
724 } else { |
|
725 #ifdef EC_HAVE_CYCLES |
862 #ifdef EC_HAVE_CYCLES |
726 cycles_t cycles_now = get_cycles(); |
863 time_us = (unsigned int) |
727 |
864 ((cycles_now - datagram->cycles_sent) * 1000LL) |
728 if (cycles_now - datagram->cycles_sent |
865 / cpu_khz; |
729 > fsm_injection_timeout_cycles) |
|
730 #else |
866 #else |
731 if (jiffies - datagram->jiffies_sent |
867 time_us = (unsigned int) |
732 > fsm_injection_timeout_jiffies) |
868 ((jiffies - datagram->jiffies_sent) * 1000000 / HZ); |
733 #endif |
869 #endif |
734 { |
870 EC_MASTER_ERR(master, "Timeout %u us: Injecting" |
735 unsigned int time_us; |
871 " external datagram %s size=%zu," |
736 |
872 " max_queue_size=%zu\n", time_us, datagram->name, |
737 list_del_init(&datagram->fsm_queue); |
873 datagram->data_size, master->max_queue_size); |
738 datagram->state = EC_DATAGRAM_ERROR; |
874 #endif |
739 #ifdef EC_HAVE_CYCLES |
875 } |
740 time_us = (unsigned int) |
876 else { |
741 ((cycles_now - datagram->cycles_sent) * 1000LL) |
|
742 / cpu_khz; |
|
743 #else |
|
744 time_us = (unsigned int) |
|
745 ((jiffies - datagram->jiffies_sent) * 1000000 / HZ); |
|
746 #endif |
|
747 EC_MASTER_ERR(master, "Timeout %u us: Injecting" |
|
748 " fsm datagram %p size=%zu," |
|
749 " max_queue_size=%zu\n", time_us, datagram, |
|
750 datagram->data_size, master->max_queue_size); |
|
751 } |
|
752 #if DEBUG_INJECT |
877 #if DEBUG_INJECT |
753 else { |
878 EC_MASTER_DBG(master, 1, "Deferred injecting" |
754 EC_MASTER_DBG(master, 2, "Deferred injecting" |
879 " external datagram %s size=%u, queue_size=%u\n", |
755 " of fsm datagram %p" |
880 datagram->name, datagram->data_size, queue_size); |
756 " size=%zu, queue_size=%zu\n", |
881 #endif |
757 datagram, datagram->data_size, queue_size); |
882 break; |
758 } |
|
759 #endif |
|
760 } |
883 } |
761 } |
884 } |
762 } |
885 |
763 |
886 master->ext_ring_idx_rt = |
764 unlock: |
887 (master->ext_ring_idx_rt + 1) % EC_EXT_RING_SIZE; |
765 ec_mutex_unlock(&master->fsm_queue_mutex); |
888 } |
766 unlock_cb: |
889 |
767 if (master->fsm_queue_unlock_cb) { |
890 #if DEBUG_INJECT |
768 master->fsm_queue_unlock_cb(master->fsm_queue_locking_data); |
891 EC_MASTER_DBG(master, 1, "Injected %u datagrams.\n", datagram_count); |
769 } |
892 #endif |
770 } |
893 } |
771 |
894 |
772 /*****************************************************************************/ |
895 /*****************************************************************************/ |
773 |
896 |
774 /** Sets the expected interval between calls to ecrt_master_send |
897 /** Sets the expected interval between calls to ecrt_master_send |
861 * infinite loop!). Set the state to EC_DATAGRAM_QUEUED again, probably |
947 * infinite loop!). Set the state to EC_DATAGRAM_QUEUED again, probably |
862 * causing an unmatched datagram. */ |
948 * causing an unmatched datagram. */ |
863 list_for_each_entry(queued_datagram, &master->datagram_queue, queue) { |
949 list_for_each_entry(queued_datagram, &master->datagram_queue, queue) { |
864 if (queued_datagram == datagram) { |
950 if (queued_datagram == datagram) { |
865 datagram->skip_count++; |
951 datagram->skip_count++; |
866 if (master->debug_level) { |
952 #ifdef EC_RT_SYSLOG |
867 EC_MASTER_DBG(master, 1, "Skipping datagram %p (", datagram); |
953 EC_MASTER_DBG(master, 1, |
868 ec_datagram_output_info(datagram); |
954 "Datagram %p already queued (skipping).\n", datagram); |
869 printk(")\n"); |
955 #endif |
870 } |
956 datagram->state = EC_DATAGRAM_QUEUED; |
871 goto queued; |
957 return; |
872 } |
958 } |
873 } |
959 } |
874 |
960 |
875 list_add_tail(&datagram->queue, &master->datagram_queue); |
961 list_add_tail(&datagram->queue, &master->datagram_queue); |
876 queued: |
|
877 datagram->state = EC_DATAGRAM_QUEUED; |
962 datagram->state = EC_DATAGRAM_QUEUED; |
878 } |
963 } |
879 |
964 |
880 /*****************************************************************************/ |
965 /*****************************************************************************/ |
881 |
966 |
882 /** Sends the datagrams in the queue. |
967 /** Places a datagram in the non-application datagram queue. |
883 * |
968 */ |
884 */ |
969 void ec_master_queue_datagram_ext( |
885 void ec_master_send_datagrams(ec_master_t *master /**< EtherCAT master */) |
970 ec_master_t *master, /**< EtherCAT master */ |
|
971 ec_datagram_t *datagram /**< datagram */ |
|
972 ) |
|
973 { |
|
974 down(&master->ext_queue_sem); |
|
975 list_add_tail(&datagram->queue, &master->ext_datagram_queue); |
|
976 up(&master->ext_queue_sem); |
|
977 } |
|
978 |
|
979 /*****************************************************************************/ |
|
980 |
|
981 /** Sends the datagrams in the queue for a certain device. |
|
982 * |
|
983 */ |
|
984 void ec_master_send_datagrams( |
|
985 ec_master_t *master, /**< EtherCAT master */ |
|
986 ec_device_index_t device_index /**< Device index. */ |
|
987 ) |
886 { |
988 { |
887 ec_datagram_t *datagram, *next; |
989 ec_datagram_t *datagram, *next; |
888 size_t datagram_size; |
990 size_t datagram_size; |
889 uint8_t *frame_data, *cur_data, *frame_datagram_data; |
991 uint8_t *frame_data, *cur_data = NULL; |
890 void *follows_word; |
992 void *follows_word; |
891 #ifdef EC_HAVE_CYCLES |
993 #ifdef EC_HAVE_CYCLES |
892 cycles_t cycles_start, cycles_sent, cycles_end; |
994 cycles_t cycles_start, cycles_sent, cycles_end; |
893 #endif |
995 #endif |
894 unsigned long jiffies_sent; |
996 unsigned long jiffies_sent; |
895 unsigned int frame_count, more_datagrams_waiting; |
997 unsigned int frame_count, more_datagrams_waiting; |
896 struct list_head sent_datagrams; |
998 struct list_head sent_datagrams; |
897 ec_fmmu_config_t* domain_fmmu; |
|
898 |
999 |
899 #ifdef EC_HAVE_CYCLES |
1000 #ifdef EC_HAVE_CYCLES |
900 cycles_start = get_cycles(); |
1001 cycles_start = get_cycles(); |
901 #endif |
1002 #endif |
902 frame_count = 0; |
1003 frame_count = 0; |
903 INIT_LIST_HEAD(&sent_datagrams); |
1004 INIT_LIST_HEAD(&sent_datagrams); |
904 |
1005 |
905 EC_MASTER_DBG(master, 2, "ec_master_send_datagrams\n"); |
1006 EC_MASTER_DBG(master, 2, "%s(device_index = %u)\n", |
|
1007 __func__, device_index); |
906 |
1008 |
907 do { |
1009 do { |
908 // fetch pointer to transmit socket buffer |
1010 frame_data = NULL; |
909 frame_data = ec_device_tx_data(&master->main_device); |
|
910 cur_data = frame_data + EC_FRAME_HEADER_SIZE; |
|
911 follows_word = NULL; |
1011 follows_word = NULL; |
912 more_datagrams_waiting = 0; |
1012 more_datagrams_waiting = 0; |
913 |
1013 |
914 // fill current frame with datagrams |
1014 // fill current frame with datagrams |
915 list_for_each_entry(datagram, &master->datagram_queue, queue) { |
1015 list_for_each_entry(datagram, &master->datagram_queue, queue) { |
916 if (datagram->state != EC_DATAGRAM_QUEUED) continue; |
1016 if (datagram->state != EC_DATAGRAM_QUEUED || |
|
1017 datagram->device_index != device_index) { |
|
1018 continue; |
|
1019 } |
|
1020 |
|
1021 if (!frame_data) { |
|
1022 // fetch pointer to transmit socket buffer |
|
1023 frame_data = |
|
1024 ec_device_tx_data(&master->devices[device_index]); |
|
1025 cur_data = frame_data + EC_FRAME_HEADER_SIZE; |
|
1026 } |
917 |
1027 |
918 // does the current datagram fit in the frame? |
1028 // does the current datagram fit in the frame? |
919 datagram_size = EC_DATAGRAM_HEADER_SIZE + datagram->data_size |
1029 datagram_size = EC_DATAGRAM_HEADER_SIZE + datagram->data_size |
920 + EC_DATAGRAM_FOOTER_SIZE; |
1030 + EC_DATAGRAM_FOOTER_SIZE; |
921 if (cur_data - frame_data + datagram_size > ETH_DATA_LEN) { |
1031 if (cur_data - frame_data + datagram_size > ETH_DATA_LEN) { |
924 } |
1034 } |
925 |
1035 |
926 list_add_tail(&datagram->sent, &sent_datagrams); |
1036 list_add_tail(&datagram->sent, &sent_datagrams); |
927 datagram->index = master->datagram_index++; |
1037 datagram->index = master->datagram_index++; |
928 |
1038 |
929 EC_MASTER_DBG(master, 2, "Adding datagram %p i=0x%02X size=%zu\n", |
1039 EC_MASTER_DBG(master, 2, "Adding datagram 0x%02X\n", |
930 datagram, datagram->index, datagram_size); |
1040 datagram->index); |
931 |
1041 |
932 // set "datagram following" flag in previous frame |
1042 // set "datagram following" flag in previous datagram |
933 if (follows_word) { |
1043 if (follows_word) { |
934 EC_WRITE_U16(follows_word, |
1044 EC_WRITE_U16(follows_word, |
935 EC_READ_U16(follows_word) | 0x8000); |
1045 EC_READ_U16(follows_word) | 0x8000); |
936 } |
1046 } |
937 |
1047 |
938 // EtherCAT datagram header |
1048 // EtherCAT datagram header |
939 EC_WRITE_U8 (cur_data, datagram->type); |
1049 EC_WRITE_U8 (cur_data, datagram->type); |
940 EC_WRITE_U8 (cur_data + 1, datagram->index); |
1050 EC_WRITE_U8 (cur_data + 1, datagram->index); |
941 memcpy(cur_data + 2, datagram->address, EC_ADDR_LEN); |
1051 memcpy(cur_data + 2, datagram->address, EC_ADDR_LEN); |
942 EC_WRITE_U16(cur_data + 6, datagram->data_size & 0x7FF); |
1052 EC_WRITE_U16(cur_data + 6, datagram->data_size & 0x7FF); |
943 EC_WRITE_U16(cur_data + 8, 0x0000); |
1053 EC_WRITE_U16(cur_data + 8, 0x0000); |
944 follows_word = cur_data + 6; |
1054 follows_word = cur_data + 6; |
945 cur_data += EC_DATAGRAM_HEADER_SIZE; |
1055 cur_data += EC_DATAGRAM_HEADER_SIZE; |
946 |
1056 |
947 // EtherCAT datagram data |
1057 // EtherCAT datagram data |
948 frame_datagram_data = cur_data; |
1058 memcpy(cur_data, datagram->data, datagram->data_size); |
949 |
|
950 // distinguish between domain and non-domain datagrams... |
|
951 // this is not nice... FIXME |
|
952 if (datagram->domain) { |
|
953 unsigned int datagram_address = |
|
954 EC_READ_U32(datagram->address); |
|
955 int i = 0; |
|
956 uint8_t *domain_data = datagram->data; |
|
957 |
|
958 // FIXME all FMMU configs are taken into acount, |
|
959 // maybe the belong to another datagram? |
|
960 // test with large process data! |
|
961 |
|
962 list_for_each_entry(domain_fmmu, |
|
963 &datagram->domain->fmmu_configs, list) { |
|
964 if (domain_fmmu->dir == EC_DIR_OUTPUT) { |
|
965 unsigned int frame_offset = |
|
966 domain_fmmu->logical_start_address |
|
967 - datagram_address; |
|
968 memcpy(frame_datagram_data + frame_offset, |
|
969 domain_data, domain_fmmu->data_size); |
|
970 if (unlikely(master->debug_level > 1)) { |
|
971 EC_MASTER_DBG(master, 0, "Sending datagram %p" |
|
972 " i=0x%02X FMMU %u fp=%u" |
|
973 " dp=%zu size=%u\n", |
|
974 datagram, datagram->index, i, frame_offset, |
|
975 domain_data - datagram->data, |
|
976 domain_fmmu->data_size); |
|
977 ec_print_data(domain_data, |
|
978 domain_fmmu->data_size); |
|
979 } |
|
980 } |
|
981 domain_data += domain_fmmu->data_size; |
|
982 i++; |
|
983 } |
|
984 } else { |
|
985 memcpy(frame_datagram_data, datagram->data, |
|
986 datagram->data_size); |
|
987 } |
|
988 cur_data += datagram->data_size; |
1059 cur_data += datagram->data_size; |
989 |
1060 |
990 // EtherCAT datagram footer |
1061 // EtherCAT datagram footer |
991 EC_WRITE_U16(cur_data, 0x0000); // reset working counter |
1062 EC_WRITE_U16(cur_data, 0x0000); // reset working counter |
992 cur_data += EC_DATAGRAM_FOOTER_SIZE; |
1063 cur_data += EC_DATAGRAM_FOOTER_SIZE; |
1029 while (more_datagrams_waiting); |
1101 while (more_datagrams_waiting); |
1030 |
1102 |
1031 #ifdef EC_HAVE_CYCLES |
1103 #ifdef EC_HAVE_CYCLES |
1032 if (unlikely(master->debug_level > 1)) { |
1104 if (unlikely(master->debug_level > 1)) { |
1033 cycles_end = get_cycles(); |
1105 cycles_end = get_cycles(); |
1034 EC_MASTER_DBG(master, 0, "ec_master_send_datagrams" |
1106 EC_MASTER_DBG(master, 0, "%s()" |
1035 " sent %u frames in %uus.\n", frame_count, |
1107 " sent %u frames in %uus.\n", __func__, frame_count, |
1036 (unsigned int) (cycles_end - cycles_start) * 1000 / cpu_khz); |
1108 (unsigned int) (cycles_end - cycles_start) * 1000 / cpu_khz); |
1037 } |
1109 } |
1038 #endif |
1110 #endif |
1039 } |
1111 } |
1040 |
1112 |
1041 /*****************************************************************************/ |
1113 /*****************************************************************************/ |
1042 |
1114 |
1043 /** Processes a received frame. |
1115 /** Processes a received frame. |
1044 * |
1116 * |
1045 * This function is called by the network driver for every received frame. |
1117 * This function is called by the network driver for every received frame. |
1046 * |
1118 * |
1047 * \return 0 in case of success, else < 0 |
1119 * \return 0 in case of success, else < 0 |
1048 */ |
1120 */ |
1049 void ec_master_receive_datagrams( |
1121 void ec_master_receive_datagrams( |
1050 ec_master_t *master, /**< EtherCAT master */ |
1122 ec_master_t *master, /**< EtherCAT master */ |
1051 const uint8_t *frame_data, /**< Frame data */ |
1123 ec_device_t *device, /**< EtherCAT device */ |
1052 size_t size /**< Size of the received data */ |
1124 const uint8_t *frame_data, /**< frame data */ |
|
1125 size_t size /**< size of the received data */ |
1053 ) |
1126 ) |
1054 { |
1127 { |
1055 size_t frame_size, data_size; |
1128 size_t frame_size, data_size; |
1056 uint8_t datagram_type, datagram_index; |
1129 uint8_t datagram_type, datagram_index; |
1057 unsigned int datagram_follows, matched; |
1130 unsigned int cmd_follows, matched; |
1058 const uint8_t *cur_data, *frame_datagram_data; |
1131 const uint8_t *cur_data; |
1059 ec_datagram_t *datagram; |
1132 ec_datagram_t *datagram; |
1060 ec_fmmu_config_t* domain_fmmu; |
|
1061 |
1133 |
1062 if (unlikely(size < EC_FRAME_HEADER_SIZE)) { |
1134 if (unlikely(size < EC_FRAME_HEADER_SIZE)) { |
1063 if (master->debug_level) { |
1135 if (master->debug_level || FORCE_OUTPUT_CORRUPTED) { |
1064 EC_MASTER_DBG(master, 0, "Corrupted frame received" |
1136 EC_MASTER_DBG(master, 0, "Corrupted frame received" |
1065 " (size %zu < %u byte):\n", |
1137 " on %s (size %zu < %u byte):\n", |
1066 size, EC_FRAME_HEADER_SIZE); |
1138 device->dev->name, size, EC_FRAME_HEADER_SIZE); |
1067 ec_print_data(frame_data, size); |
1139 ec_print_data(frame_data, size); |
1068 } |
1140 } |
1069 master->stats.corrupted++; |
1141 master->stats.corrupted++; |
|
1142 #ifdef EC_RT_SYSLOG |
1070 ec_master_output_stats(master); |
1143 ec_master_output_stats(master); |
|
1144 #endif |
1071 return; |
1145 return; |
1072 } |
1146 } |
1073 |
1147 |
1074 cur_data = frame_data; |
1148 cur_data = frame_data; |
1075 |
1149 |
1076 // check length of entire frame |
1150 // check length of entire frame |
1077 frame_size = EC_READ_U16(cur_data) & 0x07FF; |
1151 frame_size = EC_READ_U16(cur_data) & 0x07FF; |
1078 cur_data += EC_FRAME_HEADER_SIZE; |
1152 cur_data += EC_FRAME_HEADER_SIZE; |
1079 |
1153 |
1080 if (unlikely(frame_size > size)) { |
1154 if (unlikely(frame_size > size)) { |
1081 if (master->debug_level) { |
1155 if (master->debug_level || FORCE_OUTPUT_CORRUPTED) { |
1082 EC_MASTER_DBG(master, 0, "Corrupted frame received" |
1156 EC_MASTER_DBG(master, 0, "Corrupted frame received" |
1083 " (invalid frame size %zu for " |
1157 " on %s (invalid frame size %zu for " |
1084 "received size %zu):\n", frame_size, size); |
1158 "received size %zu):\n", device->dev->name, |
|
1159 frame_size, size); |
1085 ec_print_data(frame_data, size); |
1160 ec_print_data(frame_data, size); |
1086 } |
1161 } |
1087 master->stats.corrupted++; |
1162 master->stats.corrupted++; |
|
1163 #ifdef EC_RT_SYSLOG |
1088 ec_master_output_stats(master); |
1164 ec_master_output_stats(master); |
|
1165 #endif |
1089 return; |
1166 return; |
1090 } |
1167 } |
1091 |
1168 |
1092 datagram_follows = 1; |
1169 cmd_follows = 1; |
1093 |
1170 while (cmd_follows) { |
1094 while (datagram_follows) { |
|
1095 |
|
1096 // process datagram header |
1171 // process datagram header |
1097 datagram_type = EC_READ_U8(cur_data); |
1172 datagram_type = EC_READ_U8 (cur_data); |
1098 datagram_index = EC_READ_U8(cur_data + 1); |
1173 datagram_index = EC_READ_U8 (cur_data + 1); |
1099 data_size = EC_READ_U16(cur_data + 6) & 0x07FF; |
1174 data_size = EC_READ_U16(cur_data + 6) & 0x07FF; |
1100 datagram_follows = EC_READ_U16(cur_data + 6) & 0x8000; |
1175 cmd_follows = EC_READ_U16(cur_data + 6) & 0x8000; |
1101 cur_data += EC_DATAGRAM_HEADER_SIZE; |
1176 cur_data += EC_DATAGRAM_HEADER_SIZE; |
1102 |
1177 |
1103 if (unlikely(cur_data - frame_data |
1178 if (unlikely(cur_data - frame_data |
1104 + data_size + EC_DATAGRAM_FOOTER_SIZE > size)) { |
1179 + data_size + EC_DATAGRAM_FOOTER_SIZE > size)) { |
1105 if (master->debug_level) { |
1180 if (master->debug_level || FORCE_OUTPUT_CORRUPTED) { |
1106 EC_MASTER_DBG(master, 0, "Corrupted frame received" |
1181 EC_MASTER_DBG(master, 0, "Corrupted frame received" |
1107 " (invalid data size %zu):\n", data_size); |
1182 " on %s (invalid data size %zu):\n", |
|
1183 device->dev->name, data_size); |
1108 ec_print_data(frame_data, size); |
1184 ec_print_data(frame_data, size); |
1109 } |
1185 } |
1110 master->stats.corrupted++; |
1186 master->stats.corrupted++; |
|
1187 #ifdef EC_RT_SYSLOG |
1111 ec_master_output_stats(master); |
1188 ec_master_output_stats(master); |
|
1189 #endif |
1112 return; |
1190 return; |
1113 } |
1191 } |
1114 |
1192 |
1115 // search for matching datagram in the queue |
1193 // search for matching datagram in the queue |
1116 matched = 0; |
1194 matched = 0; |
1125 } |
1203 } |
1126 |
1204 |
1127 // no matching datagram was found |
1205 // no matching datagram was found |
1128 if (!matched) { |
1206 if (!matched) { |
1129 master->stats.unmatched++; |
1207 master->stats.unmatched++; |
|
1208 #ifdef EC_RT_SYSLOG |
1130 ec_master_output_stats(master); |
1209 ec_master_output_stats(master); |
|
1210 #endif |
1131 |
1211 |
1132 if (unlikely(master->debug_level > 0)) { |
1212 if (unlikely(master->debug_level > 0)) { |
1133 EC_MASTER_DBG(master, 0, "UNMATCHED datagram:\n"); |
1213 EC_MASTER_DBG(master, 0, "UNMATCHED datagram:\n"); |
1134 ec_print_data(cur_data - EC_DATAGRAM_HEADER_SIZE, |
1214 ec_print_data(cur_data - EC_DATAGRAM_HEADER_SIZE, |
1135 EC_DATAGRAM_HEADER_SIZE + data_size |
1215 EC_DATAGRAM_HEADER_SIZE + data_size |
1136 + EC_DATAGRAM_FOOTER_SIZE); |
1216 + EC_DATAGRAM_FOOTER_SIZE); |
1137 #ifdef EC_DEBUG_RING |
1217 #ifdef EC_DEBUG_RING |
1138 ec_device_debug_ring_print(&master->main_device); |
1218 ec_device_debug_ring_print(&master->devices[EC_DEVICE_MAIN]); |
1139 #endif |
1219 #endif |
1140 } |
1220 } |
1141 |
1221 |
1142 cur_data += data_size + EC_DATAGRAM_FOOTER_SIZE; |
1222 cur_data += data_size + EC_DATAGRAM_FOOTER_SIZE; |
1143 continue; |
1223 continue; |
1144 } |
1224 } |
1145 |
1225 |
1146 frame_datagram_data = cur_data; |
1226 if (datagram->type != EC_DATAGRAM_APWR && |
1147 |
|
1148 // distinguish between domain and non-domain datagrams |
|
1149 // this is not nice FIXME |
|
1150 if (datagram->domain) { |
|
1151 size_t datagram_address = EC_READ_U32(datagram->address); |
|
1152 int i = 0; |
|
1153 uint8_t *domain_data = datagram->data; |
|
1154 |
|
1155 // FIXME see ecrt_master_send_datagrams() |
|
1156 // it is not correct to walk though *all* FMMU configs, |
|
1157 // because they may not all belong to the same frame! |
|
1158 |
|
1159 list_for_each_entry(domain_fmmu, &datagram->domain->fmmu_configs, |
|
1160 list) { |
|
1161 if (domain_fmmu->dir == EC_DIR_INPUT) { |
|
1162 unsigned int frame_offset = |
|
1163 domain_fmmu->logical_start_address - datagram_address; |
|
1164 memcpy(domain_data, frame_datagram_data + frame_offset, |
|
1165 domain_fmmu->data_size); |
|
1166 if (unlikely(master->debug_level > 1)) { |
|
1167 EC_MASTER_DBG(master, 0, "Receiving datagram %p" |
|
1168 " i=0x%02X fmmu %u fp=%u" |
|
1169 " dp=%zu size=%u\n", |
|
1170 datagram, datagram->index, i, |
|
1171 frame_offset, domain_data - datagram->data, |
|
1172 domain_fmmu->data_size); |
|
1173 ec_print_data(domain_data, domain_fmmu->data_size); |
|
1174 } |
|
1175 } |
|
1176 domain_data += domain_fmmu->data_size; |
|
1177 i++; |
|
1178 } |
|
1179 } else if (datagram->type != EC_DATAGRAM_APWR && |
|
1180 datagram->type != EC_DATAGRAM_FPWR && |
1227 datagram->type != EC_DATAGRAM_FPWR && |
1181 datagram->type != EC_DATAGRAM_BWR && |
1228 datagram->type != EC_DATAGRAM_BWR && |
1182 datagram->type != EC_DATAGRAM_LWR) { |
1229 datagram->type != EC_DATAGRAM_LWR) { |
1183 // copy received data into the datagram memory, |
1230 // copy received data into the datagram memory, |
1184 // if something has been read |
1231 // if something has been read |
1185 memcpy(datagram->data, frame_datagram_data, data_size); |
1232 memcpy(datagram->data, cur_data, data_size); |
1186 } |
1233 } |
1187 |
|
1188 cur_data += data_size; |
1234 cur_data += data_size; |
1189 |
1235 |
1190 // set the datagram's working counter |
1236 // set the datagram's working counter |
1191 datagram->working_counter = EC_READ_U16(cur_data); |
1237 datagram->working_counter = EC_READ_U16(cur_data); |
1192 cur_data += EC_DATAGRAM_FOOTER_SIZE; |
1238 cur_data += EC_DATAGRAM_FOOTER_SIZE; |
1193 |
1239 |
1194 // dequeue the received datagram |
1240 // dequeue the received datagram |
1195 datagram->state = EC_DATAGRAM_RECEIVED; |
1241 datagram->state = EC_DATAGRAM_RECEIVED; |
1196 #ifdef EC_HAVE_CYCLES |
1242 #ifdef EC_HAVE_CYCLES |
1197 datagram->cycles_received = master->main_device.cycles_poll; |
1243 datagram->cycles_received = |
1198 #endif |
1244 master->devices[EC_DEVICE_MAIN].cycles_poll; |
1199 datagram->jiffies_received = master->main_device.jiffies_poll; |
1245 #endif |
1200 EC_MASTER_DBG(master, 2, "removing datagram %p i=0x%02X\n",datagram, |
1246 datagram->jiffies_received = |
1201 datagram->index); |
1247 master->devices[EC_DEVICE_MAIN].jiffies_poll; |
1202 list_del_init(&datagram->queue); |
1248 list_del_init(&datagram->queue); |
1203 } |
1249 } |
1204 } |
1250 } |
1205 |
1251 |
1206 /*****************************************************************************/ |
1252 /*****************************************************************************/ |
1312 |
1437 |
1313 #endif // EC_USE_HRTIMER |
1438 #endif // EC_USE_HRTIMER |
1314 |
1439 |
1315 /*****************************************************************************/ |
1440 /*****************************************************************************/ |
1316 |
1441 |
|
1442 /** Execute slave FSMs. |
|
1443 */ |
|
1444 void ec_master_exec_slave_fsms( |
|
1445 ec_master_t *master /**< EtherCAT master. */ |
|
1446 ) |
|
1447 { |
|
1448 ec_datagram_t *datagram; |
|
1449 ec_fsm_slave_t *fsm, *next; |
|
1450 unsigned int count = 0; |
|
1451 |
|
1452 list_for_each_entry_safe(fsm, next, &master->fsm_exec_list, list) { |
|
1453 if (!fsm->datagram) { |
|
1454 EC_MASTER_WARN(master, "Slave %u FSM has zero datagram." |
|
1455 "This is a bug!\n", fsm->slave->ring_position); |
|
1456 list_del_init(&fsm->list); |
|
1457 master->fsm_exec_count--; |
|
1458 return; |
|
1459 } |
|
1460 |
|
1461 if (fsm->datagram->state == EC_DATAGRAM_INIT || |
|
1462 fsm->datagram->state == EC_DATAGRAM_QUEUED || |
|
1463 fsm->datagram->state == EC_DATAGRAM_SENT) { |
|
1464 // previous datagram was not sent or received yet. |
|
1465 // wait until next thread execution |
|
1466 return; |
|
1467 } |
|
1468 |
|
1469 datagram = ec_master_get_external_datagram(master); |
|
1470 if (!datagram) { |
|
1471 // no free datagrams at the moment |
|
1472 EC_MASTER_WARN(master, "No free datagram during" |
|
1473 " slave FSM execution. This is a bug!\n"); |
|
1474 continue; |
|
1475 } |
|
1476 |
|
1477 #if DEBUG_INJECT |
|
1478 EC_MASTER_DBG(master, 1, "Executing slave %u FSM.\n", |
|
1479 fsm->slave->ring_position); |
|
1480 #endif |
|
1481 if (ec_fsm_slave_exec(fsm, datagram)) { |
|
1482 // FSM consumed datagram |
|
1483 #if DEBUG_INJECT |
|
1484 EC_MASTER_DBG(master, 1, "FSM consumed datagram %s\n", |
|
1485 datagram->name); |
|
1486 #endif |
|
1487 master->ext_ring_idx_fsm = |
|
1488 (master->ext_ring_idx_fsm + 1) % EC_EXT_RING_SIZE; |
|
1489 } |
|
1490 else { |
|
1491 // FSM finished |
|
1492 list_del_init(&fsm->list); |
|
1493 master->fsm_exec_count--; |
|
1494 #if DEBUG_INJECT |
|
1495 EC_MASTER_DBG(master, 1, "FSM finished. %u remaining.\n", |
|
1496 master->fsm_exec_count); |
|
1497 #endif |
|
1498 } |
|
1499 } |
|
1500 |
|
1501 while (master->fsm_exec_count < EC_EXT_RING_SIZE / 2 |
|
1502 && count < master->slave_count) { |
|
1503 |
|
1504 if (ec_fsm_slave_is_ready(&master->fsm_slave->fsm)) { |
|
1505 datagram = ec_master_get_external_datagram(master); |
|
1506 |
|
1507 if (ec_fsm_slave_exec(&master->fsm_slave->fsm, datagram)) { |
|
1508 master->ext_ring_idx_fsm = |
|
1509 (master->ext_ring_idx_fsm + 1) % EC_EXT_RING_SIZE; |
|
1510 list_add_tail(&master->fsm_slave->fsm.list, |
|
1511 &master->fsm_exec_list); |
|
1512 master->fsm_exec_count++; |
|
1513 #if DEBUG_INJECT |
|
1514 EC_MASTER_DBG(master, 1, "New slave %u FSM" |
|
1515 " consumed datagram %s, now %u FSMs in list.\n", |
|
1516 master->fsm_slave->ring_position, datagram->name, |
|
1517 master->fsm_exec_count); |
|
1518 #endif |
|
1519 } |
|
1520 } |
|
1521 |
|
1522 master->fsm_slave++; |
|
1523 if (master->fsm_slave >= master->slaves + master->slave_count) { |
|
1524 master->fsm_slave = master->slaves; |
|
1525 } |
|
1526 count++; |
|
1527 } |
|
1528 } |
|
1529 |
|
1530 /*****************************************************************************/ |
|
1531 |
1317 /** Master kernel thread function for IDLE phase. |
1532 /** Master kernel thread function for IDLE phase. |
1318 */ |
1533 */ |
1319 static int ec_master_idle_thread(void *priv_data) |
1534 static int ec_master_idle_thread(void *priv_data) |
1320 { |
1535 { |
1321 ec_master_t *master = (ec_master_t *) priv_data; |
1536 ec_master_t *master = (ec_master_t *) priv_data; |
1322 ec_slave_t *slave = NULL; |
1537 int fsm_exec; |
1323 #ifdef EC_USE_HRTIMER |
1538 #ifdef EC_USE_HRTIMER |
1324 size_t sent_bytes; |
1539 size_t sent_bytes; |
1325 #endif |
1540 #endif |
1326 |
1541 |
1327 // send interval in IDLE phase |
1542 // send interval in IDLE phase |
1328 ec_master_set_send_interval(master, 1000000 / HZ); |
1543 ec_master_set_send_interval(master, 1000000 / HZ); |
1329 |
1544 |
1330 EC_MASTER_DBG(master, 1, "Idle thread running with send interval = %u us," |
1545 EC_MASTER_DBG(master, 1, "Idle thread running with send interval = %u us," |
1331 " max data size=%zu\n", master->send_interval, |
1546 " max data size=%zu\n", master->send_interval, |
1332 master->max_queue_size); |
1547 master->max_queue_size); |
1333 |
1548 |
1334 while (!kthread_should_stop()) { |
1549 while (!kthread_should_stop()) { |
1335 ec_datagram_output_stats(&master->fsm_datagram); |
1550 ec_datagram_output_stats(&master->fsm_datagram); |
1336 |
1551 |
1337 // receive |
1552 // receive |
1338 ec_mutex_lock(&master->io_mutex); |
1553 down(&master->io_sem); |
1339 ecrt_master_receive(master); |
1554 ecrt_master_receive(master); |
1340 ec_mutex_unlock(&master->io_mutex); |
1555 up(&master->io_sem); |
1341 |
1556 |
1342 // execute master & slave state machines |
1557 // execute master & slave state machines |
1343 if (ec_mutex_lock_interruptible(&master->master_mutex)) { |
1558 if (down_interruptible(&master->master_sem)) { |
1344 break; |
1559 break; |
1345 } |
1560 } |
1346 if (ec_fsm_master_exec(&master->fsm)) { |
1561 |
1347 ec_master_mbox_queue_datagrams(master, &master->fsm_mbox); |
1562 fsm_exec = ec_fsm_master_exec(&master->fsm); |
1348 } |
1563 |
1349 for (slave = master->slaves; |
1564 ec_master_exec_slave_fsms(master); |
1350 slave < master->slaves + master->slave_count; |
1565 |
1351 slave++) { |
1566 up(&master->master_sem); |
1352 ec_fsm_slave_exec(&slave->fsm); // may queue datagram in fsm queue |
|
1353 } |
|
1354 #if defined(EC_EOE) |
|
1355 if (!ec_master_eoe_processing(master)) { |
|
1356 master->fsm.idle = 0; // pump the bus as fast as possible |
|
1357 } |
|
1358 #endif |
|
1359 ec_mutex_unlock(&master->master_mutex); |
|
1360 |
1567 |
1361 // queue and send |
1568 // queue and send |
1362 ec_mutex_lock(&master->io_mutex); |
1569 down(&master->io_sem); |
|
1570 if (fsm_exec) { |
|
1571 ec_master_queue_datagram(master, &master->fsm_datagram); |
|
1572 } |
1363 ecrt_master_send(master); |
1573 ecrt_master_send(master); |
1364 #ifdef EC_USE_HRTIMER |
1574 #ifdef EC_USE_HRTIMER |
1365 sent_bytes = master->main_device.tx_skb[ |
1575 sent_bytes = master->devices[EC_DEVICE_MAIN].tx_skb[ |
1366 master->main_device.tx_ring_index]->len; |
1576 master->devices[EC_DEVICE_MAIN].tx_ring_index]->len; |
1367 #endif |
1577 #endif |
1368 ec_mutex_unlock(&master->io_mutex); |
1578 up(&master->io_sem); |
1369 |
1579 |
1370 if (ec_fsm_master_idle(&master->fsm)) { |
1580 if (ec_fsm_master_idle(&master->fsm)) { |
1371 #ifdef EC_USE_HRTIMER |
1581 #ifdef EC_USE_HRTIMER |
1372 ec_master_nanosleep(master->send_interval * 1000); |
1582 ec_master_nanosleep(master->send_interval * 1000); |
1373 #else |
1583 #else |
1435 else { |
1644 else { |
1436 schedule(); |
1645 schedule(); |
1437 } |
1646 } |
1438 #endif |
1647 #endif |
1439 } |
1648 } |
1440 |
1649 |
1441 EC_MASTER_DBG(master, 1, "Master OP thread exiting...\n"); |
1650 EC_MASTER_DBG(master, 1, "Master OP thread exiting...\n"); |
1442 return 0; |
1651 return 0; |
1443 } |
1652 } |
1444 |
1653 |
1445 /*****************************************************************************/ |
1654 /*****************************************************************************/ |
1446 |
1655 |
1447 #ifdef EC_EOE |
1656 #ifdef EC_EOE |
|
1657 /** Starts Ethernet over EtherCAT processing on demand. |
|
1658 */ |
|
1659 void ec_master_eoe_start(ec_master_t *master /**< EtherCAT master */) |
|
1660 { |
|
1661 struct sched_param param = { .sched_priority = 0 }; |
|
1662 |
|
1663 if (master->eoe_thread) { |
|
1664 EC_MASTER_WARN(master, "EoE already running!\n"); |
|
1665 return; |
|
1666 } |
|
1667 |
|
1668 if (list_empty(&master->eoe_handlers)) |
|
1669 return; |
|
1670 |
|
1671 if (!master->send_cb || !master->receive_cb) { |
|
1672 EC_MASTER_WARN(master, "No EoE processing" |
|
1673 " because of missing callbacks!\n"); |
|
1674 return; |
|
1675 } |
|
1676 |
|
1677 EC_MASTER_INFO(master, "Starting EoE thread.\n"); |
|
1678 master->eoe_thread = kthread_run(ec_master_eoe_thread, master, |
|
1679 "EtherCAT-EoE"); |
|
1680 if (IS_ERR(master->eoe_thread)) { |
|
1681 int err = (int) PTR_ERR(master->eoe_thread); |
|
1682 EC_MASTER_ERR(master, "Failed to start EoE thread (error %i)!\n", |
|
1683 err); |
|
1684 master->eoe_thread = NULL; |
|
1685 return; |
|
1686 } |
|
1687 |
|
1688 sched_setscheduler(master->eoe_thread, SCHED_NORMAL, ¶m); |
|
1689 set_user_nice(master->eoe_thread, 0); |
|
1690 } |
|
1691 |
|
1692 /*****************************************************************************/ |
|
1693 |
|
1694 /** Stops the Ethernet over EtherCAT processing. |
|
1695 */ |
|
1696 void ec_master_eoe_stop(ec_master_t *master /**< EtherCAT master */) |
|
1697 { |
|
1698 if (master->eoe_thread) { |
|
1699 EC_MASTER_INFO(master, "Stopping EoE thread.\n"); |
|
1700 |
|
1701 kthread_stop(master->eoe_thread); |
|
1702 master->eoe_thread = NULL; |
|
1703 EC_MASTER_INFO(master, "EoE thread exited.\n"); |
|
1704 } |
|
1705 } |
1448 |
1706 |
1449 /*****************************************************************************/ |
1707 /*****************************************************************************/ |
1450 |
1708 |
1451 /** Does the Ethernet over EtherCAT processing. |
1709 /** Does the Ethernet over EtherCAT processing. |
1452 */ |
1710 */ |
1453 static int ec_master_eoe_processing(ec_master_t *master) |
1711 static int ec_master_eoe_thread(void *priv_data) |
1454 { |
1712 { |
|
1713 ec_master_t *master = (ec_master_t *) priv_data; |
1455 ec_eoe_t *eoe; |
1714 ec_eoe_t *eoe; |
1456 unsigned int none_open, sth_to_send, all_idle; |
1715 unsigned int none_open, sth_to_send, all_idle; |
1457 none_open = 1; |
1716 |
1458 all_idle = 1; |
1717 EC_MASTER_DBG(master, 1, "EoE thread running.\n"); |
1459 |
1718 |
1460 list_for_each_entry(eoe, &master->eoe_handlers, list) { |
1719 while (!kthread_should_stop()) { |
1461 if (ec_eoe_is_open(eoe)) { |
1720 none_open = 1; |
1462 none_open = 0; |
1721 all_idle = 1; |
1463 break; |
1722 |
1464 } |
|
1465 } |
|
1466 if (none_open) |
|
1467 return all_idle; |
|
1468 |
|
1469 // actual EoE processing |
|
1470 sth_to_send = 0; |
|
1471 list_for_each_entry(eoe, &master->eoe_handlers, list) { |
|
1472 ec_eoe_run(eoe); |
|
1473 if (eoe->queue_datagram) { |
|
1474 sth_to_send = 1; |
|
1475 } |
|
1476 if (!ec_eoe_is_idle(eoe)) { |
|
1477 all_idle = 0; |
|
1478 } |
|
1479 } |
|
1480 |
|
1481 if (sth_to_send) { |
|
1482 list_for_each_entry(eoe, &master->eoe_handlers, list) { |
1723 list_for_each_entry(eoe, &master->eoe_handlers, list) { |
1483 ec_eoe_queue(eoe); |
1724 if (ec_eoe_is_open(eoe)) { |
1484 } |
1725 none_open = 0; |
1485 } |
1726 break; |
1486 return all_idle; |
1727 } |
1487 } |
1728 } |
1488 |
1729 if (none_open) |
1489 #endif // EC_EOE |
1730 goto schedule; |
1490 |
1731 |
1491 /*****************************************************************************/ |
1732 // receive datagrams |
1492 |
1733 master->receive_cb(master->cb_data); |
1493 /** Detaches the slave configurations from the slaves. |
1734 |
1494 */ |
1735 // actual EoE processing |
1495 void ec_master_detach_slave_configs( |
1736 sth_to_send = 0; |
1496 ec_master_t *master /**< EtherCAT master. */ |
1737 list_for_each_entry(eoe, &master->eoe_handlers, list) { |
1497 ) |
1738 ec_eoe_run(eoe); |
1498 { |
1739 if (eoe->queue_datagram) { |
1499 ec_slave_config_t *sc; |
1740 sth_to_send = 1; |
1500 |
1741 } |
1501 list_for_each_entry(sc, &master->configs, list) { |
1742 if (!ec_eoe_is_idle(eoe)) { |
1502 ec_slave_config_detach(sc); |
1743 all_idle = 0; |
1503 } |
1744 } |
1504 } |
1745 } |
|
1746 |
|
1747 if (sth_to_send) { |
|
1748 list_for_each_entry(eoe, &master->eoe_handlers, list) { |
|
1749 ec_eoe_queue(eoe); |
|
1750 } |
|
1751 // (try to) send datagrams |
|
1752 down(&master->ext_queue_sem); |
|
1753 master->send_cb(master->cb_data); |
|
1754 up(&master->ext_queue_sem); |
|
1755 } |
|
1756 |
|
1757 schedule: |
|
1758 if (all_idle) { |
|
1759 set_current_state(TASK_INTERRUPTIBLE); |
|
1760 schedule_timeout(1); |
|
1761 } else { |
|
1762 schedule(); |
|
1763 } |
|
1764 } |
|
1765 |
|
1766 EC_MASTER_DBG(master, 1, "EoE thread exiting...\n"); |
|
1767 return 0; |
|
1768 } |
|
1769 #endif |
1505 |
1770 |
1506 /*****************************************************************************/ |
1771 /*****************************************************************************/ |
1507 |
1772 |
1508 /** Attaches the slave configurations to the slaves. |
1773 /** Attaches the slave configurations to the slaves. |
1509 */ |
1774 */ |
2124 |
2430 |
2125 /*****************************************************************************/ |
2431 /*****************************************************************************/ |
2126 |
2432 |
2127 void ecrt_master_send(ec_master_t *master) |
2433 void ecrt_master_send(ec_master_t *master) |
2128 { |
2434 { |
|
2435 ec_datagram_t *datagram, *n; |
|
2436 ec_device_index_t dev_idx; |
|
2437 |
|
2438 if (master->injection_seq_rt != master->injection_seq_fsm) { |
|
2439 // inject datagram produced by master FSM |
|
2440 ec_master_queue_datagram(master, &master->fsm_datagram); |
|
2441 master->injection_seq_rt = master->injection_seq_fsm; |
|
2442 } |
|
2443 |
|
2444 ec_master_inject_external_datagrams(master); |
|
2445 |
|
2446 for (dev_idx = EC_DEVICE_MAIN; dev_idx < ec_master_num_devices(master); |
|
2447 dev_idx++) { |
|
2448 if (unlikely(!master->devices[dev_idx].link_state)) { |
|
2449 // link is down, no datagram can be sent |
|
2450 list_for_each_entry_safe(datagram, n, |
|
2451 &master->datagram_queue, queue) { |
|
2452 if (datagram->device_index == dev_idx) { |
|
2453 datagram->state = EC_DATAGRAM_ERROR; |
|
2454 list_del_init(&datagram->queue); |
|
2455 } |
|
2456 } |
|
2457 |
|
2458 if (!master->devices[dev_idx].dev) { |
|
2459 continue; |
|
2460 } |
|
2461 |
|
2462 // query link state |
|
2463 ec_device_poll(&master->devices[dev_idx]); |
|
2464 |
|
2465 // clear frame statistics |
|
2466 ec_device_clear_stats(&master->devices[dev_idx]); |
|
2467 continue; |
|
2468 } |
|
2469 |
|
2470 // send frames |
|
2471 ec_master_send_datagrams(master, dev_idx); |
|
2472 } |
|
2473 } |
|
2474 |
|
2475 /*****************************************************************************/ |
|
2476 |
|
2477 void ecrt_master_receive(ec_master_t *master) |
|
2478 { |
|
2479 unsigned int dev_idx; |
2129 ec_datagram_t *datagram, *next; |
2480 ec_datagram_t *datagram, *next; |
2130 |
2481 |
2131 ec_master_inject_fsm_datagrams(master); |
|
2132 |
|
2133 if (unlikely(!master->main_device.link_state)) { |
|
2134 // link is down, no datagram can be sent |
|
2135 list_for_each_entry_safe(datagram, next, &master->datagram_queue, |
|
2136 queue) { |
|
2137 datagram->state = EC_DATAGRAM_ERROR; |
|
2138 list_del_init(&datagram->queue); |
|
2139 } |
|
2140 |
|
2141 // query link state |
|
2142 ec_device_poll(&master->main_device); |
|
2143 |
|
2144 // clear frame statistics |
|
2145 ec_device_clear_stats(&master->main_device); |
|
2146 return; |
|
2147 } |
|
2148 |
|
2149 // send frames |
|
2150 ec_master_send_datagrams(master); |
|
2151 } |
|
2152 |
|
2153 /*****************************************************************************/ |
|
2154 |
|
2155 void ecrt_master_receive(ec_master_t *master) |
|
2156 { |
|
2157 ec_datagram_t *datagram, *next; |
|
2158 |
|
2159 // receive datagrams |
2482 // receive datagrams |
2160 ec_device_poll(&master->main_device); |
2483 for (dev_idx = EC_DEVICE_MAIN; dev_idx < ec_master_num_devices(master); |
|
2484 dev_idx++) { |
|
2485 ec_device_poll(&master->devices[dev_idx]); |
|
2486 } |
|
2487 ec_master_update_device_stats(master); |
2161 |
2488 |
2162 // dequeue all datagrams that timed out |
2489 // dequeue all datagrams that timed out |
2163 list_for_each_entry_safe(datagram, next, &master->datagram_queue, queue) { |
2490 list_for_each_entry_safe(datagram, next, &master->datagram_queue, queue) { |
2164 if (datagram->state != EC_DATAGRAM_SENT) continue; |
2491 if (datagram->state != EC_DATAGRAM_SENT) continue; |
2165 |
2492 |
2166 #ifdef EC_HAVE_CYCLES |
2493 #ifdef EC_HAVE_CYCLES |
2167 if (master->main_device.cycles_poll - datagram->cycles_sent |
2494 if (master->devices[EC_DEVICE_MAIN].cycles_poll - |
2168 > timeout_cycles) { |
2495 datagram->cycles_sent > timeout_cycles) { |
2169 #else |
2496 #else |
2170 if (master->main_device.jiffies_poll - datagram->jiffies_sent |
2497 if (master->devices[EC_DEVICE_MAIN].jiffies_poll - |
2171 > timeout_jiffies) { |
2498 datagram->jiffies_sent > timeout_jiffies) { |
2172 #endif |
2499 #endif |
2173 list_del_init(&datagram->queue); |
2500 list_del_init(&datagram->queue); |
2174 datagram->state = EC_DATAGRAM_TIMED_OUT; |
2501 datagram->state = EC_DATAGRAM_TIMED_OUT; |
2175 master->stats.timeouts++; |
2502 master->stats.timeouts++; |
|
2503 |
|
2504 #ifdef EC_RT_SYSLOG |
2176 ec_master_output_stats(master); |
2505 ec_master_output_stats(master); |
2177 |
2506 |
2178 if (unlikely(master->debug_level > 0)) { |
2507 if (unlikely(master->debug_level > 0)) { |
2179 unsigned int time_us; |
2508 unsigned int time_us; |
2180 #ifdef EC_HAVE_CYCLES |
2509 #ifdef EC_HAVE_CYCLES |
2181 time_us = (unsigned int) (master->main_device.cycles_poll - |
2510 time_us = (unsigned int) |
|
2511 (master->devices[EC_DEVICE_MAIN].cycles_poll - |
2182 datagram->cycles_sent) * 1000 / cpu_khz; |
2512 datagram->cycles_sent) * 1000 / cpu_khz; |
2183 #else |
2513 #else |
2184 time_us = (unsigned int) ((master->main_device.jiffies_poll - |
2514 time_us = (unsigned int) |
|
2515 ((master->devices[EC_DEVICE_MAIN].jiffies_poll - |
2185 datagram->jiffies_sent) * 1000000 / HZ); |
2516 datagram->jiffies_sent) * 1000000 / HZ); |
2186 #endif |
2517 #endif |
2187 EC_MASTER_DBG(master, 0, "TIMED OUT datagram %p," |
2518 EC_MASTER_DBG(master, 0, "TIMED OUT datagram %p," |
2188 " index %02X waited %u us.\n", |
2519 " index %02X waited %u us.\n", |
2189 datagram, datagram->index, time_us); |
2520 datagram, datagram->index, time_us); |
2190 } |
2521 } |
2191 } |
2522 #endif /* RT_SYSLOG */ |
2192 } |
2523 } |
2193 } |
2524 } |
2194 |
2525 } |
|
2526 |
|
2527 /*****************************************************************************/ |
|
2528 |
|
2529 void ecrt_master_send_ext(ec_master_t *master) |
|
2530 { |
|
2531 ec_datagram_t *datagram, *next; |
|
2532 |
|
2533 list_for_each_entry_safe(datagram, next, &master->ext_datagram_queue, |
|
2534 queue) { |
|
2535 list_del(&datagram->queue); |
|
2536 ec_master_queue_datagram(master, datagram); |
|
2537 } |
|
2538 |
|
2539 ecrt_master_send(master); |
|
2540 } |
2195 |
2541 |
2196 /*****************************************************************************/ |
2542 /*****************************************************************************/ |
2197 |
2543 |
2198 /** Same as ecrt_master_slave_config(), but with ERR_PTR() return value. |
2544 /** Same as ecrt_master_slave_config(), but with ERR_PTR() return value. |
2199 */ |
2545 */ |
2326 strncpy(slave_info->name, slave->sii.name, EC_MAX_STRING_LENGTH); |
2698 strncpy(slave_info->name, slave->sii.name, EC_MAX_STRING_LENGTH); |
2327 } else { |
2699 } else { |
2328 slave_info->name[0] = 0; |
2700 slave_info->name[0] = 0; |
2329 } |
2701 } |
2330 |
2702 |
2331 ec_mutex_unlock(&master->master_mutex); |
2703 out_get_slave: |
|
2704 up(&master->master_sem); |
|
2705 |
|
2706 return ret; |
|
2707 } |
|
2708 |
|
2709 /*****************************************************************************/ |
|
2710 |
|
2711 void ecrt_master_callbacks(ec_master_t *master, |
|
2712 void (*send_cb)(void *), void (*receive_cb)(void *), void *cb_data) |
|
2713 { |
|
2714 EC_MASTER_DBG(master, 1, "ecrt_master_callbacks(master = 0x%p," |
|
2715 " send_cb = 0x%p, receive_cb = 0x%p, cb_data = 0x%p)\n", |
|
2716 master, send_cb, receive_cb, cb_data); |
|
2717 |
|
2718 master->app_send_cb = send_cb; |
|
2719 master->app_receive_cb = receive_cb; |
|
2720 master->app_cb_data = cb_data; |
|
2721 } |
|
2722 |
|
2723 /*****************************************************************************/ |
|
2724 |
|
2725 void ecrt_master_state(const ec_master_t *master, ec_master_state_t *state) |
|
2726 { |
|
2727 ec_device_index_t dev_idx; |
|
2728 |
|
2729 state->slaves_responding = 0U; |
|
2730 state->al_states = 0; |
|
2731 state->link_up = 0U; |
|
2732 |
|
2733 for (dev_idx = EC_DEVICE_MAIN; dev_idx < ec_master_num_devices(master); |
|
2734 dev_idx++) { |
|
2735 /* Announce sum of responding slaves on all links. */ |
|
2736 state->slaves_responding += master->fsm.slaves_responding[dev_idx]; |
|
2737 |
|
2738 /* Binary-or slave states of all links. */ |
|
2739 state->al_states |= master->fsm.slave_states[dev_idx]; |
|
2740 |
|
2741 /* Signal link up if at least one device has link. */ |
|
2742 state->link_up |= master->devices[dev_idx].link_state; |
|
2743 } |
|
2744 } |
|
2745 |
|
2746 /*****************************************************************************/ |
|
2747 |
|
2748 int ecrt_master_link_state(const ec_master_t *master, unsigned int dev_idx, |
|
2749 ec_master_link_state_t *state) |
|
2750 { |
|
2751 if (dev_idx >= ec_master_num_devices(master)) { |
|
2752 return -EINVAL; |
|
2753 } |
|
2754 |
|
2755 state->slaves_responding = master->fsm.slaves_responding[dev_idx]; |
|
2756 state->al_states = master->fsm.slave_states[dev_idx]; |
|
2757 state->link_up = master->devices[dev_idx].link_state; |
2332 |
2758 |
2333 return 0; |
2759 return 0; |
2334 } |
2760 } |
2335 |
2761 |
2336 /*****************************************************************************/ |
2762 /*****************************************************************************/ |
2337 |
2763 |
2338 void ecrt_master_callbacks(ec_master_t *master, |
|
2339 void (*lock_cb)(void *), void (*unlock_cb)(void *), |
|
2340 void *cb_data) |
|
2341 { |
|
2342 EC_MASTER_DBG(master, 1,"ecrt_master_callbacks(master = %p, " |
|
2343 "lock_cb = %p, unlock_cb = %p, cb_data = %p)\n", |
|
2344 master, lock_cb, unlock_cb, cb_data); |
|
2345 |
|
2346 master->app_fsm_queue_lock_cb = lock_cb; |
|
2347 master->app_fsm_queue_unlock_cb = unlock_cb; |
|
2348 master->app_fsm_queue_locking_data = cb_data; |
|
2349 } |
|
2350 |
|
2351 |
|
2352 /*****************************************************************************/ |
|
2353 |
|
2354 void ecrt_master_state(const ec_master_t *master, ec_master_state_t *state) |
|
2355 { |
|
2356 state->slaves_responding = master->fsm.slaves_responding; |
|
2357 state->al_states = master->fsm.slave_states; |
|
2358 state->link_up = master->main_device.link_state; |
|
2359 } |
|
2360 |
|
2361 /*****************************************************************************/ |
|
2362 |
|
2363 void ecrt_master_configured_slaves_state( |
|
2364 const ec_master_t *master, |
|
2365 ec_master_state_t *state |
|
2366 ) |
|
2367 { |
|
2368 const ec_slave_config_t *sc; |
|
2369 ec_slave_config_state_t sc_state; |
|
2370 |
|
2371 // collect al_states of all configured online slaves |
|
2372 state->al_states = 0; |
|
2373 list_for_each_entry(sc, &master->configs, list) { |
|
2374 ecrt_slave_config_state(sc,&sc_state); |
|
2375 if (sc_state.online) |
|
2376 state->al_states |= sc_state.al_state; |
|
2377 } |
|
2378 |
|
2379 state->slaves_responding = master->fsm.slaves_responding; |
|
2380 state->link_up = master->main_device.link_state; |
|
2381 } |
|
2382 |
|
2383 /*****************************************************************************/ |
|
2384 |
|
2385 void ecrt_master_application_time(ec_master_t *master, uint64_t app_time) |
2764 void ecrt_master_application_time(ec_master_t *master, uint64_t app_time) |
2386 { |
2765 { |
2387 master->app_time = app_time; |
2766 master->app_time = app_time; |
2388 |
2767 |
2389 if (unlikely(!master->has_app_time)) { |
2768 if (unlikely(!master->has_app_time)) { |
2390 EC_MASTER_DBG(master, 1, "Set application start time = %llu\n", |
|
2391 app_time); |
|
2392 master->app_start_time = app_time; |
2769 master->app_start_time = app_time; |
2393 #ifdef EC_HAVE_CYCLES |
|
2394 master->dc_cycles_app_start_time = get_cycles(); |
|
2395 #endif |
|
2396 master->dc_jiffies_app_start_time = jiffies; |
|
2397 master->has_app_time = 1; |
2770 master->has_app_time = 1; |
2398 } |
2771 } |
2399 } |
2772 } |
2400 |
2773 |
2401 /*****************************************************************************/ |
2774 /*****************************************************************************/ |
2402 |
2775 |
|
2776 int ecrt_master_reference_clock_time(ec_master_t *master, uint32_t *time) |
|
2777 { |
|
2778 if (!master->dc_ref_clock) { |
|
2779 return -ENXIO; |
|
2780 } |
|
2781 |
|
2782 if (master->sync_datagram.state != EC_DATAGRAM_RECEIVED) { |
|
2783 return -EIO; |
|
2784 } |
|
2785 |
|
2786 // Get returned datagram time, transmission delay removed. |
|
2787 *time = EC_READ_U32(master->sync_datagram.data) - |
|
2788 master->dc_ref_clock->transmission_delay; |
|
2789 |
|
2790 return 0; |
|
2791 } |
|
2792 |
|
2793 /*****************************************************************************/ |
|
2794 |
2403 void ecrt_master_sync_reference_clock(ec_master_t *master) |
2795 void ecrt_master_sync_reference_clock(ec_master_t *master) |
2404 { |
2796 { |
2405 EC_WRITE_U32(master->ref_sync_datagram.data, master->app_time); |
2797 if (master->dc_ref_clock) { |
2406 ec_master_queue_datagram(master, &master->ref_sync_datagram); |
2798 EC_WRITE_U32(master->ref_sync_datagram.data, master->app_time); |
|
2799 ec_master_queue_datagram(master, &master->ref_sync_datagram); |
|
2800 } |
2407 } |
2801 } |
2408 |
2802 |
2409 /*****************************************************************************/ |
2803 /*****************************************************************************/ |
2410 |
2804 |
2411 void ecrt_master_sync_slave_clocks(ec_master_t *master) |
2805 void ecrt_master_sync_slave_clocks(ec_master_t *master) |
2412 { |
2806 { |
2413 ec_datagram_zero(&master->sync_datagram); |
2807 if (master->dc_ref_clock) { |
2414 ec_master_queue_datagram(master, &master->sync_datagram); |
2808 ec_datagram_zero(&master->sync_datagram); |
|
2809 ec_master_queue_datagram(master, &master->sync_datagram); |
|
2810 } |
2415 } |
2811 } |
2416 |
2812 |
2417 /*****************************************************************************/ |
2813 /*****************************************************************************/ |
2418 |
2814 |
2419 void ecrt_master_sync_monitor_queue(ec_master_t *master) |
2815 void ecrt_master_sync_monitor_queue(ec_master_t *master) |
2451 if (!data_size) { |
2848 if (!data_size) { |
2452 EC_MASTER_ERR(master, "Zero data size!\n"); |
2849 EC_MASTER_ERR(master, "Zero data size!\n"); |
2453 return -EINVAL; |
2850 return -EINVAL; |
2454 } |
2851 } |
2455 |
2852 |
2456 request = kmalloc(sizeof(*request), GFP_KERNEL); |
2853 ec_sdo_request_init(&request); |
2457 if (!request) { |
2854 ecrt_sdo_request_index(&request, index, subindex); |
2458 return -ENOMEM; |
2855 ret = ec_sdo_request_alloc(&request, data_size); |
2459 } |
2856 if (ret) { |
2460 kref_init(&request->refcount); |
2857 ec_sdo_request_clear(&request); |
2461 |
2858 return ret; |
2462 ec_sdo_request_init(&request->req); |
2859 } |
2463 ec_sdo_request_address(&request->req, index, subindex); |
2860 |
2464 if (ec_sdo_request_alloc(&request->req, data_size)) { |
2861 memcpy(request.data, data, data_size); |
2465 kref_put(&request->refcount, ec_master_sdo_request_release); |
2862 request.data_size = data_size; |
2466 return -ENOMEM; |
2863 ecrt_sdo_request_write(&request); |
2467 } |
2864 |
2468 memcpy(request->req.data, data, data_size); |
2865 if (down_interruptible(&master->master_sem)) { |
2469 request->req.data_size = data_size; |
2866 ec_sdo_request_clear(&request); |
2470 ecrt_sdo_request_write(&request->req); |
|
2471 |
|
2472 if (ec_mutex_lock_interruptible(&master->master_mutex)) { |
|
2473 kref_put(&request->refcount, ec_master_sdo_request_release); |
|
2474 return -EINTR; |
2867 return -EINTR; |
2475 } |
2868 } |
2476 |
2869 |
2477 if (!(request->slave = ec_master_find_slave( |
2870 if (!(slave = ec_master_find_slave(master, 0, slave_position))) { |
2478 master, 0, slave_position))) { |
2871 up(&master->master_sem); |
2479 ec_mutex_unlock(&master->master_mutex); |
|
2480 EC_MASTER_ERR(master, "Slave %u does not exist!\n", slave_position); |
2872 EC_MASTER_ERR(master, "Slave %u does not exist!\n", slave_position); |
2481 kref_put(&request->refcount, ec_master_sdo_request_release); |
2873 ec_sdo_request_clear(&request); |
2482 return -EINVAL; |
2874 return -EINVAL; |
2483 } |
2875 } |
2484 |
2876 |
2485 EC_SLAVE_DBG(request->slave, 1, "Schedule SDO download request %p.\n", |
2877 EC_SLAVE_DBG(slave, 1, "Scheduling SDO download request.\n"); |
2486 request); |
2878 |
2487 |
2879 // schedule request. |
2488 // schedule request |
2880 list_add_tail(&request.list, &slave->sdo_requests); |
2489 kref_get(&request->refcount); |
2881 |
2490 list_add_tail(&request->list, &request->slave->slave_sdo_requests); |
2882 up(&master->master_sem); |
2491 |
|
2492 ec_mutex_unlock(&master->master_mutex); |
|
2493 |
2883 |
2494 // wait for processing through FSM |
2884 // wait for processing through FSM |
2495 if (wait_event_interruptible(request->slave->sdo_queue, |
2885 if (wait_event_interruptible(master->request_queue, |
2496 ((request->req.state == EC_INT_REQUEST_SUCCESS) || |
2886 request.state != EC_INT_REQUEST_QUEUED)) { |
2497 (request->req.state == EC_INT_REQUEST_FAILURE)))) { |
|
2498 // interrupted by signal |
2887 // interrupted by signal |
2499 kref_put(&request->refcount, ec_master_sdo_request_release); |
2888 down(&master->master_sem); |
2500 return -EINTR; |
2889 if (request.state == EC_INT_REQUEST_QUEUED) { |
2501 } |
2890 list_del(&request.list); |
2502 |
2891 up(&master->master_sem); |
2503 EC_SLAVE_DBG(request->slave, 1, "Finished SDO download request %p.\n", |
2892 ec_sdo_request_clear(&request); |
2504 request); |
2893 return -EINTR; |
2505 |
2894 } |
2506 *abort_code = request->req.abort_code; |
2895 // request already processing: interrupt not possible. |
2507 |
2896 up(&master->master_sem); |
2508 if (request->req.state == EC_INT_REQUEST_SUCCESS) { |
2897 } |
2509 retval = 0; |
2898 |
2510 } else if (request->req.errno) { |
2899 // wait until master FSM has finished processing |
2511 retval = -request->req.errno; |
2900 wait_event(master->request_queue, request.state != EC_INT_REQUEST_BUSY); |
|
2901 |
|
2902 *abort_code = request.abort_code; |
|
2903 |
|
2904 if (request.state == EC_INT_REQUEST_SUCCESS) { |
|
2905 ret = 0; |
|
2906 } else if (request.errno) { |
|
2907 ret = -request.errno; |
2512 } else { |
2908 } else { |
2513 retval = -EIO; |
2909 ret = -EIO; |
2514 } |
2910 } |
2515 |
2911 |
2516 kref_put(&request->refcount, ec_master_sdo_request_release); |
2912 ec_sdo_request_clear(&request); |
2517 return retval; |
2913 return ret; |
2518 } |
2914 } |
2519 |
2915 |
2520 /*****************************************************************************/ |
2916 /*****************************************************************************/ |
2521 |
2917 |
2522 int ecrt_master_sdo_download_complete(ec_master_t *master, |
2918 int ecrt_master_sdo_download_complete(ec_master_t *master, |
2523 uint16_t slave_position, uint16_t index, uint8_t *data, |
2919 uint16_t slave_position, uint16_t index, uint8_t *data, |
2524 size_t data_size, uint32_t *abort_code) |
2920 size_t data_size, uint32_t *abort_code) |
2525 { |
2921 { |
2526 ec_master_sdo_request_t *request; |
2922 ec_sdo_request_t request; |
2527 int retval; |
2923 ec_slave_t *slave; |
|
2924 int ret; |
2528 |
2925 |
2529 EC_MASTER_DBG(master, 1, "%s(master = 0x%p," |
2926 EC_MASTER_DBG(master, 1, "%s(master = 0x%p," |
2530 " slave_position = %u, index = 0x%04X," |
2927 " slave_position = %u, index = 0x%04X," |
2531 " data = 0x%p, data_size = %zu, abort_code = 0x%p)\n", |
2928 " data = 0x%p, data_size = %zu, abort_code = 0x%p)\n", |
2532 __func__, master, slave_position, index, data, data_size, |
2929 __func__, master, slave_position, index, data, data_size, |
2535 if (!data_size) { |
2932 if (!data_size) { |
2536 EC_MASTER_ERR(master, "Zero data size!\n"); |
2933 EC_MASTER_ERR(master, "Zero data size!\n"); |
2537 return -EINVAL; |
2934 return -EINVAL; |
2538 } |
2935 } |
2539 |
2936 |
2540 request = kmalloc(sizeof(*request), GFP_KERNEL); |
2937 ec_sdo_request_init(&request); |
2541 if (!request) { |
2938 ecrt_sdo_request_index(&request, index, 0); |
2542 return -ENOMEM; |
2939 ret = ec_sdo_request_alloc(&request, data_size); |
2543 } |
2940 if (ret) { |
2544 kref_init(&request->refcount); |
2941 ec_sdo_request_clear(&request); |
2545 |
2942 return ret; |
2546 ec_sdo_request_init(&request->req); |
2943 } |
2547 ec_sdo_request_address(&request->req, index, 0); |
2944 |
2548 if (ec_sdo_request_alloc(&request->req, data_size)) { |
2945 request.complete_access = 1; |
2549 kref_put(&request->refcount, ec_master_sdo_request_release); |
2946 memcpy(request.data, data, data_size); |
2550 return -ENOMEM; |
2947 request.data_size = data_size; |
2551 } |
2948 ecrt_sdo_request_write(&request); |
2552 |
2949 |
2553 request->req.complete_access = 1; |
2950 if (down_interruptible(&master->master_sem)) { |
2554 memcpy(request->req.data, data, data_size); |
2951 ec_sdo_request_clear(&request); |
2555 request->req.data_size = data_size; |
|
2556 ecrt_sdo_request_write(&request->req); |
|
2557 |
|
2558 if (ec_mutex_lock_interruptible(&master->master_mutex)) { |
|
2559 kref_put(&request->refcount, ec_master_sdo_request_release); |
|
2560 return -EINTR; |
2952 return -EINTR; |
2561 } |
2953 } |
2562 |
2954 |
2563 if (!(request->slave = ec_master_find_slave( |
2955 if (!(slave = ec_master_find_slave(master, 0, slave_position))) { |
2564 master, 0, slave_position))) { |
2956 up(&master->master_sem); |
2565 ec_mutex_unlock(&master->master_mutex); |
|
2566 EC_MASTER_ERR(master, "Slave %u does not exist!\n", slave_position); |
2957 EC_MASTER_ERR(master, "Slave %u does not exist!\n", slave_position); |
2567 kref_put(&request->refcount, ec_master_sdo_request_release); |
2958 ec_sdo_request_clear(&request); |
2568 return -EINVAL; |
2959 return -EINVAL; |
2569 } |
2960 } |
2570 |
2961 |
2571 EC_SLAVE_DBG(request->slave, 1, "Schedule SDO download request %p" |
2962 EC_SLAVE_DBG(slave, 1, "Scheduling SDO download request" |
2572 " (complete access).\n", request); |
2963 " (complete access).\n"); |
2573 |
2964 |
2574 // schedule request |
2965 // schedule request. |
2575 kref_get(&request->refcount); |
2966 list_add_tail(&request.list, &slave->sdo_requests); |
2576 list_add_tail(&request->list, &request->slave->slave_sdo_requests); |
2967 |
2577 |
2968 up(&master->master_sem); |
2578 ec_mutex_unlock(&master->master_mutex); |
|
2579 |
2969 |
2580 // wait for processing through FSM |
2970 // wait for processing through FSM |
2581 if (wait_event_interruptible(request->slave->sdo_queue, |
2971 if (wait_event_interruptible(master->request_queue, |
2582 ((request->req.state == EC_INT_REQUEST_SUCCESS) || |
2972 request.state != EC_INT_REQUEST_QUEUED)) { |
2583 (request->req.state == EC_INT_REQUEST_FAILURE)))) { |
|
2584 // interrupted by signal |
2973 // interrupted by signal |
2585 kref_put(&request->refcount, ec_master_sdo_request_release); |
2974 down(&master->master_sem); |
2586 return -EINTR; |
2975 if (request.state == EC_INT_REQUEST_QUEUED) { |
2587 } |
2976 list_del(&request.list); |
2588 |
2977 up(&master->master_sem); |
2589 EC_SLAVE_DBG(request->slave, 1, "Finished SDO download request %p" |
2978 ec_sdo_request_clear(&request); |
2590 " (complete access).\n", request); |
2979 return -EINTR; |
2591 |
2980 } |
2592 *abort_code = request->req.abort_code; |
2981 // request already processing: interrupt not possible. |
2593 |
2982 up(&master->master_sem); |
2594 if (request->req.state == EC_INT_REQUEST_SUCCESS) { |
2983 } |
2595 retval = 0; |
2984 |
2596 } else if (request->req.errno) { |
2985 // wait until master FSM has finished processing |
2597 retval = -request->req.errno; |
2986 wait_event(master->request_queue, request.state != EC_INT_REQUEST_BUSY); |
|
2987 |
|
2988 *abort_code = request.abort_code; |
|
2989 |
|
2990 if (request.state == EC_INT_REQUEST_SUCCESS) { |
|
2991 ret = 0; |
|
2992 } else if (request.errno) { |
|
2993 ret = -request.errno; |
2598 } else { |
2994 } else { |
2599 retval = -EIO; |
2995 ret = -EIO; |
2600 } |
2996 } |
2601 |
2997 |
2602 kref_put(&request->refcount, ec_master_sdo_request_release); |
2998 ec_sdo_request_clear(&request); |
2603 return retval; |
2999 return ret; |
2604 } |
3000 } |
2605 |
3001 |
2606 /*****************************************************************************/ |
3002 /*****************************************************************************/ |
2607 |
3003 |
2608 int ecrt_master_sdo_upload(ec_master_t *master, uint16_t slave_position, |
3004 int ecrt_master_sdo_upload(ec_master_t *master, uint16_t slave_position, |
2609 uint16_t index, uint8_t subindex, uint8_t *target, |
3005 uint16_t index, uint8_t subindex, uint8_t *target, |
2610 size_t target_size, size_t *result_size, uint32_t *abort_code) |
3006 size_t target_size, size_t *result_size, uint32_t *abort_code) |
2611 { |
3007 { |
2612 ec_master_sdo_request_t *request; |
3008 ec_sdo_request_t request; |
2613 int retval; |
3009 ec_slave_t *slave; |
|
3010 int ret = 0; |
2614 |
3011 |
2615 EC_MASTER_DBG(master, 1, "%s(master = 0x%p," |
3012 EC_MASTER_DBG(master, 1, "%s(master = 0x%p," |
2616 " slave_position = %u, index = 0x%04X, subindex = 0x%02X," |
3013 " slave_position = %u, index = 0x%04X, subindex = 0x%02X," |
2617 " target = 0x%p, target_size = %zu, result_size = 0x%p, " |
3014 " target = 0x%p, target_size = %zu, result_size = 0x%p," |
2618 " abort_code = 0x%p)\n", |
3015 " abort_code = 0x%p)\n", |
2619 __func__, master, slave_position, index, subindex, target, |
3016 __func__, master, slave_position, index, subindex, |
2620 target_size, result_size, abort_code); |
3017 target, target_size, result_size, abort_code); |
2621 |
3018 |
2622 request = kmalloc(sizeof(*request), GFP_KERNEL); |
3019 ec_sdo_request_init(&request); |
2623 if (!request) { |
3020 ecrt_sdo_request_index(&request, index, subindex); |
2624 return -ENOMEM; |
3021 ecrt_sdo_request_read(&request); |
2625 } |
3022 |
2626 kref_init(&request->refcount); |
3023 if (down_interruptible(&master->master_sem)) { |
2627 |
3024 ec_sdo_request_clear(&request); |
2628 ec_sdo_request_init(&request->req); |
|
2629 ec_sdo_request_address(&request->req, index, subindex); |
|
2630 ecrt_sdo_request_read(&request->req); |
|
2631 |
|
2632 if (ec_mutex_lock_interruptible(&master->master_mutex)) { |
|
2633 kref_put(&request->refcount, ec_master_sdo_request_release); |
|
2634 return -EINTR; |
3025 return -EINTR; |
2635 } |
3026 } |
2636 |
3027 |
2637 if (!(request->slave = ec_master_find_slave( |
3028 if (!(slave = ec_master_find_slave(master, 0, slave_position))) { |
2638 master, 0, slave_position))) { |
3029 up(&master->master_sem); |
2639 ec_mutex_unlock(&master->master_mutex); |
3030 ec_sdo_request_clear(&request); |
2640 EC_MASTER_ERR(master, "Slave %u does not exist!\n", slave_position); |
3031 EC_MASTER_ERR(master, "Slave %u does not exist!\n", slave_position); |
2641 kref_put(&request->refcount, ec_master_sdo_request_release); |
|
2642 return -EINVAL; |
3032 return -EINVAL; |
2643 } |
3033 } |
2644 |
3034 |
2645 EC_SLAVE_DBG(request->slave, 1, "Schedule SDO upload request %p.\n", |
3035 EC_SLAVE_DBG(slave, 1, "Scheduling SDO upload request.\n"); |
2646 request); |
3036 |
2647 |
3037 // schedule request. |
2648 // schedule request |
3038 list_add_tail(&request.list, &slave->sdo_requests); |
2649 kref_get(&request->refcount); |
3039 |
2650 list_add_tail(&request->list, &request->slave->slave_sdo_requests); |
3040 up(&master->master_sem); |
2651 |
|
2652 ec_mutex_unlock(&master->master_mutex); |
|
2653 |
3041 |
2654 // wait for processing through FSM |
3042 // wait for processing through FSM |
2655 if (wait_event_interruptible(request->slave->sdo_queue, |
3043 if (wait_event_interruptible(master->request_queue, |
2656 ((request->req.state == EC_INT_REQUEST_SUCCESS) || |
3044 request.state != EC_INT_REQUEST_QUEUED)) { |
2657 (request->req.state == EC_INT_REQUEST_FAILURE)))) { |
|
2658 // interrupted by signal |
3045 // interrupted by signal |
2659 kref_put(&request->refcount, ec_master_sdo_request_release); |
3046 down(&master->master_sem); |
2660 return -EINTR; |
3047 if (request.state == EC_INT_REQUEST_QUEUED) { |
2661 } |
3048 list_del(&request.list); |
2662 |
3049 up(&master->master_sem); |
2663 EC_SLAVE_DBG(request->slave, 1, "Finished SDO upload request %p.\n", |
3050 ec_sdo_request_clear(&request); |
2664 request); |
3051 return -EINTR; |
2665 |
3052 } |
2666 *abort_code = request->req.abort_code; |
3053 // request already processing: interrupt not possible. |
2667 |
3054 up(&master->master_sem); |
2668 if (request->req.state != EC_INT_REQUEST_SUCCESS) { |
3055 } |
|
3056 |
|
3057 // wait until master FSM has finished processing |
|
3058 wait_event(master->request_queue, request.state != EC_INT_REQUEST_BUSY); |
|
3059 |
|
3060 *abort_code = request.abort_code; |
|
3061 |
|
3062 if (request.state != EC_INT_REQUEST_SUCCESS) { |
2669 *result_size = 0; |
3063 *result_size = 0; |
2670 if (request->req.errno) { |
3064 if (request.errno) { |
2671 retval = -request->req.errno; |
3065 ret = -request.errno; |
2672 } else { |
3066 } else { |
2673 retval = -EIO; |
3067 ret = -EIO; |
2674 } |
3068 } |
2675 } else { |
3069 } else { |
2676 if (request->req.data_size > target_size) { |
3070 if (request.data_size > target_size) { |
2677 EC_MASTER_ERR(master, "Buffer too small.\n"); |
3071 EC_MASTER_ERR(master, "Buffer too small.\n"); |
2678 kref_put(&request->refcount, ec_master_sdo_request_release); |
3072 ret = -EOVERFLOW; |
2679 return -EOVERFLOW; |
3073 } |
2680 } |
3074 else { |
2681 memcpy(target, request->req.data, request->req.data_size); |
3075 memcpy(target, request.data, request.data_size); |
2682 *result_size = request->req.data_size; |
3076 *result_size = request.data_size; |
2683 retval = 0; |
3077 ret = 0; |
2684 } |
3078 } |
2685 |
3079 } |
2686 kref_put(&request->refcount, ec_master_sdo_request_release); |
3080 |
2687 return retval; |
3081 ec_sdo_request_clear(&request); |
|
3082 return ret; |
2688 } |
3083 } |
2689 |
3084 |
2690 /*****************************************************************************/ |
3085 /*****************************************************************************/ |
2691 |
3086 |
2692 int ecrt_master_write_idn(ec_master_t *master, uint16_t slave_position, |
3087 int ecrt_master_write_idn(ec_master_t *master, uint16_t slave_position, |
2693 uint8_t drive_no, uint16_t idn, uint8_t *data, size_t data_size, |
3088 uint8_t drive_no, uint16_t idn, uint8_t *data, size_t data_size, |
2694 uint16_t *error_code) |
3089 uint16_t *error_code) |
2695 { |
3090 { |
2696 ec_master_soe_request_t *request; |
3091 ec_soe_request_t request; |
2697 int retval; |
3092 ec_slave_t *slave; |
|
3093 int ret; |
2698 |
3094 |
2699 if (drive_no > 7) { |
3095 if (drive_no > 7) { |
2700 EC_MASTER_ERR(master, "Invalid drive number!\n"); |
3096 EC_MASTER_ERR(master, "Invalid drive number!\n"); |
2701 return -EINVAL; |
3097 return -EINVAL; |
2702 } |
3098 } |
2703 |
3099 |
2704 request = kmalloc(sizeof(*request), GFP_KERNEL); |
3100 ec_soe_request_init(&request); |
2705 if (!request) { |
3101 ec_soe_request_set_drive_no(&request, drive_no); |
2706 return -ENOMEM; |
3102 ec_soe_request_set_idn(&request, idn); |
2707 } |
3103 |
2708 kref_init(&request->refcount); |
3104 ret = ec_soe_request_alloc(&request, data_size); |
2709 |
3105 if (ret) { |
2710 INIT_LIST_HEAD(&request->list); |
3106 ec_soe_request_clear(&request); |
2711 ec_soe_request_init(&request->req); |
3107 return ret; |
2712 ec_soe_request_set_drive_no(&request->req, drive_no); |
3108 } |
2713 ec_soe_request_set_idn(&request->req, idn); |
3109 |
2714 |
3110 memcpy(request.data, data, data_size); |
2715 if (ec_soe_request_alloc(&request->req, data_size)) { |
3111 request.data_size = data_size; |
2716 ec_soe_request_clear(&request->req); |
3112 ec_soe_request_write(&request); |
2717 kref_put(&request->refcount,ec_master_soe_request_release); |
3113 |
2718 return -ENOMEM; |
3114 if (down_interruptible(&master->master_sem)) { |
2719 } |
3115 ec_soe_request_clear(&request); |
2720 |
|
2721 memcpy(request->req.data, data, data_size); |
|
2722 request->req.data_size = data_size; |
|
2723 ec_soe_request_write(&request->req); |
|
2724 |
|
2725 if (ec_mutex_lock_interruptible(&master->master_mutex)) { |
|
2726 kref_put(&request->refcount,ec_master_soe_request_release); |
|
2727 return -EINTR; |
3116 return -EINTR; |
2728 } |
3117 } |
2729 |
3118 |
2730 if (!(request->slave = ec_master_find_slave( |
3119 if (!(slave = ec_master_find_slave(master, 0, slave_position))) { |
2731 master, 0, slave_position))) { |
3120 up(&master->master_sem); |
2732 ec_mutex_unlock(&master->master_mutex); |
|
2733 EC_MASTER_ERR(master, "Slave %u does not exist!\n", |
3121 EC_MASTER_ERR(master, "Slave %u does not exist!\n", |
2734 slave_position); |
3122 slave_position); |
2735 kref_put(&request->refcount,ec_master_soe_request_release); |
3123 ec_soe_request_clear(&request); |
2736 return -EINVAL; |
3124 return -EINVAL; |
2737 } |
3125 } |
2738 |
3126 |
2739 EC_SLAVE_DBG(request->slave, 1, "Scheduled SoE write request %p.\n", |
3127 EC_SLAVE_DBG(slave, 1, "Scheduling SoE write request.\n"); |
2740 request); |
|
2741 |
3128 |
2742 // schedule SoE write request. |
3129 // schedule SoE write request. |
2743 list_add_tail(&request->list, &request->slave->soe_requests); |
3130 list_add_tail(&request.list, &slave->soe_requests); |
2744 kref_get(&request->refcount); |
3131 |
2745 |
3132 up(&master->master_sem); |
2746 ec_mutex_unlock(&master->master_mutex); |
|
2747 |
3133 |
2748 // wait for processing through FSM |
3134 // wait for processing through FSM |
2749 if (wait_event_interruptible(request->slave->soe_queue, |
3135 if (wait_event_interruptible(master->request_queue, |
2750 ((request->req.state == EC_INT_REQUEST_SUCCESS) || |
3136 request.state != EC_INT_REQUEST_QUEUED)) { |
2751 (request->req.state == EC_INT_REQUEST_FAILURE)))) { |
3137 // interrupted by signal |
2752 // interrupted by signal |
3138 down(&master->master_sem); |
2753 kref_put(&request->refcount,ec_master_soe_request_release); |
3139 if (request.state == EC_INT_REQUEST_QUEUED) { |
2754 return -EINTR; |
3140 // abort request |
2755 } |
3141 list_del(&request.list); |
|
3142 up(&master->master_sem); |
|
3143 ec_soe_request_clear(&request); |
|
3144 return -EINTR; |
|
3145 } |
|
3146 up(&master->master_sem); |
|
3147 } |
|
3148 |
|
3149 // wait until master FSM has finished processing |
|
3150 wait_event(master->request_queue, request.state != EC_INT_REQUEST_BUSY); |
2756 |
3151 |
2757 if (error_code) { |
3152 if (error_code) { |
2758 *error_code = request->req.error_code; |
3153 *error_code = request.error_code; |
2759 } |
3154 } |
2760 retval = request->req.state == EC_INT_REQUEST_SUCCESS ? 0 : -EIO; |
3155 ret = request.state == EC_INT_REQUEST_SUCCESS ? 0 : -EIO; |
2761 kref_put(&request->refcount,ec_master_soe_request_release); |
3156 ec_soe_request_clear(&request); |
2762 |
3157 |
2763 return retval; |
3158 return ret; |
2764 } |
3159 } |
2765 |
3160 |
2766 /*****************************************************************************/ |
3161 /*****************************************************************************/ |
2767 |
3162 |
2768 int ecrt_master_read_idn(ec_master_t *master, uint16_t slave_position, |
3163 int ecrt_master_read_idn(ec_master_t *master, uint16_t slave_position, |
2769 uint8_t drive_no, uint16_t idn, uint8_t *target, size_t target_size, |
3164 uint8_t drive_no, uint16_t idn, uint8_t *target, size_t target_size, |
2770 size_t *result_size, uint16_t *error_code) |
3165 size_t *result_size, uint16_t *error_code) |
2771 { |
3166 { |
2772 ec_master_soe_request_t *request; |
3167 ec_soe_request_t request; |
|
3168 ec_slave_t *slave; |
|
3169 int ret; |
2773 |
3170 |
2774 if (drive_no > 7) { |
3171 if (drive_no > 7) { |
2775 EC_MASTER_ERR(master, "Invalid drive number!\n"); |
3172 EC_MASTER_ERR(master, "Invalid drive number!\n"); |
2776 return -EINVAL; |
3173 return -EINVAL; |
2777 } |
3174 } |
2778 |
3175 |
2779 request = kmalloc(sizeof(*request), GFP_KERNEL); |
3176 ec_soe_request_init(&request); |
2780 if (!request) { |
3177 ec_soe_request_set_drive_no(&request, drive_no); |
2781 return -ENOMEM; |
3178 ec_soe_request_set_idn(&request, idn); |
2782 } |
3179 ec_soe_request_read(&request); |
2783 kref_init(&request->refcount); |
3180 |
2784 |
3181 if (down_interruptible(&master->master_sem)) { |
2785 INIT_LIST_HEAD(&request->list); |
3182 ec_soe_request_clear(&request); |
2786 ec_soe_request_init(&request->req); |
|
2787 ec_soe_request_set_drive_no(&request->req, drive_no); |
|
2788 ec_soe_request_set_idn(&request->req, idn); |
|
2789 ec_soe_request_read(&request->req); |
|
2790 |
|
2791 if (ec_mutex_lock_interruptible(&master->master_mutex)) { |
|
2792 kref_put(&request->refcount,ec_master_soe_request_release); |
|
2793 return -EINTR; |
3183 return -EINTR; |
2794 } |
3184 } |
2795 |
3185 |
2796 if (!(request->slave = ec_master_find_slave(master, 0, slave_position))) { |
3186 if (!(slave = ec_master_find_slave(master, 0, slave_position))) { |
2797 ec_mutex_unlock(&master->master_mutex); |
3187 up(&master->master_sem); |
2798 kref_put(&request->refcount,ec_master_soe_request_release); |
3188 ec_soe_request_clear(&request); |
2799 EC_MASTER_ERR(master, "Slave %u does not exist!\n", slave_position); |
3189 EC_MASTER_ERR(master, "Slave %u does not exist!\n", slave_position); |
2800 return -EINVAL; |
3190 return -EINVAL; |
2801 } |
3191 } |
2802 |
3192 |
|
3193 EC_SLAVE_DBG(slave, 1, "Scheduling SoE read request.\n"); |
|
3194 |
2803 // schedule request. |
3195 // schedule request. |
2804 list_add_tail(&request->list, &request->slave->soe_requests); |
3196 list_add_tail(&request.list, &slave->soe_requests); |
2805 kref_get(&request->refcount); |
3197 |
2806 |
3198 up(&master->master_sem); |
2807 ec_mutex_unlock(&master->master_mutex); |
|
2808 |
|
2809 EC_SLAVE_DBG(request->slave, 1, "Scheduled SoE read request %p.\n", |
|
2810 request); |
|
2811 |
3199 |
2812 // wait for processing through FSM |
3200 // wait for processing through FSM |
2813 if (wait_event_interruptible(request->slave->soe_queue, |
3201 if (wait_event_interruptible(master->request_queue, |
2814 ((request->req.state == EC_INT_REQUEST_SUCCESS) || |
3202 request.state != EC_INT_REQUEST_QUEUED)) { |
2815 (request->req.state == EC_INT_REQUEST_FAILURE)))) { |
3203 // interrupted by signal |
2816 // interrupted by signal |
3204 down(&master->master_sem); |
2817 kref_put(&request->refcount,ec_master_soe_request_release); |
3205 if (request.state == EC_INT_REQUEST_QUEUED) { |
2818 return -EINTR; |
3206 list_del(&request.list); |
2819 } |
3207 up(&master->master_sem); |
|
3208 ec_soe_request_clear(&request); |
|
3209 return -EINTR; |
|
3210 } |
|
3211 // request already processing: interrupt not possible. |
|
3212 up(&master->master_sem); |
|
3213 } |
|
3214 |
|
3215 // wait until master FSM has finished processing |
|
3216 wait_event(master->request_queue, request.state != EC_INT_REQUEST_BUSY); |
2820 |
3217 |
2821 if (error_code) { |
3218 if (error_code) { |
2822 *error_code = request->req.error_code; |
3219 *error_code = request.error_code; |
2823 } |
3220 } |
2824 |
3221 |
2825 EC_SLAVE_DBG(request->slave, 1, "SoE request %p read %zd bytes" |
3222 if (request.state != EC_INT_REQUEST_SUCCESS) { |
2826 " via SoE.\n", request, request->req.data_size); |
|
2827 |
|
2828 if (request->req.state != EC_INT_REQUEST_SUCCESS) { |
|
2829 if (result_size) { |
3223 if (result_size) { |
2830 *result_size = 0; |
3224 *result_size = 0; |
2831 } |
3225 } |
2832 kref_put(&request->refcount,ec_master_soe_request_release); |
3226 ret = -EIO; |
2833 return -EIO; |
3227 } else { // success |
2834 } else { |
3228 if (request.data_size > target_size) { |
2835 if (request->req.data_size > target_size) { |
|
2836 EC_MASTER_ERR(master, "Buffer too small.\n"); |
3229 EC_MASTER_ERR(master, "Buffer too small.\n"); |
2837 kref_put(&request->refcount,ec_master_soe_request_release); |
3230 ret = -EOVERFLOW; |
2838 return -EOVERFLOW; |
3231 } |
2839 } |
3232 else { // data fits in buffer |
2840 if (result_size) { |
3233 if (result_size) { |
2841 *result_size = request->req.data_size; |
3234 *result_size = request.data_size; |
2842 } |
3235 } |
2843 memcpy(target, request->req.data, request->req.data_size); |
3236 memcpy(target, request.data, request.data_size); |
2844 kref_put(&request->refcount,ec_master_soe_request_release); |
3237 ret = 0; |
2845 return 0; |
3238 } |
2846 } |
3239 } |
|
3240 |
|
3241 ec_soe_request_clear(&request); |
|
3242 return ret; |
2847 } |
3243 } |
2848 |
3244 |
2849 /*****************************************************************************/ |
3245 /*****************************************************************************/ |
2850 |
3246 |
2851 void ecrt_master_reset(ec_master_t *master) |
3247 void ecrt_master_reset(ec_master_t *master) |