157 init_waitqueue_head(&slave->foe_queue); |
157 init_waitqueue_head(&slave->foe_queue); |
158 |
158 |
159 INIT_LIST_HEAD(&slave->soe_requests); |
159 INIT_LIST_HEAD(&slave->soe_requests); |
160 init_waitqueue_head(&slave->soe_queue); |
160 init_waitqueue_head(&slave->soe_queue); |
161 |
161 |
162 // init state machine datagram |
162 // init datagram |
163 ec_datagram_init(&slave->fsm_datagram); |
163 ec_datagram_init(&slave->datagram); |
164 snprintf(slave->fsm_datagram.name, EC_DATAGRAM_NAME_SIZE, |
164 snprintf(slave->datagram.name, EC_DATAGRAM_NAME_SIZE, |
165 "slave%u-fsm", slave->ring_position); |
165 "slave%u-fsm", slave->ring_position); |
166 ret = ec_datagram_prealloc(&slave->fsm_datagram, EC_MAX_DATA_SIZE); |
166 ret = ec_datagram_prealloc(&slave->datagram, EC_MAX_DATA_SIZE); |
167 if (ret < 0) { |
167 if (ret < 0) { |
168 ec_datagram_clear(&slave->fsm_datagram); |
168 ec_datagram_clear(&slave->datagram); |
169 EC_SLAVE_ERR(slave, "Failed to allocate FSM datagram.\n"); |
169 EC_SLAVE_ERR(slave, "Failed to allocate FSM datagram.\n"); |
170 return; |
170 return; |
171 } |
171 } |
|
172 ec_mbox_init(&slave->mbox,&slave->datagram); |
172 |
173 |
173 // create state machine object |
174 // create state machine object |
174 ec_fsm_slave_init(&slave->fsm, slave, &slave->fsm_datagram); |
175 ec_fsm_slave_init(&slave->fsm, slave, &slave->mbox); |
175 } |
176 } |
176 |
177 |
177 /*****************************************************************************/ |
178 /*****************************************************************************/ |
178 |
179 |
179 /** |
180 /** |
192 while (!list_empty(&slave->slave_sdo_requests)) { |
193 while (!list_empty(&slave->slave_sdo_requests)) { |
193 ec_master_sdo_request_t *request = |
194 ec_master_sdo_request_t *request = |
194 list_entry(slave->slave_sdo_requests.next, |
195 list_entry(slave->slave_sdo_requests.next, |
195 ec_master_sdo_request_t, list); |
196 ec_master_sdo_request_t, list); |
196 list_del_init(&request->list); // dequeue |
197 list_del_init(&request->list); // dequeue |
197 EC_SLAVE_WARN(slave, "Discarding SDO request," |
198 EC_SLAVE_WARN(slave, "Discarding SDO request %p," |
198 " slave about to be deleted.\n"); |
199 " slave about to be deleted.\n",request); |
199 request->req.state = EC_INT_REQUEST_FAILURE; |
200 request->req.state = EC_INT_REQUEST_FAILURE; |
|
201 kref_put(&request->refcount,ec_master_sdo_request_release); |
200 wake_up(&slave->sdo_queue); |
202 wake_up(&slave->sdo_queue); |
201 } |
203 } |
202 |
204 |
203 while (!list_empty(&slave->foe_requests)) { |
205 while (!list_empty(&slave->foe_requests)) { |
204 ec_master_foe_request_t *request = |
206 ec_master_foe_request_t *request = |
206 ec_master_foe_request_t, list); |
208 ec_master_foe_request_t, list); |
207 list_del_init(&request->list); // dequeue |
209 list_del_init(&request->list); // dequeue |
208 EC_SLAVE_WARN(slave, "Discarding FoE request," |
210 EC_SLAVE_WARN(slave, "Discarding FoE request," |
209 " slave about to be deleted.\n"); |
211 " slave about to be deleted.\n"); |
210 request->req.state = EC_INT_REQUEST_FAILURE; |
212 request->req.state = EC_INT_REQUEST_FAILURE; |
|
213 kref_put(&request->refcount,ec_master_foe_request_release); |
211 wake_up(&slave->foe_queue); |
214 wake_up(&slave->foe_queue); |
212 } |
215 } |
213 |
216 |
214 while (!list_empty(&slave->soe_requests)) { |
217 while (!list_empty(&slave->soe_requests)) { |
215 ec_master_soe_request_t *request = |
218 ec_master_soe_request_t *request = |
217 ec_master_soe_request_t, list); |
220 ec_master_soe_request_t, list); |
218 list_del_init(&request->list); // dequeue |
221 list_del_init(&request->list); // dequeue |
219 EC_SLAVE_WARN(slave, "Discarding SoE request," |
222 EC_SLAVE_WARN(slave, "Discarding SoE request," |
220 " slave about to be deleted.\n"); |
223 " slave about to be deleted.\n"); |
221 request->req.state = EC_INT_REQUEST_FAILURE; |
224 request->req.state = EC_INT_REQUEST_FAILURE; |
|
225 kref_put(&request->refcount,ec_master_soe_request_release); |
222 wake_up(&slave->soe_queue); |
226 wake_up(&slave->soe_queue); |
223 } |
227 } |
224 |
228 |
225 if (slave->config) |
229 if (slave->config) |
226 ec_slave_config_detach(slave->config); |
230 ec_slave_config_detach(slave->config); |
250 } |
254 } |
251 |
255 |
252 if (slave->sii_words) |
256 if (slave->sii_words) |
253 kfree(slave->sii_words); |
257 kfree(slave->sii_words); |
254 ec_fsm_slave_clear(&slave->fsm); |
258 ec_fsm_slave_clear(&slave->fsm); |
255 ec_datagram_clear(&slave->fsm_datagram); |
259 ec_mbox_clear(&slave->mbox); |
256 } |
260 } |
257 |
261 |
258 /*****************************************************************************/ |
262 /*****************************************************************************/ |
259 |
263 |
260 /** Clear the sync manager array. |
264 /** Clear the sync manager array. |
801 } |
805 } |
802 } |
806 } |
803 |
807 |
804 /*****************************************************************************/ |
808 /*****************************************************************************/ |
805 |
809 |
|
810 /** returns the previous connected port of a given port. |
|
811 */ |
|
812 |
|
813 unsigned int ec_slave_get_previous_port( |
|
814 ec_slave_t *slave, /**< EtherCAT slave. */ |
|
815 unsigned int i /**< Port index */ |
|
816 ) |
|
817 { |
|
818 do |
|
819 { |
|
820 switch (i) |
|
821 { |
|
822 case 0: i = 2; break; |
|
823 case 1: i = 3; break; |
|
824 case 2: i = 1; break; |
|
825 case 3: |
|
826 default:i = 0; break; |
|
827 } |
|
828 if (slave->ports[i].next_slave) |
|
829 return i; |
|
830 } while (i); |
|
831 return 0; |
|
832 } |
|
833 |
|
834 /*****************************************************************************/ |
|
835 |
|
836 /** returns the next connected port of a given port. |
|
837 */ |
|
838 |
|
839 unsigned int ec_slave_get_next_port( |
|
840 ec_slave_t *slave, /**< EtherCAT slave. */ |
|
841 unsigned int i /**< Port index */ |
|
842 ) |
|
843 { |
|
844 do |
|
845 { |
|
846 switch (i) |
|
847 { |
|
848 case 0: i = 3; break; |
|
849 case 1: i = 2; break; |
|
850 case 3: i = 1; break; |
|
851 case 2: |
|
852 default:i = 0; break; |
|
853 } |
|
854 if (slave->ports[i].next_slave) |
|
855 return i; |
|
856 } while (i); |
|
857 return 0; |
|
858 } |
|
859 |
|
860 |
|
861 /*****************************************************************************/ |
|
862 |
806 /** Calculates the sum of round-trip-times of connected ports 1-3. |
863 /** Calculates the sum of round-trip-times of connected ports 1-3. |
807 */ |
864 */ |
808 uint32_t ec_slave_calc_rtt_sum( |
865 uint32_t ec_slave_calc_rtt_sum( |
809 ec_slave_t *slave /**< EtherCAT slave. */ |
866 ec_slave_t *slave /**< EtherCAT slave. */ |
810 ) |
867 ) |
811 { |
868 { |
812 uint32_t rtt_sum = 0, rtt; |
869 uint32_t rtt_sum = 0, rtt; |
813 unsigned int i; |
870 unsigned int i = ec_slave_get_next_port(slave,0); |
814 |
871 while (i != 0) { |
815 for (i = 1; i < EC_MAX_PORTS; i++) { |
872 rtt = slave->ports[i].receive_time - slave->ports[ec_slave_get_previous_port(slave,i)].receive_time; |
816 if (slave->ports[i].next_slave) { |
873 rtt_sum += rtt; |
817 rtt = slave->ports[i].receive_time - slave->ports[i - 1].receive_time; |
874 i = ec_slave_get_next_port(slave,i); |
818 rtt_sum += rtt; |
|
819 } |
|
820 } |
875 } |
821 |
876 |
822 return rtt_sum; |
877 return rtt_sum; |
823 } |
878 } |
824 |
879 |
828 */ |
883 */ |
829 ec_slave_t *ec_slave_find_next_dc_slave( |
884 ec_slave_t *ec_slave_find_next_dc_slave( |
830 ec_slave_t *slave /**< EtherCAT slave. */ |
885 ec_slave_t *slave /**< EtherCAT slave. */ |
831 ) |
886 ) |
832 { |
887 { |
|
888 unsigned int i; |
833 ec_slave_t *dc_slave = NULL; |
889 ec_slave_t *dc_slave = NULL; |
834 |
890 |
835 if (slave->base_dc_supported) { |
891 if (slave->base_dc_supported) { |
836 dc_slave = slave; |
892 dc_slave = slave; |
837 } else { |
893 } else { |
838 unsigned int i; |
894 i = ec_slave_get_next_port(slave,0); |
839 |
895 while (i != 0) { |
840 for (i = 1; i < EC_MAX_PORTS; i++) { |
|
841 ec_slave_t *next = slave->ports[i].next_slave; |
896 ec_slave_t *next = slave->ports[i].next_slave; |
842 if (next) { |
897 if (next) { |
843 dc_slave = ec_slave_find_next_dc_slave(next); |
898 dc_slave = ec_slave_find_next_dc_slave(next); |
844 if (dc_slave) |
899 if (dc_slave) |
845 break; |
900 break; |
846 } |
901 } |
|
902 i = ec_slave_get_next_port(slave,i); |
847 } |
903 } |
848 } |
904 } |
849 |
905 |
850 return dc_slave; |
906 return dc_slave; |
851 } |
907 } |
857 void ec_slave_calc_port_delays( |
913 void ec_slave_calc_port_delays( |
858 ec_slave_t *slave /**< EtherCAT slave. */ |
914 ec_slave_t *slave /**< EtherCAT slave. */ |
859 ) |
915 ) |
860 { |
916 { |
861 unsigned int i; |
917 unsigned int i; |
862 ec_slave_t *next, *next_dc; |
918 ec_slave_t *next_dc; |
863 uint32_t rtt, next_rtt_sum; |
919 uint32_t rtt, next_rtt_sum; |
864 |
920 |
865 if (!slave->base_dc_supported) |
921 if (!slave->base_dc_supported) |
866 return; |
922 return; |
867 |
923 |
868 for (i = 1; i < EC_MAX_PORTS; i++) { |
924 i = ec_slave_get_next_port(slave,0); |
869 next = slave->ports[i].next_slave; |
925 while (i != 0) { |
870 if (!next) |
926 next_dc = ec_slave_find_next_dc_slave(slave->ports[i].next_slave); |
871 continue; |
927 if (next_dc) { |
872 next_dc = ec_slave_find_next_dc_slave(next); |
928 rtt = slave->ports[i].receive_time - slave->ports[ec_slave_get_previous_port(slave,i)].receive_time; |
873 if (!next_dc) |
929 next_rtt_sum = ec_slave_calc_rtt_sum(next_dc); |
874 continue; |
930 |
875 |
931 slave->ports[i].delay_to_next_dc = (rtt - next_rtt_sum) / 2; // FIXME |
876 rtt = slave->ports[i].receive_time - slave->ports[i - 1].receive_time; |
932 next_dc->ports[0].delay_to_next_dc = (rtt - next_rtt_sum) / 2; |
877 next_rtt_sum = ec_slave_calc_rtt_sum(next_dc); |
|
878 |
|
879 slave->ports[i].delay_to_next_dc = (rtt - next_rtt_sum) / 2; // FIXME |
|
880 next_dc->ports[0].delay_to_next_dc = (rtt - next_rtt_sum) / 2; |
|
881 |
933 |
882 #if 0 |
934 #if 0 |
883 EC_SLAVE_DBG(slave, 1, "delay %u:%u rtt=%u" |
935 EC_SLAVE_DBG(slave, 1, "delay %u:%u rtt=%u" |
884 " next_rtt_sum=%u delay=%u\n", |
936 " next_rtt_sum=%u delay=%u\n", |
885 slave->ring_position, i, rtt, next_rtt_sum, |
937 slave->ring_position, i, rtt, next_rtt_sum, |
886 slave->ports[i].delay_to_next_dc); |
938 slave->ports[i].delay_to_next_dc); |
887 #endif |
939 #endif |
|
940 } |
|
941 i = ec_slave_get_next_port(slave,i); |
888 } |
942 } |
889 } |
943 } |
890 |
944 |
891 /*****************************************************************************/ |
945 /*****************************************************************************/ |
892 |
946 |
896 ec_slave_t *slave, /**< Current slave. */ |
950 ec_slave_t *slave, /**< Current slave. */ |
897 uint32_t *delay /**< Sum of delays. */ |
951 uint32_t *delay /**< Sum of delays. */ |
898 ) |
952 ) |
899 { |
953 { |
900 unsigned int i; |
954 unsigned int i; |
901 ec_slave_t *next, *next_dc; |
955 ec_slave_t *next_dc; |
902 |
956 |
903 #if 0 |
957 #if 1 |
904 EC_SLAVE_DBG(slave, 1, "%u\n", *delay); |
958 EC_SLAVE_DBG(slave, 1, "%u\n", *delay); |
905 #endif |
959 #endif |
906 |
960 |
907 slave->transmission_delay = *delay; |
961 slave->transmission_delay = *delay; |
908 |
962 |
909 for (i = 1; i < EC_MAX_PORTS; i++) { |
963 i = ec_slave_get_next_port(slave,0); |
|
964 while (i != 0) { |
910 ec_slave_port_t *port = &slave->ports[i]; |
965 ec_slave_port_t *port = &slave->ports[i]; |
911 next = port->next_slave; |
966 next_dc = ec_slave_find_next_dc_slave(port->next_slave); |
912 if (!next) |
967 if (next_dc) { |
913 continue; |
968 *delay = *delay + port->delay_to_next_dc; |
914 next_dc = ec_slave_find_next_dc_slave(next); |
|
915 if (!next_dc) |
|
916 continue; |
|
917 |
|
918 *delay = *delay + port->delay_to_next_dc; |
|
919 #if 0 |
969 #if 0 |
920 EC_SLAVE_DBG(slave, 1, "%u:%u %u\n", slave->ring_position, i, *delay); |
970 EC_SLAVE_DBG(slave, 1, "%u:%u %u\n", slave->ring_position, i, *delay); |
921 #endif |
971 #endif |
922 ec_slave_calc_transmission_delays_rec(next_dc, delay); |
972 ec_slave_calc_transmission_delays_rec(next_dc, delay); |
|
973 } |
|
974 i = ec_slave_get_next_port(slave,i); |
923 } |
975 } |
924 |
976 |
925 *delay = *delay + slave->ports[0].delay_to_next_dc; |
977 *delay = *delay + slave->ports[0].delay_to_next_dc; |
926 } |
978 } |
927 |
979 |