37 #include <linux/module.h> 48 #define DEBUG_REDUNDANCY 0 50 #ifndef list_next_entry 51 #define list_next_entry(pos, member) \ 52 list_entry((pos)->member.next, typeof(*(pos)), member) 72 domain->
index = index;
102 list_for_each_entry_safe(datagram_pair, next_pair,
105 kfree(datagram_pair);
137 uint32_t logical_domain_offset;
138 unsigned fmmu_data_size;
173 " Added %u bytes at %u.\n",
189 uint32_t logical_offset,
192 const unsigned int used[]
200 "Failed to allocate domain datagram pair!\n");
207 kfree(datagram_pair);
215 "Adding datagram pair with expected WC %u.\n",
241 for (; first_fmmu != cur_fmmu;
242 first_fmmu = list_entry(first_fmmu->
list.next,
245 if (first_fmmu->
sc == cur_fmmu->
sc 246 && first_fmmu->
dir == cur_fmmu->
dir) {
270 uint32_t datagram_begin_offset,
271 uint32_t datagram_end_offset,
280 data_size = datagram_end_offset - datagram_begin_offset;
282 memset(datagram_used, 0,
sizeof(datagram_used));
283 for (curr_fmmu = datagram_first_fmmu;
284 &curr_fmmu->
list != &datagram_end_fmmu->
list;
285 curr_fmmu = list_next_entry(curr_fmmu, list)) {
287 datagram_used[curr_fmmu->
dir]++;
294 domain->
data + datagram_begin_offset,
310 uint32_t base_address
313 uint32_t datagram_offset = 0;
314 unsigned int datagram_count = 0;
318 unsigned candidate_start = 0;
319 unsigned valid_start = 0;
327 (uint8_t *) kmalloc(domain->
data_size, GFP_KERNEL))) {
329 " internal memory for domain %u!\n",
340 datagram_first_fmmu =
344 list_for_each_entry(fmmu, &domain->
fmmu_configs, list) {
347 "FMMU size %u bytes exceeds maximum data size %u",
357 valid_start = candidate_start;
363 datagram_first_fmmu, valid_fmmu);
367 datagram_offset = valid_start;
369 datagram_first_fmmu = fmmu;
379 if (domain->
data_size > datagram_offset) {
381 datagram_first_fmmu, fmmu);
388 " %zu byte, expected working counter %u.\n", domain->
index,
392 list_for_each_entry(datagram_pair, &domain->
datagram_pairs, list) {
396 " %zu byte, type %s at %p.\n", datagram->
name,
411 unsigned int num = 0;
413 list_for_each_entry(fmmu, &domain->
fmmu_configs, list) {
433 list_for_each_entry(fmmu, &domain->
fmmu_configs, list) {
444 #if EC_MAX_NUM_DEVICES > 1 449 uint8_t *send_buffer,
455 uint8_t *sent = send_buffer + offset;
456 uint8_t *recv = datagram->
data + offset;
459 for (i = 0; i < size; i++) {
460 if (recv[i] != sent[i]) {
482 "domain = 0x%p, regs = 0x%p)\n", domain, regs);
484 for (reg = regs; reg->
index; reg++) {
513 "domain = 0x%p, mem = 0x%p)\n", domain, mem);
536 uint16_t wc_sum[EC_MAX_NUM_DEVICES] = {}, wc_total;
538 #if EC_MAX_NUM_DEVICES > 1 539 uint16_t datagram_pair_wc, redundant_wc;
540 unsigned int datagram_offset;
543 unsigned int redundancy;
545 unsigned int dev_idx;
547 unsigned int wc_change;
555 #if EC_MAX_NUM_DEVICES > 1 561 #if EC_MAX_NUM_DEVICES > 1 564 uint32_t logical_datagram_address =
566 size_t datagram_size = main_datagram->
data_size;
570 main_datagram->
name, logical_datagram_address);
574 list_for_each_entry_from(fmmu, &domain->
fmmu_configs, list) {
591 "input fmmu log_off=%u size=%u offset=%u\n",
604 if (data_changed(pair->send_buffer, main_datagram,
610 }
else if (data_changed(pair->send_buffer, backup_datagram,
616 memcpy(main_datagram->
data + datagram_offset,
617 backup_datagram->
data + datagram_offset,
619 }
else if (datagram_pair_wc ==
624 "no change but complete\n");
629 datagram_pair_wc = 0;
632 "no change and incomplete\n");
637 #endif // EC_MAX_NUM_DEVICES > 1 640 #if EC_MAX_NUM_DEVICES > 1 644 redundant_wc += wc_sum[dev_idx];
647 redundancy = redundant_wc > 0;
652 "Domain %u: Redundant link in use!\n",
656 "Domain %u: Redundant link unused again.\n",
678 wc_total += wc_sum[dev_idx];
691 " changed to %u/%u", domain->
index,
695 " changes - now %u/%u", domain->
index,
699 #if EC_MAX_NUM_DEVICES > 1 701 printk(KERN_CONT
" (");
707 printk(KERN_CONT
"+");
710 printk(KERN_CONT
")");
713 printk(KERN_CONT
".\n");
727 list_for_each_entry(datagram_pair, &domain->
datagram_pairs, list) {
729 #if EC_MAX_NUM_DEVICES > 1 731 memcpy(datagram_pair->send_buffer,
754 unsigned int dev_idx;
unsigned int working_counter
Value of the last working counter.
size_t ecrt_domain_size(const ec_domain_t *domain)
Returns the current size of the domain's process data.
const ec_slave_config_t * sc
EtherCAT slave config.
uint8_t subindex
PDO entry subindex.
uint16_t position
Slave position.
size_t data_size
Size of the data in data.
uint32_t logical_domain_offset
Logical offset address relative to domain->logical_base_address.
size_t data_size
Size of the process data.
uint32_t offset_used[EC_DIR_COUNT]
Next available domain offset of PDO, by direction.
unsigned int expected_working_counter
Expectord working conter.
unsigned int redundancy_active
Redundant link is in use.
uint16_t index
PDO entry index.
#define ec_master_num_devices(MASTER)
Number of Ethernet devices.
int ecrt_domain_reg_pdo_entry_list(ec_domain_t *domain, const ec_pdo_entry_reg_t *regs)
Registers a bunch of PDO entries for a domain.
static int emplace_datagram(ec_domain_t *domain, uint32_t datagram_begin_offset, uint32_t datagram_end_offset, const ec_fmmu_config_t *datagram_first_fmmu, const ec_fmmu_config_t *datagram_end_fmmu)
Domain finish helper function.
unsigned int data_size
Covered PDO size.
char name[EC_DATAGRAM_NAME_SIZE]
Description of the datagram.
ec_wc_state_t wc_state
Working counter interpretation.
void ecrt_domain_external_memory(ec_domain_t *domain, uint8_t *mem)
Provide external memory to store the domain's process data.
void ec_domain_clear_data(ec_domain_t *)
Frees internally allocated memory.
Global definitions and macros.
Some of the registered process data were exchanged.
EtherCAT master structure.
uint8_t * data
Memory for the process data.
uint16_t alias
Slave alias address.
#define EC_MASTER_DBG(master, level, fmt, args...)
Convenience macro for printing master-specific debug messages to syslog.
struct list_head list
List node used by domain.
unsigned int working_counter_changes
Working counter changes since last notification.
uint16_t ec_pdo_list_total_size(const ec_pdo_list_t *pl)
Calculates the total size of the mapped PDO entries.
const ec_domain_t * domain
Domain.
ec_sync_config_t sync_configs[EC_MAX_SYNC_MANAGERS]
Sync manager configurations.
uint32_t vendor_id
Slave vendor ID.
unsigned int * bit_position
Pointer to a variable to store a bit position (0-7) within the offset.
void ec_domain_clear(ec_domain_t *domain)
Domain destructor.
uint8_t sync_index
Index of sync manager to use.
int ec_domain_finish(ec_domain_t *domain, uint32_t base_address)
Finishes a domain.
unsigned int debug_level
Master debug level.
uint16_t ec_datagram_pair_process(ec_datagram_pair_t *pair, uint16_t wc_sum[])
Process received data.
ec_pdo_list_t pdos
Current PDO assignment.
ec_device_index_t
Master devices.
void ec_datagram_pair_clear(ec_datagram_pair_t *pair)
Datagram pair destructor.
unsigned int index
Index (just a number).
#define EC_READ_U32(DATA)
Read a 32-bit unsigned value from EtherCAT data.
struct list_head fmmu_configs
FMMU configurations contained.
#define EC_MASTER_WARN(master, fmt, args...)
Convenience macro for printing master-specific warnings to syslog.
void ec_fmmu_set_domain_offset_size(ec_fmmu_config_t *fmmu, uint32_t logical_domain_offset, unsigned data_size)
unsigned int ec_domain_fmmu_count(const ec_domain_t *domain)
Get the number of FMMU configurations of the domain.
#define EC_MASTER_ERR(master, fmt, args...)
Convenience macro for printing master-specific errors to syslog.
void ec_master_queue_datagram(ec_master_t *master, ec_datagram_t *datagram)
Places a datagram in the datagram queue.
Values read by the master.
ec_origin_t data_origin
Origin of the data memory.
void ec_print_data(const uint8_t *, size_t)
Outputs frame contents for debugging purposes.
uint16_t working_counter[EC_MAX_NUM_DEVICES]
Last working counter values.
uint32_t logical_base_address
Logical offset address of the process data.
uint16_t expected_working_counter
Expected working counter.
unsigned int redundancy_active
Non-zero, if redundancy is in use.
uint8_t allow_overlapping_pdos
Allow input PDOs use the same frame space as output PDOs.
int ecrt_slave_config_reg_pdo_entry(ec_slave_config_t *sc, uint16_t index, uint8_t subindex, ec_domain_t *domain, unsigned int *bit_position)
Registers a PDO entry for process data exchange in a domain.
ec_lock_t master_sem
Master semaphore.
const ec_slave_config_t * sc_in_work
slave_config which is actively being registered in this domain (i.e.
int ec_datagram_pair_init(ec_datagram_pair_t *pair, ec_domain_t *domain, uint32_t logical_offset, uint8_t *data, size_t data_size, const unsigned int used[])
Datagram pair constructor.
void ec_domain_add_fmmu_config(ec_domain_t *domain, ec_fmmu_config_t *fmmu)
Adds an FMMU configuration to the domain.
struct list_head list
List header.
uint8_t * ecrt_domain_data(ec_domain_t *domain)
Returns the domain's process data.
List record type for PDO entry mass-registration.
EtherCAT domain structure.
No registered process data were exchanged.
All registered process data were exchanged.
EtherCAT datagram pair structure.
const char * ec_datagram_type_string(const ec_datagram_t *datagram)
Returns a string describing the datagram type.
uint8_t * data
Datagram payload.
EtherCAT slave configuration.
ec_datagram_t datagrams[EC_MAX_NUM_DEVICES]
Datagrams.
EtherCAT slave configuration structure.
ec_slave_config_t * ecrt_master_slave_config_err(ec_master_t *master, uint16_t alias, uint16_t position, uint32_t vendor_id, uint32_t product_code)
Same as ecrt_master_slave_config(), but with ERR_PTR() return value.
unsigned int * offset
Pointer to a variable to store the PDO entry's (byte-)offset in the process data. ...
void ecrt_domain_state(const ec_domain_t *domain, ec_domain_state_t *state)
Reads the state of a domain.
uint8_t address[EC_ADDR_LEN]
Recipient address.
void ecrt_domain_process(ec_domain_t *domain)
Determines the states of the domain's datagrams.
void ec_domain_init(ec_domain_t *domain, ec_master_t *master, unsigned int index)
Domain constructor.
ec_direction_t dir
FMMU direction.
static int shall_count(const ec_fmmu_config_t *cur_fmmu, const ec_fmmu_config_t *first_fmmu)
Domain finish helper function.
Values written by the master.
struct list_head datagram_pairs
Datagrams pairs (main/backup) for process data exchange.
void ecrt_domain_queue(ec_domain_t *domain)
(Re-)queues all domain datagrams in the master's datagram queue.
#define EC_MASTER_INFO(master, fmt, args...)
Convenience macro for printing master-specific information to syslog.
uint32_t product_code
Slave product code.
unsigned long notify_jiffies
Time of last notification.
int ec_domain_add_datagram_pair(ec_domain_t *domain, uint32_t logical_offset, size_t data_size, uint8_t *data, const unsigned int used[])
Allocates a domain datagram pair and appends it to the list.
ec_master_t * master
EtherCAT master owning the domain.
#define EC_MAX_DATA_SIZE
Resulting maximum data size of a single datagram in a frame.
const ec_fmmu_config_t * ec_domain_find_fmmu(const ec_domain_t *domain, unsigned int pos)
Get a certain FMMU configuration via its position in the list.