00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00039
00040
00041 #include <linux/module.h>
00042
00043 #include "globals.h"
00044 #include "domain.h"
00045 #include "master.h"
00046
00047
00048
00049 void ec_domain_clear_field_regs(ec_domain_t *);
00050 ssize_t ec_show_domain_attribute(struct kobject *, struct attribute *, char *);
00051
00052
00053
00056 EC_SYSFS_READ_ATTR(image_size);
00057
00058 static struct attribute *def_attrs[] = {
00059 &attr_image_size,
00060 NULL,
00061 };
00062
00063 static struct sysfs_ops sysfs_ops = {
00064 .show = &ec_show_domain_attribute,
00065 .store = NULL
00066 };
00067
00068 static struct kobj_type ktype_ec_domain = {
00069 .release = ec_domain_clear,
00070 .sysfs_ops = &sysfs_ops,
00071 .default_attrs = def_attrs
00072 };
00073
00076
00077
00083 int ec_domain_init(ec_domain_t *domain,
00084 ec_master_t *master,
00085 unsigned int index
00086 )
00087 {
00088 domain->master = master;
00089 domain->index = index;
00090 domain->data_size = 0;
00091 domain->base_address = 0;
00092 domain->response_count = 0xFFFFFFFF;
00093
00094 INIT_LIST_HEAD(&domain->field_regs);
00095 INIT_LIST_HEAD(&domain->datagrams);
00096
00097
00098 memset(&domain->kobj, 0x00, sizeof(struct kobject));
00099 kobject_init(&domain->kobj);
00100 domain->kobj.ktype = &ktype_ec_domain;
00101 domain->kobj.parent = &master->kobj;
00102 if (kobject_set_name(&domain->kobj, "domain%i", index)) {
00103 EC_ERR("Failed to set kobj name.\n");
00104 return -1;
00105 }
00106
00107 return 0;
00108 }
00109
00110
00111
00116 void ec_domain_clear(struct kobject *kobj )
00117 {
00118 ec_datagram_t *datagram, *next;
00119 ec_domain_t *domain;
00120
00121 domain = container_of(kobj, ec_domain_t, kobj);
00122
00123 EC_INFO("Clearing domain %i.\n", domain->index);
00124
00125 list_for_each_entry_safe(datagram, next, &domain->datagrams, list) {
00126 ec_datagram_clear(datagram);
00127 kfree(datagram);
00128 }
00129
00130 ec_domain_clear_field_regs(domain);
00131
00132 kfree(domain);
00133 }
00134
00135
00136
00142 int ec_domain_reg_field(ec_domain_t *domain,
00143 ec_slave_t *slave,
00144 const ec_sync_t *sync,
00145 uint32_t field_offset,
00146 void **data_ptr
00148 )
00149 {
00150 ec_field_reg_t *field_reg;
00151
00152 if (!(field_reg =
00153 (ec_field_reg_t *) kmalloc(sizeof(ec_field_reg_t), GFP_KERNEL))) {
00154 EC_ERR("Failed to allocate field registration.\n");
00155 return -1;
00156 }
00157
00158 if (ec_slave_prepare_fmmu(slave, domain, sync)) {
00159 EC_ERR("FMMU configuration failed.\n");
00160 kfree(field_reg);
00161 return -1;
00162 }
00163
00164 field_reg->slave = slave;
00165 field_reg->sync = sync;
00166 field_reg->field_offset = field_offset;
00167 field_reg->data_ptr = data_ptr;
00168
00169 list_add_tail(&field_reg->list, &domain->field_regs);
00170 return 0;
00171 }
00172
00173
00174
00179 void ec_domain_clear_field_regs(ec_domain_t *domain )
00180 {
00181 ec_field_reg_t *field_reg, *next;
00182
00183 list_for_each_entry_safe(field_reg, next, &domain->field_regs, list) {
00184 list_del(&field_reg->list);
00185 kfree(field_reg);
00186 }
00187 }
00188
00189
00190
00196 int ec_domain_add_datagram(ec_domain_t *domain,
00197 uint32_t offset,
00198 size_t data_size
00199 )
00200 {
00201 ec_datagram_t *datagram;
00202
00203 if (!(datagram = kmalloc(sizeof(ec_datagram_t), GFP_KERNEL))) {
00204 EC_ERR("Failed to allocate domain datagram!\n");
00205 return -1;
00206 }
00207
00208 ec_datagram_init(datagram);
00209
00210 if (ec_datagram_lrw(datagram, offset, data_size)) {
00211 kfree(datagram);
00212 return -1;
00213 }
00214
00215 list_add_tail(&datagram->list, &domain->datagrams);
00216 return 0;
00217 }
00218
00219
00220
00229 int ec_domain_alloc(ec_domain_t *domain,
00230 uint32_t base_address
00231 )
00232 {
00233 ec_field_reg_t *field_reg;
00234 ec_slave_t *slave;
00235 ec_fmmu_t *fmmu;
00236 unsigned int i, j, cmd_count;
00237 uint32_t field_off, field_off_cmd;
00238 uint32_t cmd_offset;
00239 size_t cmd_data_size, sync_size;
00240 ec_datagram_t *datagram;
00241
00242 domain->base_address = base_address;
00243
00244
00245 domain->data_size = 0;
00246 cmd_offset = base_address;
00247 cmd_data_size = 0;
00248 cmd_count = 0;
00249 list_for_each_entry(slave, &domain->master->slaves, list) {
00250 for (j = 0; j < slave->fmmu_count; j++) {
00251 fmmu = &slave->fmmus[j];
00252 if (fmmu->domain == domain) {
00253 fmmu->logical_start_address = base_address + domain->data_size;
00254 sync_size = ec_slave_calc_sync_size(slave, fmmu->sync);
00255 domain->data_size += sync_size;
00256 if (cmd_data_size + sync_size > EC_MAX_DATA_SIZE) {
00257 if (ec_domain_add_datagram(domain, cmd_offset,
00258 cmd_data_size)) return -1;
00259 cmd_offset += cmd_data_size;
00260 cmd_data_size = 0;
00261 cmd_count++;
00262 }
00263 cmd_data_size += sync_size;
00264 }
00265 }
00266 }
00267
00268
00269 if (cmd_data_size) {
00270 if (ec_domain_add_datagram(domain, cmd_offset, cmd_data_size))
00271 return -1;
00272 cmd_count++;
00273 }
00274
00275 if (!cmd_count) {
00276 EC_WARN("Domain %i contains no data!\n", domain->index);
00277 ec_domain_clear_field_regs(domain);
00278 return 0;
00279 }
00280
00281
00282 list_for_each_entry(field_reg, &domain->field_regs, list) {
00283 for (i = 0; i < field_reg->slave->fmmu_count; i++) {
00284 fmmu = &field_reg->slave->fmmus[i];
00285 if (fmmu->domain == domain && fmmu->sync == field_reg->sync) {
00286 field_off = fmmu->logical_start_address +
00287 field_reg->field_offset;
00288
00289 list_for_each_entry(datagram, &domain->datagrams, list) {
00290 field_off_cmd = field_off - datagram->address.logical;
00291 if (field_off >= datagram->address.logical &&
00292 field_off_cmd < datagram->mem_size) {
00293 *field_reg->data_ptr = datagram->data + field_off_cmd;
00294 }
00295 }
00296 if (!field_reg->data_ptr) {
00297 EC_ERR("Failed to assign data pointer!\n");
00298 return -1;
00299 }
00300 break;
00301 }
00302 }
00303 }
00304
00305 EC_INFO("Domain %i - Allocated %i bytes in %i datagram%s\n",
00306 domain->index, domain->data_size, cmd_count,
00307 cmd_count == 1 ? "" : "s");
00308
00309 ec_domain_clear_field_regs(domain);
00310
00311 return 0;
00312 }
00313
00314
00315
00323 void ec_domain_response_count(ec_domain_t *domain,
00324 unsigned int count
00325 )
00326 {
00327 if (count != domain->response_count) {
00328 domain->response_count = count;
00329 EC_INFO("Domain %i working counter change: %i\n", domain->index,
00330 count);
00331 }
00332 }
00333
00334
00335
00341 ssize_t ec_show_domain_attribute(struct kobject *kobj,
00342 struct attribute *attr,
00343 char *buffer
00344 )
00345 {
00346 ec_domain_t *domain = container_of(kobj, ec_domain_t, kobj);
00347
00348 if (attr == &attr_image_size) {
00349 return sprintf(buffer, "%i\n", domain->data_size);
00350 }
00351
00352 return 0;
00353 }
00354
00355
00356
00357
00358
00370 ec_slave_t *ecrt_domain_register_field(ec_domain_t *domain,
00372 const char *address,
00375 const char *vendor_name,
00377 const char *product_name,
00379 void **data_ptr,
00382 const char *field_name,
00384 unsigned int field_index,
00387 unsigned int field_count
00390 )
00391 {
00392 ec_slave_t *slave;
00393 const ec_slave_type_t *type;
00394 ec_master_t *master;
00395 const ec_sync_t *sync;
00396 const ec_field_t *field;
00397 unsigned int field_counter, i, j, orig_field_index, orig_field_count;
00398 uint32_t field_offset;
00399
00400 master = domain->master;
00401
00402
00403 if (!(slave = ecrt_master_get_slave(master, address))) return NULL;
00404
00405 if (!(type = slave->type)) {
00406 EC_ERR("Slave \"%s\" (position %i) has unknown type!\n", address,
00407 slave->ring_position);
00408 return NULL;
00409 }
00410
00411 if (strcmp(vendor_name, type->vendor_name) ||
00412 strcmp(product_name, type->product_name)) {
00413 EC_ERR("Invalid slave type at position %i - Requested: \"%s %s\","
00414 " found: \"%s %s\".\n", slave->ring_position, vendor_name,
00415 product_name, type->vendor_name, type->product_name);
00416 return NULL;
00417 }
00418
00419 if (!data_ptr) {
00420
00421 slave->registered = 1;
00422 }
00423
00424 if (!field_count) field_count = 1;
00425 orig_field_index = field_index;
00426 orig_field_count = field_count;
00427
00428 field_counter = 0;
00429 for (i = 0; type->sync_managers[i]; i++) {
00430 sync = type->sync_managers[i];
00431 field_offset = 0;
00432 for (j = 0; sync->fields[j]; j++) {
00433 field = sync->fields[j];
00434 if (!strcmp(field->name, field_name)) {
00435 if (field_counter++ == field_index) {
00436 if (data_ptr)
00437 ec_domain_reg_field(domain, slave, sync, field_offset,
00438 data_ptr++);
00439 if (!(--field_count)) return slave;
00440 field_index++;
00441 }
00442 }
00443 field_offset += field->size;
00444 }
00445 }
00446
00447 EC_ERR("Slave %i (\"%s %s\") registration mismatch: Field \"%s\","
00448 " index %i, count %i.\n", slave->ring_position, vendor_name,
00449 product_name, field_name, orig_field_index, orig_field_count);
00450 return NULL;
00451 }
00452
00453
00454
00462 int ecrt_domain_register_field_list(ec_domain_t *domain,
00464 const ec_field_init_t *fields
00466 )
00467 {
00468 const ec_field_init_t *field;
00469
00470 for (field = fields; field->slave_address; field++)
00471 if (!ecrt_domain_register_field(domain, field->slave_address,
00472 field->vendor_name,
00473 field->product_name, field->data_ptr,
00474 field->field_name, field->field_index,
00475 field->field_count))
00476 return -1;
00477
00478 return 0;
00479 }
00480
00481
00482
00488 void ecrt_domain_queue(ec_domain_t *domain )
00489 {
00490 ec_datagram_t *datagram;
00491
00492 list_for_each_entry(datagram, &domain->datagrams, list) {
00493 ec_master_queue_datagram(domain->master, datagram);
00494 }
00495 }
00496
00497
00498
00504 void ecrt_domain_process(ec_domain_t *domain )
00505 {
00506 unsigned int working_counter_sum;
00507 ec_datagram_t *datagram;
00508
00509 working_counter_sum = 0;
00510
00511 list_for_each_entry(datagram, &domain->datagrams, list) {
00512 if (datagram->state == EC_CMD_RECEIVED) {
00513 working_counter_sum += datagram->working_counter;
00514 }
00515 }
00516
00517 ec_domain_response_count(domain, working_counter_sum);
00518 }
00519
00520
00521
00528 int ecrt_domain_state(ec_domain_t *domain )
00529 {
00530 ec_datagram_t *datagram;
00531
00532 list_for_each_entry(datagram, &domain->datagrams, list) {
00533 if (datagram->state != EC_CMD_RECEIVED) return -1;
00534 }
00535
00536 return 0;
00537 }
00538
00539
00540
00543 EXPORT_SYMBOL(ecrt_domain_register_field);
00544 EXPORT_SYMBOL(ecrt_domain_register_field_list);
00545 EXPORT_SYMBOL(ecrt_domain_queue);
00546 EXPORT_SYMBOL(ecrt_domain_process);
00547 EXPORT_SYMBOL(ecrt_domain_state);
00548
00551