219 fsm->slave_states = EC_READ_U8(datagram->data); |
219 fsm->slave_states = EC_READ_U8(datagram->data); |
220 ec_state_string(fsm->slave_states, states); |
220 ec_state_string(fsm->slave_states, states); |
221 EC_INFO("Slave states: %s.\n", states); |
221 EC_INFO("Slave states: %s.\n", states); |
222 } |
222 } |
223 |
223 |
224 // topology change in idle mode: clear all slaves and scan the bus |
224 if (fsm->topology_change_pending) { |
225 if (fsm->topology_change_pending && |
225 down(&master->scan_sem); |
226 master->mode == EC_MASTER_MODE_IDLE) { |
226 if (!master->allow_scan) { |
227 fsm->topology_change_pending = 0; |
227 up(&master->scan_sem); |
228 fsm->tainted = 0; |
228 } |
229 fsm->idle = 0; |
229 else { |
230 fsm->scan_jiffies = jiffies; |
230 master->scan_state = EC_REQUEST_IN_PROGRESS; |
231 |
231 up(&master->scan_sem); |
232 ec_master_eoe_stop(master); |
232 |
233 ec_master_destroy_slaves(master); |
233 // topology change when scan is allowed: |
234 |
234 // clear all slaves and scan the bus |
235 master->slave_count = datagram->working_counter; |
235 fsm->topology_change_pending = 0; |
236 |
236 fsm->tainted = 0; |
237 if (!master->slave_count) { |
237 fsm->idle = 0; |
238 // no slaves present -> finish state machine. |
238 fsm->scan_jiffies = jiffies; |
239 fsm->state = ec_fsm_master_state_end; |
239 |
240 return; |
240 ec_master_eoe_stop(master); |
241 } |
241 ec_master_destroy_slaves(master); |
242 |
242 |
243 // init slaves |
243 master->slave_count = datagram->working_counter; |
244 for (i = 0; i < master->slave_count; i++) { |
244 |
245 if (!(slave = (ec_slave_t *) kmalloc(sizeof(ec_slave_t), |
245 if (!master->slave_count) { |
246 GFP_ATOMIC))) { |
246 // no slaves present -> finish state machine. |
247 EC_ERR("Failed to allocate slave %i!\n", i); |
247 master->scan_state = EC_REQUEST_COMPLETE; |
248 ec_master_destroy_slaves(master); |
248 wake_up_interruptible(&master->scan_queue); |
249 fsm->state = ec_fsm_master_state_error; |
249 fsm->state = ec_fsm_master_state_end; |
250 return; |
250 return; |
251 } |
251 } |
252 |
252 |
253 if (ec_slave_init(slave, master, i, i + 1)) { |
253 // init slaves |
254 // freeing of "slave" already done |
254 for (i = 0; i < master->slave_count; i++) { |
255 ec_master_destroy_slaves(master); |
255 if (!(slave = (ec_slave_t *) kmalloc(sizeof(ec_slave_t), |
256 fsm->state = ec_fsm_master_state_error; |
256 GFP_ATOMIC))) { |
257 return; |
257 EC_ERR("Failed to allocate slave %i!\n", i); |
|
258 ec_master_destroy_slaves(master); |
|
259 master->scan_state = EC_REQUEST_FAILURE; |
|
260 wake_up_interruptible(&master->scan_queue); |
|
261 fsm->state = ec_fsm_master_state_error; |
|
262 return; |
|
263 } |
|
264 |
|
265 if (ec_slave_init(slave, master, i, i + 1)) { |
|
266 // freeing of "slave" already done |
|
267 ec_master_destroy_slaves(master); |
|
268 master->scan_state = EC_REQUEST_FAILURE; |
|
269 wake_up_interruptible(&master->scan_queue); |
|
270 fsm->state = ec_fsm_master_state_error; |
|
271 return; |
|
272 } |
|
273 |
|
274 list_add_tail(&slave->list, &master->slaves); |
258 } |
275 } |
259 |
276 |
260 list_add_tail(&slave->list, &master->slaves); |
277 EC_INFO("Scanning bus.\n"); |
261 } |
278 |
262 |
279 // begin scanning of slaves |
263 EC_INFO("Scanning bus.\n"); |
280 fsm->slave = list_entry(master->slaves.next, ec_slave_t, list); |
264 |
281 fsm->state = ec_fsm_master_state_scan_slaves; |
265 // begin scanning of slaves |
282 ec_fsm_slave_start_scan(&fsm->fsm_slave, fsm->slave); |
266 fsm->slave = list_entry(master->slaves.next, ec_slave_t, list); |
283 ec_fsm_slave_exec(&fsm->fsm_slave); // execute immediately |
267 fsm->state = ec_fsm_master_state_scan_slaves; |
284 return; |
268 ec_fsm_slave_start_scan(&fsm->fsm_slave, fsm->slave); |
285 } |
269 ec_fsm_slave_exec(&fsm->fsm_slave); // execute immediately |
|
270 return; |
|
271 } |
286 } |
272 |
287 |
273 // fetch state from each slave |
288 // fetch state from each slave |
274 fsm->slave = list_entry(master->slaves.next, ec_slave_t, list); |
289 fsm->slave = list_entry(master->slaves.next, ec_slave_t, list); |
275 ec_datagram_nprd(fsm->datagram, fsm->slave->station_address, 0x0130, 2); |
290 ec_datagram_nprd(fsm->datagram, fsm->slave->station_address, 0x0130, 2); |
390 } |
405 } |
391 |
406 |
392 /*****************************************************************************/ |
407 /*****************************************************************************/ |
393 |
408 |
394 /** |
409 /** |
395 Master action: PROC_STATES. |
410 */ |
396 Processes the slave states. |
411 |
397 */ |
412 int ec_fsm_master_action_configure( |
398 |
413 ec_fsm_master_t *fsm /**< master state machine */ |
399 void ec_fsm_master_action_process_states(ec_fsm_master_t *fsm |
414 ) |
400 /**< master state machine */ |
415 { |
401 ) |
416 ec_slave_t *slave; |
402 { |
|
403 ec_master_t *master = fsm->master; |
417 ec_master_t *master = fsm->master; |
404 ec_slave_t *slave; |
|
405 char old_state[EC_STATE_STRING_SIZE], new_state[EC_STATE_STRING_SIZE]; |
418 char old_state[EC_STATE_STRING_SIZE], new_state[EC_STATE_STRING_SIZE]; |
406 |
419 |
407 // check if any slaves are not in the state, they're supposed to be |
420 // check if any slaves are not in the state, they're supposed to be |
|
421 // FIXME do not check all slaves in every cycle... |
408 list_for_each_entry(slave, &master->slaves, list) { |
422 list_for_each_entry(slave, &master->slaves, list) { |
409 if (slave->error_flag |
423 if (slave->error_flag |
410 || slave->online_state == EC_SLAVE_OFFLINE |
424 || slave->online_state == EC_SLAVE_OFFLINE |
411 || slave->requested_state == EC_SLAVE_STATE_UNKNOWN |
425 || slave->requested_state == EC_SLAVE_STATE_UNKNOWN |
412 || (slave->current_state == slave->requested_state |
426 || (slave->current_state == slave->requested_state |
413 && slave->self_configured)) continue; |
427 && slave->self_configured)) continue; |
414 |
428 |
415 if (master->debug_level) { |
429 if (master->debug_level) { |
416 ec_state_string(slave->current_state, old_state); |
430 ec_state_string(slave->current_state, old_state); |
417 if (slave->current_state != slave->requested_state) { |
431 if (slave->current_state != slave->requested_state) { |
418 ec_state_string(slave->requested_state, new_state); |
432 ec_state_string(slave->requested_state, new_state); |
419 EC_DBG("Changing state of slave %i (%s -> %s).\n", |
433 EC_DBG("Changing state of slave %i (%s -> %s).\n", |
420 slave->ring_position, old_state, new_state); |
434 slave->ring_position, old_state, new_state); |
421 } |
435 } |
422 else if (!slave->self_configured) { |
436 else if (!slave->self_configured) { |
423 EC_DBG("Reconfiguring slave %i (%s).\n", |
437 EC_DBG("Reconfiguring slave %i (%s).\n", |
424 slave->ring_position, old_state); |
438 slave->ring_position, old_state); |
425 } |
439 } |
426 } |
440 } |
427 |
441 |
428 fsm->idle = 0; |
442 fsm->idle = 0; |
429 fsm->slave = slave; |
443 fsm->slave = slave; |
430 fsm->state = ec_fsm_master_state_configure_slave; |
444 fsm->state = ec_fsm_master_state_configure_slave; |
431 ec_fsm_slave_start_conf(&fsm->fsm_slave, slave); |
445 ec_fsm_slave_start_conf(&fsm->fsm_slave, slave); |
432 ec_fsm_slave_exec(&fsm->fsm_slave); // execute immediately |
446 ec_fsm_slave_exec(&fsm->fsm_slave); // execute immediately |
433 return; |
447 return 1; |
|
448 } |
|
449 |
|
450 if (fsm->config_error) |
|
451 master->config_state = EC_REQUEST_FAILURE; |
|
452 else |
|
453 master->config_state = EC_REQUEST_COMPLETE; |
|
454 wake_up_interruptible(&master->config_queue); |
|
455 return 0; |
|
456 } |
|
457 |
|
458 /*****************************************************************************/ |
|
459 |
|
460 /** |
|
461 Master action: PROC_STATES. |
|
462 Processes the slave states. |
|
463 */ |
|
464 |
|
465 void ec_fsm_master_action_process_states(ec_fsm_master_t *fsm |
|
466 /**< master state machine */ |
|
467 ) |
|
468 { |
|
469 ec_master_t *master = fsm->master; |
|
470 ec_slave_t *slave; |
|
471 |
|
472 down(&master->config_sem); |
|
473 if (!master->allow_config) { |
|
474 up(&master->config_sem); |
|
475 } |
|
476 else { |
|
477 master->config_state = EC_REQUEST_IN_PROGRESS; |
|
478 fsm->config_error = 0; |
|
479 up(&master->config_sem); |
|
480 |
|
481 // check for pending slave configurations |
|
482 if (ec_fsm_master_action_configure(fsm)) |
|
483 return; |
434 } |
484 } |
435 |
485 |
436 // Check, if EoE processing has to be started |
486 // Check, if EoE processing has to be started |
437 ec_master_eoe_start(master); |
487 ec_master_eoe_start(master); |
438 |
488 |