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
00035
00036
00037 #include <linux/module.h>
00038 #include <linux/vmalloc.h>
00039
00040 #include "master.h"
00041 #include "slave_config.h"
00042 #include "voe_handler.h"
00043 #include "ethernet.h"
00044 #include "ioctl.h"
00045
00050 #define DEBUG_LATENCY 0
00051
00054 #if 0
00055 #define ATTRIBUTES __attribute__ ((__noinline__))
00056 #else
00057 #define ATTRIBUTES
00058 #endif
00059
00060
00061
00064 static void ec_ioctl_strcpy(
00065 char *target,
00066 const char *source
00067 )
00068 {
00069 if (source) {
00070 strncpy(target, source, EC_IOCTL_STRING_SIZE);
00071 target[EC_IOCTL_STRING_SIZE - 1] = 0;
00072 } else {
00073 target[0] = 0;
00074 }
00075 }
00076
00077
00078
00083 static ATTRIBUTES int ec_ioctl_module(
00084 void *arg
00085 )
00086 {
00087 ec_ioctl_module_t data;
00088
00089 data.ioctl_version_magic = EC_IOCTL_VERSION_MAGIC;
00090 data.master_count = ec_master_count();
00091
00092 if (copy_to_user((void __user *) arg, &data, sizeof(data)))
00093 return -EFAULT;
00094
00095 return 0;
00096 }
00097
00098
00099
00104 static ATTRIBUTES int ec_ioctl_master(
00105 ec_master_t *master,
00106 void *arg
00107 )
00108 {
00109 ec_ioctl_master_t io;
00110 unsigned int dev_idx, j;
00111
00112 if (down_interruptible(&master->master_sem)) {
00113 return -EINTR;
00114 }
00115
00116 io.slave_count = master->slave_count;
00117 io.config_count = ec_master_config_count(master);
00118 io.domain_count = ec_master_domain_count(master);
00119 #ifdef EC_EOE
00120 io.eoe_handler_count = ec_master_eoe_handler_count(master);
00121 #endif
00122 io.phase = (uint8_t) master->phase;
00123 io.active = (uint8_t) master->active;
00124 io.scan_busy = master->scan_busy;
00125
00126 up(&master->master_sem);
00127
00128 if (down_interruptible(&master->device_sem)) {
00129 return -EINTR;
00130 }
00131
00132 for (dev_idx = EC_DEVICE_MAIN;
00133 dev_idx < ec_master_num_devices(master); dev_idx++) {
00134 ec_device_t *device = &master->devices[dev_idx];
00135
00136 if (device->dev) {
00137 memcpy(io.devices[dev_idx].address, device->dev->dev_addr,
00138 ETH_ALEN);
00139 } else {
00140 memcpy(io.devices[dev_idx].address, master->macs[dev_idx],
00141 ETH_ALEN);
00142 }
00143 io.devices[dev_idx].attached = device->dev ? 1 : 0;
00144 io.devices[dev_idx].link_state = device->link_state ? 1 : 0;
00145 io.devices[dev_idx].tx_count = device->tx_count;
00146 io.devices[dev_idx].rx_count = device->rx_count;
00147 io.devices[dev_idx].tx_bytes = device->tx_bytes;
00148 io.devices[dev_idx].rx_bytes = device->rx_bytes;
00149 io.devices[dev_idx].tx_errors = device->tx_errors;
00150 for (j = 0; j < EC_RATE_COUNT; j++) {
00151 io.devices[dev_idx].tx_frame_rates[j] =
00152 device->tx_frame_rates[j];
00153 io.devices[dev_idx].rx_frame_rates[j] =
00154 device->rx_frame_rates[j];
00155 io.devices[dev_idx].tx_byte_rates[j] =
00156 device->tx_byte_rates[j];
00157 io.devices[dev_idx].rx_byte_rates[j] =
00158 device->rx_byte_rates[j];
00159 }
00160 }
00161 io.num_devices = ec_master_num_devices(master);
00162
00163 io.tx_count = master->device_stats.tx_count;
00164 io.rx_count = master->device_stats.rx_count;
00165 io.tx_bytes = master->device_stats.tx_bytes;
00166 io.rx_bytes = master->device_stats.rx_bytes;
00167 for (j = 0; j < EC_RATE_COUNT; j++) {
00168 io.tx_frame_rates[j] =
00169 master->device_stats.tx_frame_rates[j];
00170 io.rx_frame_rates[j] =
00171 master->device_stats.rx_frame_rates[j];
00172 io.tx_byte_rates[j] =
00173 master->device_stats.tx_byte_rates[j];
00174 io.rx_byte_rates[j] =
00175 master->device_stats.rx_byte_rates[j];
00176 io.loss_rates[j] =
00177 master->device_stats.loss_rates[j];
00178 }
00179
00180 up(&master->device_sem);
00181
00182 io.app_time = master->app_time;
00183 io.ref_clock =
00184 master->dc_ref_clock ? master->dc_ref_clock->ring_position : 0xffff;
00185
00186 if (copy_to_user((void __user *) arg, &io, sizeof(io))) {
00187 return -EFAULT;
00188 }
00189
00190 return 0;
00191 }
00192
00193
00194
00199 static ATTRIBUTES int ec_ioctl_slave(
00200 ec_master_t *master,
00201 void *arg
00202 )
00203 {
00204 ec_ioctl_slave_t data;
00205 const ec_slave_t *slave;
00206 int i;
00207
00208 if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
00209 return -EFAULT;
00210 }
00211
00212 if (down_interruptible(&master->master_sem))
00213 return -EINTR;
00214
00215 if (!(slave = ec_master_find_slave_const(
00216 master, 0, data.position))) {
00217 up(&master->master_sem);
00218 EC_MASTER_ERR(master, "Slave %u does not exist!\n", data.position);
00219 return -EINVAL;
00220 }
00221
00222 data.device_index = slave->device_index;
00223 data.vendor_id = slave->sii.vendor_id;
00224 data.product_code = slave->sii.product_code;
00225 data.revision_number = slave->sii.revision_number;
00226 data.serial_number = slave->sii.serial_number;
00227 data.alias = slave->effective_alias;
00228 data.boot_rx_mailbox_offset = slave->sii.boot_rx_mailbox_offset;
00229 data.boot_rx_mailbox_size = slave->sii.boot_rx_mailbox_size;
00230 data.boot_tx_mailbox_offset = slave->sii.boot_tx_mailbox_offset;
00231 data.boot_tx_mailbox_size = slave->sii.boot_tx_mailbox_size;
00232 data.std_rx_mailbox_offset = slave->sii.std_rx_mailbox_offset;
00233 data.std_rx_mailbox_size = slave->sii.std_rx_mailbox_size;
00234 data.std_tx_mailbox_offset = slave->sii.std_tx_mailbox_offset;
00235 data.std_tx_mailbox_size = slave->sii.std_tx_mailbox_size;
00236 data.mailbox_protocols = slave->sii.mailbox_protocols;
00237 data.has_general_category = slave->sii.has_general;
00238 data.coe_details = slave->sii.coe_details;
00239 data.general_flags = slave->sii.general_flags;
00240 data.current_on_ebus = slave->sii.current_on_ebus;
00241 for (i = 0; i < EC_MAX_PORTS; i++) {
00242 data.ports[i].desc = slave->ports[i].desc;
00243 data.ports[i].link.link_up = slave->ports[i].link.link_up;
00244 data.ports[i].link.loop_closed = slave->ports[i].link.loop_closed;
00245 data.ports[i].link.signal_detected =
00246 slave->ports[i].link.signal_detected;
00247 data.ports[i].receive_time = slave->ports[i].receive_time;
00248 if (slave->ports[i].next_slave) {
00249 data.ports[i].next_slave =
00250 slave->ports[i].next_slave->ring_position;
00251 } else {
00252 data.ports[i].next_slave = 0xffff;
00253 }
00254 data.ports[i].delay_to_next_dc = slave->ports[i].delay_to_next_dc;
00255 }
00256 data.fmmu_bit = slave->base_fmmu_bit_operation;
00257 data.dc_supported = slave->base_dc_supported;
00258 data.dc_range = slave->base_dc_range;
00259 data.has_dc_system_time = slave->has_dc_system_time;
00260 data.transmission_delay = slave->transmission_delay;
00261 data.al_state = slave->current_state;
00262 data.error_flag = slave->error_flag;
00263
00264 data.sync_count = slave->sii.sync_count;
00265 data.sdo_count = ec_slave_sdo_count(slave);
00266 data.sii_nwords = slave->sii_nwords;
00267 ec_ioctl_strcpy(data.group, slave->sii.group);
00268 ec_ioctl_strcpy(data.image, slave->sii.image);
00269 ec_ioctl_strcpy(data.order, slave->sii.order);
00270 ec_ioctl_strcpy(data.name, slave->sii.name);
00271
00272 up(&master->master_sem);
00273
00274 if (copy_to_user((void __user *) arg, &data, sizeof(data)))
00275 return -EFAULT;
00276
00277 return 0;
00278 }
00279
00280
00281
00286 static ATTRIBUTES int ec_ioctl_slave_sync(
00287 ec_master_t *master,
00288 void *arg
00289 )
00290 {
00291 ec_ioctl_slave_sync_t data;
00292 const ec_slave_t *slave;
00293 const ec_sync_t *sync;
00294
00295 if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
00296 return -EFAULT;
00297 }
00298
00299 if (down_interruptible(&master->master_sem))
00300 return -EINTR;
00301
00302 if (!(slave = ec_master_find_slave_const(
00303 master, 0, data.slave_position))) {
00304 up(&master->master_sem);
00305 EC_MASTER_ERR(master, "Slave %u does not exist!\n",
00306 data.slave_position);
00307 return -EINVAL;
00308 }
00309
00310 if (data.sync_index >= slave->sii.sync_count) {
00311 up(&master->master_sem);
00312 EC_SLAVE_ERR(slave, "Sync manager %u does not exist!\n",
00313 data.sync_index);
00314 return -EINVAL;
00315 }
00316
00317 sync = &slave->sii.syncs[data.sync_index];
00318
00319 data.physical_start_address = sync->physical_start_address;
00320 data.default_size = sync->default_length;
00321 data.control_register = sync->control_register;
00322 data.enable = sync->enable;
00323 data.pdo_count = ec_pdo_list_count(&sync->pdos);
00324
00325 up(&master->master_sem);
00326
00327 if (copy_to_user((void __user *) arg, &data, sizeof(data)))
00328 return -EFAULT;
00329
00330 return 0;
00331 }
00332
00333
00334
00339 static ATTRIBUTES int ec_ioctl_slave_sync_pdo(
00340 ec_master_t *master,
00341 void *arg
00342 )
00343 {
00344 ec_ioctl_slave_sync_pdo_t data;
00345 const ec_slave_t *slave;
00346 const ec_sync_t *sync;
00347 const ec_pdo_t *pdo;
00348
00349 if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
00350 return -EFAULT;
00351 }
00352
00353 if (down_interruptible(&master->master_sem))
00354 return -EINTR;
00355
00356 if (!(slave = ec_master_find_slave_const(
00357 master, 0, data.slave_position))) {
00358 up(&master->master_sem);
00359 EC_MASTER_ERR(master, "Slave %u does not exist!\n",
00360 data.slave_position);
00361 return -EINVAL;
00362 }
00363
00364 if (data.sync_index >= slave->sii.sync_count) {
00365 up(&master->master_sem);
00366 EC_SLAVE_ERR(slave, "Sync manager %u does not exist!\n",
00367 data.sync_index);
00368 return -EINVAL;
00369 }
00370
00371 sync = &slave->sii.syncs[data.sync_index];
00372 if (!(pdo = ec_pdo_list_find_pdo_by_pos_const(
00373 &sync->pdos, data.pdo_pos))) {
00374 up(&master->master_sem);
00375 EC_SLAVE_ERR(slave, "Sync manager %u does not contain a PDO with "
00376 "position %u!\n", data.sync_index, data.pdo_pos);
00377 return -EINVAL;
00378 }
00379
00380 data.index = pdo->index;
00381 data.entry_count = ec_pdo_entry_count(pdo);
00382 ec_ioctl_strcpy(data.name, pdo->name);
00383
00384 up(&master->master_sem);
00385
00386 if (copy_to_user((void __user *) arg, &data, sizeof(data)))
00387 return -EFAULT;
00388
00389 return 0;
00390 }
00391
00392
00393
00398 static ATTRIBUTES int ec_ioctl_slave_sync_pdo_entry(
00399 ec_master_t *master,
00400 void *arg
00401 )
00402 {
00403 ec_ioctl_slave_sync_pdo_entry_t data;
00404 const ec_slave_t *slave;
00405 const ec_sync_t *sync;
00406 const ec_pdo_t *pdo;
00407 const ec_pdo_entry_t *entry;
00408
00409 if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
00410 return -EFAULT;
00411 }
00412
00413 if (down_interruptible(&master->master_sem))
00414 return -EINTR;
00415
00416 if (!(slave = ec_master_find_slave_const(
00417 master, 0, data.slave_position))) {
00418 up(&master->master_sem);
00419 EC_MASTER_ERR(master, "Slave %u does not exist!\n",
00420 data.slave_position);
00421 return -EINVAL;
00422 }
00423
00424 if (data.sync_index >= slave->sii.sync_count) {
00425 up(&master->master_sem);
00426 EC_SLAVE_ERR(slave, "Sync manager %u does not exist!\n",
00427 data.sync_index);
00428 return -EINVAL;
00429 }
00430
00431 sync = &slave->sii.syncs[data.sync_index];
00432 if (!(pdo = ec_pdo_list_find_pdo_by_pos_const(
00433 &sync->pdos, data.pdo_pos))) {
00434 up(&master->master_sem);
00435 EC_SLAVE_ERR(slave, "Sync manager %u does not contain a PDO with "
00436 "position %u!\n", data.sync_index, data.pdo_pos);
00437 return -EINVAL;
00438 }
00439
00440 if (!(entry = ec_pdo_find_entry_by_pos_const(
00441 pdo, data.entry_pos))) {
00442 up(&master->master_sem);
00443 EC_SLAVE_ERR(slave, "PDO 0x%04X does not contain an entry with "
00444 "position %u!\n", data.pdo_pos, data.entry_pos);
00445 return -EINVAL;
00446 }
00447
00448 data.index = entry->index;
00449 data.subindex = entry->subindex;
00450 data.bit_length = entry->bit_length;
00451 ec_ioctl_strcpy(data.name, entry->name);
00452
00453 up(&master->master_sem);
00454
00455 if (copy_to_user((void __user *) arg, &data, sizeof(data)))
00456 return -EFAULT;
00457
00458 return 0;
00459 }
00460
00461
00462
00467 static ATTRIBUTES int ec_ioctl_domain(
00468 ec_master_t *master,
00469 void *arg
00470 )
00471 {
00472 ec_ioctl_domain_t data;
00473 const ec_domain_t *domain;
00474 unsigned int dev_idx;
00475
00476 if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
00477 return -EFAULT;
00478 }
00479
00480 if (down_interruptible(&master->master_sem))
00481 return -EINTR;
00482
00483 if (!(domain = ec_master_find_domain_const(master, data.index))) {
00484 up(&master->master_sem);
00485 EC_MASTER_ERR(master, "Domain %u does not exist!\n", data.index);
00486 return -EINVAL;
00487 }
00488
00489 data.data_size = domain->data_size;
00490 data.logical_base_address = domain->logical_base_address;
00491 for (dev_idx = EC_DEVICE_MAIN;
00492 dev_idx < ec_master_num_devices(domain->master); dev_idx++) {
00493 data.working_counter[dev_idx] = domain->working_counter[dev_idx];
00494 }
00495 data.expected_working_counter = domain->expected_working_counter;
00496 data.fmmu_count = ec_domain_fmmu_count(domain);
00497
00498 up(&master->master_sem);
00499
00500 if (copy_to_user((void __user *) arg, &data, sizeof(data)))
00501 return -EFAULT;
00502
00503 return 0;
00504 }
00505
00506
00507
00512 static ATTRIBUTES int ec_ioctl_domain_fmmu(
00513 ec_master_t *master,
00514 void *arg
00515 )
00516 {
00517 ec_ioctl_domain_fmmu_t data;
00518 const ec_domain_t *domain;
00519 const ec_fmmu_config_t *fmmu;
00520
00521 if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
00522 return -EFAULT;
00523 }
00524
00525 if (down_interruptible(&master->master_sem))
00526 return -EINTR;
00527
00528 if (!(domain = ec_master_find_domain_const(master, data.domain_index))) {
00529 up(&master->master_sem);
00530 EC_MASTER_ERR(master, "Domain %u does not exist!\n",
00531 data.domain_index);
00532 return -EINVAL;
00533 }
00534
00535 if (!(fmmu = ec_domain_find_fmmu(domain, data.fmmu_index))) {
00536 up(&master->master_sem);
00537 EC_MASTER_ERR(master, "Domain %u has less than %u"
00538 " fmmu configurations.\n",
00539 data.domain_index, data.fmmu_index + 1);
00540 return -EINVAL;
00541 }
00542
00543 data.slave_config_alias = fmmu->sc->alias;
00544 data.slave_config_position = fmmu->sc->position;
00545 data.sync_index = fmmu->sync_index;
00546 data.dir = fmmu->dir;
00547 data.logical_address = fmmu->logical_start_address;
00548 data.data_size = fmmu->data_size;
00549
00550 up(&master->master_sem);
00551
00552 if (copy_to_user((void __user *) arg, &data, sizeof(data)))
00553 return -EFAULT;
00554
00555 return 0;
00556 }
00557
00558
00559
00564 static ATTRIBUTES int ec_ioctl_domain_data(
00565 ec_master_t *master,
00566 void *arg
00567 )
00568 {
00569 ec_ioctl_domain_data_t data;
00570 const ec_domain_t *domain;
00571
00572 if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
00573 return -EFAULT;
00574 }
00575
00576 if (down_interruptible(&master->master_sem))
00577 return -EINTR;
00578
00579 if (!(domain = ec_master_find_domain_const(master, data.domain_index))) {
00580 up(&master->master_sem);
00581 EC_MASTER_ERR(master, "Domain %u does not exist!\n",
00582 data.domain_index);
00583 return -EINVAL;
00584 }
00585
00586 if (domain->data_size != data.data_size) {
00587 up(&master->master_sem);
00588 EC_MASTER_ERR(master, "Data size mismatch %u/%zu!\n",
00589 data.data_size, domain->data_size);
00590 return -EFAULT;
00591 }
00592
00593 if (copy_to_user((void __user *) data.target, domain->data,
00594 domain->data_size)) {
00595 up(&master->master_sem);
00596 return -EFAULT;
00597 }
00598
00599 up(&master->master_sem);
00600 return 0;
00601 }
00602
00603
00604
00609 static ATTRIBUTES int ec_ioctl_master_debug(
00610 ec_master_t *master,
00611 void *arg
00612 )
00613 {
00614 return ec_master_debug_level(master, (unsigned long) arg);
00615 }
00616
00617
00618
00623 static ATTRIBUTES int ec_ioctl_master_rescan(
00624 ec_master_t *master,
00625 void *arg
00626 )
00627 {
00628 master->fsm.rescan_required = 1;
00629 return 0;
00630 }
00631
00632
00633
00638 static ATTRIBUTES int ec_ioctl_slave_state(
00639 ec_master_t *master,
00640 void *arg
00641 )
00642 {
00643 ec_ioctl_slave_state_t data;
00644 ec_slave_t *slave;
00645
00646 if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
00647 return -EFAULT;
00648 }
00649
00650 if (down_interruptible(&master->master_sem))
00651 return -EINTR;
00652
00653 if (!(slave = ec_master_find_slave(
00654 master, 0, data.slave_position))) {
00655 up(&master->master_sem);
00656 EC_MASTER_ERR(master, "Slave %u does not exist!\n",
00657 data.slave_position);
00658 return -EINVAL;
00659 }
00660
00661 ec_slave_request_state(slave, data.al_state);
00662
00663 up(&master->master_sem);
00664 return 0;
00665 }
00666
00667
00668
00673 static ATTRIBUTES int ec_ioctl_slave_sdo(
00674 ec_master_t *master,
00675 void *arg
00676 )
00677 {
00678 ec_ioctl_slave_sdo_t data;
00679 const ec_slave_t *slave;
00680 const ec_sdo_t *sdo;
00681
00682 if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
00683 return -EFAULT;
00684 }
00685
00686 if (down_interruptible(&master->master_sem))
00687 return -EINTR;
00688
00689 if (!(slave = ec_master_find_slave_const(
00690 master, 0, data.slave_position))) {
00691 up(&master->master_sem);
00692 EC_MASTER_ERR(master, "Slave %u does not exist!\n",
00693 data.slave_position);
00694 return -EINVAL;
00695 }
00696
00697 if (!(sdo = ec_slave_get_sdo_by_pos_const(
00698 slave, data.sdo_position))) {
00699 up(&master->master_sem);
00700 EC_SLAVE_ERR(slave, "SDO %u does not exist!\n", data.sdo_position);
00701 return -EINVAL;
00702 }
00703
00704 data.sdo_index = sdo->index;
00705 data.max_subindex = sdo->max_subindex;
00706 ec_ioctl_strcpy(data.name, sdo->name);
00707
00708 up(&master->master_sem);
00709
00710 if (copy_to_user((void __user *) arg, &data, sizeof(data)))
00711 return -EFAULT;
00712
00713 return 0;
00714 }
00715
00716
00717
00722 static ATTRIBUTES int ec_ioctl_slave_sdo_entry(
00723 ec_master_t *master,
00724 void *arg
00725 )
00726 {
00727 ec_ioctl_slave_sdo_entry_t data;
00728 const ec_slave_t *slave;
00729 const ec_sdo_t *sdo;
00730 const ec_sdo_entry_t *entry;
00731
00732 if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
00733 return -EFAULT;
00734 }
00735
00736 if (down_interruptible(&master->master_sem))
00737 return -EINTR;
00738
00739 if (!(slave = ec_master_find_slave_const(
00740 master, 0, data.slave_position))) {
00741 up(&master->master_sem);
00742 EC_MASTER_ERR(master, "Slave %u does not exist!\n",
00743 data.slave_position);
00744 return -EINVAL;
00745 }
00746
00747 if (data.sdo_spec <= 0) {
00748 if (!(sdo = ec_slave_get_sdo_by_pos_const(
00749 slave, -data.sdo_spec))) {
00750 up(&master->master_sem);
00751 EC_SLAVE_ERR(slave, "SDO %u does not exist!\n", -data.sdo_spec);
00752 return -EINVAL;
00753 }
00754 } else {
00755 if (!(sdo = ec_slave_get_sdo_const(
00756 slave, data.sdo_spec))) {
00757 up(&master->master_sem);
00758 EC_SLAVE_ERR(slave, "SDO 0x%04X does not exist!\n",
00759 data.sdo_spec);
00760 return -EINVAL;
00761 }
00762 }
00763
00764 if (!(entry = ec_sdo_get_entry_const(
00765 sdo, data.sdo_entry_subindex))) {
00766 up(&master->master_sem);
00767 EC_SLAVE_ERR(slave, "SDO entry 0x%04X:%02X does not exist!\n",
00768 sdo->index, data.sdo_entry_subindex);
00769 return -EINVAL;
00770 }
00771
00772 data.data_type = entry->data_type;
00773 data.bit_length = entry->bit_length;
00774 data.read_access[EC_SDO_ENTRY_ACCESS_PREOP] =
00775 entry->read_access[EC_SDO_ENTRY_ACCESS_PREOP];
00776 data.read_access[EC_SDO_ENTRY_ACCESS_SAFEOP] =
00777 entry->read_access[EC_SDO_ENTRY_ACCESS_SAFEOP];
00778 data.read_access[EC_SDO_ENTRY_ACCESS_OP] =
00779 entry->read_access[EC_SDO_ENTRY_ACCESS_OP];
00780 data.write_access[EC_SDO_ENTRY_ACCESS_PREOP] =
00781 entry->write_access[EC_SDO_ENTRY_ACCESS_PREOP];
00782 data.write_access[EC_SDO_ENTRY_ACCESS_SAFEOP] =
00783 entry->write_access[EC_SDO_ENTRY_ACCESS_SAFEOP];
00784 data.write_access[EC_SDO_ENTRY_ACCESS_OP] =
00785 entry->write_access[EC_SDO_ENTRY_ACCESS_OP];
00786 ec_ioctl_strcpy(data.description, entry->description);
00787
00788 up(&master->master_sem);
00789
00790 if (copy_to_user((void __user *) arg, &data, sizeof(data)))
00791 return -EFAULT;
00792
00793 return 0;
00794 }
00795
00796
00797
00802 static ATTRIBUTES int ec_ioctl_slave_sdo_upload(
00803 ec_master_t *master,
00804 void *arg
00805 )
00806 {
00807 ec_ioctl_slave_sdo_upload_t data;
00808 uint8_t *target;
00809 int ret;
00810
00811 if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
00812 return -EFAULT;
00813 }
00814
00815 if (!(target = kmalloc(data.target_size, GFP_KERNEL))) {
00816 EC_MASTER_ERR(master, "Failed to allocate %zu bytes"
00817 " for SDO upload.\n", data.target_size);
00818 return -ENOMEM;
00819 }
00820
00821 ret = ecrt_master_sdo_upload(master, data.slave_position,
00822 data.sdo_index, data.sdo_entry_subindex, target,
00823 data.target_size, &data.data_size, &data.abort_code);
00824
00825 if (!ret) {
00826 if (copy_to_user((void __user *) data.target,
00827 target, data.data_size)) {
00828 kfree(target);
00829 return -EFAULT;
00830 }
00831 }
00832
00833 kfree(target);
00834
00835 if (__copy_to_user((void __user *) arg, &data, sizeof(data))) {
00836 return -EFAULT;
00837 }
00838
00839 return ret;
00840 }
00841
00842
00843
00848 static ATTRIBUTES int ec_ioctl_slave_sdo_download(
00849 ec_master_t *master,
00850 void *arg
00851 )
00852 {
00853 ec_ioctl_slave_sdo_download_t data;
00854 uint8_t *sdo_data;
00855 int retval;
00856
00857 if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
00858 return -EFAULT;
00859 }
00860
00861 if (!(sdo_data = kmalloc(data.data_size, GFP_KERNEL))) {
00862 EC_MASTER_ERR(master, "Failed to allocate %zu bytes"
00863 " for SDO download.\n", data.data_size);
00864 return -ENOMEM;
00865 }
00866
00867 if (copy_from_user(sdo_data, (void __user *) data.data, data.data_size)) {
00868 kfree(sdo_data);
00869 return -EFAULT;
00870 }
00871
00872 if (data.complete_access) {
00873 retval = ecrt_master_sdo_download_complete(master, data.slave_position,
00874 data.sdo_index, sdo_data, data.data_size, &data.abort_code);
00875 } else {
00876 retval = ecrt_master_sdo_download(master, data.slave_position,
00877 data.sdo_index, data.sdo_entry_subindex, sdo_data,
00878 data.data_size, &data.abort_code);
00879 }
00880
00881 kfree(sdo_data);
00882
00883 if (__copy_to_user((void __user *) arg, &data, sizeof(data))) {
00884 retval = -EFAULT;
00885 }
00886
00887 return retval;
00888 }
00889
00890
00891
00896 static ATTRIBUTES int ec_ioctl_slave_sii_read(
00897 ec_master_t *master,
00898 void *arg
00899 )
00900 {
00901 ec_ioctl_slave_sii_t data;
00902 const ec_slave_t *slave;
00903 int retval;
00904
00905 if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
00906 return -EFAULT;
00907 }
00908
00909 if (down_interruptible(&master->master_sem))
00910 return -EINTR;
00911
00912 if (!(slave = ec_master_find_slave_const(
00913 master, 0, data.slave_position))) {
00914 up(&master->master_sem);
00915 EC_MASTER_ERR(master, "Slave %u does not exist!\n",
00916 data.slave_position);
00917 return -EINVAL;
00918 }
00919
00920 if (!data.nwords
00921 || data.offset + data.nwords > slave->sii_nwords) {
00922 up(&master->master_sem);
00923 EC_SLAVE_ERR(slave, "Invalid SII read offset/size %u/%u for slave SII"
00924 " size %zu!\n", data.offset, data.nwords, slave->sii_nwords);
00925 return -EINVAL;
00926 }
00927
00928 if (copy_to_user((void __user *) data.words,
00929 slave->sii_words + data.offset, data.nwords * 2))
00930 retval = -EFAULT;
00931 else
00932 retval = 0;
00933
00934 up(&master->master_sem);
00935 return retval;
00936 }
00937
00938
00939
00944 static ATTRIBUTES int ec_ioctl_slave_sii_write(
00945 ec_master_t *master,
00946 void *arg
00947 )
00948 {
00949 ec_ioctl_slave_sii_t data;
00950 ec_slave_t *slave;
00951 unsigned int byte_size;
00952 uint16_t *words;
00953 ec_sii_write_request_t request;
00954
00955 if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
00956 return -EFAULT;
00957 }
00958
00959 if (!data.nwords) {
00960 return 0;
00961 }
00962
00963 byte_size = sizeof(uint16_t) * data.nwords;
00964 if (!(words = kmalloc(byte_size, GFP_KERNEL))) {
00965 EC_MASTER_ERR(master, "Failed to allocate %u bytes"
00966 " for SII contents.\n", byte_size);
00967 return -ENOMEM;
00968 }
00969
00970 if (copy_from_user(words,
00971 (void __user *) data.words, byte_size)) {
00972 kfree(words);
00973 return -EFAULT;
00974 }
00975
00976 if (down_interruptible(&master->master_sem)) {
00977 kfree(words);
00978 return -EINTR;
00979 }
00980
00981 if (!(slave = ec_master_find_slave(
00982 master, 0, data.slave_position))) {
00983 up(&master->master_sem);
00984 EC_MASTER_ERR(master, "Slave %u does not exist!\n",
00985 data.slave_position);
00986 kfree(words);
00987 return -EINVAL;
00988 }
00989
00990
00991 INIT_LIST_HEAD(&request.list);
00992 request.slave = slave;
00993 request.words = words;
00994 request.offset = data.offset;
00995 request.nwords = data.nwords;
00996 request.state = EC_INT_REQUEST_QUEUED;
00997
00998
00999 list_add_tail(&request.list, &master->sii_requests);
01000
01001 up(&master->master_sem);
01002
01003
01004 if (wait_event_interruptible(master->request_queue,
01005 request.state != EC_INT_REQUEST_QUEUED)) {
01006
01007 down(&master->master_sem);
01008 if (request.state == EC_INT_REQUEST_QUEUED) {
01009
01010 list_del(&request.list);
01011 up(&master->master_sem);
01012 kfree(words);
01013 return -EINTR;
01014 }
01015 up(&master->master_sem);
01016 }
01017
01018
01019 wait_event(master->request_queue, request.state != EC_INT_REQUEST_BUSY);
01020
01021 kfree(words);
01022
01023 return request.state == EC_INT_REQUEST_SUCCESS ? 0 : -EIO;
01024 }
01025
01026
01027
01032 static ATTRIBUTES int ec_ioctl_slave_reg_read(
01033 ec_master_t *master,
01034 void *arg
01035 )
01036 {
01037 ec_ioctl_slave_reg_t io;
01038 ec_slave_t *slave;
01039 ec_reg_request_t request;
01040 int ret;
01041
01042 if (copy_from_user(&io, (void __user *) arg, sizeof(io))) {
01043 return -EFAULT;
01044 }
01045
01046 if (!io.size) {
01047 return 0;
01048 }
01049
01050
01051 ret = ec_reg_request_init(&request, io.size);
01052 if (ret) {
01053 return ret;
01054 }
01055
01056 ecrt_reg_request_read(&request, io.address, io.size);
01057
01058 if (down_interruptible(&master->master_sem)) {
01059 ec_reg_request_clear(&request);
01060 return -EINTR;
01061 }
01062
01063 if (!(slave = ec_master_find_slave(
01064 master, 0, io.slave_position))) {
01065 up(&master->master_sem);
01066 ec_reg_request_clear(&request);
01067 EC_MASTER_ERR(master, "Slave %u does not exist!\n",
01068 io.slave_position);
01069 return -EINVAL;
01070 }
01071
01072
01073 list_add_tail(&request.list, &slave->reg_requests);
01074
01075 up(&master->master_sem);
01076
01077
01078 if (wait_event_interruptible(master->request_queue,
01079 request.state != EC_INT_REQUEST_QUEUED)) {
01080
01081 down(&master->master_sem);
01082 if (request.state == EC_INT_REQUEST_QUEUED) {
01083
01084 list_del(&request.list);
01085 up(&master->master_sem);
01086 ec_reg_request_clear(&request);
01087 return -EINTR;
01088 }
01089 up(&master->master_sem);
01090 }
01091
01092
01093 wait_event(master->request_queue, request.state != EC_INT_REQUEST_BUSY);
01094
01095 if (request.state == EC_INT_REQUEST_SUCCESS) {
01096 if (copy_to_user((void __user *) io.data, request.data, io.size)) {
01097 return -EFAULT;
01098 }
01099 }
01100 ec_reg_request_clear(&request);
01101
01102 return request.state == EC_INT_REQUEST_SUCCESS ? 0 : -EIO;
01103 }
01104
01105
01106
01111 static ATTRIBUTES int ec_ioctl_slave_reg_write(
01112 ec_master_t *master,
01113 void *arg
01114 )
01115 {
01116 ec_ioctl_slave_reg_t io;
01117 ec_slave_t *slave;
01118 ec_reg_request_t request;
01119 int ret;
01120
01121 if (copy_from_user(&io, (void __user *) arg, sizeof(io))) {
01122 return -EFAULT;
01123 }
01124
01125 if (!io.size) {
01126 return 0;
01127 }
01128
01129
01130 ret = ec_reg_request_init(&request, io.size);
01131 if (ret) {
01132 return ret;
01133 }
01134
01135 if (copy_from_user(request.data, (void __user *) io.data, io.size)) {
01136 ec_reg_request_clear(&request);
01137 return -EFAULT;
01138 }
01139
01140 ecrt_reg_request_write(&request, io.address, io.size);
01141
01142 if (down_interruptible(&master->master_sem)) {
01143 ec_reg_request_clear(&request);
01144 return -EINTR;
01145 }
01146
01147 if (io.emergency) {
01148 request.ring_position = io.slave_position;
01149
01150 list_add_tail(&request.list, &master->emerg_reg_requests);
01151 }
01152 else {
01153 if (!(slave = ec_master_find_slave(master, 0, io.slave_position))) {
01154 up(&master->master_sem);
01155 ec_reg_request_clear(&request);
01156 EC_MASTER_ERR(master, "Slave %u does not exist!\n",
01157 io.slave_position);
01158 return -EINVAL;
01159 }
01160
01161
01162 list_add_tail(&request.list, &slave->reg_requests);
01163 }
01164
01165 up(&master->master_sem);
01166
01167
01168 if (wait_event_interruptible(master->request_queue,
01169 request.state != EC_INT_REQUEST_QUEUED)) {
01170
01171 down(&master->master_sem);
01172 if (request.state == EC_INT_REQUEST_QUEUED) {
01173
01174 list_del(&request.list);
01175 up(&master->master_sem);
01176 ec_reg_request_clear(&request);
01177 return -EINTR;
01178 }
01179 up(&master->master_sem);
01180 }
01181
01182
01183 wait_event(master->request_queue, request.state != EC_INT_REQUEST_BUSY);
01184
01185 ec_reg_request_clear(&request);
01186
01187 return request.state == EC_INT_REQUEST_SUCCESS ? 0 : -EIO;
01188 }
01189
01190
01191
01196 static ATTRIBUTES int ec_ioctl_config(
01197 ec_master_t *master,
01198 void *arg
01199 )
01200 {
01201 ec_ioctl_config_t data;
01202 const ec_slave_config_t *sc;
01203 uint8_t i;
01204
01205 if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
01206 return -EFAULT;
01207 }
01208
01209 if (down_interruptible(&master->master_sem))
01210 return -EINTR;
01211
01212 if (!(sc = ec_master_get_config_const(
01213 master, data.config_index))) {
01214 up(&master->master_sem);
01215 EC_MASTER_ERR(master, "Slave config %u does not exist!\n",
01216 data.config_index);
01217 return -EINVAL;
01218 }
01219
01220 data.alias = sc->alias;
01221 data.position = sc->position;
01222 data.vendor_id = sc->vendor_id;
01223 data.product_code = sc->product_code;
01224 for (i = 0; i < EC_MAX_SYNC_MANAGERS; i++) {
01225 data.syncs[i].dir = sc->sync_configs[i].dir;
01226 data.syncs[i].watchdog_mode = sc->sync_configs[i].watchdog_mode;
01227 data.syncs[i].pdo_count =
01228 ec_pdo_list_count(&sc->sync_configs[i].pdos);
01229 }
01230 data.watchdog_divider = sc->watchdog_divider;
01231 data.watchdog_intervals = sc->watchdog_intervals;
01232 data.sdo_count = ec_slave_config_sdo_count(sc);
01233 data.idn_count = ec_slave_config_idn_count(sc);
01234 data.slave_position = sc->slave ? sc->slave->ring_position : -1;
01235 data.dc_assign_activate = sc->dc_assign_activate;
01236 for (i = 0; i < EC_SYNC_SIGNAL_COUNT; i++) {
01237 data.dc_sync[i] = sc->dc_sync[i];
01238 }
01239
01240 up(&master->master_sem);
01241
01242 if (copy_to_user((void __user *) arg, &data, sizeof(data)))
01243 return -EFAULT;
01244
01245 return 0;
01246 }
01247
01248
01249
01254 static ATTRIBUTES int ec_ioctl_config_pdo(
01255 ec_master_t *master,
01256 void *arg
01257 )
01258 {
01259 ec_ioctl_config_pdo_t data;
01260 const ec_slave_config_t *sc;
01261 const ec_pdo_t *pdo;
01262
01263 if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
01264 return -EFAULT;
01265 }
01266
01267 if (data.sync_index >= EC_MAX_SYNC_MANAGERS) {
01268 EC_MASTER_ERR(master, "Invalid sync manager index %u!\n",
01269 data.sync_index);
01270 return -EINVAL;
01271 }
01272
01273 if (down_interruptible(&master->master_sem))
01274 return -EINTR;
01275
01276 if (!(sc = ec_master_get_config_const(
01277 master, data.config_index))) {
01278 up(&master->master_sem);
01279 EC_MASTER_ERR(master, "Slave config %u does not exist!\n",
01280 data.config_index);
01281 return -EINVAL;
01282 }
01283
01284 if (!(pdo = ec_pdo_list_find_pdo_by_pos_const(
01285 &sc->sync_configs[data.sync_index].pdos,
01286 data.pdo_pos))) {
01287 up(&master->master_sem);
01288 EC_MASTER_ERR(master, "Invalid PDO position!\n");
01289 return -EINVAL;
01290 }
01291
01292 data.index = pdo->index;
01293 data.entry_count = ec_pdo_entry_count(pdo);
01294 ec_ioctl_strcpy(data.name, pdo->name);
01295
01296 up(&master->master_sem);
01297
01298 if (copy_to_user((void __user *) arg, &data, sizeof(data)))
01299 return -EFAULT;
01300
01301 return 0;
01302 }
01303
01304
01305
01310 static ATTRIBUTES int ec_ioctl_config_pdo_entry(
01311 ec_master_t *master,
01312 void *arg
01313 )
01314 {
01315 ec_ioctl_config_pdo_entry_t data;
01316 const ec_slave_config_t *sc;
01317 const ec_pdo_t *pdo;
01318 const ec_pdo_entry_t *entry;
01319
01320 if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
01321 return -EFAULT;
01322 }
01323
01324 if (data.sync_index >= EC_MAX_SYNC_MANAGERS) {
01325 EC_MASTER_ERR(master, "Invalid sync manager index %u!\n",
01326 data.sync_index);
01327 return -EINVAL;
01328 }
01329
01330 if (down_interruptible(&master->master_sem))
01331 return -EINTR;
01332
01333 if (!(sc = ec_master_get_config_const(
01334 master, data.config_index))) {
01335 up(&master->master_sem);
01336 EC_MASTER_ERR(master, "Slave config %u does not exist!\n",
01337 data.config_index);
01338 return -EINVAL;
01339 }
01340
01341 if (!(pdo = ec_pdo_list_find_pdo_by_pos_const(
01342 &sc->sync_configs[data.sync_index].pdos,
01343 data.pdo_pos))) {
01344 up(&master->master_sem);
01345 EC_MASTER_ERR(master, "Invalid PDO position!\n");
01346 return -EINVAL;
01347 }
01348
01349 if (!(entry = ec_pdo_find_entry_by_pos_const(
01350 pdo, data.entry_pos))) {
01351 up(&master->master_sem);
01352 EC_MASTER_ERR(master, "Entry not found!\n");
01353 return -EINVAL;
01354 }
01355
01356 data.index = entry->index;
01357 data.subindex = entry->subindex;
01358 data.bit_length = entry->bit_length;
01359 ec_ioctl_strcpy(data.name, entry->name);
01360
01361 up(&master->master_sem);
01362
01363 if (copy_to_user((void __user *) arg, &data, sizeof(data)))
01364 return -EFAULT;
01365
01366 return 0;
01367 }
01368
01369
01370
01375 static ATTRIBUTES int ec_ioctl_config_sdo(
01376 ec_master_t *master,
01377 void *arg
01378 )
01379 {
01380 ec_ioctl_config_sdo_t *ioctl;
01381 const ec_slave_config_t *sc;
01382 const ec_sdo_request_t *req;
01383
01384 if (!(ioctl = kmalloc(sizeof(*ioctl), GFP_KERNEL))) {
01385 return -ENOMEM;
01386 }
01387
01388 if (copy_from_user(ioctl, (void __user *) arg, sizeof(*ioctl))) {
01389 kfree(ioctl);
01390 return -EFAULT;
01391 }
01392
01393 if (down_interruptible(&master->master_sem)) {
01394 kfree(ioctl);
01395 return -EINTR;
01396 }
01397
01398 if (!(sc = ec_master_get_config_const(
01399 master, ioctl->config_index))) {
01400 up(&master->master_sem);
01401 EC_MASTER_ERR(master, "Slave config %u does not exist!\n",
01402 ioctl->config_index);
01403 kfree(ioctl);
01404 return -EINVAL;
01405 }
01406
01407 if (!(req = ec_slave_config_get_sdo_by_pos_const(
01408 sc, ioctl->sdo_pos))) {
01409 up(&master->master_sem);
01410 EC_MASTER_ERR(master, "Invalid SDO position!\n");
01411 kfree(ioctl);
01412 return -EINVAL;
01413 }
01414
01415 ioctl->index = req->index;
01416 ioctl->subindex = req->subindex;
01417 ioctl->size = req->data_size;
01418 memcpy(ioctl->data, req->data,
01419 min((u32) ioctl->size, (u32) EC_MAX_SDO_DATA_SIZE));
01420 ioctl->complete_access = req->complete_access;
01421
01422 up(&master->master_sem);
01423
01424 if (copy_to_user((void __user *) arg, ioctl, sizeof(*ioctl))) {
01425 kfree(ioctl);
01426 return -EFAULT;
01427 }
01428
01429 kfree(ioctl);
01430 return 0;
01431 }
01432
01433
01434
01439 static ATTRIBUTES int ec_ioctl_config_idn(
01440 ec_master_t *master,
01441 void *arg
01442 )
01443 {
01444 ec_ioctl_config_idn_t *ioctl;
01445 const ec_slave_config_t *sc;
01446 const ec_soe_request_t *req;
01447
01448 if (!(ioctl = kmalloc(sizeof(*ioctl), GFP_KERNEL))) {
01449 return -ENOMEM;
01450 }
01451
01452 if (copy_from_user(ioctl, (void __user *) arg, sizeof(*ioctl))) {
01453 kfree(ioctl);
01454 return -EFAULT;
01455 }
01456
01457 if (down_interruptible(&master->master_sem)) {
01458 kfree(ioctl);
01459 return -EINTR;
01460 }
01461
01462 if (!(sc = ec_master_get_config_const(
01463 master, ioctl->config_index))) {
01464 up(&master->master_sem);
01465 EC_MASTER_ERR(master, "Slave config %u does not exist!\n",
01466 ioctl->config_index);
01467 kfree(ioctl);
01468 return -EINVAL;
01469 }
01470
01471 if (!(req = ec_slave_config_get_idn_by_pos_const(
01472 sc, ioctl->idn_pos))) {
01473 up(&master->master_sem);
01474 EC_MASTER_ERR(master, "Invalid IDN position!\n");
01475 kfree(ioctl);
01476 return -EINVAL;
01477 }
01478
01479 ioctl->drive_no = req->drive_no;
01480 ioctl->idn = req->idn;
01481 ioctl->state = req->state;
01482 ioctl->size = req->data_size;
01483 memcpy(ioctl->data, req->data,
01484 min((u32) ioctl->size, (u32) EC_MAX_IDN_DATA_SIZE));
01485
01486 up(&master->master_sem);
01487
01488 if (copy_to_user((void __user *) arg, ioctl, sizeof(*ioctl))) {
01489 kfree(ioctl);
01490 return -EFAULT;
01491 }
01492
01493 kfree(ioctl);
01494 return 0;
01495 }
01496
01497
01498
01499 #ifdef EC_EOE
01500
01505 static ATTRIBUTES int ec_ioctl_eoe_handler(
01506 ec_master_t *master,
01507 void *arg
01508 )
01509 {
01510 ec_ioctl_eoe_handler_t data;
01511 const ec_eoe_t *eoe;
01512
01513 if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
01514 return -EFAULT;
01515 }
01516
01517 if (down_interruptible(&master->master_sem))
01518 return -EINTR;
01519
01520 if (!(eoe = ec_master_get_eoe_handler_const(master, data.eoe_index))) {
01521 up(&master->master_sem);
01522 EC_MASTER_ERR(master, "EoE handler %u does not exist!\n",
01523 data.eoe_index);
01524 return -EINVAL;
01525 }
01526
01527 if (eoe->slave) {
01528 data.slave_position = eoe->slave->ring_position;
01529 } else {
01530 data.slave_position = 0xffff;
01531 }
01532 snprintf(data.name, EC_DATAGRAM_NAME_SIZE, eoe->dev->name);
01533 data.open = eoe->opened;
01534 data.rx_bytes = eoe->stats.tx_bytes;
01535 data.rx_rate = eoe->tx_rate;
01536 data.tx_bytes = eoe->stats.rx_bytes;
01537 data.tx_rate = eoe->tx_rate;
01538 data.tx_queued_frames = eoe->tx_queued_frames;
01539 data.tx_queue_size = eoe->tx_queue_size;
01540
01541 up(&master->master_sem);
01542
01543 if (copy_to_user((void __user *) arg, &data, sizeof(data)))
01544 return -EFAULT;
01545
01546 return 0;
01547 }
01548
01549 #endif
01550
01551
01552
01557 static ATTRIBUTES int ec_ioctl_request(
01558 ec_master_t *master,
01559 void *arg,
01560 ec_ioctl_context_t *ctx
01561 )
01562 {
01563 ec_master_t *m;
01564 int ret = 0;
01565
01566 m = ecrt_request_master_err(master->index);
01567 if (IS_ERR(m)) {
01568 ret = PTR_ERR(m);
01569 } else {
01570 ctx->requested = 1;
01571 }
01572
01573 return ret;
01574 }
01575
01576
01577
01582 static ATTRIBUTES int ec_ioctl_create_domain(
01583 ec_master_t *master,
01584 void *arg,
01585 ec_ioctl_context_t *ctx
01586 )
01587 {
01588 ec_domain_t *domain;
01589
01590 if (unlikely(!ctx->requested))
01591 return -EPERM;
01592
01593 domain = ecrt_master_create_domain_err(master);
01594 if (IS_ERR(domain))
01595 return PTR_ERR(domain);
01596
01597 return domain->index;
01598 }
01599
01600
01601
01606 static ATTRIBUTES int ec_ioctl_create_slave_config(
01607 ec_master_t *master,
01608 void *arg,
01609 ec_ioctl_context_t *ctx
01610 )
01611 {
01612 ec_ioctl_config_t data;
01613 ec_slave_config_t *sc, *entry;
01614
01615 if (unlikely(!ctx->requested))
01616 return -EPERM;
01617
01618 if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
01619 return -EFAULT;
01620 }
01621
01622 sc = ecrt_master_slave_config_err(master, data.alias, data.position,
01623 data.vendor_id, data.product_code);
01624 if (IS_ERR(sc))
01625 return PTR_ERR(sc);
01626
01627 data.config_index = 0;
01628
01629 if (down_interruptible(&master->master_sem))
01630 return -EINTR;
01631
01632 list_for_each_entry(entry, &master->configs, list) {
01633 if (entry == sc)
01634 break;
01635 data.config_index++;
01636 }
01637
01638 up(&master->master_sem);
01639
01640 if (copy_to_user((void __user *) arg, &data, sizeof(data)))
01641 return -EFAULT;
01642
01643 return 0;
01644 }
01645
01646
01647
01652 static ATTRIBUTES int ec_ioctl_select_ref_clock(
01653 ec_master_t *master,
01654 void *arg,
01655 ec_ioctl_context_t *ctx
01656 )
01657 {
01658 unsigned long config_index = (unsigned long) arg;
01659 ec_slave_config_t *sc = NULL;
01660 int ret = 0;
01661
01662 if (unlikely(!ctx->requested)) {
01663 ret = -EPERM;
01664 goto out_return;
01665 }
01666
01667 if (down_interruptible(&master->master_sem)) {
01668 ret = -EINTR;
01669 goto out_return;
01670 }
01671
01672 if (config_index != 0xFFFFFFFF) {
01673 if (!(sc = ec_master_get_config(master, config_index))) {
01674 ret = -ENOENT;
01675 goto out_up;
01676 }
01677 }
01678
01679 ecrt_master_select_reference_clock(master, sc);
01680
01681 out_up:
01682 up(&master->master_sem);
01683 out_return:
01684 return ret;
01685 }
01686
01687
01688
01693 static ATTRIBUTES int ec_ioctl_activate(
01694 ec_master_t *master,
01695 void *arg,
01696 ec_ioctl_context_t *ctx
01697 )
01698 {
01699 ec_ioctl_master_activate_t io;
01700 ec_domain_t *domain;
01701 off_t offset;
01702 int ret;
01703
01704 if (unlikely(!ctx->requested))
01705 return -EPERM;
01706
01707 io.process_data = NULL;
01708
01709
01710
01711 ctx->process_data_size = 0;
01712
01713 if (down_interruptible(&master->master_sem))
01714 return -EINTR;
01715
01716 list_for_each_entry(domain, &master->domains, list) {
01717 ctx->process_data_size += ecrt_domain_size(domain);
01718 }
01719
01720 up(&master->master_sem);
01721
01722 if (ctx->process_data_size) {
01723 ctx->process_data = vmalloc(ctx->process_data_size);
01724 if (!ctx->process_data) {
01725 ctx->process_data_size = 0;
01726 return -ENOMEM;
01727 }
01728
01729
01730
01731
01732 offset = 0;
01733 list_for_each_entry(domain, &master->domains, list) {
01734 ecrt_domain_external_memory(domain,
01735 ctx->process_data + offset);
01736 offset += ecrt_domain_size(domain);
01737 }
01738
01739 #ifdef EC_IOCTL_RTDM
01740
01741
01742
01743 ret = ec_rtdm_mmap(ctx, &io.process_data);
01744 if (ret < 0) {
01745 EC_MASTER_ERR(master, "Failed to map process data"
01746 " memory to user space (code %i).\n", ret);
01747 return ret;
01748 }
01749 #endif
01750 }
01751
01752 io.process_data_size = ctx->process_data_size;
01753
01754 #ifndef EC_IOCTL_RTDM
01755 ecrt_master_callbacks(master, ec_master_internal_send_cb,
01756 ec_master_internal_receive_cb, master);
01757 #endif
01758
01759 ret = ecrt_master_activate(master);
01760 if (ret < 0)
01761 return ret;
01762
01763 if (copy_to_user((void __user *) arg, &io,
01764 sizeof(ec_ioctl_master_activate_t)))
01765 return -EFAULT;
01766
01767 return 0;
01768 }
01769
01770
01771
01776 static ATTRIBUTES int ec_ioctl_deactivate(
01777 ec_master_t *master,
01778 void *arg,
01779 ec_ioctl_context_t *ctx
01780 )
01781 {
01782 if (unlikely(!ctx->requested))
01783 return -EPERM;
01784
01785 ecrt_master_deactivate(master);
01786 return 0;
01787 }
01788
01789
01790
01795 static ATTRIBUTES int ec_ioctl_set_send_interval(
01796 ec_master_t *master,
01797 void *arg,
01798 ec_ioctl_context_t *ctx
01799 )
01800 {
01801 size_t send_interval;
01802
01803 if (unlikely(!ctx->requested)) {
01804 return -EPERM;
01805 }
01806
01807 if (copy_from_user(&send_interval, (void __user *) arg,
01808 sizeof(send_interval))) {
01809 return -EFAULT;
01810 }
01811
01812 if (down_interruptible(&master->master_sem))
01813 return -EINTR;
01814
01815 ec_master_set_send_interval(master, send_interval);
01816
01817 up(&master->master_sem);
01818 return 0;
01819 }
01820
01821
01822
01827 static ATTRIBUTES int ec_ioctl_send(
01828 ec_master_t *master,
01829 void *arg,
01830 ec_ioctl_context_t *ctx
01831 )
01832 {
01833 if (unlikely(!ctx->requested)) {
01834 return -EPERM;
01835 }
01836
01837 ecrt_master_send(master);
01838 return 0;
01839 }
01840
01841
01842
01847 static ATTRIBUTES int ec_ioctl_receive(
01848 ec_master_t *master,
01849 void *arg,
01850 ec_ioctl_context_t *ctx
01851 )
01852 {
01853 if (unlikely(!ctx->requested)) {
01854 return -EPERM;
01855 }
01856
01857 ecrt_master_receive(master);
01858 return 0;
01859 }
01860
01861
01862
01867 static ATTRIBUTES int ec_ioctl_master_state(
01868 ec_master_t *master,
01869 void *arg,
01870 ec_ioctl_context_t *ctx
01871 )
01872 {
01873 ec_master_state_t data;
01874
01875 ecrt_master_state(master, &data);
01876
01877 if (copy_to_user((void __user *) arg, &data, sizeof(data)))
01878 return -EFAULT;
01879
01880 return 0;
01881 }
01882
01883
01884
01889 static ATTRIBUTES int ec_ioctl_master_link_state(
01890 ec_master_t *master,
01891 void *arg,
01892 ec_ioctl_context_t *ctx
01893 )
01894 {
01895 ec_ioctl_link_state_t ioctl;
01896 ec_master_link_state_t state;
01897 int ret;
01898
01899 if (copy_from_user(&ioctl, (void __user *) arg, sizeof(ioctl))) {
01900 return -EFAULT;
01901 }
01902
01903 ret = ecrt_master_link_state(master, ioctl.dev_idx, &state);
01904 if (ret < 0) {
01905 return ret;
01906 }
01907
01908 if (copy_to_user((void __user *) ioctl.state, &state, sizeof(state))) {
01909 return -EFAULT;
01910 }
01911
01912 return 0;
01913 }
01914
01915
01916
01921 static ATTRIBUTES int ec_ioctl_app_time(
01922 ec_master_t *master,
01923 void *arg,
01924 ec_ioctl_context_t *ctx
01925 )
01926 {
01927 ec_ioctl_app_time_t data;
01928
01929 if (unlikely(!ctx->requested))
01930 return -EPERM;
01931
01932 if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
01933 return -EFAULT;
01934 }
01935
01936 ecrt_master_application_time(master, data.app_time);
01937 return 0;
01938 }
01939
01940
01941
01946 static ATTRIBUTES int ec_ioctl_sync_ref(
01947 ec_master_t *master,
01948 void *arg,
01949 ec_ioctl_context_t *ctx
01950 )
01951 {
01952 if (unlikely(!ctx->requested)) {
01953 return -EPERM;
01954 }
01955
01956 ecrt_master_sync_reference_clock(master);
01957 return 0;
01958 }
01959
01960
01961
01966 static ATTRIBUTES int ec_ioctl_sync_slaves(
01967 ec_master_t *master,
01968 void *arg,
01969 ec_ioctl_context_t *ctx
01970 )
01971 {
01972 if (unlikely(!ctx->requested)) {
01973 return -EPERM;
01974 }
01975
01976 ecrt_master_sync_slave_clocks(master);
01977 return 0;
01978 }
01979
01980
01981
01986 static ATTRIBUTES int ec_ioctl_ref_clock_time(
01987 ec_master_t *master,
01988 void *arg,
01989 ec_ioctl_context_t *ctx
01990 )
01991 {
01992 uint32_t time;
01993 int ret;
01994
01995 if (unlikely(!ctx->requested)) {
01996 return -EPERM;
01997 }
01998
01999 ret = ecrt_master_reference_clock_time(master, &time);
02000 if (ret) {
02001 return ret;
02002 }
02003
02004 if (copy_to_user((void __user *) arg, &time, sizeof(time))) {
02005 return -EFAULT;
02006 }
02007
02008 return 0;
02009 }
02010
02011
02012
02017 static ATTRIBUTES int ec_ioctl_sync_mon_queue(
02018 ec_master_t *master,
02019 void *arg,
02020 ec_ioctl_context_t *ctx
02021 )
02022 {
02023 if (unlikely(!ctx->requested)) {
02024 return -EPERM;
02025 }
02026
02027 ecrt_master_sync_monitor_queue(master);
02028 return 0;
02029 }
02030
02031
02032
02037 static ATTRIBUTES int ec_ioctl_sync_mon_process(
02038 ec_master_t *master,
02039 void *arg,
02040 ec_ioctl_context_t *ctx
02041 )
02042 {
02043 uint32_t time_diff;
02044
02045 if (unlikely(!ctx->requested))
02046 return -EPERM;
02047
02048 time_diff = ecrt_master_sync_monitor_process(master);
02049
02050 if (copy_to_user((void __user *) arg, &time_diff, sizeof(time_diff)))
02051 return -EFAULT;
02052
02053 return 0;
02054 }
02055
02056
02057
02062 static ATTRIBUTES int ec_ioctl_reset(
02063 ec_master_t *master,
02064 void *arg,
02065 ec_ioctl_context_t *ctx
02066 )
02067 {
02068 down(&master->master_sem);
02069 ecrt_master_reset(master);
02070 up(&master->master_sem);
02071 return 0;
02072 }
02073
02074
02075
02080 static ATTRIBUTES int ec_ioctl_sc_sync(
02081 ec_master_t *master,
02082 void *arg,
02083 ec_ioctl_context_t *ctx
02084 )
02085 {
02086 ec_ioctl_config_t data;
02087 ec_slave_config_t *sc;
02088 unsigned int i;
02089 int ret = 0;
02090
02091 if (unlikely(!ctx->requested)) {
02092 ret = -EPERM;
02093 goto out_return;
02094 }
02095
02096 if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
02097 ret = -EFAULT;
02098 goto out_return;
02099 }
02100
02101 if (down_interruptible(&master->master_sem)) {
02102 ret = -EINTR;
02103 goto out_return;
02104 }
02105
02106 if (!(sc = ec_master_get_config(master, data.config_index))) {
02107 ret = -ENOENT;
02108 goto out_up;
02109 }
02110
02111 for (i = 0; i < EC_MAX_SYNC_MANAGERS; i++) {
02112 if (data.syncs[i].config_this) {
02113 ret = ecrt_slave_config_sync_manager(sc, i, data.syncs[i].dir,
02114 data.syncs[i].watchdog_mode);
02115 if (ret) {
02116 goto out_up;
02117 }
02118 }
02119 }
02120
02121 out_up:
02122 up(&master->master_sem);
02123 out_return:
02124 return ret;
02125 }
02126
02127
02128
02133 static ATTRIBUTES int ec_ioctl_sc_watchdog(
02134 ec_master_t *master,
02135 void *arg,
02136 ec_ioctl_context_t *ctx
02137 )
02138 {
02139 ec_ioctl_config_t data;
02140 ec_slave_config_t *sc;
02141 int ret = 0;
02142
02143 if (unlikely(!ctx->requested)) {
02144 ret = -EPERM;
02145 goto out_return;
02146 }
02147
02148 if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
02149 ret = -EFAULT;
02150 goto out_return;
02151 }
02152
02153 if (down_interruptible(&master->master_sem)) {
02154 ret = -EINTR;
02155 goto out_return;
02156 }
02157
02158 if (!(sc = ec_master_get_config(master, data.config_index))) {
02159 ret = -ENOENT;
02160 goto out_up;
02161 }
02162
02163 ecrt_slave_config_watchdog(sc,
02164 data.watchdog_divider, data.watchdog_intervals);
02165
02166 out_up:
02167 up(&master->master_sem);
02168 out_return:
02169 return ret;
02170 }
02171
02172
02173
02178 static ATTRIBUTES int ec_ioctl_sc_add_pdo(
02179 ec_master_t *master,
02180 void *arg,
02181 ec_ioctl_context_t *ctx
02182 )
02183 {
02184 ec_ioctl_config_pdo_t data;
02185 ec_slave_config_t *sc;
02186
02187 if (unlikely(!ctx->requested))
02188 return -EPERM;
02189
02190 if (copy_from_user(&data, (void __user *) arg, sizeof(data)))
02191 return -EFAULT;
02192
02193 if (down_interruptible(&master->master_sem))
02194 return -EINTR;
02195
02196 if (!(sc = ec_master_get_config(master, data.config_index))) {
02197 up(&master->master_sem);
02198 return -ENOENT;
02199 }
02200
02201 up(&master->master_sem);
02203 return ecrt_slave_config_pdo_assign_add(sc, data.sync_index, data.index);
02204 }
02205
02206
02207
02212 static ATTRIBUTES int ec_ioctl_sc_clear_pdos(
02213 ec_master_t *master,
02214 void *arg,
02215 ec_ioctl_context_t *ctx
02216 )
02217 {
02218 ec_ioctl_config_pdo_t data;
02219 ec_slave_config_t *sc;
02220
02221 if (unlikely(!ctx->requested))
02222 return -EPERM;
02223
02224 if (copy_from_user(&data, (void __user *) arg, sizeof(data)))
02225 return -EFAULT;
02226
02227 if (down_interruptible(&master->master_sem))
02228 return -EINTR;
02229
02230 if (!(sc = ec_master_get_config(master, data.config_index))) {
02231 up(&master->master_sem);
02232 return -ENOENT;
02233 }
02234
02235 up(&master->master_sem);
02237 ecrt_slave_config_pdo_assign_clear(sc, data.sync_index);
02238 return 0;
02239 }
02240
02241
02242
02247 static ATTRIBUTES int ec_ioctl_sc_add_entry(
02248 ec_master_t *master,
02249 void *arg,
02250 ec_ioctl_context_t *ctx
02251 )
02252 {
02253 ec_ioctl_add_pdo_entry_t data;
02254 ec_slave_config_t *sc;
02255
02256 if (unlikely(!ctx->requested))
02257 return -EPERM;
02258
02259 if (copy_from_user(&data, (void __user *) arg, sizeof(data)))
02260 return -EFAULT;
02261
02262 if (down_interruptible(&master->master_sem))
02263 return -EINTR;
02264
02265 if (!(sc = ec_master_get_config(master, data.config_index))) {
02266 up(&master->master_sem);
02267 return -ENOENT;
02268 }
02269
02270 up(&master->master_sem);
02272 return ecrt_slave_config_pdo_mapping_add(sc, data.pdo_index,
02273 data.entry_index, data.entry_subindex, data.entry_bit_length);
02274 }
02275
02276
02277
02282 static ATTRIBUTES int ec_ioctl_sc_clear_entries(
02283 ec_master_t *master,
02284 void *arg,
02285 ec_ioctl_context_t *ctx
02286 )
02287 {
02288 ec_ioctl_config_pdo_t data;
02289 ec_slave_config_t *sc;
02290
02291 if (unlikely(!ctx->requested))
02292 return -EPERM;
02293
02294 if (copy_from_user(&data, (void __user *) arg, sizeof(data)))
02295 return -EFAULT;
02296
02297 if (down_interruptible(&master->master_sem))
02298 return -EINTR;
02299
02300 if (!(sc = ec_master_get_config(master, data.config_index))) {
02301 up(&master->master_sem);
02302 return -ENOENT;
02303 }
02304
02305 up(&master->master_sem);
02307 ecrt_slave_config_pdo_mapping_clear(sc, data.index);
02308 return 0;
02309 }
02310
02311
02312
02317 static ATTRIBUTES int ec_ioctl_sc_reg_pdo_entry(
02318 ec_master_t *master,
02319 void *arg,
02320 ec_ioctl_context_t *ctx
02321 )
02322 {
02323 ec_ioctl_reg_pdo_entry_t data;
02324 ec_slave_config_t *sc;
02325 ec_domain_t *domain;
02326 int ret;
02327
02328 if (unlikely(!ctx->requested))
02329 return -EPERM;
02330
02331 if (copy_from_user(&data, (void __user *) arg, sizeof(data)))
02332 return -EFAULT;
02333
02334 if (down_interruptible(&master->master_sem))
02335 return -EINTR;
02336
02337 if (!(sc = ec_master_get_config(master, data.config_index))) {
02338 up(&master->master_sem);
02339 return -ENOENT;
02340 }
02341
02342 if (!(domain = ec_master_find_domain(master, data.domain_index))) {
02343 up(&master->master_sem);
02344 return -ENOENT;
02345 }
02346
02347 up(&master->master_sem);
02349 ret = ecrt_slave_config_reg_pdo_entry(sc, data.entry_index,
02350 data.entry_subindex, domain, &data.bit_position);
02351
02352 if (copy_to_user((void __user *) arg, &data, sizeof(data)))
02353 return -EFAULT;
02354
02355 return ret;
02356 }
02357
02358
02359
02364 static ATTRIBUTES int ec_ioctl_sc_reg_pdo_pos(
02365 ec_master_t *master,
02366 void *arg,
02367 ec_ioctl_context_t *ctx
02368 )
02369 {
02370 ec_ioctl_reg_pdo_pos_t io;
02371 ec_slave_config_t *sc;
02372 ec_domain_t *domain;
02373 int ret;
02374
02375 if (unlikely(!ctx->requested)) {
02376 return -EPERM;
02377 }
02378
02379 if (copy_from_user(&io, (void __user *) arg, sizeof(io))) {
02380 return -EFAULT;
02381 }
02382
02383 if (down_interruptible(&master->master_sem)) {
02384 return -EINTR;
02385 }
02386
02387 if (!(sc = ec_master_get_config(master, io.config_index))) {
02388 up(&master->master_sem);
02389 return -ENOENT;
02390 }
02391
02392 if (!(domain = ec_master_find_domain(master, io.domain_index))) {
02393 up(&master->master_sem);
02394 return -ENOENT;
02395 }
02396
02397 up(&master->master_sem);
02399 ret = ecrt_slave_config_reg_pdo_entry_pos(sc, io.sync_index,
02400 io.pdo_pos, io.entry_pos, domain, &io.bit_position);
02401
02402 if (copy_to_user((void __user *) arg, &io, sizeof(io)))
02403 return -EFAULT;
02404
02405 return ret;
02406 }
02407
02408
02409
02414 static ATTRIBUTES int ec_ioctl_sc_dc(
02415 ec_master_t *master,
02416 void *arg,
02417 ec_ioctl_context_t *ctx
02418 )
02419 {
02420 ec_ioctl_config_t data;
02421 ec_slave_config_t *sc;
02422
02423 if (unlikely(!ctx->requested))
02424 return -EPERM;
02425
02426 if (copy_from_user(&data, (void __user *) arg, sizeof(data)))
02427 return -EFAULT;
02428
02429 if (down_interruptible(&master->master_sem))
02430 return -EINTR;
02431
02432 if (!(sc = ec_master_get_config(master, data.config_index))) {
02433 up(&master->master_sem);
02434 return -ENOENT;
02435 }
02436
02437 ecrt_slave_config_dc(sc, data.dc_assign_activate,
02438 data.dc_sync[0].cycle_time,
02439 data.dc_sync[0].shift_time,
02440 data.dc_sync[1].cycle_time,
02441 data.dc_sync[1].shift_time);
02442
02443 up(&master->master_sem);
02444
02445 return 0;
02446 }
02447
02448
02449
02454 static ATTRIBUTES int ec_ioctl_sc_sdo(
02455 ec_master_t *master,
02456 void *arg,
02457 ec_ioctl_context_t *ctx
02458 )
02459 {
02460 ec_ioctl_sc_sdo_t data;
02461 ec_slave_config_t *sc;
02462 uint8_t *sdo_data = NULL;
02463 int ret;
02464
02465 if (unlikely(!ctx->requested))
02466 return -EPERM;
02467
02468 if (copy_from_user(&data, (void __user *) arg, sizeof(data)))
02469 return -EFAULT;
02470
02471 if (!data.size)
02472 return -EINVAL;
02473
02474 if (!(sdo_data = kmalloc(data.size, GFP_KERNEL))) {
02475 return -ENOMEM;
02476 }
02477
02478 if (copy_from_user(sdo_data, (void __user *) data.data, data.size)) {
02479 kfree(sdo_data);
02480 return -EFAULT;
02481 }
02482
02483 if (down_interruptible(&master->master_sem)) {
02484 kfree(sdo_data);
02485 return -EINTR;
02486 }
02487
02488 if (!(sc = ec_master_get_config(master, data.config_index))) {
02489 up(&master->master_sem);
02490 kfree(sdo_data);
02491 return -ENOENT;
02492 }
02493
02494 up(&master->master_sem);
02496 if (data.complete_access) {
02497 ret = ecrt_slave_config_complete_sdo(sc,
02498 data.index, sdo_data, data.size);
02499 } else {
02500 ret = ecrt_slave_config_sdo(sc, data.index, data.subindex, sdo_data,
02501 data.size);
02502 }
02503 kfree(sdo_data);
02504 return ret;
02505 }
02506
02507
02508
02513 static ATTRIBUTES int ec_ioctl_sc_emerg_size(
02514 ec_master_t *master,
02515 void *arg,
02516 ec_ioctl_context_t *ctx
02517 )
02518 {
02519 ec_ioctl_sc_emerg_t io;
02520 ec_slave_config_t *sc;
02521 int ret;
02522
02523 if (unlikely(!ctx->requested))
02524 return -EPERM;
02525
02526 if (copy_from_user(&io, (void __user *) arg, sizeof(io)))
02527 return -EFAULT;
02528
02529 if (down_interruptible(&master->master_sem)) {
02530 return -EINTR;
02531 }
02532
02533 if (!(sc = ec_master_get_config(master, io.config_index))) {
02534 up(&master->master_sem);
02535 return -ENOENT;
02536 }
02537
02538 ret = ecrt_slave_config_emerg_size(sc, io.size);
02539
02540 up(&master->master_sem);
02541
02542 return ret;
02543 }
02544
02545
02546
02551 static ATTRIBUTES int ec_ioctl_sc_emerg_pop(
02552 ec_master_t *master,
02553 void *arg,
02554 ec_ioctl_context_t *ctx
02555 )
02556 {
02557 ec_ioctl_sc_emerg_t io;
02558 ec_slave_config_t *sc;
02559 u8 msg[EC_COE_EMERGENCY_MSG_SIZE];
02560 int ret;
02561
02562 if (unlikely(!ctx->requested)) {
02563 return -EPERM;
02564 }
02565
02566 if (copy_from_user(&io, (void __user *) arg, sizeof(io))) {
02567 return -EFAULT;
02568 }
02569
02570
02571
02572
02573 if (!(sc = ec_master_get_config(master, io.config_index))) {
02574 return -ENOENT;
02575 }
02576
02577 ret = ecrt_slave_config_emerg_pop(sc, msg);
02578 if (ret < 0) {
02579 return ret;
02580 }
02581
02582 if (copy_to_user((void __user *) io.target, msg, sizeof(msg))) {
02583 return -EFAULT;
02584 }
02585
02586 return ret;
02587 }
02588
02589
02590
02595 static ATTRIBUTES int ec_ioctl_sc_emerg_clear(
02596 ec_master_t *master,
02597 void *arg,
02598 ec_ioctl_context_t *ctx
02599 )
02600 {
02601 ec_ioctl_sc_emerg_t io;
02602 ec_slave_config_t *sc;
02603
02604 if (unlikely(!ctx->requested)) {
02605 return -EPERM;
02606 }
02607
02608 if (copy_from_user(&io, (void __user *) arg, sizeof(io))) {
02609 return -EFAULT;
02610 }
02611
02612
02613
02614
02615 if (!(sc = ec_master_get_config(master, io.config_index))) {
02616 return -ENOENT;
02617 }
02618
02619 return ecrt_slave_config_emerg_clear(sc);
02620 }
02621
02622
02623
02628 static ATTRIBUTES int ec_ioctl_sc_emerg_overruns(
02629 ec_master_t *master,
02630 void *arg,
02631 ec_ioctl_context_t *ctx
02632 )
02633 {
02634 ec_ioctl_sc_emerg_t io;
02635 ec_slave_config_t *sc;
02636 int ret;
02637
02638 if (unlikely(!ctx->requested)) {
02639 return -EPERM;
02640 }
02641
02642 if (copy_from_user(&io, (void __user *) arg, sizeof(io))) {
02643 return -EFAULT;
02644 }
02645
02646
02647
02648
02649 if (!(sc = ec_master_get_config(master, io.config_index))) {
02650 return -ENOENT;
02651 }
02652
02653 ret = ecrt_slave_config_emerg_overruns(sc);
02654 if (ret < 0) {
02655 return ret;
02656 }
02657
02658 io.overruns = ret;
02659
02660 if (copy_to_user((void __user *) arg, &io, sizeof(io))) {
02661 return -EFAULT;
02662 }
02663
02664 return 0;
02665 }
02666
02667
02668
02673 static ATTRIBUTES int ec_ioctl_sc_create_sdo_request(
02674 ec_master_t *master,
02675 void *arg,
02676 ec_ioctl_context_t *ctx
02677 )
02678 {
02679 ec_ioctl_sdo_request_t data;
02680 ec_slave_config_t *sc;
02681 ec_sdo_request_t *req;
02682
02683 if (unlikely(!ctx->requested))
02684 return -EPERM;
02685
02686 if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
02687 return -EFAULT;
02688 }
02689
02690 data.request_index = 0;
02691
02692 if (down_interruptible(&master->master_sem))
02693 return -EINTR;
02694
02695 sc = ec_master_get_config(master, data.config_index);
02696 if (!sc) {
02697 up(&master->master_sem);
02698 return -ENOENT;
02699 }
02700
02701 list_for_each_entry(req, &sc->sdo_requests, list) {
02702 data.request_index++;
02703 }
02704
02705 up(&master->master_sem);
02707 req = ecrt_slave_config_create_sdo_request_err(sc, data.sdo_index,
02708 data.sdo_subindex, data.size);
02709 if (IS_ERR(req))
02710 return PTR_ERR(req);
02711
02712 if (copy_to_user((void __user *) arg, &data, sizeof(data)))
02713 return -EFAULT;
02714
02715 return 0;
02716 }
02717
02718
02719
02724 static ATTRIBUTES int ec_ioctl_sc_create_reg_request(
02725 ec_master_t *master,
02726 void *arg,
02727 ec_ioctl_context_t *ctx
02728 )
02729 {
02730 ec_ioctl_reg_request_t io;
02731 ec_slave_config_t *sc;
02732 ec_reg_request_t *reg;
02733
02734 if (unlikely(!ctx->requested)) {
02735 return -EPERM;
02736 }
02737
02738 if (copy_from_user(&io, (void __user *) arg, sizeof(io))) {
02739 return -EFAULT;
02740 }
02741
02742 io.request_index = 0;
02743
02744 if (down_interruptible(&master->master_sem)) {
02745 return -EINTR;
02746 }
02747
02748 sc = ec_master_get_config(master, io.config_index);
02749 if (!sc) {
02750 up(&master->master_sem);
02751 return -ENOENT;
02752 }
02753
02754 list_for_each_entry(reg, &sc->reg_requests, list) {
02755 io.request_index++;
02756 }
02757
02758 up(&master->master_sem);
02760 reg = ecrt_slave_config_create_reg_request_err(sc, io.mem_size);
02761 if (IS_ERR(reg)) {
02762 return PTR_ERR(reg);
02763 }
02764
02765 if (copy_to_user((void __user *) arg, &io, sizeof(io))) {
02766 return -EFAULT;
02767 }
02768
02769 return 0;
02770 }
02771
02772
02773
02778 static ATTRIBUTES int ec_ioctl_sc_create_voe_handler(
02779 ec_master_t *master,
02780 void *arg,
02781 ec_ioctl_context_t *ctx
02782 )
02783 {
02784 ec_ioctl_voe_t data;
02785 ec_slave_config_t *sc;
02786 ec_voe_handler_t *voe;
02787
02788 if (unlikely(!ctx->requested))
02789 return -EPERM;
02790
02791 if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
02792 return -EFAULT;
02793 }
02794
02795 data.voe_index = 0;
02796
02797 if (down_interruptible(&master->master_sem))
02798 return -EINTR;
02799
02800 sc = ec_master_get_config(master, data.config_index);
02801 if (!sc) {
02802 up(&master->master_sem);
02803 return -ENOENT;
02804 }
02805
02806 list_for_each_entry(voe, &sc->voe_handlers, list) {
02807 data.voe_index++;
02808 }
02809
02810 up(&master->master_sem);
02812 voe = ecrt_slave_config_create_voe_handler_err(sc, data.size);
02813 if (IS_ERR(voe))
02814 return PTR_ERR(voe);
02815
02816 if (copy_to_user((void __user *) arg, &data, sizeof(data)))
02817 return -EFAULT;
02818
02819 return 0;
02820 }
02821
02822
02823
02828 static ATTRIBUTES int ec_ioctl_sc_state(
02829 ec_master_t *master,
02830 void *arg,
02831 ec_ioctl_context_t *ctx
02832 )
02833 {
02834 ec_ioctl_sc_state_t data;
02835 const ec_slave_config_t *sc;
02836 ec_slave_config_state_t state;
02837
02838 if (unlikely(!ctx->requested))
02839 return -EPERM;
02840
02841 if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
02842 return -EFAULT;
02843 }
02844
02845
02846
02847
02848 if (!(sc = ec_master_get_config_const(master, data.config_index))) {
02849 return -ENOENT;
02850 }
02851
02852 ecrt_slave_config_state(sc, &state);
02853
02854 if (copy_to_user((void __user *) data.state, &state, sizeof(state)))
02855 return -EFAULT;
02856
02857 return 0;
02858 }
02859
02860
02861
02866 static ATTRIBUTES int ec_ioctl_sc_idn(
02867 ec_master_t *master,
02868 void *arg,
02869 ec_ioctl_context_t *ctx
02870 )
02871 {
02872 ec_ioctl_sc_idn_t ioctl;
02873 ec_slave_config_t *sc;
02874 uint8_t *data = NULL;
02875 int ret;
02876
02877 if (unlikely(!ctx->requested))
02878 return -EPERM;
02879
02880 if (copy_from_user(&ioctl, (void __user *) arg, sizeof(ioctl)))
02881 return -EFAULT;
02882
02883 if (!ioctl.size)
02884 return -EINVAL;
02885
02886 if (!(data = kmalloc(ioctl.size, GFP_KERNEL))) {
02887 return -ENOMEM;
02888 }
02889
02890 if (copy_from_user(data, (void __user *) ioctl.data, ioctl.size)) {
02891 kfree(data);
02892 return -EFAULT;
02893 }
02894
02895 if (down_interruptible(&master->master_sem)) {
02896 kfree(data);
02897 return -EINTR;
02898 }
02899
02900 if (!(sc = ec_master_get_config(master, ioctl.config_index))) {
02901 up(&master->master_sem);
02902 kfree(data);
02903 return -ENOENT;
02904 }
02905
02906 up(&master->master_sem);
02908 ret = ecrt_slave_config_idn(
02909 sc, ioctl.drive_no, ioctl.idn, ioctl.al_state, data, ioctl.size);
02910 kfree(data);
02911 return ret;
02912 }
02913
02914
02915
02920 static ATTRIBUTES int ec_ioctl_domain_size(
02921 ec_master_t *master,
02922 void *arg,
02923 ec_ioctl_context_t *ctx
02924 )
02925 {
02926 const ec_domain_t *domain;
02927
02928 if (unlikely(!ctx->requested)) {
02929 return -EPERM;
02930 }
02931
02932 if (down_interruptible(&master->master_sem)) {
02933 return -EINTR;
02934 }
02935
02936 list_for_each_entry(domain, &master->domains, list) {
02937 if (domain->index == (unsigned long) arg) {
02938 size_t size = ecrt_domain_size(domain);
02939 up(&master->master_sem);
02940 return size;
02941 }
02942 }
02943
02944 up(&master->master_sem);
02945 return -ENOENT;
02946 }
02947
02948
02949
02954 static ATTRIBUTES int ec_ioctl_domain_offset(
02955 ec_master_t *master,
02956 void *arg,
02957 ec_ioctl_context_t *ctx
02958 )
02959 {
02960 int offset = 0;
02961 const ec_domain_t *domain;
02962
02963 if (unlikely(!ctx->requested))
02964 return -EPERM;
02965
02966 if (down_interruptible(&master->master_sem)) {
02967 return -EINTR;
02968 }
02969
02970 list_for_each_entry(domain, &master->domains, list) {
02971 if (domain->index == (unsigned long) arg) {
02972 up(&master->master_sem);
02973 return offset;
02974 }
02975 offset += ecrt_domain_size(domain);
02976 }
02977
02978 up(&master->master_sem);
02979 return -ENOENT;
02980 }
02981
02982
02983
02988 static ATTRIBUTES int ec_ioctl_domain_process(
02989 ec_master_t *master,
02990 void *arg,
02991 ec_ioctl_context_t *ctx
02992 )
02993 {
02994 ec_domain_t *domain;
02995
02996 if (unlikely(!ctx->requested))
02997 return -EPERM;
02998
02999
03000
03001
03002 if (!(domain = ec_master_find_domain(master, (unsigned long) arg))) {
03003 return -ENOENT;
03004 }
03005
03006 ecrt_domain_process(domain);
03007 return 0;
03008 }
03009
03010
03011
03016 static ATTRIBUTES int ec_ioctl_domain_queue(
03017 ec_master_t *master,
03018 void *arg,
03019 ec_ioctl_context_t *ctx
03020 )
03021 {
03022 ec_domain_t *domain;
03023
03024 if (unlikely(!ctx->requested))
03025 return -EPERM;
03026
03027
03028
03029
03030 if (!(domain = ec_master_find_domain(master, (unsigned long) arg))) {
03031 return -ENOENT;
03032 }
03033
03034 ecrt_domain_queue(domain);
03035 return 0;
03036 }
03037
03038
03039
03044 static ATTRIBUTES int ec_ioctl_domain_state(
03045 ec_master_t *master,
03046 void *arg,
03047 ec_ioctl_context_t *ctx
03048 )
03049 {
03050 ec_ioctl_domain_state_t data;
03051 const ec_domain_t *domain;
03052 ec_domain_state_t state;
03053
03054 if (unlikely(!ctx->requested))
03055 return -EPERM;
03056
03057 if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
03058 return -EFAULT;
03059 }
03060
03061
03062
03063
03064 if (!(domain = ec_master_find_domain_const(master, data.domain_index))) {
03065 return -ENOENT;
03066 }
03067
03068 ecrt_domain_state(domain, &state);
03069
03070 if (copy_to_user((void __user *) data.state, &state, sizeof(state)))
03071 return -EFAULT;
03072
03073 return 0;
03074 }
03075
03076
03077
03082 static ATTRIBUTES int ec_ioctl_sdo_request_index(
03083 ec_master_t *master,
03084 void *arg,
03085 ec_ioctl_context_t *ctx
03086 )
03087 {
03088 ec_ioctl_sdo_request_t data;
03089 ec_slave_config_t *sc;
03090 ec_sdo_request_t *req;
03091
03092 if (unlikely(!ctx->requested))
03093 return -EPERM;
03094
03095 if (copy_from_user(&data, (void __user *) arg, sizeof(data)))
03096 return -EFAULT;
03097
03098
03099
03100
03101 if (!(sc = ec_master_get_config(master, data.config_index))) {
03102 return -ENOENT;
03103 }
03104
03105 if (!(req = ec_slave_config_find_sdo_request(sc, data.request_index))) {
03106 return -ENOENT;
03107 }
03108
03109 ecrt_sdo_request_index(req, data.sdo_index, data.sdo_subindex);
03110 return 0;
03111 }
03112
03113
03114
03119 static ATTRIBUTES int ec_ioctl_sdo_request_timeout(
03120 ec_master_t *master,
03121 void *arg,
03122 ec_ioctl_context_t *ctx
03123 )
03124 {
03125 ec_ioctl_sdo_request_t data;
03126 ec_slave_config_t *sc;
03127 ec_sdo_request_t *req;
03128
03129 if (unlikely(!ctx->requested))
03130 return -EPERM;
03131
03132 if (copy_from_user(&data, (void __user *) arg, sizeof(data)))
03133 return -EFAULT;
03134
03135
03136
03137
03138 if (!(sc = ec_master_get_config(master, data.config_index))) {
03139 return -ENOENT;
03140 }
03141
03142 if (!(req = ec_slave_config_find_sdo_request(sc, data.request_index))) {
03143 return -ENOENT;
03144 }
03145
03146 ecrt_sdo_request_timeout(req, data.timeout);
03147 return 0;
03148 }
03149
03150
03151
03156 static ATTRIBUTES int ec_ioctl_sdo_request_state(
03157 ec_master_t *master,
03158 void *arg,
03159 ec_ioctl_context_t *ctx
03160 )
03161 {
03162 ec_ioctl_sdo_request_t data;
03163 ec_slave_config_t *sc;
03164 ec_sdo_request_t *req;
03165
03166 if (unlikely(!ctx->requested))
03167 return -EPERM;
03168
03169 if (copy_from_user(&data, (void __user *) arg, sizeof(data)))
03170 return -EFAULT;
03171
03172
03173
03174
03175 if (!(sc = ec_master_get_config(master, data.config_index))) {
03176 return -ENOENT;
03177 }
03178
03179 if (!(req = ec_slave_config_find_sdo_request(sc, data.request_index))) {
03180 return -ENOENT;
03181 }
03182
03183 data.state = ecrt_sdo_request_state(req);
03184 if (data.state == EC_REQUEST_SUCCESS && req->dir == EC_DIR_INPUT)
03185 data.size = ecrt_sdo_request_data_size(req);
03186 else
03187 data.size = 0;
03188
03189 if (copy_to_user((void __user *) arg, &data, sizeof(data)))
03190 return -EFAULT;
03191
03192 return 0;
03193 }
03194
03195
03196
03201 static ATTRIBUTES int ec_ioctl_sdo_request_read(
03202 ec_master_t *master,
03203 void *arg,
03204 ec_ioctl_context_t *ctx
03205 )
03206 {
03207 ec_ioctl_sdo_request_t data;
03208 ec_slave_config_t *sc;
03209 ec_sdo_request_t *req;
03210
03211 if (unlikely(!ctx->requested))
03212 return -EPERM;
03213
03214 if (copy_from_user(&data, (void __user *) arg, sizeof(data)))
03215 return -EFAULT;
03216
03217
03218
03219
03220 if (!(sc = ec_master_get_config(master, data.config_index))) {
03221 return -ENOENT;
03222 }
03223
03224 if (!(req = ec_slave_config_find_sdo_request(sc, data.request_index))) {
03225 return -ENOENT;
03226 }
03227
03228 ecrt_sdo_request_read(req);
03229 return 0;
03230 }
03231
03232
03233
03238 static ATTRIBUTES int ec_ioctl_sdo_request_write(
03239 ec_master_t *master,
03240 void *arg,
03241 ec_ioctl_context_t *ctx
03242 )
03243 {
03244 ec_ioctl_sdo_request_t data;
03245 ec_slave_config_t *sc;
03246 ec_sdo_request_t *req;
03247 int ret;
03248
03249 if (unlikely(!ctx->requested))
03250 return -EPERM;
03251
03252 if (copy_from_user(&data, (void __user *) arg, sizeof(data)))
03253 return -EFAULT;
03254
03255 if (!data.size) {
03256 EC_MASTER_ERR(master, "SDO download: Data size may not be zero!\n");
03257 return -EINVAL;
03258 }
03259
03260
03261
03262
03263 if (!(sc = ec_master_get_config(master, data.config_index))) {
03264 return -ENOENT;
03265 }
03266
03267 if (!(req = ec_slave_config_find_sdo_request(sc, data.request_index))) {
03268 return -ENOENT;
03269 }
03270
03271 ret = ec_sdo_request_alloc(req, data.size);
03272 if (ret)
03273 return ret;
03274
03275 if (copy_from_user(req->data, (void __user *) data.data, data.size))
03276 return -EFAULT;
03277
03278 req->data_size = data.size;
03279 ecrt_sdo_request_write(req);
03280 return 0;
03281 }
03282
03283
03284
03289 static ATTRIBUTES int ec_ioctl_sdo_request_data(
03290 ec_master_t *master,
03291 void *arg,
03292 ec_ioctl_context_t *ctx
03293 )
03294 {
03295 ec_ioctl_sdo_request_t data;
03296 ec_slave_config_t *sc;
03297 ec_sdo_request_t *req;
03298
03299 if (unlikely(!ctx->requested))
03300 return -EPERM;
03301
03302 if (copy_from_user(&data, (void __user *) arg, sizeof(data)))
03303 return -EFAULT;
03304
03305
03306
03307
03308 if (!(sc = ec_master_get_config(master, data.config_index))) {
03309 return -ENOENT;
03310 }
03311
03312 if (!(req = ec_slave_config_find_sdo_request(sc, data.request_index))) {
03313 return -ENOENT;
03314 }
03315
03316 if (copy_to_user((void __user *) data.data, ecrt_sdo_request_data(req),
03317 ecrt_sdo_request_data_size(req)))
03318 return -EFAULT;
03319
03320 return 0;
03321 }
03322
03323
03324
03329 static ATTRIBUTES int ec_ioctl_reg_request_data(
03330 ec_master_t *master,
03331 void *arg,
03332 ec_ioctl_context_t *ctx
03333 )
03334 {
03335 ec_ioctl_reg_request_t io;
03336 ec_slave_config_t *sc;
03337 ec_reg_request_t *reg;
03338
03339 if (unlikely(!ctx->requested)) {
03340 return -EPERM;
03341 }
03342
03343 if (copy_from_user(&io, (void __user *) arg, sizeof(io))) {
03344 return -EFAULT;
03345 }
03346
03347 if (io.mem_size <= 0) {
03348 return 0;
03349 }
03350
03351
03352
03353
03354 if (!(sc = ec_master_get_config(master, io.config_index))) {
03355 return -ENOENT;
03356 }
03357
03358 if (!(reg = ec_slave_config_find_reg_request(sc, io.request_index))) {
03359 return -ENOENT;
03360 }
03361
03362 if (copy_to_user((void __user *) io.data, ecrt_reg_request_data(reg),
03363 min(reg->mem_size, io.mem_size))) {
03364 return -EFAULT;
03365 }
03366
03367 return 0;
03368 }
03369
03370
03371
03376 static ATTRIBUTES int ec_ioctl_reg_request_state(
03377 ec_master_t *master,
03378 void *arg,
03379 ec_ioctl_context_t *ctx
03380 )
03381 {
03382 ec_ioctl_reg_request_t io;
03383 ec_slave_config_t *sc;
03384 ec_reg_request_t *reg;
03385
03386 if (unlikely(!ctx->requested)) {
03387 return -EPERM;
03388 }
03389
03390 if (copy_from_user(&io, (void __user *) arg, sizeof(io))) {
03391 return -EFAULT;
03392 }
03393
03394
03395
03396
03397 if (!(sc = ec_master_get_config(master, io.config_index))) {
03398 return -ENOENT;
03399 }
03400
03401 if (!(reg = ec_slave_config_find_reg_request(sc, io.request_index))) {
03402 return -ENOENT;
03403 }
03404
03405 io.state = ecrt_reg_request_state(reg);
03406 io.new_data = io.state == EC_REQUEST_SUCCESS && reg->dir == EC_DIR_INPUT;
03407
03408 if (copy_to_user((void __user *) arg, &io, sizeof(io))) {
03409 return -EFAULT;
03410 }
03411
03412 return 0;
03413 }
03414
03415
03416
03421 static ATTRIBUTES int ec_ioctl_reg_request_write(
03422 ec_master_t *master,
03423 void *arg,
03424 ec_ioctl_context_t *ctx
03425 )
03426 {
03427 ec_ioctl_reg_request_t io;
03428 ec_slave_config_t *sc;
03429 ec_reg_request_t *reg;
03430
03431 if (unlikely(!ctx->requested)) {
03432 return -EPERM;
03433 }
03434
03435 if (copy_from_user(&io, (void __user *) arg, sizeof(io))) {
03436 return -EFAULT;
03437 }
03438
03439
03440
03441
03442 if (!(sc = ec_master_get_config(master, io.config_index))) {
03443 return -ENOENT;
03444 }
03445
03446 if (!(reg = ec_slave_config_find_reg_request(sc, io.request_index))) {
03447 return -ENOENT;
03448 }
03449
03450 if (io.transfer_size > reg->mem_size) {
03451 return -EOVERFLOW;
03452 }
03453
03454 if (copy_from_user(reg->data, (void __user *) io.data,
03455 io.transfer_size)) {
03456 return -EFAULT;
03457 }
03458
03459 ecrt_reg_request_write(reg, io.address, io.transfer_size);
03460 return 0;
03461 }
03462
03463
03464
03469 static ATTRIBUTES int ec_ioctl_reg_request_read(
03470 ec_master_t *master,
03471 void *arg,
03472 ec_ioctl_context_t *ctx
03473 )
03474 {
03475 ec_ioctl_reg_request_t io;
03476 ec_slave_config_t *sc;
03477 ec_reg_request_t *reg;
03478
03479 if (unlikely(!ctx->requested)) {
03480 return -EPERM;
03481 }
03482
03483 if (copy_from_user(&io, (void __user *) arg, sizeof(io))) {
03484 return -EFAULT;
03485 }
03486
03487
03488
03489
03490 if (!(sc = ec_master_get_config(master, io.config_index))) {
03491 return -ENOENT;
03492 }
03493
03494 if (!(reg = ec_slave_config_find_reg_request(sc, io.request_index))) {
03495 return -ENOENT;
03496 }
03497
03498 if (io.transfer_size > reg->mem_size) {
03499 return -EOVERFLOW;
03500 }
03501
03502 ecrt_reg_request_read(reg, io.address, io.transfer_size);
03503 return 0;
03504 }
03505
03506
03507
03512 static ATTRIBUTES int ec_ioctl_voe_send_header(
03513 ec_master_t *master,
03514 void *arg,
03515 ec_ioctl_context_t *ctx
03516 )
03517 {
03518 ec_ioctl_voe_t data;
03519 ec_slave_config_t *sc;
03520 ec_voe_handler_t *voe;
03521 uint32_t vendor_id;
03522 uint16_t vendor_type;
03523
03524 if (unlikely(!ctx->requested))
03525 return -EPERM;
03526
03527 if (copy_from_user(&data, (void __user *) arg, sizeof(data)))
03528 return -EFAULT;
03529
03530 if (get_user(vendor_id, data.vendor_id))
03531 return -EFAULT;
03532
03533 if (get_user(vendor_type, data.vendor_type))
03534 return -EFAULT;
03535
03536
03537
03538
03539 if (!(sc = ec_master_get_config(master, data.config_index))) {
03540 return -ENOENT;
03541 }
03542
03543 if (!(voe = ec_slave_config_find_voe_handler(sc, data.voe_index))) {
03544 return -ENOENT;
03545 }
03546
03547 ecrt_voe_handler_send_header(voe, vendor_id, vendor_type);
03548 return 0;
03549 }
03550
03551
03552
03557 static ATTRIBUTES int ec_ioctl_voe_rec_header(
03558 ec_master_t *master,
03559 void *arg,
03560 ec_ioctl_context_t *ctx
03561 )
03562 {
03563 ec_ioctl_voe_t data;
03564 ec_slave_config_t *sc;
03565 ec_voe_handler_t *voe;
03566 uint32_t vendor_id;
03567 uint16_t vendor_type;
03568
03569 if (unlikely(!ctx->requested))
03570 return -EPERM;
03571
03572 if (copy_from_user(&data, (void __user *) arg, sizeof(data)))
03573 return -EFAULT;
03574
03575
03576
03577
03578 if (!(sc = ec_master_get_config(master, data.config_index))) {
03579 return -ENOENT;
03580 }
03581
03582 if (!(voe = ec_slave_config_find_voe_handler(sc, data.voe_index))) {
03583 return -ENOENT;
03584 }
03585
03586 ecrt_voe_handler_received_header(voe, &vendor_id, &vendor_type);
03587
03588 if (likely(data.vendor_id))
03589 if (put_user(vendor_id, data.vendor_id))
03590 return -EFAULT;
03591
03592 if (likely(data.vendor_type))
03593 if (put_user(vendor_type, data.vendor_type))
03594 return -EFAULT;
03595
03596 return 0;
03597 }
03598
03599
03600
03605 static ATTRIBUTES int ec_ioctl_voe_read(
03606 ec_master_t *master,
03607 void *arg,
03608 ec_ioctl_context_t *ctx
03609 )
03610 {
03611 ec_ioctl_voe_t data;
03612 ec_slave_config_t *sc;
03613 ec_voe_handler_t *voe;
03614
03615 if (unlikely(!ctx->requested))
03616 return -EPERM;
03617
03618 if (copy_from_user(&data, (void __user *) arg, sizeof(data)))
03619 return -EFAULT;
03620
03621
03622
03623
03624 if (!(sc = ec_master_get_config(master, data.config_index))) {
03625 return -ENOENT;
03626 }
03627
03628 if (!(voe = ec_slave_config_find_voe_handler(sc, data.voe_index))) {
03629 return -ENOENT;
03630 }
03631
03632 ecrt_voe_handler_read(voe);
03633 return 0;
03634 }
03635
03636
03637
03642 static ATTRIBUTES int ec_ioctl_voe_read_nosync(
03643 ec_master_t *master,
03644 void *arg,
03645 ec_ioctl_context_t *ctx
03646 )
03647 {
03648 ec_ioctl_voe_t data;
03649 ec_slave_config_t *sc;
03650 ec_voe_handler_t *voe;
03651
03652 if (unlikely(!ctx->requested))
03653 return -EPERM;
03654
03655 if (copy_from_user(&data, (void __user *) arg, sizeof(data)))
03656 return -EFAULT;
03657
03658
03659
03660
03661 if (!(sc = ec_master_get_config(master, data.config_index))) {
03662 return -ENOENT;
03663 }
03664
03665 if (!(voe = ec_slave_config_find_voe_handler(sc, data.voe_index))) {
03666 return -ENOENT;
03667 }
03668
03669 ecrt_voe_handler_read_nosync(voe);
03670 return 0;
03671 }
03672
03673
03674
03679 static ATTRIBUTES int ec_ioctl_voe_write(
03680 ec_master_t *master,
03681 void *arg,
03682 ec_ioctl_context_t *ctx
03683 )
03684 {
03685 ec_ioctl_voe_t data;
03686 ec_slave_config_t *sc;
03687 ec_voe_handler_t *voe;
03688
03689 if (unlikely(!ctx->requested))
03690 return -EPERM;
03691
03692 if (copy_from_user(&data, (void __user *) arg, sizeof(data)))
03693 return -EFAULT;
03694
03695
03696
03697
03698 if (!(sc = ec_master_get_config(master, data.config_index))) {
03699 return -ENOENT;
03700 }
03701
03702 if (!(voe = ec_slave_config_find_voe_handler(sc, data.voe_index))) {
03703 return -ENOENT;
03704 }
03705
03706 if (data.size) {
03707 if (data.size > ec_voe_handler_mem_size(voe))
03708 return -EOVERFLOW;
03709
03710 if (copy_from_user(ecrt_voe_handler_data(voe),
03711 (void __user *) data.data, data.size))
03712 return -EFAULT;
03713 }
03714
03715 ecrt_voe_handler_write(voe, data.size);
03716 return 0;
03717 }
03718
03719
03720
03725 static ATTRIBUTES int ec_ioctl_voe_exec(
03726 ec_master_t *master,
03727 void *arg,
03728 ec_ioctl_context_t *ctx
03729 )
03730 {
03731 ec_ioctl_voe_t data;
03732 ec_slave_config_t *sc;
03733 ec_voe_handler_t *voe;
03734
03735 if (unlikely(!ctx->requested))
03736 return -EPERM;
03737
03738 if (copy_from_user(&data, (void __user *) arg, sizeof(data)))
03739 return -EFAULT;
03740
03741
03742
03743
03744 if (!(sc = ec_master_get_config(master, data.config_index))) {
03745 return -ENOENT;
03746 }
03747
03748 if (!(voe = ec_slave_config_find_voe_handler(sc, data.voe_index))) {
03749 return -ENOENT;
03750 }
03751
03752 data.state = ecrt_voe_handler_execute(voe);
03753 if (data.state == EC_REQUEST_SUCCESS && voe->dir == EC_DIR_INPUT)
03754 data.size = ecrt_voe_handler_data_size(voe);
03755 else
03756 data.size = 0;
03757
03758 if (copy_to_user((void __user *) arg, &data, sizeof(data)))
03759 return -EFAULT;
03760
03761 return 0;
03762 }
03763
03764
03765
03770 static ATTRIBUTES int ec_ioctl_voe_data(
03771 ec_master_t *master,
03772 void *arg,
03773 ec_ioctl_context_t *ctx
03774 )
03775 {
03776 ec_ioctl_voe_t data;
03777 ec_slave_config_t *sc;
03778 ec_voe_handler_t *voe;
03779
03780 if (unlikely(!ctx->requested))
03781 return -EPERM;
03782
03783 if (copy_from_user(&data, (void __user *) arg, sizeof(data)))
03784 return -EFAULT;
03785
03786
03787
03788
03789 if (!(sc = ec_master_get_config(master, data.config_index))) {
03790 return -ENOENT;
03791 }
03792
03793 if (!(voe = ec_slave_config_find_voe_handler(sc, data.voe_index))) {
03794 return -ENOENT;
03795 }
03796
03797 if (copy_to_user((void __user *) data.data, ecrt_voe_handler_data(voe),
03798 ecrt_voe_handler_data_size(voe)))
03799 return -EFAULT;
03800
03801 return 0;
03802 }
03803
03804
03805
03810 static ATTRIBUTES int ec_ioctl_slave_foe_read(
03811 ec_master_t *master,
03812 void *arg
03813 )
03814 {
03815 ec_ioctl_slave_foe_t io;
03816 ec_foe_request_t request;
03817 ec_slave_t *slave;
03818 int ret;
03819
03820 if (copy_from_user(&io, (void __user *) arg, sizeof(io))) {
03821 return -EFAULT;
03822 }
03823
03824 ec_foe_request_init(&request, io.file_name);
03825 ret = ec_foe_request_alloc(&request, 10000);
03826 if (ret) {
03827 ec_foe_request_clear(&request);
03828 return ret;
03829 }
03830
03831 ec_foe_request_read(&request);
03832
03833 if (down_interruptible(&master->master_sem)) {
03834 ec_foe_request_clear(&request);
03835 return -EINTR;
03836 }
03837
03838 if (!(slave = ec_master_find_slave(master, 0, io.slave_position))) {
03839 up(&master->master_sem);
03840 ec_foe_request_clear(&request);
03841 EC_MASTER_ERR(master, "Slave %u does not exist!\n",
03842 io.slave_position);
03843 return -EINVAL;
03844 }
03845
03846 EC_SLAVE_DBG(slave, 1, "Scheduling FoE read request.\n");
03847
03848
03849 list_add_tail(&request.list, &slave->foe_requests);
03850
03851 up(&master->master_sem);
03852
03853
03854 if (wait_event_interruptible(master->request_queue,
03855 request.state != EC_INT_REQUEST_QUEUED)) {
03856
03857 down(&master->master_sem);
03858 if (request.state == EC_INT_REQUEST_QUEUED) {
03859 list_del(&request.list);
03860 up(&master->master_sem);
03861 ec_foe_request_clear(&request);
03862 return -EINTR;
03863 }
03864
03865 up(&master->master_sem);
03866 }
03867
03868
03869 wait_event(master->request_queue, request.state != EC_INT_REQUEST_BUSY);
03870
03871 io.result = request.result;
03872 io.error_code = request.error_code;
03873
03874 if (request.state != EC_INT_REQUEST_SUCCESS) {
03875 io.data_size = 0;
03876 ret = -EIO;
03877 } else {
03878 if (request.data_size > io.buffer_size) {
03879 EC_MASTER_ERR(master, "Buffer too small.\n");
03880 ec_foe_request_clear(&request);
03881 return -EOVERFLOW;
03882 }
03883 io.data_size = request.data_size;
03884 if (copy_to_user((void __user *) io.buffer,
03885 request.buffer, io.data_size)) {
03886 ec_foe_request_clear(&request);
03887 return -EFAULT;
03888 }
03889 ret = 0;
03890 }
03891
03892 if (__copy_to_user((void __user *) arg, &io, sizeof(io))) {
03893 ret = -EFAULT;
03894 }
03895
03896 ec_foe_request_clear(&request);
03897 return ret;
03898 }
03899
03900
03901
03906 static ATTRIBUTES int ec_ioctl_slave_foe_write(
03907 ec_master_t *master,
03908 void *arg
03909 )
03910 {
03911 ec_ioctl_slave_foe_t io;
03912 ec_foe_request_t request;
03913 ec_slave_t *slave;
03914 int ret;
03915
03916 if (copy_from_user(&io, (void __user *) arg, sizeof(io))) {
03917 return -EFAULT;
03918 }
03919
03920 ec_foe_request_init(&request, io.file_name);
03921
03922 ret = ec_foe_request_alloc(&request, io.buffer_size);
03923 if (ret) {
03924 ec_foe_request_clear(&request);
03925 return ret;
03926 }
03927
03928 if (copy_from_user(request.buffer,
03929 (void __user *) io.buffer, io.buffer_size)) {
03930 ec_foe_request_clear(&request);
03931 return -EFAULT;
03932 }
03933
03934 request.data_size = io.buffer_size;
03935 ec_foe_request_write(&request);
03936
03937 if (down_interruptible(&master->master_sem)) {
03938 ec_foe_request_clear(&request);
03939 return -EINTR;
03940 }
03941
03942 if (!(slave = ec_master_find_slave(master, 0, io.slave_position))) {
03943 up(&master->master_sem);
03944 EC_MASTER_ERR(master, "Slave %u does not exist!\n",
03945 io.slave_position);
03946 ec_foe_request_clear(&request);
03947 return -EINVAL;
03948 }
03949
03950 EC_SLAVE_DBG(slave, 1, "Scheduling FoE write request.\n");
03951
03952
03953 list_add_tail(&request.list, &slave->foe_requests);
03954
03955 up(&master->master_sem);
03956
03957
03958 if (wait_event_interruptible(master->request_queue,
03959 request.state != EC_INT_REQUEST_QUEUED)) {
03960
03961 down(&master->master_sem);
03962 if (request.state == EC_INT_REQUEST_QUEUED) {
03963
03964 list_del(&request.list);
03965 up(&master->master_sem);
03966 ec_foe_request_clear(&request);
03967 return -EINTR;
03968 }
03969 up(&master->master_sem);
03970 }
03971
03972
03973 wait_event(master->request_queue, request.state != EC_INT_REQUEST_BUSY);
03974
03975 io.result = request.result;
03976 io.error_code = request.error_code;
03977
03978 ret = request.state == EC_INT_REQUEST_SUCCESS ? 0 : -EIO;
03979
03980 if (__copy_to_user((void __user *) arg, &io, sizeof(io))) {
03981 ret = -EFAULT;
03982 }
03983
03984 ec_foe_request_clear(&request);
03985 return ret;
03986 }
03987
03988
03989
03994 static ATTRIBUTES int ec_ioctl_slave_soe_read(
03995 ec_master_t *master,
03996 void *arg
03997 )
03998 {
03999 ec_ioctl_slave_soe_read_t ioctl;
04000 u8 *data;
04001 int retval;
04002
04003 if (copy_from_user(&ioctl, (void __user *) arg, sizeof(ioctl))) {
04004 return -EFAULT;
04005 }
04006
04007 data = kmalloc(ioctl.mem_size, GFP_KERNEL);
04008 if (!data) {
04009 EC_MASTER_ERR(master, "Failed to allocate %zu bytes of IDN data.\n",
04010 ioctl.mem_size);
04011 return -ENOMEM;
04012 }
04013
04014 retval = ecrt_master_read_idn(master, ioctl.slave_position,
04015 ioctl.drive_no, ioctl.idn, data, ioctl.mem_size, &ioctl.data_size,
04016 &ioctl.error_code);
04017 if (retval) {
04018 kfree(data);
04019 return retval;
04020 }
04021
04022 if (copy_to_user((void __user *) ioctl.data,
04023 data, ioctl.data_size)) {
04024 kfree(data);
04025 return -EFAULT;
04026 }
04027 kfree(data);
04028
04029 if (__copy_to_user((void __user *) arg, &ioctl, sizeof(ioctl))) {
04030 retval = -EFAULT;
04031 }
04032
04033 EC_MASTER_DBG(master, 1, "Finished SoE read request.\n");
04034 return retval;
04035 }
04036
04037
04038
04043 static ATTRIBUTES int ec_ioctl_slave_soe_write(
04044 ec_master_t *master,
04045 void *arg
04046 )
04047 {
04048 ec_ioctl_slave_soe_write_t ioctl;
04049 u8 *data;
04050 int retval;
04051
04052 if (copy_from_user(&ioctl, (void __user *) arg, sizeof(ioctl))) {
04053 return -EFAULT;
04054 }
04055
04056 data = kmalloc(ioctl.data_size, GFP_KERNEL);
04057 if (!data) {
04058 EC_MASTER_ERR(master, "Failed to allocate %zu bytes of IDN data.\n",
04059 ioctl.data_size);
04060 return -ENOMEM;
04061 }
04062 if (copy_from_user(data, (void __user *) ioctl.data, ioctl.data_size)) {
04063 kfree(data);
04064 return -EFAULT;
04065 }
04066
04067 retval = ecrt_master_write_idn(master, ioctl.slave_position,
04068 ioctl.drive_no, ioctl.idn, data, ioctl.data_size,
04069 &ioctl.error_code);
04070 kfree(data);
04071 if (retval) {
04072 return retval;
04073 }
04074
04075 if (__copy_to_user((void __user *) arg, &ioctl, sizeof(ioctl))) {
04076 retval = -EFAULT;
04077 }
04078
04079 EC_MASTER_DBG(master, 1, "Finished SoE write request.\n");
04080 return retval;
04081 }
04082
04083
04084
04087 #ifdef EC_IOCTL_RTDM
04088 #define EC_IOCTL ec_ioctl_rtdm
04089 #else
04090 #define EC_IOCTL ec_ioctl
04091 #endif
04092
04097 long EC_IOCTL(
04098 ec_master_t *master,
04099 ec_ioctl_context_t *ctx,
04100 unsigned int cmd,
04101 void *arg
04102 )
04103 {
04104 #if DEBUG_LATENCY
04105 cycles_t a = get_cycles(), b;
04106 unsigned int t;
04107 #endif
04108 int ret;
04109
04110 switch (cmd) {
04111 case EC_IOCTL_MODULE:
04112 ret = ec_ioctl_module(arg);
04113 break;
04114 case EC_IOCTL_MASTER:
04115 ret = ec_ioctl_master(master, arg);
04116 break;
04117 case EC_IOCTL_SLAVE:
04118 ret = ec_ioctl_slave(master, arg);
04119 break;
04120 case EC_IOCTL_SLAVE_SYNC:
04121 ret = ec_ioctl_slave_sync(master, arg);
04122 break;
04123 case EC_IOCTL_SLAVE_SYNC_PDO:
04124 ret = ec_ioctl_slave_sync_pdo(master, arg);
04125 break;
04126 case EC_IOCTL_SLAVE_SYNC_PDO_ENTRY:
04127 ret = ec_ioctl_slave_sync_pdo_entry(master, arg);
04128 break;
04129 case EC_IOCTL_DOMAIN:
04130 ret = ec_ioctl_domain(master, arg);
04131 break;
04132 case EC_IOCTL_DOMAIN_FMMU:
04133 ret = ec_ioctl_domain_fmmu(master, arg);
04134 break;
04135 case EC_IOCTL_DOMAIN_DATA:
04136 ret = ec_ioctl_domain_data(master, arg);
04137 break;
04138 case EC_IOCTL_MASTER_DEBUG:
04139 if (!ctx->writable) {
04140 ret = -EPERM;
04141 break;
04142 }
04143 ret = ec_ioctl_master_debug(master, arg);
04144 break;
04145 case EC_IOCTL_MASTER_RESCAN:
04146 if (!ctx->writable) {
04147 ret = -EPERM;
04148 break;
04149 }
04150 ret = ec_ioctl_master_rescan(master, arg);
04151 break;
04152 case EC_IOCTL_SLAVE_STATE:
04153 if (!ctx->writable) {
04154 ret = -EPERM;
04155 break;
04156 }
04157 ret = ec_ioctl_slave_state(master, arg);
04158 break;
04159 case EC_IOCTL_SLAVE_SDO:
04160 ret = ec_ioctl_slave_sdo(master, arg);
04161 break;
04162 case EC_IOCTL_SLAVE_SDO_ENTRY:
04163 ret = ec_ioctl_slave_sdo_entry(master, arg);
04164 break;
04165 case EC_IOCTL_SLAVE_SDO_UPLOAD:
04166 ret = ec_ioctl_slave_sdo_upload(master, arg);
04167 break;
04168 case EC_IOCTL_SLAVE_SDO_DOWNLOAD:
04169 if (!ctx->writable) {
04170 ret = -EPERM;
04171 break;
04172 }
04173 ret = ec_ioctl_slave_sdo_download(master, arg);
04174 break;
04175 case EC_IOCTL_SLAVE_SII_READ:
04176 ret = ec_ioctl_slave_sii_read(master, arg);
04177 break;
04178 case EC_IOCTL_SLAVE_SII_WRITE:
04179 if (!ctx->writable) {
04180 ret = -EPERM;
04181 break;
04182 }
04183 ret = ec_ioctl_slave_sii_write(master, arg);
04184 break;
04185 case EC_IOCTL_SLAVE_REG_READ:
04186 ret = ec_ioctl_slave_reg_read(master, arg);
04187 break;
04188 case EC_IOCTL_SLAVE_REG_WRITE:
04189 if (!ctx->writable) {
04190 ret = -EPERM;
04191 break;
04192 }
04193 ret = ec_ioctl_slave_reg_write(master, arg);
04194 break;
04195 case EC_IOCTL_SLAVE_FOE_READ:
04196 ret = ec_ioctl_slave_foe_read(master, arg);
04197 break;
04198 case EC_IOCTL_SLAVE_FOE_WRITE:
04199 if (!ctx->writable) {
04200 ret = -EPERM;
04201 break;
04202 }
04203 ret = ec_ioctl_slave_foe_write(master, arg);
04204 break;
04205 case EC_IOCTL_SLAVE_SOE_READ:
04206 ret = ec_ioctl_slave_soe_read(master, arg);
04207 break;
04208 case EC_IOCTL_SLAVE_SOE_WRITE:
04209 if (!ctx->writable) {
04210 ret = -EPERM;
04211 break;
04212 }
04213 ret = ec_ioctl_slave_soe_write(master, arg);
04214 break;
04215 case EC_IOCTL_CONFIG:
04216 ret = ec_ioctl_config(master, arg);
04217 break;
04218 case EC_IOCTL_CONFIG_PDO:
04219 ret = ec_ioctl_config_pdo(master, arg);
04220 break;
04221 case EC_IOCTL_CONFIG_PDO_ENTRY:
04222 ret = ec_ioctl_config_pdo_entry(master, arg);
04223 break;
04224 case EC_IOCTL_CONFIG_SDO:
04225 ret = ec_ioctl_config_sdo(master, arg);
04226 break;
04227 case EC_IOCTL_CONFIG_IDN:
04228 ret = ec_ioctl_config_idn(master, arg);
04229 break;
04230 #ifdef EC_EOE
04231 case EC_IOCTL_EOE_HANDLER:
04232 ret = ec_ioctl_eoe_handler(master, arg);
04233 break;
04234 #endif
04235 case EC_IOCTL_REQUEST:
04236 if (!ctx->writable) {
04237 ret = -EPERM;
04238 break;
04239 }
04240 ret = ec_ioctl_request(master, arg, ctx);
04241 break;
04242 case EC_IOCTL_CREATE_DOMAIN:
04243 if (!ctx->writable) {
04244 ret = -EPERM;
04245 break;
04246 }
04247 ret = ec_ioctl_create_domain(master, arg, ctx);
04248 break;
04249 case EC_IOCTL_CREATE_SLAVE_CONFIG:
04250 if (!ctx->writable) {
04251 ret = -EPERM;
04252 break;
04253 }
04254 ret = ec_ioctl_create_slave_config(master, arg, ctx);
04255 break;
04256 case EC_IOCTL_SELECT_REF_CLOCK:
04257 if (!ctx->writable) {
04258 ret = -EPERM;
04259 break;
04260 }
04261 ret = ec_ioctl_select_ref_clock(master, arg, ctx);
04262 break;
04263 case EC_IOCTL_ACTIVATE:
04264 if (!ctx->writable) {
04265 ret = -EPERM;
04266 break;
04267 }
04268 ret = ec_ioctl_activate(master, arg, ctx);
04269 break;
04270 case EC_IOCTL_DEACTIVATE:
04271 if (!ctx->writable) {
04272 ret = -EPERM;
04273 break;
04274 }
04275 ret = ec_ioctl_deactivate(master, arg, ctx);
04276 break;
04277 case EC_IOCTL_SEND:
04278 if (!ctx->writable) {
04279 ret = -EPERM;
04280 break;
04281 }
04282 ret = ec_ioctl_send(master, arg, ctx);
04283 break;
04284 case EC_IOCTL_RECEIVE:
04285 if (!ctx->writable) {
04286 ret = -EPERM;
04287 break;
04288 }
04289 ret = ec_ioctl_receive(master, arg, ctx);
04290 break;
04291 case EC_IOCTL_MASTER_STATE:
04292 ret = ec_ioctl_master_state(master, arg, ctx);
04293 break;
04294 case EC_IOCTL_MASTER_LINK_STATE:
04295 ret = ec_ioctl_master_link_state(master, arg, ctx);
04296 break;
04297 case EC_IOCTL_APP_TIME:
04298 if (!ctx->writable) {
04299 ret = -EPERM;
04300 break;
04301 }
04302 ret = ec_ioctl_app_time(master, arg, ctx);
04303 break;
04304 case EC_IOCTL_SYNC_REF:
04305 if (!ctx->writable) {
04306 ret = -EPERM;
04307 break;
04308 }
04309 ret = ec_ioctl_sync_ref(master, arg, ctx);
04310 break;
04311 case EC_IOCTL_SYNC_SLAVES:
04312 if (!ctx->writable) {
04313 ret = -EPERM;
04314 break;
04315 }
04316 ret = ec_ioctl_sync_slaves(master, arg, ctx);
04317 break;
04318 case EC_IOCTL_REF_CLOCK_TIME:
04319 if (!ctx->writable) {
04320 ret = -EPERM;
04321 break;
04322 }
04323 ret = ec_ioctl_ref_clock_time(master, arg, ctx);
04324 break;
04325 case EC_IOCTL_SYNC_MON_QUEUE:
04326 if (!ctx->writable) {
04327 ret = -EPERM;
04328 break;
04329 }
04330 ret = ec_ioctl_sync_mon_queue(master, arg, ctx);
04331 break;
04332 case EC_IOCTL_SYNC_MON_PROCESS:
04333 if (!ctx->writable) {
04334 ret = -EPERM;
04335 break;
04336 }
04337 ret = ec_ioctl_sync_mon_process(master, arg, ctx);
04338 break;
04339 case EC_IOCTL_RESET:
04340 if (!ctx->writable) {
04341 ret = -EPERM;
04342 break;
04343 }
04344 ret = ec_ioctl_reset(master, arg, ctx);
04345 break;
04346 case EC_IOCTL_SC_SYNC:
04347 if (!ctx->writable) {
04348 ret = -EPERM;
04349 break;
04350 }
04351 ret = ec_ioctl_sc_sync(master, arg, ctx);
04352 break;
04353 case EC_IOCTL_SC_WATCHDOG:
04354 if (!ctx->writable) {
04355 ret = -EPERM;
04356 break;
04357 }
04358 ret = ec_ioctl_sc_watchdog(master, arg, ctx);
04359 break;
04360 case EC_IOCTL_SC_ADD_PDO:
04361 if (!ctx->writable) {
04362 ret = -EPERM;
04363 break;
04364 }
04365 ret = ec_ioctl_sc_add_pdo(master, arg, ctx);
04366 break;
04367 case EC_IOCTL_SC_CLEAR_PDOS:
04368 if (!ctx->writable) {
04369 ret = -EPERM;
04370 break;
04371 }
04372 ret = ec_ioctl_sc_clear_pdos(master, arg, ctx);
04373 break;
04374 case EC_IOCTL_SC_ADD_ENTRY:
04375 if (!ctx->writable) {
04376 ret = -EPERM;
04377 break;
04378 }
04379 ret = ec_ioctl_sc_add_entry(master, arg, ctx);
04380 break;
04381 case EC_IOCTL_SC_CLEAR_ENTRIES:
04382 if (!ctx->writable) {
04383 ret = -EPERM;
04384 break;
04385 }
04386 ret = ec_ioctl_sc_clear_entries(master, arg, ctx);
04387 break;
04388 case EC_IOCTL_SC_REG_PDO_ENTRY:
04389 if (!ctx->writable) {
04390 ret = -EPERM;
04391 break;
04392 }
04393 ret = ec_ioctl_sc_reg_pdo_entry(master, arg, ctx);
04394 break;
04395 case EC_IOCTL_SC_REG_PDO_POS:
04396 if (!ctx->writable) {
04397 ret = -EPERM;
04398 break;
04399 }
04400 ret = ec_ioctl_sc_reg_pdo_pos(master, arg, ctx);
04401 break;
04402 case EC_IOCTL_SC_DC:
04403 if (!ctx->writable) {
04404 ret = -EPERM;
04405 break;
04406 }
04407 ret = ec_ioctl_sc_dc(master, arg, ctx);
04408 break;
04409 case EC_IOCTL_SC_SDO:
04410 if (!ctx->writable) {
04411 ret = -EPERM;
04412 break;
04413 }
04414 ret = ec_ioctl_sc_sdo(master, arg, ctx);
04415 break;
04416 case EC_IOCTL_SC_EMERG_SIZE:
04417 if (!ctx->writable) {
04418 ret = -EPERM;
04419 break;
04420 }
04421 ret = ec_ioctl_sc_emerg_size(master, arg, ctx);
04422 break;
04423 case EC_IOCTL_SC_EMERG_POP:
04424 if (!ctx->writable) {
04425 ret = -EPERM;
04426 break;
04427 }
04428 ret = ec_ioctl_sc_emerg_pop(master, arg, ctx);
04429 break;
04430 case EC_IOCTL_SC_EMERG_CLEAR:
04431 if (!ctx->writable) {
04432 ret = -EPERM;
04433 break;
04434 }
04435 ret = ec_ioctl_sc_emerg_clear(master, arg, ctx);
04436 break;
04437 case EC_IOCTL_SC_EMERG_OVERRUNS:
04438 ret = ec_ioctl_sc_emerg_overruns(master, arg, ctx);
04439 break;
04440 case EC_IOCTL_SC_SDO_REQUEST:
04441 if (!ctx->writable) {
04442 ret = -EPERM;
04443 break;
04444 }
04445 ret = ec_ioctl_sc_create_sdo_request(master, arg, ctx);
04446 break;
04447 case EC_IOCTL_SC_REG_REQUEST:
04448 if (!ctx->writable) {
04449 ret = -EPERM;
04450 break;
04451 }
04452 ret = ec_ioctl_sc_create_reg_request(master, arg, ctx);
04453 break;
04454 case EC_IOCTL_SC_VOE:
04455 if (!ctx->writable) {
04456 ret = -EPERM;
04457 break;
04458 }
04459 ret = ec_ioctl_sc_create_voe_handler(master, arg, ctx);
04460 break;
04461 case EC_IOCTL_SC_STATE:
04462 ret = ec_ioctl_sc_state(master, arg, ctx);
04463 break;
04464 case EC_IOCTL_SC_IDN:
04465 if (!ctx->writable) {
04466 ret = -EPERM;
04467 break;
04468 }
04469 ret = ec_ioctl_sc_idn(master, arg, ctx);
04470 break;
04471 case EC_IOCTL_DOMAIN_SIZE:
04472 ret = ec_ioctl_domain_size(master, arg, ctx);
04473 break;
04474 case EC_IOCTL_DOMAIN_OFFSET:
04475 ret = ec_ioctl_domain_offset(master, arg, ctx);
04476 break;
04477 case EC_IOCTL_DOMAIN_PROCESS:
04478 if (!ctx->writable) {
04479 ret = -EPERM;
04480 break;
04481 }
04482 ret = ec_ioctl_domain_process(master, arg, ctx);
04483 break;
04484 case EC_IOCTL_DOMAIN_QUEUE:
04485 if (!ctx->writable) {
04486 ret = -EPERM;
04487 break;
04488 }
04489 ret = ec_ioctl_domain_queue(master, arg, ctx);
04490 break;
04491 case EC_IOCTL_DOMAIN_STATE:
04492 ret = ec_ioctl_domain_state(master, arg, ctx);
04493 break;
04494 case EC_IOCTL_SDO_REQUEST_INDEX:
04495 if (!ctx->writable) {
04496 ret = -EPERM;
04497 break;
04498 }
04499 ret = ec_ioctl_sdo_request_index(master, arg, ctx);
04500 break;
04501 case EC_IOCTL_SDO_REQUEST_TIMEOUT:
04502 if (!ctx->writable) {
04503 ret = -EPERM;
04504 break;
04505 }
04506 ret = ec_ioctl_sdo_request_timeout(master, arg, ctx);
04507 break;
04508 case EC_IOCTL_SDO_REQUEST_STATE:
04509 ret = ec_ioctl_sdo_request_state(master, arg, ctx);
04510 break;
04511 case EC_IOCTL_SDO_REQUEST_READ:
04512 if (!ctx->writable) {
04513 ret = -EPERM;
04514 break;
04515 }
04516 ret = ec_ioctl_sdo_request_read(master, arg, ctx);
04517 break;
04518 case EC_IOCTL_SDO_REQUEST_WRITE:
04519 if (!ctx->writable) {
04520 ret = -EPERM;
04521 break;
04522 }
04523 ret = ec_ioctl_sdo_request_write(master, arg, ctx);
04524 break;
04525 case EC_IOCTL_SDO_REQUEST_DATA:
04526 ret = ec_ioctl_sdo_request_data(master, arg, ctx);
04527 break;
04528 case EC_IOCTL_REG_REQUEST_DATA:
04529 ret = ec_ioctl_reg_request_data(master, arg, ctx);
04530 break;
04531 case EC_IOCTL_REG_REQUEST_STATE:
04532 ret = ec_ioctl_reg_request_state(master, arg, ctx);
04533 break;
04534 case EC_IOCTL_REG_REQUEST_WRITE:
04535 if (!ctx->writable) {
04536 ret = -EPERM;
04537 break;
04538 }
04539 ret = ec_ioctl_reg_request_write(master, arg, ctx);
04540 break;
04541 case EC_IOCTL_REG_REQUEST_READ:
04542 if (!ctx->writable) {
04543 ret = -EPERM;
04544 break;
04545 }
04546 ret = ec_ioctl_reg_request_read(master, arg, ctx);
04547 break;
04548 case EC_IOCTL_VOE_SEND_HEADER:
04549 if (!ctx->writable) {
04550 ret = -EPERM;
04551 break;
04552 }
04553 ret = ec_ioctl_voe_send_header(master, arg, ctx);
04554 break;
04555 case EC_IOCTL_VOE_REC_HEADER:
04556 ret = ec_ioctl_voe_rec_header(master, arg, ctx);
04557 break;
04558 case EC_IOCTL_VOE_READ:
04559 if (!ctx->writable) {
04560 ret = -EPERM;
04561 break;
04562 }
04563 ret = ec_ioctl_voe_read(master, arg, ctx);
04564 break;
04565 case EC_IOCTL_VOE_READ_NOSYNC:
04566 if (!ctx->writable) {
04567 ret = -EPERM;
04568 break;
04569 }
04570 ret = ec_ioctl_voe_read_nosync(master, arg, ctx);
04571 break;
04572 case EC_IOCTL_VOE_WRITE:
04573 if (!ctx->writable) {
04574 ret = -EPERM;
04575 break;
04576 }
04577 ret = ec_ioctl_voe_write(master, arg, ctx);
04578 break;
04579 case EC_IOCTL_VOE_EXEC:
04580 if (!ctx->writable) {
04581 ret = -EPERM;
04582 break;
04583 }
04584 ret = ec_ioctl_voe_exec(master, arg, ctx);
04585 break;
04586 case EC_IOCTL_VOE_DATA:
04587 ret = ec_ioctl_voe_data(master, arg, ctx);
04588 break;
04589 case EC_IOCTL_SET_SEND_INTERVAL:
04590 if (!ctx->writable) {
04591 ret = -EPERM;
04592 break;
04593 }
04594 ret = ec_ioctl_set_send_interval(master, arg, ctx);
04595 break;
04596 default:
04597 ret = -ENOTTY;
04598 break;
04599 }
04600
04601 #if DEBUG_LATENCY
04602 b = get_cycles();
04603 t = (unsigned int) ((b - a) * 1000LL) / cpu_khz;
04604 if (t > 50) {
04605 EC_MASTER_WARN(master, "ioctl(0x%02x) took %u us.\n",
04606 _IOC_NR(cmd), t);
04607 }
04608 #endif
04609
04610 return ret;
04611 }
04612
04613