34 /*****************************************************************************/ |
34 /*****************************************************************************/ |
35 |
35 |
36 #include "globals.h" |
36 #include "globals.h" |
37 #include "master.h" |
37 #include "master.h" |
38 #include "mailbox.h" |
38 #include "mailbox.h" |
|
39 #include "slave_config.h" |
39 |
40 |
40 #include "fsm_slave.h" |
41 #include "fsm_slave.h" |
41 |
42 |
42 /*****************************************************************************/ |
43 /*****************************************************************************/ |
43 |
44 |
44 void ec_fsm_slave_state_idle(ec_fsm_slave_t *); |
45 void ec_fsm_slave_state_idle(ec_fsm_slave_t *, ec_datagram_t *); |
45 void ec_fsm_slave_state_ready(ec_fsm_slave_t *); |
46 void ec_fsm_slave_state_ready(ec_fsm_slave_t *, ec_datagram_t *); |
46 int ec_fsm_slave_action_process_sdo(ec_fsm_slave_t *); |
47 int ec_fsm_slave_action_process_sdo(ec_fsm_slave_t *, ec_datagram_t *); |
47 void ec_fsm_slave_state_sdo_request(ec_fsm_slave_t *); |
48 void ec_fsm_slave_state_sdo_request(ec_fsm_slave_t *, ec_datagram_t *); |
48 int ec_fsm_slave_action_process_foe(ec_fsm_slave_t *); |
49 int ec_fsm_slave_action_process_reg(ec_fsm_slave_t *, ec_datagram_t *); |
49 void ec_fsm_slave_state_foe_request(ec_fsm_slave_t *); |
50 void ec_fsm_slave_state_reg_request(ec_fsm_slave_t *, ec_datagram_t *); |
50 int ec_fsm_slave_action_process_soe(ec_fsm_slave_t *); |
51 int ec_fsm_slave_action_process_foe(ec_fsm_slave_t *, ec_datagram_t *); |
51 void ec_fsm_slave_state_soe_request(ec_fsm_slave_t *); |
52 void ec_fsm_slave_state_foe_request(ec_fsm_slave_t *, ec_datagram_t *); |
|
53 int ec_fsm_slave_action_process_soe(ec_fsm_slave_t *, ec_datagram_t *); |
|
54 void ec_fsm_slave_state_soe_request(ec_fsm_slave_t *, ec_datagram_t *); |
52 |
55 |
53 /*****************************************************************************/ |
56 /*****************************************************************************/ |
54 |
57 |
55 /** Constructor. |
58 /** Constructor. |
56 */ |
59 */ |
57 void ec_fsm_slave_init( |
60 void ec_fsm_slave_init( |
58 ec_fsm_slave_t *fsm, /**< Slave state machine. */ |
61 ec_fsm_slave_t *fsm, /**< Slave state machine. */ |
59 ec_slave_t *slave, /**< EtherCAT slave. */ |
62 ec_slave_t *slave /**< EtherCAT slave. */ |
60 ec_mailbox_t *mbox/**< Datagram object to use. */ |
|
61 ) |
63 ) |
62 { |
64 { |
63 fsm->slave = slave; |
65 fsm->slave = slave; |
64 fsm->mbox = mbox; |
66 INIT_LIST_HEAD(&fsm->list); // mark as unlisted |
65 slave->datagram.data_size = 0; |
|
66 |
|
67 EC_SLAVE_DBG(slave, 1, "Init FSM.\n"); |
|
68 |
67 |
69 fsm->state = ec_fsm_slave_state_idle; |
68 fsm->state = ec_fsm_slave_state_idle; |
70 |
69 fsm->datagram = NULL; |
71 // init sub-state-machines |
70 fsm->sdo_request = NULL; |
72 ec_fsm_coe_init(&fsm->fsm_coe, fsm->mbox); |
71 fsm->reg_request = NULL; |
73 ec_fsm_foe_init(&fsm->fsm_foe, fsm->mbox); |
72 fsm->foe_request = NULL; |
74 ec_fsm_soe_init(&fsm->fsm_soe, fsm->mbox); |
73 fsm->soe_request = NULL; |
|
74 |
|
75 // Init sub-state-machines |
|
76 ec_fsm_coe_init(&fsm->fsm_coe); |
|
77 ec_fsm_foe_init(&fsm->fsm_foe); |
|
78 ec_fsm_soe_init(&fsm->fsm_soe); |
75 } |
79 } |
76 |
80 |
77 /*****************************************************************************/ |
81 /*****************************************************************************/ |
78 |
82 |
79 /** Destructor. |
83 /** Destructor. |
80 */ |
84 */ |
81 void ec_fsm_slave_clear( |
85 void ec_fsm_slave_clear( |
82 ec_fsm_slave_t *fsm /**< Master state machine. */ |
86 ec_fsm_slave_t *fsm /**< Master state machine. */ |
83 ) |
87 ) |
84 { |
88 { |
|
89 // signal requests that are currently in operation |
|
90 |
|
91 if (fsm->sdo_request) { |
|
92 fsm->sdo_request->state = EC_INT_REQUEST_FAILURE; |
|
93 wake_up_all(&fsm->slave->master->request_queue); |
|
94 } |
|
95 |
|
96 if (fsm->reg_request) { |
|
97 fsm->reg_request->state = EC_INT_REQUEST_FAILURE; |
|
98 wake_up_all(&fsm->slave->master->request_queue); |
|
99 } |
|
100 |
|
101 if (fsm->foe_request) { |
|
102 fsm->foe_request->state = EC_INT_REQUEST_FAILURE; |
|
103 wake_up_all(&fsm->slave->master->request_queue); |
|
104 } |
|
105 |
|
106 if (fsm->soe_request) { |
|
107 fsm->soe_request->state = EC_INT_REQUEST_FAILURE; |
|
108 wake_up_all(&fsm->slave->master->request_queue); |
|
109 } |
|
110 |
85 // clear sub-state machines |
111 // clear sub-state machines |
86 ec_fsm_coe_clear(&fsm->fsm_coe); |
112 ec_fsm_coe_clear(&fsm->fsm_coe); |
87 ec_fsm_foe_clear(&fsm->fsm_foe); |
113 ec_fsm_foe_clear(&fsm->fsm_foe); |
88 ec_fsm_soe_clear(&fsm->fsm_soe); |
114 ec_fsm_soe_clear(&fsm->fsm_soe); |
89 } |
115 } |
90 |
116 |
91 /*****************************************************************************/ |
117 /*****************************************************************************/ |
92 |
118 |
93 /** Executes the current state of the state machine. |
119 /** Executes the current state of the state machine. |
94 * |
120 * |
95 * If the state machine's datagram is not sent or received yet, the execution |
121 * \return 1 if \a datagram was used, else 0. |
96 * of the state machine is delayed to the next cycle. |
|
97 * |
|
98 * \return true, if the state machine was executed |
|
99 */ |
122 */ |
100 int ec_fsm_slave_exec( |
123 int ec_fsm_slave_exec( |
101 ec_fsm_slave_t *fsm /**< Slave state machine. */ |
124 ec_fsm_slave_t *fsm, /**< Slave state machine. */ |
102 ) |
125 ec_datagram_t *datagram /**< New datagram to use. */ |
103 { |
126 ) |
104 if (ec_mbox_is_datagram_state(fsm->mbox, EC_DATAGRAM_QUEUED) |
127 { |
105 || ec_mbox_is_datagram_state(fsm->mbox, EC_DATAGRAM_SENT)) { |
128 int datagram_used; |
106 // datagram was not sent or received yet. |
129 |
107 return 0; |
130 fsm->state(fsm, datagram); |
108 } |
131 |
109 |
132 datagram_used = fsm->state != ec_fsm_slave_state_idle && |
110 fsm->state(fsm); |
133 fsm->state != ec_fsm_slave_state_ready; |
111 return 1; |
134 |
|
135 if (datagram_used) { |
|
136 fsm->datagram = datagram; |
|
137 } else { |
|
138 fsm->datagram = NULL; |
|
139 } |
|
140 |
|
141 return datagram_used; |
112 } |
142 } |
113 |
143 |
114 /*****************************************************************************/ |
144 /*****************************************************************************/ |
115 |
145 |
116 /** Sets the current state of the state machine to READY |
146 /** Sets the current state of the state machine to READY |
117 */ |
147 */ |
118 void ec_fsm_slave_ready( |
148 void ec_fsm_slave_set_ready( |
119 ec_fsm_slave_t *fsm /**< Slave state machine. */ |
149 ec_fsm_slave_t *fsm /**< Slave state machine. */ |
120 ) |
150 ) |
121 { |
151 { |
122 if (fsm->state == ec_fsm_slave_state_idle) { |
152 if (fsm->state == ec_fsm_slave_state_idle) { |
123 EC_SLAVE_DBG(fsm->slave, 1, "Ready for requests.\n"); |
153 EC_SLAVE_DBG(fsm->slave, 1, "Ready for requests.\n"); |
124 fsm->state = ec_fsm_slave_state_ready; |
154 fsm->state = ec_fsm_slave_state_ready; |
125 } |
155 } |
126 } |
156 } |
127 |
157 |
|
158 /*****************************************************************************/ |
|
159 |
|
160 /** Returns, if the FSM is currently not busy and ready to execute. |
|
161 * |
|
162 * \return Non-zero if ready. |
|
163 */ |
|
164 int ec_fsm_slave_is_ready( |
|
165 const ec_fsm_slave_t *fsm /**< Slave state machine. */ |
|
166 ) |
|
167 { |
|
168 return fsm->state == ec_fsm_slave_state_ready; |
|
169 } |
|
170 |
128 /****************************************************************************** |
171 /****************************************************************************** |
129 * Slave state machine |
172 * Slave state machine |
130 *****************************************************************************/ |
173 *****************************************************************************/ |
131 |
174 |
132 /** Slave state: IDLE. |
175 /** Slave state: IDLE. |
133 */ |
176 */ |
134 void ec_fsm_slave_state_idle( |
177 void ec_fsm_slave_state_idle( |
135 ec_fsm_slave_t *fsm /**< Slave state machine. */ |
178 ec_fsm_slave_t *fsm, /**< Slave state machine. */ |
|
179 ec_datagram_t *datagram /**< Datagram to use. */ |
136 ) |
180 ) |
137 { |
181 { |
138 // do nothing |
182 // do nothing |
139 } |
183 } |
140 |
184 |
141 /*****************************************************************************/ |
185 /*****************************************************************************/ |
142 |
186 |
143 /** Slave state: READY. |
187 /** Slave state: READY. |
144 */ |
188 */ |
145 void ec_fsm_slave_state_ready( |
189 void ec_fsm_slave_state_ready( |
146 ec_fsm_slave_t *fsm /**< Slave state machine. */ |
190 ec_fsm_slave_t *fsm, /**< Slave state machine. */ |
|
191 ec_datagram_t *datagram /**< Datagram to use. */ |
147 ) |
192 ) |
148 { |
193 { |
149 // Check for pending external SDO requests |
194 // Check for pending external SDO requests |
150 if (ec_fsm_slave_action_process_sdo(fsm)) |
195 if (ec_fsm_slave_action_process_sdo(fsm, datagram)) { |
151 return; |
196 return; |
|
197 } |
|
198 |
|
199 // Check for pending external register requests |
|
200 if (ec_fsm_slave_action_process_reg(fsm, datagram)) { |
|
201 return; |
|
202 } |
152 |
203 |
153 // Check for pending FoE requests |
204 // Check for pending FoE requests |
154 if (ec_fsm_slave_action_process_foe(fsm)) |
205 if (ec_fsm_slave_action_process_foe(fsm, datagram)) { |
155 return; |
206 return; |
|
207 } |
156 |
208 |
157 // Check for pending SoE requests |
209 // Check for pending SoE requests |
158 if (ec_fsm_slave_action_process_soe(fsm)) |
210 if (ec_fsm_slave_action_process_soe(fsm, datagram)) { |
159 return; |
211 return; |
|
212 } |
160 } |
213 } |
161 |
214 |
162 /*****************************************************************************/ |
215 /*****************************************************************************/ |
163 |
216 |
164 /** Check for pending SDO requests and process one. |
217 /** Check for pending SDO requests and process one. |
165 * |
218 * |
166 * \return non-zero, if an SDO request is processed. |
219 * \return non-zero, if an SDO request is processed. |
167 */ |
220 */ |
168 int ec_fsm_slave_action_process_sdo( |
221 int ec_fsm_slave_action_process_sdo( |
169 ec_fsm_slave_t *fsm /**< Slave state machine. */ |
222 ec_fsm_slave_t *fsm, /**< Slave state machine. */ |
170 ) |
223 ec_datagram_t *datagram /**< Datagram to use. */ |
171 { |
224 ) |
172 ec_slave_t *slave = fsm->slave; |
225 { |
173 ec_master_sdo_request_t *request, *next; |
226 ec_slave_t *slave = fsm->slave; |
174 |
227 ec_sdo_request_t *request; |
175 // search the first external request to be processed |
228 |
176 list_for_each_entry_safe(request, next, &slave->slave_sdo_requests, list) { |
229 if (list_empty(&slave->sdo_requests)) { |
177 |
230 return 0; |
178 list_del_init(&request->list); // dequeue |
231 } |
179 if (slave->current_state & EC_SLAVE_STATE_ACK_ERR) { |
232 |
180 EC_SLAVE_WARN(slave, "Aborting SDO request %p," |
233 // take the first request to be processed |
181 " slave has error flag set.\n",request); |
234 request = list_entry(slave->sdo_requests.next, ec_sdo_request_t, list); |
182 request->req.state = EC_INT_REQUEST_FAILURE; |
235 list_del_init(&request->list); // dequeue |
183 kref_put(&request->refcount,ec_master_sdo_request_release); |
236 |
184 wake_up(&slave->sdo_queue); |
237 if (slave->current_state & EC_SLAVE_STATE_ACK_ERR) { |
185 fsm->sdo_request = NULL; |
238 EC_SLAVE_WARN(slave, "Aborting SDO request," |
186 fsm->state = ec_fsm_slave_state_idle; |
239 " slave has error flag set.\n"); |
187 return 0; |
240 request->state = EC_INT_REQUEST_FAILURE; |
188 } |
241 wake_up_all(&slave->master->request_queue); |
189 |
242 fsm->state = ec_fsm_slave_state_idle; |
190 if (slave->current_state == EC_SLAVE_STATE_INIT) { |
|
191 EC_SLAVE_WARN(slave, "Aborting SDO request %p," |
|
192 " slave is in INIT.\n", request); |
|
193 request->req.state = EC_INT_REQUEST_FAILURE; |
|
194 kref_put(&request->refcount,ec_master_sdo_request_release); |
|
195 wake_up(&slave->sdo_queue); |
|
196 fsm->sdo_request = NULL; |
|
197 fsm->state = ec_fsm_slave_state_idle; |
|
198 return 0; |
|
199 } |
|
200 |
|
201 request->req.state = EC_INT_REQUEST_BUSY; |
|
202 |
|
203 // Found pending SDO request. Execute it! |
|
204 EC_SLAVE_DBG(slave, 1, "Processing SDO request %p...\n", request); |
|
205 |
|
206 // Start SDO transfer |
|
207 fsm->sdo_request = request; |
|
208 fsm->state = ec_fsm_slave_state_sdo_request; |
|
209 ec_fsm_coe_transfer(&fsm->fsm_coe, slave, &request->req); |
|
210 ec_fsm_coe_exec(&fsm->fsm_coe); // execute immediately |
|
211 ec_slave_mbox_queue_datagrams(slave, fsm->mbox); |
|
212 return 1; |
243 return 1; |
213 } |
244 } |
214 return 0; |
245 |
|
246 if (slave->current_state == EC_SLAVE_STATE_INIT) { |
|
247 EC_SLAVE_WARN(slave, "Aborting SDO request, slave is in INIT.\n"); |
|
248 request->state = EC_INT_REQUEST_FAILURE; |
|
249 wake_up_all(&slave->master->request_queue); |
|
250 fsm->state = ec_fsm_slave_state_idle; |
|
251 return 1; |
|
252 } |
|
253 |
|
254 fsm->sdo_request = request; |
|
255 request->state = EC_INT_REQUEST_BUSY; |
|
256 |
|
257 // Found pending SDO request. Execute it! |
|
258 EC_SLAVE_DBG(slave, 1, "Processing SDO request...\n"); |
|
259 |
|
260 // Start SDO transfer |
|
261 fsm->state = ec_fsm_slave_state_sdo_request; |
|
262 ec_fsm_coe_transfer(&fsm->fsm_coe, slave, request); |
|
263 ec_fsm_coe_exec(&fsm->fsm_coe, datagram); // execute immediately |
|
264 return 1; |
215 } |
265 } |
216 |
266 |
217 /*****************************************************************************/ |
267 /*****************************************************************************/ |
218 |
268 |
219 /** Slave state: SDO_REQUEST. |
269 /** Slave state: SDO_REQUEST. |
220 */ |
270 */ |
221 void ec_fsm_slave_state_sdo_request( |
271 void ec_fsm_slave_state_sdo_request( |
222 ec_fsm_slave_t *fsm /**< Slave state machine. */ |
272 ec_fsm_slave_t *fsm, /**< Slave state machine. */ |
223 ) |
273 ec_datagram_t *datagram /**< Datagram to use. */ |
224 { |
274 ) |
225 ec_slave_t *slave = fsm->slave; |
275 { |
226 ec_master_sdo_request_t *request = fsm->sdo_request; |
276 ec_slave_t *slave = fsm->slave; |
227 |
277 ec_sdo_request_t *request = fsm->sdo_request; |
228 if (ec_fsm_coe_exec(&fsm->fsm_coe)) { |
278 |
229 ec_slave_mbox_queue_datagrams(slave, fsm->mbox); |
279 if (ec_fsm_coe_exec(&fsm->fsm_coe, datagram)) { |
230 return; |
280 return; |
231 } |
281 } |
|
282 |
232 if (!ec_fsm_coe_success(&fsm->fsm_coe)) { |
283 if (!ec_fsm_coe_success(&fsm->fsm_coe)) { |
233 EC_SLAVE_ERR(slave, "Failed to process SDO request %p.\n", request); |
284 EC_SLAVE_ERR(slave, "Failed to process SDO request.\n"); |
234 request->req.state = EC_INT_REQUEST_FAILURE; |
285 request->state = EC_INT_REQUEST_FAILURE; |
235 kref_put(&request->refcount, ec_master_sdo_request_release); |
286 wake_up_all(&slave->master->request_queue); |
236 wake_up(&slave->sdo_queue); |
|
237 fsm->sdo_request = NULL; |
287 fsm->sdo_request = NULL; |
238 fsm->state = ec_fsm_slave_state_idle; |
288 fsm->state = ec_fsm_slave_state_ready; |
239 return; |
289 return; |
240 } |
290 } |
241 |
291 |
242 EC_SLAVE_DBG(slave, 1, "Finished SDO request %p.\n", request); |
292 EC_SLAVE_DBG(slave, 1, "Finished SDO request.\n"); |
243 |
293 |
244 // SDO request finished |
294 // SDO request finished |
245 request->req.state = EC_INT_REQUEST_SUCCESS; |
295 request->state = EC_INT_REQUEST_SUCCESS; |
246 kref_put(&request->refcount, ec_master_sdo_request_release); |
296 wake_up_all(&slave->master->request_queue); |
247 wake_up(&slave->sdo_queue); |
|
248 |
|
249 fsm->sdo_request = NULL; |
297 fsm->sdo_request = NULL; |
250 fsm->state = ec_fsm_slave_state_ready; |
298 fsm->state = ec_fsm_slave_state_ready; |
251 } |
299 } |
252 |
300 |
253 /*****************************************************************************/ |
301 /*****************************************************************************/ |
254 |
302 |
255 /** Check for pending FOE requests and process one. |
303 /** Check for pending register requests and process one. |
256 * |
304 * |
257 * \return non-zero, if an FOE request is processed. |
305 * \return non-zero, if a register request is processed. |
|
306 */ |
|
307 int ec_fsm_slave_action_process_reg( |
|
308 ec_fsm_slave_t *fsm, /**< Slave state machine. */ |
|
309 ec_datagram_t *datagram /**< Datagram to use. */ |
|
310 ) |
|
311 { |
|
312 ec_slave_t *slave = fsm->slave; |
|
313 ec_reg_request_t *reg; |
|
314 |
|
315 fsm->reg_request = NULL; |
|
316 |
|
317 if (slave->config) { |
|
318 // search the first internal register request to be processed |
|
319 list_for_each_entry(reg, &slave->config->reg_requests, list) { |
|
320 if (reg->state == EC_INT_REQUEST_QUEUED) { |
|
321 fsm->reg_request = reg; |
|
322 break; |
|
323 } |
|
324 } |
|
325 } |
|
326 |
|
327 if (!fsm->reg_request && !list_empty(&slave->reg_requests)) { |
|
328 // take the first external request to be processed |
|
329 fsm->reg_request = |
|
330 list_entry(slave->reg_requests.next, ec_reg_request_t, list); |
|
331 list_del_init(&fsm->reg_request->list); // dequeue |
|
332 } |
|
333 |
|
334 if (!fsm->reg_request) { // no register request to process |
|
335 return 0; |
|
336 } |
|
337 |
|
338 if (slave->current_state & EC_SLAVE_STATE_ACK_ERR) { |
|
339 EC_SLAVE_WARN(slave, "Aborting register request," |
|
340 " slave has error flag set.\n"); |
|
341 fsm->reg_request->state = EC_INT_REQUEST_FAILURE; |
|
342 wake_up_all(&slave->master->request_queue); |
|
343 fsm->reg_request = NULL; |
|
344 fsm->state = ec_fsm_slave_state_idle; |
|
345 return 1; |
|
346 } |
|
347 |
|
348 // Found pending register request. Execute it! |
|
349 EC_SLAVE_DBG(slave, 1, "Processing register request...\n"); |
|
350 |
|
351 fsm->reg_request->state = EC_INT_REQUEST_BUSY; |
|
352 |
|
353 // Start register access |
|
354 if (fsm->reg_request->dir == EC_DIR_INPUT) { |
|
355 ec_datagram_fprd(datagram, slave->station_address, |
|
356 fsm->reg_request->address, fsm->reg_request->transfer_size); |
|
357 ec_datagram_zero(datagram); |
|
358 } else { |
|
359 ec_datagram_fpwr(datagram, slave->station_address, |
|
360 fsm->reg_request->address, fsm->reg_request->transfer_size); |
|
361 memcpy(datagram->data, fsm->reg_request->data, |
|
362 fsm->reg_request->transfer_size); |
|
363 } |
|
364 datagram->device_index = slave->device_index; |
|
365 fsm->state = ec_fsm_slave_state_reg_request; |
|
366 return 1; |
|
367 } |
|
368 |
|
369 /*****************************************************************************/ |
|
370 |
|
371 /** Slave state: Register request. |
|
372 */ |
|
373 void ec_fsm_slave_state_reg_request( |
|
374 ec_fsm_slave_t *fsm, /**< Slave state machine. */ |
|
375 ec_datagram_t *datagram /**< Datagram to use. */ |
|
376 ) |
|
377 { |
|
378 ec_slave_t *slave = fsm->slave; |
|
379 ec_reg_request_t *reg = fsm->reg_request; |
|
380 |
|
381 if (!reg) { |
|
382 // configuration was cleared in the meantime |
|
383 fsm->state = ec_fsm_slave_state_ready; |
|
384 fsm->reg_request = NULL; |
|
385 return; |
|
386 } |
|
387 |
|
388 if (fsm->datagram->state != EC_DATAGRAM_RECEIVED) { |
|
389 EC_SLAVE_ERR(slave, "Failed to receive register" |
|
390 " request datagram: "); |
|
391 ec_datagram_print_state(fsm->datagram); |
|
392 reg->state = EC_INT_REQUEST_FAILURE; |
|
393 wake_up_all(&slave->master->request_queue); |
|
394 fsm->reg_request = NULL; |
|
395 fsm->state = ec_fsm_slave_state_ready; |
|
396 return; |
|
397 } |
|
398 |
|
399 if (fsm->datagram->working_counter == 1) { |
|
400 if (reg->dir == EC_DIR_INPUT) { // read request |
|
401 memcpy(reg->data, fsm->datagram->data, reg->transfer_size); |
|
402 } |
|
403 |
|
404 reg->state = EC_INT_REQUEST_SUCCESS; |
|
405 EC_SLAVE_DBG(slave, 1, "Register request successful.\n"); |
|
406 } else { |
|
407 reg->state = EC_INT_REQUEST_FAILURE; |
|
408 ec_datagram_print_state(fsm->datagram); |
|
409 EC_SLAVE_ERR(slave, "Register request failed" |
|
410 " (working counter is %u).\n", |
|
411 fsm->datagram->working_counter); |
|
412 } |
|
413 |
|
414 wake_up_all(&slave->master->request_queue); |
|
415 fsm->reg_request = NULL; |
|
416 fsm->state = ec_fsm_slave_state_ready; |
|
417 } |
|
418 |
|
419 /*****************************************************************************/ |
|
420 |
|
421 /** Check for pending FoE requests and process one. |
|
422 * |
|
423 * \return non-zero, if an FoE request is processed. |
258 */ |
424 */ |
259 int ec_fsm_slave_action_process_foe( |
425 int ec_fsm_slave_action_process_foe( |
260 ec_fsm_slave_t *fsm /**< Slave state machine. */ |
426 ec_fsm_slave_t *fsm, /**< Slave state machine. */ |
261 ) |
427 ec_datagram_t *datagram /**< Datagram to use. */ |
262 { |
428 ) |
263 ec_slave_t *slave = fsm->slave; |
429 { |
264 ec_master_foe_request_t *request, *next; |
430 ec_slave_t *slave = fsm->slave; |
265 |
431 ec_foe_request_t *request; |
266 // search the first request to be processed |
432 |
267 list_for_each_entry_safe(request, next, &slave->foe_requests, list) { |
433 if (list_empty(&slave->foe_requests)) { |
268 if (slave->current_state & EC_SLAVE_STATE_ACK_ERR) { |
434 return 0; |
269 EC_SLAVE_WARN(slave, "Aborting FOE request %p," |
435 } |
270 " slave has error flag set.\n", request); |
436 |
271 request->req.state = EC_INT_REQUEST_FAILURE; |
437 // take the first request to be processed |
272 kref_put(&request->refcount, ec_master_foe_request_release); |
438 request = list_entry(slave->foe_requests.next, ec_foe_request_t, list); |
273 wake_up(&slave->foe_queue); |
439 list_del_init(&request->list); // dequeue |
274 fsm->sdo_request = NULL; |
440 |
275 fsm->state = ec_fsm_slave_state_idle; |
441 if (slave->current_state & EC_SLAVE_STATE_ACK_ERR) { |
276 return 0; |
442 EC_SLAVE_WARN(slave, "Aborting FoE request," |
277 } |
443 " slave has error flag set.\n"); |
278 list_del_init(&request->list); // dequeue |
444 request->state = EC_INT_REQUEST_FAILURE; |
279 request->req.state = EC_INT_REQUEST_BUSY; |
445 wake_up_all(&slave->master->request_queue); |
280 |
446 fsm->state = ec_fsm_slave_state_idle; |
281 EC_SLAVE_DBG(slave, 1, "Processing FoE request %p.\n", request); |
|
282 |
|
283 fsm->foe_request = request; |
|
284 fsm->state = ec_fsm_slave_state_foe_request; |
|
285 ec_fsm_foe_transfer(&fsm->fsm_foe, slave, &request->req); |
|
286 ec_fsm_foe_exec(&fsm->fsm_foe); |
|
287 ec_slave_mbox_queue_datagrams(slave, fsm->mbox); |
|
288 return 1; |
447 return 1; |
289 } |
448 } |
290 return 0; |
449 |
|
450 request->state = EC_INT_REQUEST_BUSY; |
|
451 fsm->foe_request = request; |
|
452 |
|
453 EC_SLAVE_DBG(slave, 1, "Processing FoE request.\n"); |
|
454 |
|
455 fsm->state = ec_fsm_slave_state_foe_request; |
|
456 ec_fsm_foe_transfer(&fsm->fsm_foe, slave, request); |
|
457 ec_fsm_foe_exec(&fsm->fsm_foe, datagram); |
|
458 return 1; |
291 } |
459 } |
292 |
460 |
293 /*****************************************************************************/ |
461 /*****************************************************************************/ |
294 |
462 |
295 /** Slave state: FOE REQUEST. |
463 /** Slave state: FOE REQUEST. |
296 */ |
464 */ |
297 void ec_fsm_slave_state_foe_request( |
465 void ec_fsm_slave_state_foe_request( |
298 ec_fsm_slave_t *fsm /**< Slave state machine. */ |
466 ec_fsm_slave_t *fsm, /**< Slave state machine. */ |
299 ) |
467 ec_datagram_t *datagram /**< Datagram to use. */ |
300 { |
468 ) |
301 ec_slave_t *slave = fsm->slave; |
469 { |
302 ec_master_foe_request_t *request = fsm->foe_request; |
470 ec_slave_t *slave = fsm->slave; |
303 |
471 ec_foe_request_t *request = fsm->foe_request; |
304 if (ec_fsm_foe_exec(&fsm->fsm_foe)) { |
472 |
305 ec_slave_mbox_queue_datagrams(slave, fsm->mbox); |
473 if (ec_fsm_foe_exec(&fsm->fsm_foe, datagram)) { |
306 return; |
474 return; |
307 } |
475 } |
308 |
476 |
309 if (!ec_fsm_foe_success(&fsm->fsm_foe)) { |
477 if (!ec_fsm_foe_success(&fsm->fsm_foe)) { |
310 EC_SLAVE_ERR(slave, "Failed to handle FoE request %p.\n", request); |
478 EC_SLAVE_ERR(slave, "Failed to handle FoE request.\n"); |
311 request->req.state = EC_INT_REQUEST_FAILURE; |
479 request->state = EC_INT_REQUEST_FAILURE; |
312 kref_put(&request->refcount, ec_master_foe_request_release); |
480 wake_up_all(&slave->master->request_queue); |
313 wake_up(&slave->foe_queue); |
|
314 fsm->foe_request = NULL; |
481 fsm->foe_request = NULL; |
315 fsm->state = ec_fsm_slave_state_idle; |
482 fsm->state = ec_fsm_slave_state_ready; |
316 return; |
483 return; |
317 } |
484 } |
318 |
485 |
319 // finished transferring FoE |
486 // finished transferring FoE |
320 EC_SLAVE_DBG(slave, 1, "FoE request %p successfully" |
487 EC_SLAVE_DBG(slave, 1, "Successfully transferred %zu bytes of FoE" |
321 " transferred %zu bytes.\n", request, request->req.data_size); |
488 " data.\n", request->data_size); |
322 |
489 |
323 request->req.state = EC_INT_REQUEST_SUCCESS; |
490 request->state = EC_INT_REQUEST_SUCCESS; |
324 kref_put(&request->refcount, ec_master_foe_request_release); |
491 wake_up_all(&slave->master->request_queue); |
325 wake_up(&slave->foe_queue); |
|
326 |
|
327 fsm->foe_request = NULL; |
492 fsm->foe_request = NULL; |
328 fsm->state = ec_fsm_slave_state_ready; |
493 fsm->state = ec_fsm_slave_state_ready; |
329 } |
494 } |
330 |
495 |
331 /*****************************************************************************/ |
496 /*****************************************************************************/ |
333 /** Check for pending SoE requests and process one. |
498 /** Check for pending SoE requests and process one. |
334 * |
499 * |
335 * \return non-zero, if a request is processed. |
500 * \return non-zero, if a request is processed. |
336 */ |
501 */ |
337 int ec_fsm_slave_action_process_soe( |
502 int ec_fsm_slave_action_process_soe( |
338 ec_fsm_slave_t *fsm /**< Slave state machine. */ |
503 ec_fsm_slave_t *fsm, /**< Slave state machine. */ |
339 ) |
504 ec_datagram_t *datagram /**< Datagram to use. */ |
340 { |
505 ) |
341 ec_slave_t *slave = fsm->slave; |
506 { |
342 ec_master_soe_request_t *request, *next; |
507 ec_slave_t *slave = fsm->slave; |
343 |
508 ec_soe_request_t *req; |
344 // search the first request to be processed |
509 |
345 list_for_each_entry_safe(request, next, &slave->soe_requests, list) { |
510 if (list_empty(&slave->soe_requests)) { |
346 |
511 return 0; |
347 list_del_init(&request->list); // dequeue |
512 } |
348 if (slave->current_state & EC_SLAVE_STATE_ACK_ERR) { |
513 |
349 EC_SLAVE_WARN(slave, "Aborting SoE request," |
514 // take the first request to be processed |
350 " slave has error flag set.\n"); |
515 req = list_entry(slave->soe_requests.next, ec_soe_request_t, list); |
351 request->req.state = EC_INT_REQUEST_FAILURE; |
516 list_del_init(&req->list); // dequeue |
352 kref_put(&request->refcount, ec_master_soe_request_release); |
517 |
353 wake_up(&slave->soe_queue); |
518 if (slave->current_state & EC_SLAVE_STATE_ACK_ERR) { |
354 fsm->state = ec_fsm_slave_state_idle; |
519 EC_SLAVE_WARN(slave, "Aborting SoE request," |
355 return 0; |
520 " slave has error flag set.\n"); |
356 } |
521 req->state = EC_INT_REQUEST_FAILURE; |
357 |
522 wake_up_all(&slave->master->request_queue); |
358 if (slave->current_state == EC_SLAVE_STATE_INIT) { |
523 fsm->state = ec_fsm_slave_state_idle; |
359 EC_SLAVE_WARN(slave, "Aborting SoE request, slave is in INIT.\n"); |
|
360 request->req.state = EC_INT_REQUEST_FAILURE; |
|
361 kref_put(&request->refcount, ec_master_soe_request_release); |
|
362 wake_up(&slave->soe_queue); |
|
363 fsm->state = ec_fsm_slave_state_idle; |
|
364 return 0; |
|
365 } |
|
366 |
|
367 request->req.state = EC_INT_REQUEST_BUSY; |
|
368 |
|
369 // Found pending request. Execute it! |
|
370 EC_SLAVE_DBG(slave, 1, "Processing SoE request...\n"); |
|
371 |
|
372 // Start SoE transfer |
|
373 fsm->soe_request = request; |
|
374 fsm->state = ec_fsm_slave_state_soe_request; |
|
375 ec_fsm_soe_transfer(&fsm->fsm_soe, slave, &request->req); |
|
376 ec_fsm_soe_exec(&fsm->fsm_soe); // execute immediately |
|
377 ec_slave_mbox_queue_datagrams(slave, fsm->mbox); |
|
378 return 1; |
524 return 1; |
379 } |
525 } |
380 return 0; |
526 |
|
527 if (slave->current_state == EC_SLAVE_STATE_INIT) { |
|
528 EC_SLAVE_WARN(slave, "Aborting SoE request, slave is in INIT.\n"); |
|
529 req->state = EC_INT_REQUEST_FAILURE; |
|
530 wake_up_all(&slave->master->request_queue); |
|
531 fsm->state = ec_fsm_slave_state_idle; |
|
532 return 0; |
|
533 } |
|
534 |
|
535 fsm->soe_request = req; |
|
536 req->state = EC_INT_REQUEST_BUSY; |
|
537 |
|
538 // Found pending request. Execute it! |
|
539 EC_SLAVE_DBG(slave, 1, "Processing SoE request...\n"); |
|
540 |
|
541 // Start SoE transfer |
|
542 fsm->state = ec_fsm_slave_state_soe_request; |
|
543 ec_fsm_soe_transfer(&fsm->fsm_soe, slave, req); |
|
544 ec_fsm_soe_exec(&fsm->fsm_soe, datagram); // execute immediately |
|
545 return 1; |
381 } |
546 } |
382 |
547 |
383 /*****************************************************************************/ |
548 /*****************************************************************************/ |
384 |
549 |
385 /** Slave state: SOE_REQUEST. |
550 /** Slave state: SOE_REQUEST. |
386 */ |
551 */ |
387 void ec_fsm_slave_state_soe_request( |
552 void ec_fsm_slave_state_soe_request( |
388 ec_fsm_slave_t *fsm /**< Slave state machine. */ |
553 ec_fsm_slave_t *fsm, /**< Slave state machine. */ |
389 ) |
554 ec_datagram_t *datagram /**< Datagram to use. */ |
390 { |
555 ) |
391 ec_slave_t *slave = fsm->slave; |
556 { |
392 ec_master_soe_request_t *request = fsm->soe_request; |
557 ec_slave_t *slave = fsm->slave; |
393 |
558 ec_soe_request_t *request = fsm->soe_request; |
394 if (ec_fsm_soe_exec(&fsm->fsm_soe)) { |
559 |
395 ec_slave_mbox_queue_datagrams(slave, fsm->mbox); |
560 if (ec_fsm_soe_exec(&fsm->fsm_soe, datagram)) { |
396 return; |
561 return; |
397 } |
562 } |
398 |
563 |
399 if (!ec_fsm_soe_success(&fsm->fsm_soe)) { |
564 if (!ec_fsm_soe_success(&fsm->fsm_soe)) { |
400 EC_SLAVE_ERR(slave, "Failed to process SoE request.\n"); |
565 EC_SLAVE_ERR(slave, "Failed to process SoE request.\n"); |
401 request->req.state = EC_INT_REQUEST_FAILURE; |
566 request->state = EC_INT_REQUEST_FAILURE; |
402 kref_put(&request->refcount, ec_master_soe_request_release); |
567 wake_up_all(&slave->master->request_queue); |
403 wake_up(&slave->soe_queue); |
|
404 fsm->soe_request = NULL; |
568 fsm->soe_request = NULL; |
405 fsm->state = ec_fsm_slave_state_idle; |
569 fsm->state = ec_fsm_slave_state_ready; |
406 return; |
570 return; |
407 } |
571 } |
408 |
572 |
409 EC_SLAVE_DBG(slave, 1, "Finished SoE request.\n"); |
573 EC_SLAVE_DBG(slave, 1, "Finished SoE request.\n"); |
410 |
574 |
411 // SoE request finished |
575 // SoE request finished |
412 request->req.state = EC_INT_REQUEST_SUCCESS; |
576 request->state = EC_INT_REQUEST_SUCCESS; |
413 kref_put(&request->refcount, ec_master_soe_request_release); |
577 wake_up_all(&slave->master->request_queue); |
414 wake_up(&slave->soe_queue); |
|
415 |
|
416 fsm->soe_request = NULL; |
578 fsm->soe_request = NULL; |
417 fsm->state = ec_fsm_slave_state_ready; |
579 fsm->state = ec_fsm_slave_state_ready; |
418 } |
580 } |
419 |
581 |
420 /*****************************************************************************/ |
582 /*****************************************************************************/ |