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