46 |
46 |
47 #include "domain.h" |
47 #include "domain.h" |
48 |
48 |
49 /*****************************************************************************/ |
49 /*****************************************************************************/ |
50 |
50 |
51 void ec_domain_clear(struct kobject *); |
|
52 void ec_domain_clear_data(ec_domain_t *); |
51 void ec_domain_clear_data(ec_domain_t *); |
53 ssize_t ec_show_domain_attribute(struct kobject *, struct attribute *, char *); |
|
54 |
|
55 /*****************************************************************************/ |
|
56 |
|
57 /** \cond */ |
|
58 |
|
59 EC_SYSFS_READ_ATTR(image_size); |
|
60 |
|
61 static struct attribute *def_attrs[] = { |
|
62 &attr_image_size, |
|
63 NULL, |
|
64 }; |
|
65 |
|
66 static struct sysfs_ops sysfs_ops = { |
|
67 .show = &ec_show_domain_attribute, |
|
68 .store = NULL |
|
69 }; |
|
70 |
|
71 static struct kobj_type ktype_ec_domain = { |
|
72 .release = ec_domain_clear, |
|
73 .sysfs_ops = &sysfs_ops, |
|
74 .default_attrs = def_attrs |
|
75 }; |
|
76 |
|
77 /** \endcond */ |
|
78 |
52 |
79 /*****************************************************************************/ |
53 /*****************************************************************************/ |
80 |
54 |
81 /** Domain constructor. |
55 /** Domain constructor. |
82 * |
56 */ |
83 * \return 0 in case of success, else < 0 |
57 void ec_domain_init( |
84 */ |
|
85 int ec_domain_init( |
|
86 ec_domain_t *domain, /**< EtherCAT domain. */ |
58 ec_domain_t *domain, /**< EtherCAT domain. */ |
87 ec_master_t *master, /**< Parent master. */ |
59 ec_master_t *master, /**< Parent master. */ |
88 unsigned int index /**< Index. */ |
60 unsigned int index /**< Index. */ |
89 ) |
61 ) |
90 { |
62 { |
98 INIT_LIST_HEAD(&domain->datagrams); |
70 INIT_LIST_HEAD(&domain->datagrams); |
99 domain->working_counter = 0xFFFF; |
71 domain->working_counter = 0xFFFF; |
100 domain->expected_working_counter = 0x0000; |
72 domain->expected_working_counter = 0x0000; |
101 domain->working_counter_changes = 0; |
73 domain->working_counter_changes = 0; |
102 domain->notify_jiffies = 0; |
74 domain->notify_jiffies = 0; |
103 |
|
104 // init kobject and add it to the hierarchy |
|
105 memset(&domain->kobj, 0x00, sizeof(struct kobject)); |
|
106 kobject_init(&domain->kobj); |
|
107 domain->kobj.ktype = &ktype_ec_domain; |
|
108 domain->kobj.parent = &master->kobj; |
|
109 if (kobject_set_name(&domain->kobj, "domain%u", index)) { |
|
110 EC_ERR("Failed to set kobj name.\n"); |
|
111 kobject_put(&domain->kobj); |
|
112 return -1; |
|
113 } |
|
114 if (kobject_add(&domain->kobj)) { |
|
115 EC_ERR("Failed to add domain kobject.\n"); |
|
116 kobject_put(&domain->kobj); |
|
117 return -1; |
|
118 } |
|
119 |
|
120 return 0; |
|
121 } |
75 } |
122 |
76 |
123 /*****************************************************************************/ |
77 /*****************************************************************************/ |
124 |
78 |
125 /** Domain destructor. |
79 /** Domain destructor. |
126 * |
80 */ |
127 * Clears and frees a domain object. |
81 void ec_domain_clear(ec_domain_t *domain /**< EtherCAT domain */) |
128 */ |
82 { |
129 void ec_domain_destroy(ec_domain_t *domain /**< EtherCAT domain */) |
83 ec_datagram_t *datagram, *next; |
130 { |
84 |
131 ec_datagram_t *datagram; |
85 // dequeue and free datagrams |
132 |
86 list_for_each_entry_safe(datagram, next, &domain->datagrams, list) { |
133 // dequeue datagrams |
|
134 list_for_each_entry(datagram, &domain->datagrams, list) { |
|
135 if (!list_empty(&datagram->queue)) // datagram queued? |
87 if (!list_empty(&datagram->queue)) // datagram queued? |
136 list_del_init(&datagram->queue); |
88 list_del(&datagram->queue); |
137 } |
|
138 |
|
139 // destroy self |
|
140 kobject_del(&domain->kobj); |
|
141 kobject_put(&domain->kobj); |
|
142 } |
|
143 |
|
144 /*****************************************************************************/ |
|
145 |
|
146 /** Clear and free domain. |
|
147 * |
|
148 * This method is called by the kobject, once there are no more references |
|
149 * to it. |
|
150 */ |
|
151 void ec_domain_clear(struct kobject *kobj /**< kobject of the domain */) |
|
152 { |
|
153 ec_domain_t *domain; |
|
154 ec_datagram_t *datagram, *next; |
|
155 |
|
156 domain = container_of(kobj, ec_domain_t, kobj); |
|
157 |
|
158 list_for_each_entry_safe(datagram, next, &domain->datagrams, list) { |
|
159 ec_datagram_clear(datagram); |
89 ec_datagram_clear(datagram); |
160 kfree(datagram); |
90 kfree(datagram); |
161 } |
91 } |
162 |
92 |
163 ec_domain_clear_data(domain); |
93 ec_domain_clear_data(domain); |
164 |
|
165 kfree(domain); |
|
166 } |
94 } |
167 |
95 |
168 /*****************************************************************************/ |
96 /*****************************************************************************/ |
169 |
97 |
170 /** Frees internally allocated memory. |
98 /** Frees internally allocated memory. |
321 } |
249 } |
322 |
250 |
323 datagram_size += fmmu->data_size; |
251 datagram_size += fmmu->data_size; |
324 } |
252 } |
325 |
253 |
326 // allocate last datagram, if data are left |
254 // Allocate last datagram, if data are left (this is also the case if the |
|
255 // process data fit into a single datagram) |
327 if (datagram_size) { |
256 if (datagram_size) { |
328 if (ec_domain_add_datagram(domain, |
257 if (ec_domain_add_datagram(domain, |
329 domain->logical_base_address + datagram_offset, |
258 domain->logical_base_address + datagram_offset, |
330 datagram_size, domain->data + datagram_offset, |
259 datagram_size, domain->data + datagram_offset, |
331 datagram_used)) |
260 datagram_used)) |
346 return 0; |
275 return 0; |
347 } |
276 } |
348 |
277 |
349 /*****************************************************************************/ |
278 /*****************************************************************************/ |
350 |
279 |
351 /** |
|
352 Formats attribute data for SysFS reading. |
|
353 \return number of bytes to read |
|
354 */ |
|
355 |
|
356 ssize_t ec_show_domain_attribute(struct kobject *kobj, /**< kobject */ |
|
357 struct attribute *attr, /**< attribute */ |
|
358 char *buffer /**< memory to store data in */ |
|
359 ) |
|
360 { |
|
361 ec_domain_t *domain = container_of(kobj, ec_domain_t, kobj); |
|
362 |
|
363 if (attr == &attr_image_size) { |
|
364 return sprintf(buffer, "%u\n", domain->data_size); |
|
365 } |
|
366 |
|
367 return 0; |
|
368 } |
|
369 |
|
370 /*****************************************************************************/ |
|
371 |
|
372 unsigned int ec_domain_fmmu_count(const ec_domain_t *domain) |
280 unsigned int ec_domain_fmmu_count(const ec_domain_t *domain) |
373 { |
281 { |
374 const ec_fmmu_config_t *fmmu; |
282 const ec_fmmu_config_t *fmmu; |
375 unsigned int num = 0; |
283 unsigned int num = 0; |
376 |
284 |
475 if (domain->working_counter_changes == 1) { |
383 if (domain->working_counter_changes == 1) { |
476 EC_INFO("Domain %u: Working counter changed to %u/%u.\n", |
384 EC_INFO("Domain %u: Working counter changed to %u/%u.\n", |
477 domain->index, domain->working_counter, |
385 domain->index, domain->working_counter, |
478 domain->expected_working_counter); |
386 domain->expected_working_counter); |
479 } else { |
387 } else { |
480 EC_INFO("Domain %u: %u working counter changes. Currently %u/%u.\n", |
388 EC_INFO("Domain %u: %u working counter changes. " |
481 domain->index, domain->working_counter_changes, |
389 "Currently %u/%u.\n", domain->index, |
482 domain->working_counter, domain->expected_working_counter); |
390 domain->working_counter_changes, domain->working_counter, |
|
391 domain->expected_working_counter); |
483 } |
392 } |
484 domain->working_counter_changes = 0; |
393 domain->working_counter_changes = 0; |
485 } |
394 } |
486 } |
395 } |
487 |
396 |