186 EC_ERR("No sync manager for PDO 0x%04X:%i.", |
186 EC_ERR("No sync manager for PDO 0x%04X:%i.", |
187 pdo->index, entry->subindex); |
187 pdo->index, entry->subindex); |
188 return -1; |
188 return -1; |
189 } |
189 } |
190 |
190 |
191 // Calculate offset for process data pointer |
191 // Calculate offset (in sync manager) for process data pointer |
192 bit_offset = 0; |
192 bit_offset = 0; |
193 byte_offset = 0; |
193 byte_offset = 0; |
194 list_for_each_entry(other_pdo, &slave->sii_pdos, list) { |
194 list_for_each_entry(other_pdo, &slave->sii_pdos, list) { |
195 if (other_pdo->sync_index != sync->index) continue; |
195 if (other_pdo->sync_index != sync->index) continue; |
196 |
196 |
218 |
218 |
219 data_reg->slave = slave; |
219 data_reg->slave = slave; |
220 data_reg->sync = sync; |
220 data_reg->sync = sync; |
221 data_reg->sync_offset = byte_offset; |
221 data_reg->sync_offset = byte_offset; |
222 data_reg->data_ptr = data_ptr; |
222 data_reg->data_ptr = data_ptr; |
|
223 |
|
224 list_add_tail(&data_reg->list, &domain->data_regs); |
|
225 return 0; |
|
226 } |
|
227 |
|
228 /*****************************************************************************/ |
|
229 |
|
230 /** |
|
231 Registeres a PDO range. |
|
232 \return 0 in case of success, else < 0 |
|
233 */ |
|
234 |
|
235 int ec_domain_reg_pdo_range(ec_domain_t *domain, /**< EtherCAT domain */ |
|
236 ec_slave_t *slave, /**< slave */ |
|
237 ec_direction_t dir, /**< data direction */ |
|
238 uint16_t offset, /**< offset */ |
|
239 uint16_t length, /**< length */ |
|
240 void **data_ptr /**< pointer to the process data |
|
241 pointer */ |
|
242 ) |
|
243 { |
|
244 ec_data_reg_t *data_reg; |
|
245 ec_sii_sync_t *sync; |
|
246 unsigned int sync_found, sync_index; |
|
247 uint16_t sync_length; |
|
248 |
|
249 switch (dir) { |
|
250 case EC_DIR_OUTPUT: sync_index = 2; break; |
|
251 case EC_DIR_INPUT: sync_index = 3; break; |
|
252 default: |
|
253 EC_ERR("Invalid direction!\n"); |
|
254 return -1; |
|
255 } |
|
256 |
|
257 // Find sync manager |
|
258 sync_found = 0; |
|
259 list_for_each_entry(sync, &slave->sii_syncs, list) { |
|
260 if (sync->index == sync_index) { |
|
261 sync_found = 1; |
|
262 break; |
|
263 } |
|
264 } |
|
265 |
|
266 if (!sync_found) { |
|
267 EC_ERR("No sync manager found for PDO range.\n"); |
|
268 return -1; |
|
269 } |
|
270 |
|
271 // Allocate memory for data registration object |
|
272 if (!(data_reg = |
|
273 (ec_data_reg_t *) kmalloc(sizeof(ec_data_reg_t), GFP_KERNEL))) { |
|
274 EC_ERR("Failed to allocate data registration.\n"); |
|
275 return -1; |
|
276 } |
|
277 |
|
278 if (ec_slave_prepare_fmmu(slave, domain, sync)) { |
|
279 EC_ERR("FMMU configuration failed.\n"); |
|
280 kfree(data_reg); |
|
281 return -1; |
|
282 } |
|
283 |
|
284 data_reg->slave = slave; |
|
285 data_reg->sync = sync; |
|
286 data_reg->sync_offset = offset; |
|
287 data_reg->data_ptr = data_ptr; |
|
288 |
|
289 // estimate sync manager length |
|
290 sync_length = offset + length; |
|
291 if (sync->est_length < sync_length) { |
|
292 sync->est_length = sync_length; |
|
293 if (domain->master->debug_level) { |
|
294 EC_DBG("Estimating length of sync manager %i of slave %i to %i.\n", |
|
295 sync->index, slave->ring_position, sync_length); |
|
296 } |
|
297 } |
223 |
298 |
224 list_add_tail(&data_reg->list, &domain->data_regs); |
299 list_add_tail(&data_reg->list, &domain->data_regs); |
225 return 0; |
300 return 0; |
226 } |
301 } |
227 |
302 |
497 } |
572 } |
498 |
573 |
499 /*****************************************************************************/ |
574 /*****************************************************************************/ |
500 |
575 |
501 /** |
576 /** |
|
577 Registers a PDO range in a domain. |
|
578 - If \a data_ptr is NULL, the slave is only validated. |
|
579 \return pointer to the slave on success, else NULL |
|
580 \ingroup RealtimeInterface |
|
581 */ |
|
582 |
|
583 ec_slave_t *ecrt_domain_register_pdo_range(ec_domain_t *domain, |
|
584 /**< EtherCAT domain */ |
|
585 const char *address, |
|
586 /**< ASCII address of the slave, |
|
587 see ecrt_master_get_slave() */ |
|
588 uint32_t vendor_id, |
|
589 /**< vendor ID */ |
|
590 uint32_t product_code, |
|
591 /**< product code */ |
|
592 ec_direction_t direction, |
|
593 /**< data direction */ |
|
594 uint16_t offset, |
|
595 /**< offset in slave's PDO range */ |
|
596 uint16_t length, |
|
597 /**< length of this range */ |
|
598 void **data_ptr |
|
599 /**< address of the process data |
|
600 pointer */ |
|
601 ) |
|
602 { |
|
603 ec_slave_t *slave; |
|
604 ec_master_t *master; |
|
605 |
|
606 master = domain->master; |
|
607 |
|
608 // translate address and validate slave |
|
609 if (!(slave = ecrt_master_get_slave(master, address))) return NULL; |
|
610 if (ec_slave_validate(slave, vendor_id, product_code)) return NULL; |
|
611 |
|
612 if (!data_ptr) { |
|
613 // data_ptr is NULL => mark slave as "registered" (do not warn) |
|
614 slave->registered = 1; |
|
615 return slave; |
|
616 } |
|
617 |
|
618 if (ec_domain_reg_pdo_range(domain, slave, |
|
619 direction, offset, length, data_ptr)) { |
|
620 return NULL; |
|
621 } |
|
622 |
|
623 return slave; |
|
624 } |
|
625 |
|
626 /*****************************************************************************/ |
|
627 |
|
628 /** |
502 Processes received process data and requeues the domain datagram(s). |
629 Processes received process data and requeues the domain datagram(s). |
503 \ingroup RealtimeInterface |
630 \ingroup RealtimeInterface |
504 */ |
631 */ |
505 |
632 |
506 void ecrt_domain_process(ec_domain_t *domain /**< EtherCAT domain */) |
633 void ecrt_domain_process(ec_domain_t *domain /**< EtherCAT domain */) |