diff -r 582a90a34303 -r bc1de1362efb master/master.c --- a/master/master.c Fri Mar 16 13:39:19 2007 +0000 +++ b/master/master.c Fri Mar 16 14:00:12 2007 +0000 @@ -154,7 +154,6 @@ master->eoe_timer.function = ec_master_eoe_run; master->eoe_timer.data = (unsigned long) master; master->eoe_running = 0; - master->eoe_checked = 0; INIT_LIST_HEAD(&master->eoe_handlers); master->internal_lock = SPIN_LOCK_UNLOCKED; @@ -229,40 +228,36 @@ ec_master_t *master /**< EtherCAT master */ ) { - ec_eoe_t *eoe, *next_eoe; - ec_datagram_t *datagram, *next_datagram; - + ec_master_clear_eoe_handlers(master); ec_master_destroy_slaves(master); ec_master_destroy_domains(master); - - // list of EEPROM requests is empty, - // otherwise master could not be cleared. - - // dequeue all datagrams - list_for_each_entry_safe(datagram, next_datagram, - &master->datagram_queue, queue) { - datagram->state = EC_DATAGRAM_ERROR; - list_del_init(&datagram->queue); - } - ec_fsm_master_clear(&master->fsm); ec_datagram_clear(&master->fsm_datagram); - - // clear EoE objects - list_for_each_entry_safe(eoe, next_eoe, &master->eoe_handlers, list) { + ec_device_clear(&master->backup_device); + ec_device_clear(&master->main_device); + + // destroy self + kobject_del(&master->kobj); + kobject_put(&master->kobj); +} + +/*****************************************************************************/ + +/** + * Clear and free all EoE handlers. + */ + +void ec_master_clear_eoe_handlers( + ec_master_t *master /**< EtherCAT master */ + ) +{ + ec_eoe_t *eoe, *next; + + list_for_each_entry_safe(eoe, next, &master->eoe_handlers, list) { list_del(&eoe->list); ec_eoe_clear(eoe); kfree(eoe); } - - ec_device_clear(&master->backup_device); - ec_device_clear(&master->main_device); - - // destroy self - kobject_del(&master->kobj); - kobject_put(&master->kobj); - - EC_INFO("Master %u freed.\n", master->index); } /*****************************************************************************/ @@ -413,6 +408,7 @@ int ec_master_enter_operation_mode(ec_master_t *master /**< EtherCAT master */) { ec_slave_t *slave; + ec_eoe_t *eoe; down(&master->config_sem); master->allow_config = 0; // temporarily disable slave configuration @@ -446,12 +442,20 @@ list_for_each_entry(slave, &master->slaves, list) { ec_slave_request_state(slave, EC_SLAVE_STATE_PREOP); } + // ... but set EoE slaves to OP + list_for_each_entry(eoe, &master->eoe_handlers, list) { + if (ec_eoe_is_open(eoe)) + ec_slave_request_state(eoe->slave, EC_SLAVE_STATE_OP); + } if (master->debug_level) EC_DBG("Switching to operation mode.\n"); master->mode = EC_MASTER_MODE_OPERATION; master->pdo_slaves_offline = 0; // assume all PDO slaves online + master->ext_request_cb = NULL; + master->ext_release_cb = NULL; + master->ext_cb_data = NULL; return 0; out_allow: @@ -470,6 +474,7 @@ /**< EtherCAT master */) { ec_slave_t *slave; + ec_eoe_t *eoe; master->mode = EC_MASTER_MODE_IDLE; @@ -485,15 +490,20 @@ ec_slave_reset(slave); ec_slave_request_state(slave, EC_SLAVE_STATE_PREOP); } + // ... but leave EoE slaves in OP + list_for_each_entry(eoe, &master->eoe_handlers, list) { + if (ec_eoe_is_open(eoe)) + ec_slave_request_state(eoe->slave, EC_SLAVE_STATE_OP); + } ec_master_destroy_domains(master); + if (ec_master_thread_start(master, ec_master_idle_thread)) + EC_WARN("Failed to restart master thread!\n"); + ec_master_eoe_start(master); + master->allow_scan = 1; master->allow_config = 1; - - if (ec_master_thread_start(master, ec_master_idle_thread)) { - EC_WARN("Failed to restart master thread!\n"); - } } /*****************************************************************************/ @@ -1059,48 +1069,16 @@ void ec_master_eoe_start(ec_master_t *master /**< EtherCAT master */) { - ec_eoe_t *eoe; - ec_slave_t *slave; - unsigned int coupled, found; - - if (master->eoe_running || master->eoe_checked) return; - - master->eoe_checked = 1; - - // decouple all EoE handlers - list_for_each_entry(eoe, &master->eoe_handlers, list) - eoe->slave = NULL; - - // couple a free EoE handler to every EoE-capable slave - coupled = 0; - list_for_each_entry(slave, &master->slaves, list) { - if (!(slave->sii_mailbox_protocols & EC_MBOX_EOE)) continue; - - found = 0; - list_for_each_entry(eoe, &master->eoe_handlers, list) { - if (eoe->slave) continue; - eoe->slave = slave; - found = 1; - coupled++; - EC_INFO("Coupling device %s to slave %i.\n", - eoe->dev->name, slave->ring_position); - if (eoe->opened) - ec_slave_request_state(slave, EC_SLAVE_STATE_OP); - else - ec_slave_request_state(slave, EC_SLAVE_STATE_PREOP); - break; - } - - if (!found) { - if (master->debug_level) - EC_WARN("No EoE handler for slave %i!\n", - slave->ring_position); - ec_slave_request_state(slave, EC_SLAVE_STATE_PREOP); - } - } - - if (!coupled) { - EC_INFO("No EoE handlers coupled.\n"); + if (master->eoe_running) { + EC_WARN("EoE already running!\n"); + return; + } + + if (list_empty(&master->eoe_handlers)) + return; + + if (!master->request_cb || !master->release_cb) { + EC_WARN("No EoE processing because of missing locking callbacks!\n"); return; } @@ -1110,7 +1088,6 @@ // start EoE processing master->eoe_timer.expires = jiffies + 10; add_timer(&master->eoe_timer); - return; } /*****************************************************************************/ @@ -1121,24 +1098,11 @@ void ec_master_eoe_stop(ec_master_t *master /**< EtherCAT master */) { - ec_eoe_t *eoe; - - master->eoe_checked = 0; - if (!master->eoe_running) return; EC_INFO("Stopping EoE processing.\n"); del_timer_sync(&master->eoe_timer); - - // decouple all EoE handlers - list_for_each_entry(eoe, &master->eoe_handlers, list) { - if (eoe->slave) { - ec_slave_request_state(eoe->slave, EC_SLAVE_STATE_PREOP); - eoe->slave = NULL; - } - } - master->eoe_running = 0; } @@ -1152,14 +1116,18 @@ { ec_master_t *master = (ec_master_t *) data; ec_eoe_t *eoe; - unsigned int active = 0; + unsigned int none_open = 1; cycles_t cycles_start, cycles_end; unsigned long restart_jiffies; list_for_each_entry(eoe, &master->eoe_handlers, list) { - if (ec_eoe_active(eoe)) active++; - } - if (!active) goto queue_timer; + if (ec_eoe_is_open(eoe)) { + none_open = 0; + break; + } + } + if (none_open) + goto queue_timer; // receive datagrams if (master->request_cb(master->cb_data)) goto queue_timer; @@ -1288,12 +1256,11 @@ /** * Translates an ASCII coded bus-address to a slave pointer. * These are the valid addressing schemes: - * - \a "X" = the X. slave on the bus (ring position), - * - \a "X:Y" = the Y. slave after the X. branch (bus coupler), + * - \a "X" = the Xth slave on the bus (ring position), * - \a "#X" = the slave with alias X, - * - \a "#X:Y" = the Y. slave after the branch (bus coupler) with alias X. + * - \a "#X:Y" = the Yth slave after the slave with alias X. * X and Y are zero-based indices and may be provided in hexadecimal or octal - * notation (with respective prefix). + * notation (with appropriate prefix). * \return pointer to the slave on success, else NULL */ @@ -1462,12 +1429,15 @@ master->injection_seq_fsm = 0; master->injection_seq_rt = 0; + master->request_cb = master->ext_request_cb; + master->release_cb = master->ext_release_cb; + master->cb_data = master->ext_cb_data; if (ec_master_thread_start(master, ec_master_operation_thread)) { EC_ERR("Failed to start master thread!\n"); return -1; } - + ec_master_eoe_start(master); return 0; } @@ -1577,9 +1547,9 @@ void *cb_data /**< data parameter */ ) { - master->request_cb = request_cb; - master->release_cb = release_cb; - master->cb_data = cb_data; + master->ext_request_cb = request_cb; + master->ext_release_cb = release_cb; + master->ext_cb_data = cb_data; } /*****************************************************************************/