68 sc->alias = alias; |
68 sc->alias = alias; |
69 sc->position = position; |
69 sc->position = position; |
70 sc->vendor_id = vendor_id; |
70 sc->vendor_id = vendor_id; |
71 sc->product_code = product_code; |
71 sc->product_code = product_code; |
72 sc->watchdog_divider = 0; // use default |
72 sc->watchdog_divider = 0; // use default |
|
73 sc->allow_overlapping_pdos = 0; // default not allowed |
73 sc->watchdog_intervals = 0; // use default |
74 sc->watchdog_intervals = 0; // use default |
74 |
75 |
75 sc->slave = NULL; |
76 sc->slave = NULL; |
76 |
77 |
77 for (i = 0; i < EC_MAX_SYNC_MANAGERS; i++) |
78 for (i = 0; i < EC_MAX_SYNC_MANAGERS; i++) |
179 |
180 |
180 // FMMU configuration already prepared? |
181 // FMMU configuration already prepared? |
181 for (i = 0; i < sc->used_fmmus; i++) { |
182 for (i = 0; i < sc->used_fmmus; i++) { |
182 fmmu = &sc->fmmu_configs[i]; |
183 fmmu = &sc->fmmu_configs[i]; |
183 if (fmmu->domain == domain && fmmu->sync_index == sync_index) |
184 if (fmmu->domain == domain && fmmu->sync_index == sync_index) |
184 return fmmu->logical_start_address; |
185 return fmmu->logical_domain_offset; |
185 } |
186 } |
186 |
187 |
187 if (sc->used_fmmus == EC_MAX_FMMUS) { |
188 if (sc->used_fmmus == EC_MAX_FMMUS) { |
188 EC_CONFIG_ERR(sc, "FMMU limit reached!\n"); |
189 EC_CONFIG_ERR(sc, "FMMU limit reached!\n"); |
189 return -EOVERFLOW; |
190 return -EOVERFLOW; |
190 } |
191 } |
191 |
192 |
192 fmmu = &sc->fmmu_configs[sc->used_fmmus++]; |
193 fmmu = &sc->fmmu_configs[sc->used_fmmus]; |
193 |
194 |
194 down(&sc->master->master_sem); |
195 down(&sc->master->master_sem); |
195 ec_fmmu_config_init(fmmu, sc, domain, sync_index, dir); |
196 ec_fmmu_config_init(fmmu, sc, domain, sync_index, dir); |
|
197 |
|
198 #if 0 //TODO overlapping PDOs |
|
199 // Overlapping PDO Support from 4751747d4e6d |
|
200 // FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME |
|
201 // parent code does not call ec_fmmu_config_domain |
|
202 // FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME |
|
203 fmmu_logical_start_address = domain->tx_size; |
|
204 tx_size = fmmu->data_size; |
|
205 |
|
206 // FIXME is it enough to take only the *previous* FMMU into account? |
|
207 |
|
208 // FIXME Need to qualify allow_overlapping_pdos with slave->sii.general_flags.enable_not_lrw |
|
209 |
|
210 if (sc->allow_overlapping_pdos && sc->used_fmmus > 0) { |
|
211 prev_fmmu = &sc->fmmu_configs[sc->used_fmmus - 1]; |
|
212 if (fmmu->dir != prev_fmmu->dir && prev_fmmu->tx_size != 0) { |
|
213 // prev fmmu has opposite direction |
|
214 // and is not already paired with prev-prev fmmu |
|
215 old_prev_tx_size = prev_fmmu->tx_size; |
|
216 prev_fmmu->tx_size = max(fmmu->data_size, prev_fmmu->data_size); |
|
217 domain->tx_size += prev_fmmu->tx_size - old_prev_tx_size; |
|
218 tx_size = 0; |
|
219 fmmu_logical_start_address = prev_fmmu->logical_domain_offset; |
|
220 } |
|
221 } |
|
222 |
|
223 ec_fmmu_config_domain(fmmu, domain, fmmu_logical_start_address, tx_size); |
|
224 // Overlapping PDO Support from 4751747d4e6d |
|
225 #endif |
|
226 |
|
227 sc->used_fmmus++; |
196 up(&sc->master->master_sem); |
228 up(&sc->master->master_sem); |
197 |
229 |
198 return fmmu->logical_start_address; |
230 return fmmu->logical_domain_offset; |
199 } |
231 } |
200 |
232 |
201 /*****************************************************************************/ |
233 /*****************************************************************************/ |
202 |
234 |
203 /** Attaches the configuration to the addressed slave object. |
235 /** Attaches the configuration to the addressed slave object. |
274 |
306 |
275 // invalidate processing register request |
307 // invalidate processing register request |
276 list_for_each_entry(reg, &sc->reg_requests, list) { |
308 list_for_each_entry(reg, &sc->reg_requests, list) { |
277 if (sc->slave->fsm.reg_request == reg) { |
309 if (sc->slave->fsm.reg_request == reg) { |
278 sc->slave->fsm.reg_request = NULL; |
310 sc->slave->fsm.reg_request = NULL; |
|
311 EC_SLAVE_WARN(sc->slave, "Aborting register request," |
|
312 " slave is detaching.\n"); |
|
313 reg->state = EC_INT_REQUEST_FAILURE; |
|
314 wake_up_all(&sc->slave->master->request_queue); |
279 break; |
315 break; |
280 } |
316 } |
281 } |
317 } |
282 |
318 |
283 sc->slave = NULL; |
319 sc->slave = NULL; |
515 } |
551 } |
516 |
552 |
517 return NULL; |
553 return NULL; |
518 } |
554 } |
519 |
555 |
|
556 /*****************************************************************************/ |
|
557 |
|
558 /** Expires any requests that have been started on a detached slave. |
|
559 */ |
|
560 void ec_slave_config_expire_disconnected_requests( |
|
561 ec_slave_config_t *sc /**< Slave configuration. */ |
|
562 ) |
|
563 { |
|
564 ec_sdo_request_t *sdo_req; |
|
565 ec_reg_request_t *reg_req; |
|
566 |
|
567 if (sc->slave) { return; } |
|
568 |
|
569 list_for_each_entry(sdo_req, &sc->sdo_requests, list) { |
|
570 if (sdo_req->state == EC_INT_REQUEST_QUEUED || |
|
571 sdo_req->state == EC_INT_REQUEST_BUSY) { |
|
572 EC_CONFIG_DBG(sc, 1, "Aborting SDO request; no slave attached.\n"); |
|
573 sdo_req->state = EC_INT_REQUEST_FAILURE; |
|
574 } |
|
575 } |
|
576 |
|
577 list_for_each_entry(reg_req, &sc->reg_requests, list) { |
|
578 if (reg_req->state == EC_INT_REQUEST_QUEUED || |
|
579 reg_req->state == EC_INT_REQUEST_BUSY) { |
|
580 EC_CONFIG_DBG(sc, 1, "Aborting register request; no slave attached.\n"); |
|
581 reg_req->state = EC_INT_REQUEST_FAILURE; |
|
582 } |
|
583 } |
|
584 } |
|
585 |
520 /****************************************************************************** |
586 /****************************************************************************** |
521 * Application interface |
587 * Application interface |
522 *****************************************************************************/ |
588 *****************************************************************************/ |
523 |
589 |
524 int ecrt_slave_config_sync_manager(ec_slave_config_t *sc, uint8_t sync_index, |
590 int ecrt_slave_config_sync_manager(ec_slave_config_t *sc, uint8_t sync_index, |
554 EC_CONFIG_DBG(sc, 1, "%s(sc = 0x%p, divider = %u, intervals = %u)\n", |
620 EC_CONFIG_DBG(sc, 1, "%s(sc = 0x%p, divider = %u, intervals = %u)\n", |
555 __func__, sc, divider, intervals); |
621 __func__, sc, divider, intervals); |
556 |
622 |
557 sc->watchdog_divider = divider; |
623 sc->watchdog_divider = divider; |
558 sc->watchdog_intervals = intervals; |
624 sc->watchdog_intervals = intervals; |
|
625 } |
|
626 |
|
627 /*****************************************************************************/ |
|
628 |
|
629 void ecrt_slave_config_overlapping_pdos(ec_slave_config_t *sc, |
|
630 uint8_t allow_overlapping_pdos ) |
|
631 { |
|
632 EC_CONFIG_DBG(sc, 1, "%s(sc = 0x%p, allow_overlapping_pdos = %u)\n", |
|
633 __func__, sc, allow_overlapping_pdos); |
|
634 |
|
635 sc->allow_overlapping_pdos = allow_overlapping_pdos; |
559 } |
636 } |
560 |
637 |
561 /*****************************************************************************/ |
638 /*****************************************************************************/ |
562 |
639 |
563 int ecrt_slave_config_pdo_assign_add(ec_slave_config_t *sc, |
640 int ecrt_slave_config_pdo_assign_add(ec_slave_config_t *sc, |