master/cdev.c
changeset 1079 ef1266652c4d
parent 1075 94c6e36e0f8d
child 1082 ff06c58e269c
equal deleted inserted replaced
1078:fce58ba8a912 1079:ef1266652c4d
    97 void ec_cdev_clear(ec_cdev_t *cdev /**< EtherCAT XML device */)
    97 void ec_cdev_clear(ec_cdev_t *cdev /**< EtherCAT XML device */)
    98 {
    98 {
    99     cdev_del(&cdev->cdev);
    99     cdev_del(&cdev->cdev);
   100 }
   100 }
   101 
   101 
       
   102 /*****************************************************************************/
       
   103 
       
   104 /** Get master information.
       
   105  */
       
   106 int ec_cdev_ioctl_master(
       
   107         ec_master_t *master, /**< EtherCAT master. */
       
   108         unsigned long arg /**< Userspace address to store the results. */
       
   109         )
       
   110 {
       
   111     ec_ioctl_master_t data;
       
   112 
       
   113     down(&master->master_sem);
       
   114     data.slave_count = master->slave_count;
       
   115     data.config_count = ec_master_config_count(master);
       
   116     data.domain_count = ec_master_domain_count(master);
       
   117     data.phase = (uint8_t) master->phase;
       
   118     up(&master->master_sem);
       
   119 
       
   120     down(&master->device_sem);
       
   121     memcpy(data.devices[0].address, master->main_mac, ETH_ALEN); 
       
   122     data.devices[0].attached = master->main_device.dev ? 1 : 0;
       
   123     data.devices[0].tx_count = master->main_device.tx_count;
       
   124     data.devices[0].rx_count = master->main_device.rx_count;
       
   125     memcpy(data.devices[1].address, master->backup_mac, ETH_ALEN); 
       
   126     data.devices[1].attached = master->backup_device.dev ? 1 : 0;
       
   127     data.devices[1].tx_count = master->backup_device.tx_count;
       
   128     data.devices[1].rx_count = master->backup_device.rx_count;
       
   129     up(&master->device_sem);
       
   130 
       
   131     if (copy_to_user((void __user *) arg, &data, sizeof(data)))
       
   132         return -EFAULT;
       
   133 
       
   134     return 0;
       
   135 }
       
   136 
       
   137 /*****************************************************************************/
       
   138 
       
   139 /** Get slave information.
       
   140  */
       
   141 int ec_cdev_ioctl_slave(
       
   142         ec_master_t *master, /**< EtherCAT master. */
       
   143         unsigned long arg /**< Userspace address to store the results. */
       
   144         )
       
   145 {
       
   146     ec_ioctl_slave_t data;
       
   147     const ec_slave_t *slave;
       
   148 
       
   149     if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
       
   150         return -EFAULT;
       
   151     }
       
   152 
       
   153     down(&master->master_sem);
       
   154 
       
   155     if (!(slave = ec_master_find_slave_const(
       
   156                     master, 0, data.position))) {
       
   157         up(&master->master_sem);
       
   158         EC_ERR("Slave %u does not exist!\n", data.position);
       
   159         return -EINVAL;
       
   160     }
       
   161 
       
   162     data.vendor_id = slave->sii.vendor_id;
       
   163     data.product_code = slave->sii.product_code;
       
   164     data.revision_number = slave->sii.revision_number;
       
   165     data.serial_number = slave->sii.serial_number;
       
   166     data.alias = slave->sii.alias;
       
   167     data.rx_mailbox_offset = slave->sii.rx_mailbox_offset;
       
   168     data.rx_mailbox_size = slave->sii.rx_mailbox_size;
       
   169     data.tx_mailbox_offset = slave->sii.tx_mailbox_offset;
       
   170     data.tx_mailbox_size = slave->sii.tx_mailbox_size;
       
   171     data.mailbox_protocols = slave->sii.mailbox_protocols;
       
   172     data.has_general_category = slave->sii.has_general;
       
   173     data.coe_details = slave->sii.coe_details;
       
   174     data.general_flags = slave->sii.general_flags;
       
   175     data.current_on_ebus = slave->sii.current_on_ebus;
       
   176     data.state = slave->current_state;
       
   177     data.error_flag = slave->error_flag;
       
   178 
       
   179     data.sync_count = slave->sii.sync_count;
       
   180     data.sdo_count = ec_slave_sdo_count(slave);
       
   181     data.sii_nwords = slave->sii_nwords;
       
   182 
       
   183     if (slave->sii.name) {
       
   184         strncpy(data.name, slave->sii.name,
       
   185                 EC_IOCTL_STRING_SIZE);
       
   186         data.name[EC_IOCTL_STRING_SIZE - 1] = 0;
       
   187     } else {
       
   188         data.name[0] = 0;
       
   189     }
       
   190 
       
   191     up(&master->master_sem);
       
   192 
       
   193     if (copy_to_user((void __user *) arg, &data, sizeof(data)))
       
   194         return -EFAULT;
       
   195 
       
   196     return 0;
       
   197 }
       
   198 
       
   199 /*****************************************************************************/
       
   200 
       
   201 /** Get slave sync manager information.
       
   202  */
       
   203 int ec_cdev_ioctl_slave_sync(
       
   204         ec_master_t *master, /**< EtherCAT master. */
       
   205         unsigned long arg /**< Userspace address to store the results. */
       
   206         )
       
   207 {
       
   208     ec_ioctl_slave_sync_t data;
       
   209     const ec_slave_t *slave;
       
   210     const ec_sync_t *sync;
       
   211 
       
   212     if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
       
   213         return -EFAULT;
       
   214     }
       
   215 
       
   216     down(&master->master_sem);
       
   217 
       
   218     if (!(slave = ec_master_find_slave_const(
       
   219                     master, 0, data.slave_position))) {
       
   220         up(&master->master_sem);
       
   221         EC_ERR("Slave %u does not exist!\n", data.slave_position);
       
   222         return -EINVAL;
       
   223     }
       
   224 
       
   225     if (data.sync_index >= slave->sii.sync_count) {
       
   226         up(&master->master_sem);
       
   227         EC_ERR("Sync manager %u does not exist in slave %u!\n",
       
   228                 data.sync_index, data.slave_position);
       
   229         return -EINVAL;
       
   230     }
       
   231 
       
   232     sync = &slave->sii.syncs[data.sync_index];
       
   233 
       
   234     data.physical_start_address = sync->physical_start_address;
       
   235     data.default_size = sync->default_length;
       
   236     data.control_register = sync->control_register;
       
   237     data.enable = sync->enable;
       
   238     data.assign_source = sync->assign_source;
       
   239     data.pdo_count = ec_pdo_list_count(&sync->pdos);
       
   240 
       
   241     up(&master->master_sem);
       
   242 
       
   243     if (copy_to_user((void __user *) arg, &data, sizeof(data)))
       
   244         return -EFAULT;
       
   245 
       
   246     return 0;
       
   247 }
       
   248 
       
   249 /*****************************************************************************/
       
   250 
       
   251 /** Get slave sync manager Pdo information.
       
   252  */
       
   253 int ec_cdev_ioctl_slave_sync_pdo(
       
   254         ec_master_t *master, /**< EtherCAT master. */
       
   255         unsigned long arg /**< Userspace address to store the results. */
       
   256         )
       
   257 {
       
   258     ec_ioctl_slave_sync_pdo_t data;
       
   259     const ec_slave_t *slave;
       
   260     const ec_sync_t *sync;
       
   261     const ec_pdo_t *pdo;
       
   262 
       
   263     if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
       
   264         return -EFAULT;
       
   265     }
       
   266 
       
   267     down(&master->master_sem);
       
   268 
       
   269     if (!(slave = ec_master_find_slave_const(
       
   270                     master, 0, data.slave_position))) {
       
   271         up(&master->master_sem);
       
   272         EC_ERR("Slave %u does not exist!\n", data.slave_position);
       
   273         return -EINVAL;
       
   274     }
       
   275 
       
   276     if (data.sync_index >= slave->sii.sync_count) {
       
   277         up(&master->master_sem);
       
   278         EC_ERR("Sync manager %u does not exist in slave %u!\n",
       
   279                 data.sync_index, data.slave_position);
       
   280         return -EINVAL;
       
   281     }
       
   282 
       
   283     sync = &slave->sii.syncs[data.sync_index];
       
   284     if (!(pdo = ec_pdo_list_find_pdo_by_pos_const(
       
   285                     &sync->pdos, data.pdo_pos))) {
       
   286         up(&master->master_sem);
       
   287         EC_ERR("Sync manager %u does not contain a Pdo with "
       
   288                 "position %u in slave %u!\n", data.sync_index,
       
   289                 data.pdo_pos, data.slave_position);
       
   290         return -EINVAL;
       
   291     }
       
   292 
       
   293     data.index = pdo->index;
       
   294     data.entry_count = ec_pdo_entry_count(pdo);
       
   295 
       
   296     if (pdo->name) {
       
   297         strncpy(data.name, pdo->name, EC_IOCTL_STRING_SIZE);
       
   298         data.name[EC_IOCTL_STRING_SIZE - 1] = 0;
       
   299     } else {
       
   300         data.name[0] = 0;
       
   301     }
       
   302 
       
   303     up(&master->master_sem);
       
   304 
       
   305     if (copy_to_user((void __user *) arg, &data, sizeof(data)))
       
   306         return -EFAULT;
       
   307 
       
   308     return 0;
       
   309 }
       
   310 
       
   311 /*****************************************************************************/
       
   312 
       
   313 /** Get slave sync manager Pdo entry information.
       
   314  */
       
   315 int ec_cdev_ioctl_slave_sync_pdo_entry(
       
   316         ec_master_t *master, /**< EtherCAT master. */
       
   317         unsigned long arg /**< Userspace address to store the results. */
       
   318         )
       
   319 {
       
   320     ec_ioctl_slave_sync_pdo_entry_t data;
       
   321     const ec_slave_t *slave;
       
   322     const ec_sync_t *sync;
       
   323     const ec_pdo_t *pdo;
       
   324     const ec_pdo_entry_t *entry;
       
   325 
       
   326     if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
       
   327         return -EFAULT;
       
   328     }
       
   329 
       
   330     down(&master->master_sem);
       
   331 
       
   332     if (!(slave = ec_master_find_slave_const(
       
   333                     master, 0, data.slave_position))) {
       
   334         up(&master->master_sem);
       
   335         EC_ERR("Slave %u does not exist!\n", data.slave_position);
       
   336         return -EINVAL;
       
   337     }
       
   338 
       
   339     if (data.sync_index >= slave->sii.sync_count) {
       
   340         up(&master->master_sem);
       
   341         EC_ERR("Sync manager %u does not exist in slave %u!\n",
       
   342                 data.sync_index, data.slave_position);
       
   343         return -EINVAL;
       
   344     }
       
   345 
       
   346     sync = &slave->sii.syncs[data.sync_index];
       
   347     if (!(pdo = ec_pdo_list_find_pdo_by_pos_const(
       
   348                     &sync->pdos, data.pdo_pos))) {
       
   349         up(&master->master_sem);
       
   350         EC_ERR("Sync manager %u does not contain a Pdo with "
       
   351                 "position %u in slave %u!\n", data.sync_index,
       
   352                 data.pdo_pos, data.slave_position);
       
   353         return -EINVAL;
       
   354     }
       
   355 
       
   356     if (!(entry = ec_pdo_find_entry_by_pos_const(
       
   357                     pdo, data.entry_pos))) {
       
   358         up(&master->master_sem);
       
   359         EC_ERR("Pdo 0x%04X does not contain an entry with "
       
   360                 "position %u in slave %u!\n", data.pdo_pos,
       
   361                 data.entry_pos, data.slave_position);
       
   362         return -EINVAL;
       
   363     }
       
   364 
       
   365     data.index = entry->index;
       
   366     data.subindex = entry->subindex;
       
   367     data.bit_length = entry->bit_length;
       
   368     if (entry->name) {
       
   369         strncpy(data.name, entry->name, EC_IOCTL_STRING_SIZE);
       
   370         data.name[EC_IOCTL_STRING_SIZE - 1] = 0;
       
   371     } else {
       
   372         data.name[0] = 0;
       
   373     }
       
   374 
       
   375     up(&master->master_sem);
       
   376 
       
   377     if (copy_to_user((void __user *) arg, &data, sizeof(data)))
       
   378         return -EFAULT;
       
   379 
       
   380     return 0;
       
   381 }
       
   382 
       
   383 /*****************************************************************************/
       
   384 
       
   385 /** Get domain information.
       
   386  */
       
   387 int ec_cdev_ioctl_domain(
       
   388         ec_master_t *master, /**< EtherCAT master. */
       
   389         unsigned long arg /**< Userspace address to store the results. */
       
   390         )
       
   391 {
       
   392     ec_ioctl_domain_t data;
       
   393     const ec_domain_t *domain;
       
   394 
       
   395     if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
       
   396         return -EFAULT;
       
   397     }
       
   398 
       
   399     down(&master->master_sem);
       
   400 
       
   401     if (!(domain = ec_master_find_domain_const(master, data.index))) {
       
   402         up(&master->master_sem);
       
   403         EC_ERR("Domain %u does not exist!\n", data.index);
       
   404         return -EINVAL;
       
   405     }
       
   406 
       
   407     data.data_size = domain->data_size;
       
   408     data.logical_base_address = domain->logical_base_address;
       
   409     data.working_counter = domain->working_counter;
       
   410     data.expected_working_counter = domain->expected_working_counter;
       
   411     data.fmmu_count = ec_domain_fmmu_count(domain);
       
   412 
       
   413     up(&master->master_sem);
       
   414 
       
   415     if (copy_to_user((void __user *) arg, &data, sizeof(data)))
       
   416         return -EFAULT;
       
   417 
       
   418     return 0;
       
   419 }
       
   420 
       
   421 /*****************************************************************************/
       
   422 
       
   423 /** Get domain FMMU information.
       
   424  */
       
   425 int ec_cdev_ioctl_domain_fmmu(
       
   426         ec_master_t *master, /**< EtherCAT master. */
       
   427         unsigned long arg /**< Userspace address to store the results. */
       
   428         )
       
   429 {
       
   430     ec_ioctl_domain_fmmu_t data;
       
   431     const ec_domain_t *domain;
       
   432     const ec_fmmu_config_t *fmmu;
       
   433 
       
   434     if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
       
   435         return -EFAULT;
       
   436     }
       
   437 
       
   438     down(&master->master_sem);
       
   439 
       
   440     if (!(domain = ec_master_find_domain_const(master, data.domain_index))) {
       
   441         up(&master->master_sem);
       
   442         EC_ERR("Domain %u does not exist!\n", data.domain_index);
       
   443         return -EINVAL;
       
   444     }
       
   445 
       
   446     if (!(fmmu = ec_domain_find_fmmu(domain, data.fmmu_index))) {
       
   447         up(&master->master_sem);
       
   448         EC_ERR("Domain %u has less than %u fmmu configurations.\n",
       
   449                 data.domain_index, data.fmmu_index + 1);
       
   450         return -EINVAL;
       
   451     }
       
   452 
       
   453     data.slave_config_alias = fmmu->sc->alias;
       
   454     data.slave_config_position = fmmu->sc->position;
       
   455     data.sync_index = fmmu->sync_index;
       
   456     data.dir = fmmu->dir;
       
   457     data.logical_address = fmmu->logical_start_address;
       
   458     data.data_size = fmmu->data_size;
       
   459 
       
   460     up(&master->master_sem);
       
   461 
       
   462     if (copy_to_user((void __user *) arg, &data, sizeof(data)))
       
   463         return -EFAULT;
       
   464 
       
   465     return 0;
       
   466 }
       
   467 
       
   468 /*****************************************************************************/
       
   469 
       
   470 /** Get domain data.
       
   471  */
       
   472 int ec_cdev_ioctl_domain_data(
       
   473         ec_master_t *master, /**< EtherCAT master. */
       
   474         unsigned long arg /**< Userspace address to store the results. */
       
   475         )
       
   476 {
       
   477     ec_ioctl_domain_data_t data;
       
   478     const ec_domain_t *domain;
       
   479 
       
   480     if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
       
   481         return -EFAULT;
       
   482     }
       
   483 
       
   484     down(&master->master_sem);
       
   485 
       
   486     if (!(domain = ec_master_find_domain_const(master, data.domain_index))) {
       
   487         up(&master->master_sem);
       
   488         EC_ERR("Domain %u does not exist!\n", data.domain_index);
       
   489         return -EINVAL;
       
   490     }
       
   491 
       
   492     if (domain->data_size != data.data_size) {
       
   493         up(&master->master_sem);
       
   494         EC_ERR("Data size mismatch %u/%u!\n",
       
   495                 data.data_size, domain->data_size);
       
   496         return -EFAULT;
       
   497     }
       
   498 
       
   499     if (copy_to_user((void __user *) data.target, domain->data,
       
   500                 domain->data_size))
       
   501         return -EFAULT;
       
   502 
       
   503     up(&master->master_sem);
       
   504     return 0;
       
   505 }
       
   506 
       
   507 /*****************************************************************************/
       
   508 
       
   509 /** Set master debug level.
       
   510  */
       
   511 int ec_cdev_ioctl_master_debug(
       
   512         ec_master_t *master, /**< EtherCAT master. */
       
   513         unsigned long arg /**< ioctl() argument. */
       
   514         )
       
   515 {
       
   516     if (ec_master_debug_level(master, (unsigned int) arg))
       
   517         return -EINVAL;
       
   518 
       
   519     return 0;
       
   520 }
       
   521 
       
   522 /*****************************************************************************/
       
   523 
       
   524 /** Set slave state.
       
   525  */
       
   526 int ec_cdev_ioctl_slave_state(
       
   527         ec_master_t *master, /**< EtherCAT master. */
       
   528         unsigned long arg /**< ioctl() argument. */
       
   529         )
       
   530 {
       
   531     ec_ioctl_slave_state_t data;
       
   532     ec_slave_t *slave;
       
   533 
       
   534     if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
       
   535         return -EFAULT;
       
   536     }
       
   537 
       
   538     down(&master->master_sem);
       
   539 
       
   540     if (!(slave = ec_master_find_slave(
       
   541                     master, 0, data.slave_position))) {
       
   542         EC_ERR("Slave %u does not exist!\n", data.slave_position);
       
   543         return -EINVAL;
       
   544     }
       
   545 
       
   546     ec_slave_request_state(slave, data.requested_state);
       
   547 
       
   548     up(&master->master_sem);
       
   549     return 0;
       
   550 }
       
   551 
       
   552 /*****************************************************************************/
       
   553 
       
   554 /** Get slave Sdo information.
       
   555  */
       
   556 int ec_cdev_ioctl_slave_sdo(
       
   557         ec_master_t *master, /**< EtherCAT master. */
       
   558         unsigned long arg /**< ioctl() argument. */
       
   559         )
       
   560 {
       
   561     ec_ioctl_slave_sdo_t data;
       
   562     const ec_slave_t *slave;
       
   563     const ec_sdo_t *sdo;
       
   564 
       
   565     if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
       
   566         return -EFAULT;
       
   567     }
       
   568 
       
   569     down(&master->master_sem);
       
   570 
       
   571     if (!(slave = ec_master_find_slave_const(
       
   572                     master, 0, data.slave_position))) {
       
   573         up(&master->master_sem);
       
   574         EC_ERR("Slave %u does not exist!\n", data.slave_position);
       
   575         return -EINVAL;
       
   576     }
       
   577 
       
   578     if (!(sdo = ec_slave_get_sdo_by_pos_const(
       
   579                     slave, data.sdo_position))) {
       
   580         up(&master->master_sem);
       
   581         EC_ERR("Sdo %u does not exist in slave %u!\n",
       
   582                 data.sdo_position, data.slave_position);
       
   583         return -EINVAL;
       
   584     }
       
   585 
       
   586     data.sdo_index = sdo->index;
       
   587     data.max_subindex = sdo->max_subindex;
       
   588 
       
   589     if (sdo->name) {
       
   590         strncpy(data.name, sdo->name, EC_IOCTL_STRING_SIZE);
       
   591         data.name[EC_IOCTL_STRING_SIZE - 1] = 0;
       
   592     } else {
       
   593         data.name[0] = 0;
       
   594     }
       
   595 
       
   596     up(&master->master_sem);
       
   597 
       
   598     if (copy_to_user((void __user *) arg, &data, sizeof(data)))
       
   599         return -EFAULT;
       
   600 
       
   601     return 0;
       
   602 }
       
   603 
       
   604 /*****************************************************************************/
       
   605 
       
   606 /** Get slave Sdo entry information.
       
   607  */
       
   608 int ec_cdev_ioctl_slave_sdo_entry(
       
   609         ec_master_t *master, /**< EtherCAT master. */
       
   610         unsigned long arg /**< ioctl() argument. */
       
   611         )
       
   612 {
       
   613     ec_ioctl_slave_sdo_entry_t data;
       
   614     const ec_slave_t *slave;
       
   615     const ec_sdo_t *sdo;
       
   616     const ec_sdo_entry_t *entry;
       
   617 
       
   618     if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
       
   619         return -EFAULT;
       
   620     }
       
   621 
       
   622     down(&master->master_sem);
       
   623 
       
   624     if (!(slave = ec_master_find_slave_const(
       
   625                     master, 0, data.slave_position))) {
       
   626         up(&master->master_sem);
       
   627         EC_ERR("Slave %u does not exist!\n", data.slave_position);
       
   628         return -EINVAL;
       
   629     }
       
   630 
       
   631     if (data.sdo_spec <= 0) {
       
   632         if (!(sdo = ec_slave_get_sdo_by_pos_const(
       
   633                         slave, -data.sdo_spec))) {
       
   634             up(&master->master_sem);
       
   635             EC_ERR("Sdo %u does not exist in slave %u!\n",
       
   636                     -data.sdo_spec, data.slave_position);
       
   637             return -EINVAL;
       
   638         }
       
   639     } else {
       
   640         if (!(sdo = ec_slave_get_sdo_const(
       
   641                         slave, data.sdo_spec))) {
       
   642             up(&master->master_sem);
       
   643             EC_ERR("Sdo 0x%04X does not exist in slave %u!\n",
       
   644                     data.sdo_spec, data.slave_position);
       
   645             return -EINVAL;
       
   646         }
       
   647     }
       
   648 
       
   649     if (!(entry = ec_sdo_get_entry_const(
       
   650                     sdo, data.sdo_entry_subindex))) {
       
   651         up(&master->master_sem);
       
   652         EC_ERR("Sdo entry 0x%04X:%02X does not exist "
       
   653                 "in slave %u!\n", sdo->index,
       
   654                 data.sdo_entry_subindex, data.slave_position);
       
   655         return -EINVAL;
       
   656     }
       
   657 
       
   658     data.data_type = entry->data_type;
       
   659     data.bit_length = entry->bit_length;
       
   660 
       
   661     if (entry->description) {
       
   662         strncpy(data.description, entry->description,
       
   663                 EC_IOCTL_STRING_SIZE);
       
   664         data.description[EC_IOCTL_STRING_SIZE - 1]
       
   665             = 0;
       
   666     } else {
       
   667         data.description[0] = 0;
       
   668     }
       
   669 
       
   670     up(&master->master_sem);
       
   671 
       
   672     if (copy_to_user((void __user *) arg, &data, sizeof(data)))
       
   673         return -EFAULT;
       
   674 
       
   675     return 0;
       
   676 }
       
   677 
       
   678 /*****************************************************************************/
       
   679 
       
   680 /** Upload Sdo.
       
   681  */
       
   682 int ec_cdev_ioctl_slave_sdo_upload(
       
   683         ec_master_t *master, /**< EtherCAT master. */
       
   684         unsigned long arg /**< ioctl() argument. */
       
   685         )
       
   686 {
       
   687     ec_ioctl_slave_sdo_upload_t data;
       
   688     ec_master_sdo_request_t request;
       
   689     int retval;
       
   690 
       
   691     if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
       
   692         return -EFAULT;
       
   693     }
       
   694 
       
   695     ec_sdo_request_init(&request.req);
       
   696     ec_sdo_request_address(&request.req,
       
   697             data.sdo_index, data.sdo_entry_subindex);
       
   698     ecrt_sdo_request_read(&request.req);
       
   699 
       
   700     down(&master->master_sem);
       
   701 
       
   702     if (!(request.slave = ec_master_find_slave(
       
   703                     master, 0, data.slave_position))) {
       
   704         up(&master->master_sem);
       
   705         ec_sdo_request_clear(&request.req);
       
   706         EC_ERR("Slave %u does not exist!\n", data.slave_position);
       
   707         return -EINVAL;
       
   708     }
       
   709 
       
   710     // schedule request.
       
   711     list_add_tail(&request.list, &master->slave_sdo_requests);
       
   712 
       
   713     up(&master->master_sem);
       
   714 
       
   715     // wait for processing through FSM
       
   716     if (wait_event_interruptible(master->sdo_queue,
       
   717                 request.req.state != EC_REQUEST_QUEUED)) {
       
   718         // interrupted by signal
       
   719         down(&master->master_sem);
       
   720         if (request.req.state == EC_REQUEST_QUEUED) {
       
   721             list_del(&request.req.list);
       
   722             up(&master->master_sem);
       
   723             ec_sdo_request_clear(&request.req);
       
   724             return -EINTR;
       
   725         }
       
   726         // request already processing: interrupt not possible.
       
   727         up(&master->master_sem);
       
   728     }
       
   729 
       
   730     // wait until master FSM has finished processing
       
   731     wait_event(master->sdo_queue, request.req.state != EC_REQUEST_BUSY);
       
   732 
       
   733     data.abort_code = request.req.abort_code;
       
   734 
       
   735     if (request.req.state != EC_REQUEST_SUCCESS) {
       
   736         data.data_size = 0;
       
   737         retval = -EIO;
       
   738     } else {
       
   739         if (request.req.data_size > data.target_size) {
       
   740             EC_ERR("Buffer too small.\n");
       
   741             ec_sdo_request_clear(&request.req);
       
   742             return -EOVERFLOW;
       
   743         }
       
   744         data.data_size = request.req.data_size;
       
   745 
       
   746         if (copy_to_user((void __user *) data.target,
       
   747                     request.req.data, data.data_size)) {
       
   748             ec_sdo_request_clear(&request.req);
       
   749             return -EFAULT;
       
   750         }
       
   751         retval = 0;
       
   752     }
       
   753 
       
   754     if (__copy_to_user((void __user *) arg, &data, sizeof(data))) {
       
   755         retval = -EFAULT;
       
   756     }
       
   757 
       
   758     ec_sdo_request_clear(&request.req);
       
   759     return retval;
       
   760 }
       
   761 
       
   762 /*****************************************************************************/
       
   763 
       
   764 /** Download Sdo.
       
   765  */
       
   766 int ec_cdev_ioctl_slave_sdo_download(
       
   767         ec_master_t *master, /**< EtherCAT master. */
       
   768         unsigned long arg /**< ioctl() argument. */
       
   769         )
       
   770 {
       
   771     ec_ioctl_slave_sdo_download_t data;
       
   772     ec_master_sdo_request_t request;
       
   773     int retval;
       
   774 
       
   775     if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
       
   776         return -EFAULT;
       
   777     }
       
   778 
       
   779     // copy data to download
       
   780     if (!data.data_size) {
       
   781         EC_ERR("Zero data size!\n");
       
   782         return -EINVAL;
       
   783     }
       
   784 
       
   785     ec_sdo_request_init(&request.req);
       
   786     ec_sdo_request_address(&request.req,
       
   787             data.sdo_index, data.sdo_entry_subindex);
       
   788     if (ec_sdo_request_alloc(&request.req, data.data_size)) {
       
   789         ec_sdo_request_clear(&request.req);
       
   790         return -ENOMEM;
       
   791     }
       
   792     if (copy_from_user(request.req.data,
       
   793                 (void __user *) data.data, data.data_size)) {
       
   794         ec_sdo_request_clear(&request.req);
       
   795         return -EFAULT;
       
   796     }
       
   797     request.req.data_size = data.data_size;
       
   798     ecrt_sdo_request_write(&request.req);
       
   799 
       
   800 
       
   801     down(&master->master_sem);
       
   802 
       
   803     if (!(request.slave = ec_master_find_slave(
       
   804                     master, 0, data.slave_position))) {
       
   805         up(&master->master_sem);
       
   806         EC_ERR("Slave %u does not exist!\n", data.slave_position);
       
   807         ec_sdo_request_clear(&request.req);
       
   808         return -EINVAL;
       
   809     }
       
   810     
       
   811     // schedule request.
       
   812     list_add_tail(&request.list, &master->slave_sdo_requests);
       
   813 
       
   814     up(&master->master_sem);
       
   815 
       
   816     // wait for processing through FSM
       
   817     if (wait_event_interruptible(master->sdo_queue,
       
   818                 request.req.state != EC_REQUEST_QUEUED)) {
       
   819         // interrupted by signal
       
   820         down(&master->master_sem);
       
   821         if (request.req.state == EC_REQUEST_QUEUED) {
       
   822             list_del(&request.req.list);
       
   823             up(&master->master_sem);
       
   824             ec_sdo_request_clear(&request.req);
       
   825             return -EINTR;
       
   826         }
       
   827         // request already processing: interrupt not possible.
       
   828         up(&master->master_sem);
       
   829     }
       
   830 
       
   831     // wait until master FSM has finished processing
       
   832     wait_event(master->sdo_queue, request.req.state != EC_REQUEST_BUSY);
       
   833 
       
   834     data.abort_code = request.req.abort_code;
       
   835 
       
   836     retval = request.req.state == EC_REQUEST_SUCCESS ? 0 : -EIO;
       
   837 
       
   838     if (__copy_to_user((void __user *) arg, &data, sizeof(data))) {
       
   839         retval = -EFAULT;
       
   840     }
       
   841 
       
   842     ec_sdo_request_clear(&request.req);
       
   843     return retval;
       
   844 }
       
   845 
       
   846 /*****************************************************************************/
       
   847 
       
   848 /** Read a slave's SII.
       
   849  */
       
   850 int ec_cdev_ioctl_slave_sii_read(
       
   851         ec_master_t *master, /**< EtherCAT master. */
       
   852         unsigned long arg /**< ioctl() argument. */
       
   853         )
       
   854 {
       
   855     ec_ioctl_slave_sii_t data;
       
   856     const ec_slave_t *slave;
       
   857     int retval;
       
   858 
       
   859     if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
       
   860         return -EFAULT;
       
   861     }
       
   862 
       
   863     down(&master->master_sem);
       
   864 
       
   865     if (!(slave = ec_master_find_slave_const(
       
   866                     master, 0, data.slave_position))) {
       
   867         up(&master->master_sem);
       
   868         EC_ERR("Slave %u does not exist!\n", data.slave_position);
       
   869         return -EINVAL;
       
   870     }
       
   871 
       
   872     if (!data.nwords
       
   873             || data.offset + data.nwords > slave->sii_nwords) {
       
   874         up(&master->master_sem);
       
   875         EC_ERR("Invalid SII read offset/size %u/%u for slave "
       
   876                 "SII size %u!\n", data.offset,
       
   877                 data.nwords, slave->sii_nwords);
       
   878         return -EINVAL;
       
   879     }
       
   880 
       
   881     if (copy_to_user((void __user *) data.words,
       
   882                 slave->sii_words + data.offset, data.nwords * 2))
       
   883         retval = -EFAULT;
       
   884     else
       
   885         retval = 0;
       
   886 
       
   887     up(&master->master_sem);
       
   888     return retval;
       
   889 }
       
   890 
       
   891 /*****************************************************************************/
       
   892 
       
   893 /** Write a slave's SII.
       
   894  */
       
   895 int ec_cdev_ioctl_slave_sii_write(
       
   896         ec_master_t *master, /**< EtherCAT master. */
       
   897         unsigned long arg /**< ioctl() argument. */
       
   898         )
       
   899 {
       
   900     ec_ioctl_slave_sii_t data;
       
   901     ec_slave_t *slave;
       
   902     unsigned int byte_size;
       
   903     uint16_t *words;
       
   904     ec_sii_write_request_t request;
       
   905 
       
   906     if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
       
   907         return -EFAULT;
       
   908     }
       
   909 
       
   910     if (!data.nwords)
       
   911         return 0;
       
   912 
       
   913     byte_size = sizeof(uint16_t) * data.nwords;
       
   914     if (!(words = kmalloc(byte_size, GFP_KERNEL))) {
       
   915         EC_ERR("Failed to allocate %u bytes for SII contents.\n",
       
   916                 byte_size);
       
   917         return -ENOMEM;
       
   918     }
       
   919 
       
   920     if (copy_from_user(words,
       
   921                 (void __user *) data.words, byte_size)) {
       
   922         kfree(words);
       
   923         return -EFAULT;
       
   924     }
       
   925 
       
   926     down(&master->master_sem);
       
   927 
       
   928     if (!(slave = ec_master_find_slave(
       
   929                     master, 0, data.slave_position))) {
       
   930         up(&master->master_sem);
       
   931         EC_ERR("Slave %u does not exist!\n", data.slave_position);
       
   932         kfree(words);
       
   933         return -EINVAL;
       
   934     }
       
   935 
       
   936     // init SII write request
       
   937     INIT_LIST_HEAD(&request.list);
       
   938     request.slave = slave;
       
   939     request.words = words;
       
   940     request.offset = data.offset;
       
   941     request.nwords = data.nwords;
       
   942     request.state = EC_REQUEST_QUEUED;
       
   943 
       
   944     // schedule SII write request.
       
   945     list_add_tail(&request.list, &master->sii_requests);
       
   946 
       
   947     up(&master->master_sem);
       
   948 
       
   949     // wait for processing through FSM
       
   950     if (wait_event_interruptible(master->sii_queue,
       
   951                 request.state != EC_REQUEST_QUEUED)) {
       
   952         // interrupted by signal
       
   953         down(&master->master_sem);
       
   954         if (request.state == EC_REQUEST_QUEUED) {
       
   955             // abort request
       
   956             list_del(&request.list);
       
   957             up(&master->master_sem);
       
   958             kfree(words);
       
   959             return -EINTR;
       
   960         }
       
   961         up(&master->master_sem);
       
   962     }
       
   963 
       
   964     // wait until master FSM has finished processing
       
   965     wait_event(master->sii_queue, request.state != EC_REQUEST_BUSY);
       
   966 
       
   967     kfree(words);
       
   968 
       
   969     return request.state == EC_REQUEST_SUCCESS ? 0 : -EIO;
       
   970 }
       
   971 
       
   972 /*****************************************************************************/
       
   973 
       
   974 /** Get slave configuration information.
       
   975  */
       
   976 int ec_cdev_ioctl_config(
       
   977         ec_master_t *master, /**< EtherCAT master. */
       
   978         unsigned long arg /**< ioctl() argument. */
       
   979         )
       
   980 {
       
   981     ec_ioctl_config_t data;
       
   982     const ec_slave_config_t *sc;
       
   983     uint8_t i;
       
   984 
       
   985     if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
       
   986         return -EFAULT;
       
   987     }
       
   988 
       
   989     down(&master->master_sem);
       
   990 
       
   991     if (!(sc = ec_master_get_config_const(
       
   992                     master, data.config_index))) {
       
   993         up(&master->master_sem);
       
   994         EC_ERR("Slave config %u does not exist!\n",
       
   995                 data.config_index);
       
   996         return -EINVAL;
       
   997     }
       
   998 
       
   999     data.alias = sc->alias;
       
  1000     data.position = sc->position;
       
  1001     data.vendor_id = sc->vendor_id;
       
  1002     data.product_code = sc->product_code;
       
  1003     for (i = 0; i < EC_MAX_SYNCS; i++) {
       
  1004         data.syncs[i].dir = sc->sync_configs[i].dir;
       
  1005         data.syncs[i].pdo_count =
       
  1006             ec_pdo_list_count(&sc->sync_configs[i].pdos);
       
  1007     }
       
  1008     data.sdo_count = ec_slave_config_sdo_count(sc);
       
  1009     data.attached = sc->slave != NULL;
       
  1010     data.operational = sc->slave &&
       
  1011         sc->slave->current_state == EC_SLAVE_STATE_OP;
       
  1012 
       
  1013     up(&master->master_sem);
       
  1014 
       
  1015     if (copy_to_user((void __user *) arg, &data, sizeof(data)))
       
  1016         return -EFAULT;
       
  1017 
       
  1018     return 0;
       
  1019 }
       
  1020 
       
  1021 /*****************************************************************************/
       
  1022 
       
  1023 /** Get slave configuration Pdo information.
       
  1024  */
       
  1025 int ec_cdev_ioctl_config_pdo(
       
  1026         ec_master_t *master, /**< EtherCAT master. */
       
  1027         unsigned long arg /**< ioctl() argument. */
       
  1028         )
       
  1029 {
       
  1030     ec_ioctl_config_pdo_t data;
       
  1031     const ec_slave_config_t *sc;
       
  1032     const ec_pdo_t *pdo;
       
  1033 
       
  1034     if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
       
  1035         return -EFAULT;
       
  1036     }
       
  1037 
       
  1038     if (data.sync_index >= EC_MAX_SYNCS) {
       
  1039         EC_ERR("Invalid sync manager index %u!\n",
       
  1040                 data.sync_index);
       
  1041         return -EINVAL;
       
  1042     }
       
  1043 
       
  1044     down(&master->master_sem);
       
  1045 
       
  1046     if (!(sc = ec_master_get_config_const(
       
  1047                     master, data.config_index))) {
       
  1048         up(&master->master_sem);
       
  1049         EC_ERR("Slave config %u does not exist!\n",
       
  1050                 data.config_index);
       
  1051         return -EINVAL;
       
  1052     }
       
  1053 
       
  1054     if (!(pdo = ec_pdo_list_find_pdo_by_pos_const(
       
  1055                     &sc->sync_configs[data.sync_index].pdos,
       
  1056                     data.pdo_pos))) {
       
  1057         up(&master->master_sem);
       
  1058         EC_ERR("Invalid Pdo position!\n");
       
  1059         return -EINVAL;
       
  1060     }
       
  1061 
       
  1062     data.index = pdo->index;
       
  1063     data.entry_count = ec_pdo_entry_count(pdo);
       
  1064 
       
  1065     if (pdo->name) {
       
  1066         strncpy(data.name, pdo->name, EC_IOCTL_STRING_SIZE);
       
  1067         data.name[EC_IOCTL_STRING_SIZE - 1] = 0;
       
  1068     } else {
       
  1069         data.name[0] = 0;
       
  1070     }
       
  1071 
       
  1072     up(&master->master_sem);
       
  1073 
       
  1074     if (copy_to_user((void __user *) arg, &data, sizeof(data)))
       
  1075         return -EFAULT;
       
  1076 
       
  1077     return 0;
       
  1078 }
       
  1079 
       
  1080 /*****************************************************************************/
       
  1081 
       
  1082 /** Get slave configuration Pdo entry information.
       
  1083  */
       
  1084 int ec_cdev_ioctl_config_pdo_entry(
       
  1085         ec_master_t *master, /**< EtherCAT master. */
       
  1086         unsigned long arg /**< ioctl() argument. */
       
  1087         )
       
  1088 {
       
  1089     ec_ioctl_config_pdo_entry_t data;
       
  1090     const ec_slave_config_t *sc;
       
  1091     const ec_pdo_t *pdo;
       
  1092     const ec_pdo_entry_t *entry;
       
  1093 
       
  1094     if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
       
  1095         return -EFAULT;
       
  1096     }
       
  1097 
       
  1098     if (data.sync_index >= EC_MAX_SYNCS) {
       
  1099         EC_ERR("Invalid sync manager index %u!\n",
       
  1100                 data.sync_index);
       
  1101         return -EINVAL;
       
  1102     }
       
  1103 
       
  1104     down(&master->master_sem);
       
  1105 
       
  1106     if (!(sc = ec_master_get_config_const(
       
  1107                     master, data.config_index))) {
       
  1108         up(&master->master_sem);
       
  1109         EC_ERR("Slave config %u does not exist!\n",
       
  1110                 data.config_index);
       
  1111         return -EINVAL;
       
  1112     }
       
  1113 
       
  1114     if (!(pdo = ec_pdo_list_find_pdo_by_pos_const(
       
  1115                     &sc->sync_configs[data.sync_index].pdos,
       
  1116                     data.pdo_pos))) {
       
  1117         up(&master->master_sem);
       
  1118         EC_ERR("Invalid Pdo position!\n");
       
  1119         return -EINVAL;
       
  1120     }
       
  1121 
       
  1122     if (!(entry = ec_pdo_find_entry_by_pos_const(
       
  1123                     pdo, data.entry_pos))) {
       
  1124         up(&master->master_sem);
       
  1125         EC_ERR("Entry not found!\n");
       
  1126         return -EINVAL;
       
  1127     }
       
  1128 
       
  1129     data.index = entry->index;
       
  1130     data.subindex = entry->subindex;
       
  1131     data.bit_length = entry->bit_length;
       
  1132     if (entry->name) {
       
  1133         strncpy(data.name, entry->name, EC_IOCTL_STRING_SIZE);
       
  1134         data.name[EC_IOCTL_STRING_SIZE - 1] = 0;
       
  1135     } else {
       
  1136         data.name[0] = 0;
       
  1137     }
       
  1138 
       
  1139     up(&master->master_sem);
       
  1140 
       
  1141     if (copy_to_user((void __user *) arg, &data, sizeof(data)))
       
  1142         return -EFAULT;
       
  1143 
       
  1144     return 0;
       
  1145 }
       
  1146 
       
  1147 /*****************************************************************************/
       
  1148 
       
  1149 /** Get slave configuration Sdo information.
       
  1150  */
       
  1151 int ec_cdev_ioctl_config_sdo(
       
  1152         ec_master_t *master, /**< EtherCAT master. */
       
  1153         unsigned long arg /**< ioctl() argument. */
       
  1154         )
       
  1155 {
       
  1156     ec_ioctl_config_sdo_t data;
       
  1157     const ec_slave_config_t *sc;
       
  1158     const ec_sdo_request_t *req;
       
  1159 
       
  1160     if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
       
  1161         return -EFAULT;
       
  1162     }
       
  1163 
       
  1164     down(&master->master_sem);
       
  1165 
       
  1166     if (!(sc = ec_master_get_config_const(
       
  1167                     master, data.config_index))) {
       
  1168         up(&master->master_sem);
       
  1169         EC_ERR("Slave config %u does not exist!\n",
       
  1170                 data.config_index);
       
  1171         return -EINVAL;
       
  1172     }
       
  1173 
       
  1174     if (!(req = ec_slave_config_get_sdo_by_pos_const(
       
  1175                     sc, data.sdo_pos))) {
       
  1176         up(&master->master_sem);
       
  1177         EC_ERR("Invalid Sdo position!\n");
       
  1178         return -EINVAL;
       
  1179     }
       
  1180 
       
  1181     data.index = req->index;
       
  1182     data.subindex = req->subindex;
       
  1183     data.size = req->data_size;
       
  1184     memcpy(&data.data, req->data, min((u32) data.size, (u32) 4));
       
  1185 
       
  1186     up(&master->master_sem);
       
  1187 
       
  1188     if (copy_to_user((void __user *) arg, &data, sizeof(data)))
       
  1189         return -EFAULT;
       
  1190 
       
  1191     return 0;
       
  1192 }
       
  1193 
   102 /******************************************************************************
  1194 /******************************************************************************
   103  * File operations
  1195  * File operations
   104  *****************************************************************************/
  1196  *****************************************************************************/
   105 
  1197 
   106 int eccdev_open(struct inode *inode, struct file *filp)
  1198 int eccdev_open(struct inode *inode, struct file *filp)
   130 
  1222 
   131 long eccdev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
  1223 long eccdev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
   132 {
  1224 {
   133     ec_cdev_t *cdev = (ec_cdev_t *) filp->private_data;
  1225     ec_cdev_t *cdev = (ec_cdev_t *) filp->private_data;
   134     ec_master_t *master = cdev->master;
  1226     ec_master_t *master = cdev->master;
   135     long retval = 0;
       
   136 
  1227 
   137     if (master->debug_level)
  1228     if (master->debug_level)
   138         EC_DBG("ioctl(filp = %x, cmd = %u (%u), arg = %x)\n",
  1229         EC_DBG("ioctl(filp = %x, cmd = %u (%u), arg = %x)\n",
   139                 (u32) filp, (u32) cmd, (u32) _IOC_NR(cmd), (u32) arg);
  1230                 (u32) filp, (u32) cmd, (u32) _IOC_NR(cmd), (u32) arg);
   140 
  1231 
   141     down(&master->master_sem);
       
   142 
       
   143     switch (cmd) {
  1232     switch (cmd) {
   144         case EC_IOCTL_MASTER:
  1233         case EC_IOCTL_MASTER:
   145             {
  1234             return ec_cdev_ioctl_master(master, arg);
   146                 ec_ioctl_master_t data;
       
   147 
       
   148                 data.slave_count = master->slave_count;
       
   149                 data.config_count = ec_master_config_count(master);
       
   150                 data.domain_count = ec_master_domain_count(master);
       
   151                 data.phase = (uint8_t) master->phase;
       
   152                 
       
   153                 memcpy(data.devices[0].address, master->main_mac, ETH_ALEN); 
       
   154                 data.devices[0].attached = master->main_device.dev ? 1 : 0;
       
   155                 data.devices[0].tx_count = master->main_device.tx_count;
       
   156                 data.devices[0].rx_count = master->main_device.rx_count;
       
   157                 memcpy(data.devices[1].address, master->backup_mac, ETH_ALEN); 
       
   158                 data.devices[1].attached = master->backup_device.dev ? 1 : 0;
       
   159                 data.devices[1].tx_count = master->backup_device.tx_count;
       
   160                 data.devices[1].rx_count = master->backup_device.rx_count;
       
   161 
       
   162                 if (copy_to_user((void __user *) arg, &data, sizeof(data)))
       
   163                     retval = -EFAULT;
       
   164                 break;
       
   165             }
       
   166 
       
   167         case EC_IOCTL_SLAVE:
  1235         case EC_IOCTL_SLAVE:
   168             {
  1236             return ec_cdev_ioctl_slave(master, arg);
   169                 ec_ioctl_slave_t data;
  1237         case EC_IOCTL_SLAVE_SYNC:
   170                 const ec_slave_t *slave;
  1238             return ec_cdev_ioctl_slave_sync(master, arg);
   171 
  1239         case EC_IOCTL_SLAVE_SYNC_PDO:
   172                 if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
  1240             return ec_cdev_ioctl_slave_sync_pdo(master, arg);
   173                     retval = -EFAULT;
  1241         case EC_IOCTL_SLAVE_SYNC_PDO_ENTRY:
   174                     break;
  1242             return ec_cdev_ioctl_slave_sync_pdo_entry(master, arg);
   175                 }
       
   176 
       
   177                 if (!(slave = ec_master_find_slave(
       
   178                                 master, 0, data.position))) {
       
   179                     EC_ERR("Slave %u does not exist!\n", data.position);
       
   180                     retval = -EINVAL;
       
   181                     break;
       
   182                 }
       
   183 
       
   184                 data.vendor_id = slave->sii.vendor_id;
       
   185                 data.product_code = slave->sii.product_code;
       
   186                 data.revision_number = slave->sii.revision_number;
       
   187                 data.serial_number = slave->sii.serial_number;
       
   188                 data.alias = slave->sii.alias;
       
   189                 data.rx_mailbox_offset = slave->sii.rx_mailbox_offset;
       
   190                 data.rx_mailbox_size = slave->sii.rx_mailbox_size;
       
   191                 data.tx_mailbox_offset = slave->sii.tx_mailbox_offset;
       
   192                 data.tx_mailbox_size = slave->sii.tx_mailbox_size;
       
   193                 data.mailbox_protocols = slave->sii.mailbox_protocols;
       
   194                 data.has_general_category = slave->sii.has_general;
       
   195                 data.coe_details = slave->sii.coe_details;
       
   196                 data.general_flags = slave->sii.general_flags;
       
   197                 data.current_on_ebus = slave->sii.current_on_ebus;
       
   198                 data.state = slave->current_state;
       
   199                 data.error_flag = slave->error_flag;
       
   200 
       
   201                 data.sync_count = slave->sii.sync_count;
       
   202                 data.sdo_count = ec_slave_sdo_count(slave);
       
   203                 data.sii_nwords = slave->sii_nwords;
       
   204 
       
   205                 if (slave->sii.name) {
       
   206                     strncpy(data.name, slave->sii.name,
       
   207                             EC_IOCTL_STRING_SIZE);
       
   208                     data.name[EC_IOCTL_STRING_SIZE - 1] = 0;
       
   209                 } else {
       
   210                     data.name[0] = 0;
       
   211                 }
       
   212 
       
   213                 if (copy_to_user((void __user *) arg, &data, sizeof(data)))
       
   214                     retval = -EFAULT;
       
   215                 break;
       
   216             }
       
   217 
       
   218         case EC_IOCTL_SYNC:
       
   219             {
       
   220                 ec_ioctl_sync_t data;
       
   221                 const ec_slave_t *slave;
       
   222                 const ec_sync_t *sync;
       
   223 
       
   224                 if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
       
   225                     retval = -EFAULT;
       
   226                     break;
       
   227                 }
       
   228                 
       
   229                 if (!(slave = ec_master_find_slave(
       
   230                                 master, 0, data.slave_position))) {
       
   231                     EC_ERR("Slave %u does not exist!\n", data.slave_position);
       
   232                     retval = -EINVAL;
       
   233                     break;
       
   234                 }
       
   235 
       
   236                 if (data.sync_index >= slave->sii.sync_count) {
       
   237                     EC_ERR("Sync manager %u does not exist in slave %u!\n",
       
   238                             data.sync_index, data.slave_position);
       
   239                     retval = -EINVAL;
       
   240                     break;
       
   241                 }
       
   242 
       
   243                 sync = &slave->sii.syncs[data.sync_index];
       
   244 
       
   245                 data.physical_start_address = sync->physical_start_address;
       
   246                 data.default_size = sync->default_length;
       
   247                 data.control_register = sync->control_register;
       
   248                 data.enable = sync->enable;
       
   249                 data.assign_source = sync->assign_source;
       
   250                 data.pdo_count = ec_pdo_list_count(&sync->pdos);
       
   251 
       
   252                 if (copy_to_user((void __user *) arg, &data, sizeof(data)))
       
   253                     retval = -EFAULT;
       
   254                 break;
       
   255             }
       
   256 
       
   257         case EC_IOCTL_PDO:
       
   258             {
       
   259                 ec_ioctl_pdo_t data;
       
   260                 const ec_slave_t *slave;
       
   261                 const ec_sync_t *sync;
       
   262                 const ec_pdo_t *pdo;
       
   263 
       
   264                 if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
       
   265                     retval = -EFAULT;
       
   266                     break;
       
   267                 }
       
   268                 
       
   269                 if (!(slave = ec_master_find_slave(
       
   270                                 master, 0, data.slave_position))) {
       
   271                     EC_ERR("Slave %u does not exist!\n", data.slave_position);
       
   272                     retval = -EINVAL;
       
   273                     break;
       
   274                 }
       
   275 
       
   276                 if (data.sync_index >= slave->sii.sync_count) {
       
   277                     EC_ERR("Sync manager %u does not exist in slave %u!\n",
       
   278                             data.sync_index, data.slave_position);
       
   279                     retval = -EINVAL;
       
   280                     break;
       
   281                 }
       
   282 
       
   283                 sync = &slave->sii.syncs[data.sync_index];
       
   284                 if (!(pdo = ec_pdo_list_find_pdo_by_pos_const(
       
   285                                 &sync->pdos, data.pdo_pos))) {
       
   286                     EC_ERR("Sync manager %u does not contain a Pdo with "
       
   287                             "position %u in slave %u!\n", data.sync_index,
       
   288                             data.pdo_pos, data.slave_position);
       
   289                     retval = -EINVAL;
       
   290                     break;
       
   291                 }
       
   292 
       
   293                 data.index = pdo->index;
       
   294                 data.entry_count = ec_pdo_entry_count(pdo);
       
   295 
       
   296                 if (pdo->name) {
       
   297                     strncpy(data.name, pdo->name, EC_IOCTL_STRING_SIZE);
       
   298                     data.name[EC_IOCTL_STRING_SIZE - 1] = 0;
       
   299                 } else {
       
   300                     data.name[0] = 0;
       
   301                 }
       
   302 
       
   303                 if (copy_to_user((void __user *) arg, &data, sizeof(data)))
       
   304                     retval = -EFAULT;
       
   305                 break;
       
   306             }
       
   307 
       
   308         case EC_IOCTL_PDO_ENTRY:
       
   309             {
       
   310                 ec_ioctl_pdo_entry_t data;
       
   311                 const ec_slave_t *slave;
       
   312                 const ec_sync_t *sync;
       
   313                 const ec_pdo_t *pdo;
       
   314                 const ec_pdo_entry_t *entry;
       
   315 
       
   316                 if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
       
   317                     retval = -EFAULT;
       
   318                     break;
       
   319                 }
       
   320                 
       
   321                 if (!(slave = ec_master_find_slave(
       
   322                                 master, 0, data.slave_position))) {
       
   323                     EC_ERR("Slave %u does not exist!\n", data.slave_position);
       
   324                     retval = -EINVAL;
       
   325                     break;
       
   326                 }
       
   327 
       
   328                 if (data.sync_index >= slave->sii.sync_count) {
       
   329                     EC_ERR("Sync manager %u does not exist in slave %u!\n",
       
   330                             data.sync_index, data.slave_position);
       
   331                     retval = -EINVAL;
       
   332                     break;
       
   333                 }
       
   334 
       
   335                 sync = &slave->sii.syncs[data.sync_index];
       
   336                 if (!(pdo = ec_pdo_list_find_pdo_by_pos_const(
       
   337                                 &sync->pdos, data.pdo_pos))) {
       
   338                     EC_ERR("Sync manager %u does not contain a Pdo with "
       
   339                             "position %u in slave %u!\n", data.sync_index,
       
   340                             data.pdo_pos, data.slave_position);
       
   341                     retval = -EINVAL;
       
   342                     break;
       
   343                 }
       
   344 
       
   345                 if (!(entry = ec_pdo_find_entry_by_pos_const(
       
   346                                 pdo, data.entry_pos))) {
       
   347                     EC_ERR("Pdo 0x%04X does not contain an entry with "
       
   348                             "position %u in slave %u!\n", data.pdo_pos,
       
   349                             data.entry_pos, data.slave_position);
       
   350                     retval = -EINVAL;
       
   351                     break;
       
   352                 }
       
   353 
       
   354                 data.index = entry->index;
       
   355                 data.subindex = entry->subindex;
       
   356                 data.bit_length = entry->bit_length;
       
   357                 if (entry->name) {
       
   358                     strncpy(data.name, entry->name, EC_IOCTL_STRING_SIZE);
       
   359                     data.name[EC_IOCTL_STRING_SIZE - 1] = 0;
       
   360                 } else {
       
   361                     data.name[0] = 0;
       
   362                 }
       
   363 
       
   364                 if (copy_to_user((void __user *) arg, &data, sizeof(data)))
       
   365                     retval = -EFAULT;
       
   366                 break;
       
   367             }
       
   368 
       
   369         case EC_IOCTL_DOMAIN:
  1243         case EC_IOCTL_DOMAIN:
   370             {
  1244             return ec_cdev_ioctl_domain(master, arg);
   371                 ec_ioctl_domain_t data;
       
   372                 const ec_domain_t *domain;
       
   373 
       
   374                 if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
       
   375                     retval = -EFAULT;
       
   376                     break;
       
   377                 }
       
   378                 
       
   379                 if (!(domain = ec_master_find_domain(master, data.index))) {
       
   380                     EC_ERR("Domain %u does not exist!\n", data.index);
       
   381                     retval = -EINVAL;
       
   382                     break;
       
   383                 }
       
   384 
       
   385                 data.data_size = domain->data_size;
       
   386                 data.logical_base_address = domain->logical_base_address;
       
   387                 data.working_counter = domain->working_counter;
       
   388                 data.expected_working_counter = domain->expected_working_counter;
       
   389                 data.fmmu_count = ec_domain_fmmu_count(domain);
       
   390 
       
   391                 if (copy_to_user((void __user *) arg, &data, sizeof(data)))
       
   392                     retval = -EFAULT;
       
   393                 break;
       
   394             }
       
   395 
       
   396         case EC_IOCTL_DOMAIN_FMMU:
  1245         case EC_IOCTL_DOMAIN_FMMU:
   397             {
  1246             return ec_cdev_ioctl_domain_fmmu(master, arg);
   398                 ec_ioctl_domain_fmmu_t data;
  1247         case EC_IOCTL_DOMAIN_DATA:
   399                 const ec_domain_t *domain;
  1248             return ec_cdev_ioctl_domain_data(master, arg);
   400                 const ec_fmmu_config_t *fmmu;
  1249         case EC_IOCTL_MASTER_DEBUG:
   401 
       
   402                 if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
       
   403                     retval = -EFAULT;
       
   404                     break;
       
   405                 }
       
   406                 
       
   407                 if (!(domain = ec_master_find_domain(master, data.domain_index))) {
       
   408                     EC_ERR("Domain %u does not exist!\n", data.domain_index);
       
   409                     retval = -EINVAL;
       
   410                     break;
       
   411                 }
       
   412 
       
   413                 if (!(fmmu = ec_domain_find_fmmu(domain, data.fmmu_index))) {
       
   414                     EC_ERR("Domain %u has less than %u fmmu configurations.\n",
       
   415                             data.domain_index, data.fmmu_index + 1);
       
   416                     retval = -EINVAL;
       
   417                     break;
       
   418                 }
       
   419 
       
   420                 data.slave_config_alias = fmmu->sc->alias;
       
   421                 data.slave_config_position = fmmu->sc->position;
       
   422                 data.sync_index = fmmu->sync_index;
       
   423                 data.dir = fmmu->dir;
       
   424                 data.logical_address = fmmu->logical_start_address;
       
   425                 data.data_size = fmmu->data_size;
       
   426 
       
   427                 if (copy_to_user((void __user *) arg, &data, sizeof(data)))
       
   428                     retval = -EFAULT;
       
   429                 break;
       
   430             }
       
   431 
       
   432         case EC_IOCTL_DATA:
       
   433             {
       
   434                 ec_ioctl_data_t data;
       
   435                 const ec_domain_t *domain;
       
   436 
       
   437                 if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
       
   438                     retval = -EFAULT;
       
   439                     break;
       
   440                 }
       
   441                 
       
   442                 if (!(domain = ec_master_find_domain(master, data.domain_index))) {
       
   443                     EC_ERR("Domain %u does not exist!\n", data.domain_index);
       
   444                     retval = -EINVAL;
       
   445                     break;
       
   446                 }
       
   447 
       
   448                 if (domain->data_size != data.data_size) {
       
   449                     EC_ERR("Data size mismatch %u/%u!\n",
       
   450                             data.data_size, domain->data_size);
       
   451                     retval = -EFAULT;
       
   452                     break;
       
   453                 }
       
   454 
       
   455                 if (copy_to_user((void __user *) data.target, domain->data,
       
   456                             domain->data_size))
       
   457                     retval = -EFAULT;
       
   458                 break;
       
   459             }
       
   460 
       
   461         case EC_IOCTL_SET_DEBUG:
       
   462             if (!(filp->f_mode & FMODE_WRITE))
  1250             if (!(filp->f_mode & FMODE_WRITE))
   463                 return -EPERM;
  1251                 return -EPERM;
   464             if (ec_master_debug_level(master, (unsigned int) arg))
  1252             return ec_cdev_ioctl_master_debug(master, arg);
   465                 retval = -EINVAL;
       
   466             break;
       
   467 
       
   468         case EC_IOCTL_SLAVE_STATE:
  1253         case EC_IOCTL_SLAVE_STATE:
   469             {
  1254             if (!(filp->f_mode & FMODE_WRITE))
   470                 ec_ioctl_slave_state_t data;
  1255                 return -EPERM;
   471                 ec_slave_t *slave;
  1256             return ec_cdev_ioctl_slave_state(master, arg);
   472 
  1257         case EC_IOCTL_SLAVE_SDO:
   473                 if (!(filp->f_mode & FMODE_WRITE))
  1258             return ec_cdev_ioctl_slave_sdo(master, arg);
   474                     return -EPERM;
  1259         case EC_IOCTL_SLAVE_SDO_ENTRY:
   475 
  1260             return ec_cdev_ioctl_slave_sdo_entry(master, arg);
   476                 if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
  1261         case EC_IOCTL_SLAVE_SDO_UPLOAD:
   477                     retval = -EFAULT;
  1262             return ec_cdev_ioctl_slave_sdo_upload(master, arg);
   478                     break;
  1263         case EC_IOCTL_SLAVE_SDO_DOWNLOAD:
   479                 }
  1264             if (!(filp->f_mode & FMODE_WRITE))
   480                 
  1265                 return -EPERM;
   481                 if (!(slave = ec_master_find_slave(
  1266             return ec_cdev_ioctl_slave_sdo_download(master, arg);
   482                                 master, 0, data.slave_position))) {
  1267         case EC_IOCTL_SLAVE_SII_READ:
   483                     EC_ERR("Slave %u does not exist!\n", data.slave_position);
  1268             return ec_cdev_ioctl_slave_sii_read(master, arg);
   484                     retval = -EINVAL;
  1269         case EC_IOCTL_SLAVE_SII_WRITE:
   485                     break;
  1270             if (!(filp->f_mode & FMODE_WRITE))
   486                 }
  1271                 return -EPERM;
   487 
  1272             return ec_cdev_ioctl_slave_sii_write(master, arg);
   488                 ec_slave_request_state(slave, data.requested_state);
       
   489                 break;
       
   490             }
       
   491 
       
   492         case EC_IOCTL_SDO:
       
   493             {
       
   494                 ec_ioctl_sdo_t data;
       
   495                 const ec_slave_t *slave;
       
   496                 const ec_sdo_t *sdo;
       
   497 
       
   498                 if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
       
   499                     retval = -EFAULT;
       
   500                     break;
       
   501                 }
       
   502                 
       
   503                 if (!(slave = ec_master_find_slave(
       
   504                                 master, 0, data.slave_position))) {
       
   505                     EC_ERR("Slave %u does not exist!\n", data.slave_position);
       
   506                     retval = -EINVAL;
       
   507                     break;
       
   508                 }
       
   509 
       
   510                 if (!(sdo = ec_slave_get_sdo_by_pos_const(
       
   511                                 slave, data.sdo_position))) {
       
   512                     EC_ERR("Sdo %u does not exist in slave %u!\n",
       
   513                             data.sdo_position, data.slave_position);
       
   514                     retval = -EINVAL;
       
   515                     break;
       
   516                 }
       
   517 
       
   518                 data.sdo_index = sdo->index;
       
   519                 data.max_subindex = sdo->max_subindex;
       
   520 
       
   521                 if (sdo->name) {
       
   522                     strncpy(data.name, sdo->name, EC_IOCTL_STRING_SIZE);
       
   523                     data.name[EC_IOCTL_STRING_SIZE - 1] = 0;
       
   524                 } else {
       
   525                     data.name[0] = 0;
       
   526                 }
       
   527 
       
   528                 if (copy_to_user((void __user *) arg, &data, sizeof(data)))
       
   529                     retval = -EFAULT;
       
   530                 break;
       
   531             }
       
   532 
       
   533         case EC_IOCTL_SDO_ENTRY:
       
   534             {
       
   535                 ec_ioctl_sdo_entry_t data;
       
   536                 const ec_slave_t *slave;
       
   537                 const ec_sdo_t *sdo;
       
   538                 const ec_sdo_entry_t *entry;
       
   539 
       
   540                 if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
       
   541                     retval = -EFAULT;
       
   542                     break;
       
   543                 }
       
   544                 
       
   545                 if (!(slave = ec_master_find_slave(
       
   546                                 master, 0, data.slave_position))) {
       
   547                     EC_ERR("Slave %u does not exist!\n", data.slave_position);
       
   548                     retval = -EINVAL;
       
   549                     break;
       
   550                 }
       
   551 
       
   552                 if (data.sdo_spec <= 0) {
       
   553                     if (!(sdo = ec_slave_get_sdo_by_pos_const(
       
   554                                     slave, -data.sdo_spec))) {
       
   555                         EC_ERR("Sdo %u does not exist in slave %u!\n",
       
   556                                 -data.sdo_spec, data.slave_position);
       
   557                         retval = -EINVAL;
       
   558                         break;
       
   559                     }
       
   560                 } else {
       
   561                     if (!(sdo = ec_slave_get_sdo_const(
       
   562                                     slave, data.sdo_spec))) {
       
   563                         EC_ERR("Sdo 0x%04X does not exist in slave %u!\n",
       
   564                                 data.sdo_spec, data.slave_position);
       
   565                         retval = -EINVAL;
       
   566                         break;
       
   567                     }
       
   568                 }
       
   569 
       
   570                 if (!(entry = ec_sdo_get_entry_const(
       
   571                                 sdo, data.sdo_entry_subindex))) {
       
   572                     EC_ERR("Sdo entry 0x%04X:%02X does not exist "
       
   573                             "in slave %u!\n", sdo->index,
       
   574                             data.sdo_entry_subindex, data.slave_position);
       
   575                     retval = -EINVAL;
       
   576                     break;
       
   577                 }
       
   578 
       
   579                 data.data_type = entry->data_type;
       
   580                 data.bit_length = entry->bit_length;
       
   581 
       
   582                 if (entry->description) {
       
   583                     strncpy(data.description, entry->description,
       
   584                             EC_IOCTL_STRING_SIZE);
       
   585                     data.description[EC_IOCTL_STRING_SIZE - 1]
       
   586                         = 0;
       
   587                 } else {
       
   588                     data.description[0] = 0;
       
   589                 }
       
   590 
       
   591                 if (copy_to_user((void __user *) arg, &data, sizeof(data)))
       
   592                     retval = -EFAULT;
       
   593                 break;
       
   594             }
       
   595 
       
   596         case EC_IOCTL_SDO_UPLOAD:
       
   597             {
       
   598                 ec_ioctl_sdo_upload_t data;
       
   599                 ec_master_sdo_request_t request;
       
   600 
       
   601                 if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
       
   602                     retval = -EFAULT;
       
   603                     break;
       
   604                 }
       
   605                 
       
   606                 if (!(request.slave = ec_master_find_slave(
       
   607                                 master, 0, data.slave_position))) {
       
   608                     EC_ERR("Slave %u does not exist!\n", data.slave_position);
       
   609                     retval = -EINVAL;
       
   610                     break;
       
   611                 }
       
   612 
       
   613                 ec_sdo_request_init(&request.req);
       
   614                 ec_sdo_request_address(&request.req,
       
   615                         data.sdo_index, data.sdo_entry_subindex);
       
   616                 ecrt_sdo_request_read(&request.req);
       
   617 
       
   618                 // schedule request.
       
   619                 down(&master->sdo_sem);
       
   620                 list_add_tail(&request.list, &master->slave_sdo_requests);
       
   621                 up(&master->sdo_sem);
       
   622 
       
   623                 // wait for processing through FSM
       
   624                 if (wait_event_interruptible(master->sdo_queue,
       
   625                             request.req.state != EC_REQUEST_QUEUED)) {
       
   626                     // interrupted by signal
       
   627                     down(&master->sdo_sem);
       
   628                     if (request.req.state == EC_REQUEST_QUEUED) {
       
   629                         list_del(&request.req.list);
       
   630                         up(&master->sdo_sem);
       
   631                         ec_sdo_request_clear(&request.req);
       
   632                         retval = -EINTR;
       
   633                         break;
       
   634                     }
       
   635                     // request already processing: interrupt not possible.
       
   636                     up(&master->sdo_sem);
       
   637                 }
       
   638 
       
   639                 // wait until master FSM has finished processing
       
   640                 wait_event(master->sdo_queue, request.req.state != EC_REQUEST_BUSY);
       
   641                 
       
   642                 data.abort_code = request.req.abort_code;
       
   643 
       
   644                 if (request.req.state != EC_REQUEST_SUCCESS) {
       
   645                     data.data_size = 0;
       
   646                     retval = -EIO;
       
   647                 } else {
       
   648                     if (request.req.data_size > data.target_size) {
       
   649                         EC_ERR("Buffer too small.\n");
       
   650                         ec_sdo_request_clear(&request.req);
       
   651                         retval = -EOVERFLOW;
       
   652                         break;
       
   653                     }
       
   654                     data.data_size = request.req.data_size;
       
   655 
       
   656                     if (copy_to_user((void __user *) data.target,
       
   657                                 request.req.data, data.data_size)) {
       
   658                         ec_sdo_request_clear(&request.req);
       
   659                         retval = -EFAULT;
       
   660                         break;
       
   661                     }
       
   662                 }
       
   663 
       
   664                 if (__copy_to_user((void __user *) arg, &data, sizeof(data))) {
       
   665                     retval = -EFAULT;
       
   666                 }
       
   667 
       
   668                 ec_sdo_request_clear(&request.req);
       
   669                 break;
       
   670             }
       
   671 
       
   672         case EC_IOCTL_SDO_DOWNLOAD:
       
   673             {
       
   674                 ec_ioctl_sdo_download_t data;
       
   675                 ec_master_sdo_request_t request;
       
   676 
       
   677                 if (!(filp->f_mode & FMODE_WRITE))
       
   678                     return -EPERM;
       
   679 
       
   680                 if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
       
   681                     retval = -EFAULT;
       
   682                     break;
       
   683                 }
       
   684                 
       
   685                 if (!(request.slave = ec_master_find_slave(
       
   686                                 master, 0, data.slave_position))) {
       
   687                     EC_ERR("Slave %u does not exist!\n", data.slave_position);
       
   688                     retval = -EINVAL;
       
   689                     break;
       
   690                 }
       
   691 
       
   692                 // copy data to download
       
   693                 if (!data.data_size) {
       
   694                     EC_ERR("Zero data size!\n");
       
   695                     retval = -EINVAL;
       
   696                     break;
       
   697                 }
       
   698 
       
   699                 ec_sdo_request_init(&request.req);
       
   700                 ec_sdo_request_address(&request.req,
       
   701                         data.sdo_index, data.sdo_entry_subindex);
       
   702                 if (ec_sdo_request_alloc(&request.req, data.data_size)) {
       
   703                     ec_sdo_request_clear(&request.req);
       
   704                     retval = -ENOMEM;
       
   705                     break;
       
   706                 }
       
   707                 if (copy_from_user(request.req.data,
       
   708                             (void __user *) data.data, data.data_size)) {
       
   709                     ec_sdo_request_clear(&request.req);
       
   710                     retval = -EFAULT;
       
   711                     break;
       
   712                 }
       
   713                 request.req.data_size = data.data_size;
       
   714                 ecrt_sdo_request_write(&request.req);
       
   715 
       
   716                 // schedule request.
       
   717                 down(&master->sdo_sem);
       
   718                 list_add_tail(&request.list, &master->slave_sdo_requests);
       
   719                 up(&master->sdo_sem);
       
   720 
       
   721                 // wait for processing through FSM
       
   722                 if (wait_event_interruptible(master->sdo_queue,
       
   723                             request.req.state != EC_REQUEST_QUEUED)) {
       
   724                     // interrupted by signal
       
   725                     down(&master->sdo_sem);
       
   726                     if (request.req.state == EC_REQUEST_QUEUED) {
       
   727                         list_del(&request.req.list);
       
   728                         up(&master->sdo_sem);
       
   729                         ec_sdo_request_clear(&request.req);
       
   730                         retval = -EINTR;
       
   731                         break;
       
   732                     }
       
   733                     // request already processing: interrupt not possible.
       
   734                     up(&master->sdo_sem);
       
   735                 }
       
   736 
       
   737                 // wait until master FSM has finished processing
       
   738                 wait_event(master->sdo_queue, request.req.state != EC_REQUEST_BUSY);
       
   739 
       
   740                 data.abort_code = request.req.abort_code;
       
   741 
       
   742                 if (request.req.state != EC_REQUEST_SUCCESS) {
       
   743                     retval = -EIO;
       
   744                 }
       
   745 
       
   746                 if (__copy_to_user((void __user *) arg, &data, sizeof(data))) {
       
   747                     retval = -EFAULT;
       
   748                 }
       
   749 
       
   750                 ec_sdo_request_clear(&request.req);
       
   751                 break;
       
   752             }
       
   753 
       
   754         case EC_IOCTL_SII_READ:
       
   755             {
       
   756                 ec_ioctl_sii_t data;
       
   757                 const ec_slave_t *slave;
       
   758 
       
   759                 if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
       
   760                     retval = -EFAULT;
       
   761                     break;
       
   762                 }
       
   763                 
       
   764                 if (!(slave = ec_master_find_slave(
       
   765                                 master, 0, data.slave_position))) {
       
   766                     EC_ERR("Slave %u does not exist!\n", data.slave_position);
       
   767                     retval = -EINVAL;
       
   768                     break;
       
   769                 }
       
   770 
       
   771                 if (!data.nwords
       
   772                         || data.offset + data.nwords > slave->sii_nwords) {
       
   773                     EC_ERR("Invalid SII read offset/size %u/%u for slave "
       
   774                             "SII size %u!\n", data.offset,
       
   775                             data.nwords, slave->sii_nwords);
       
   776                     retval = -EINVAL;
       
   777                     break;
       
   778                 }
       
   779 
       
   780                 if (copy_to_user((void __user *) data.words,
       
   781                             slave->sii_words + data.offset, data.nwords * 2))
       
   782                     retval = -EFAULT;
       
   783                 break;
       
   784             }
       
   785 
       
   786         case EC_IOCTL_SII_WRITE:
       
   787             {
       
   788                 ec_ioctl_sii_t data;
       
   789                 ec_slave_t *slave;
       
   790                 unsigned int byte_size;
       
   791                 uint16_t *words;
       
   792 
       
   793                 if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
       
   794                     retval = -EFAULT;
       
   795                     break;
       
   796                 }
       
   797                 
       
   798                 if (!(slave = ec_master_find_slave(
       
   799                                 master, 0, data.slave_position))) {
       
   800                     EC_ERR("Slave %u does not exist!\n", data.slave_position);
       
   801                     retval = -EINVAL;
       
   802                     break;
       
   803                 }
       
   804 
       
   805                 if (!data.nwords)
       
   806                     break;
       
   807 
       
   808                 byte_size = sizeof(uint16_t) * data.nwords;
       
   809                 if (!(words = kmalloc(byte_size, GFP_KERNEL))) {
       
   810                     EC_ERR("Failed to allocate %u bytes for SII contents.\n",
       
   811                             byte_size);
       
   812                     retval = -ENOMEM;
       
   813                     break;
       
   814                 }
       
   815 
       
   816                 if (copy_from_user(words,
       
   817                             (void __user *) data.words, byte_size)) {
       
   818                     retval = -EFAULT;
       
   819                     kfree(words);
       
   820                     break;
       
   821                 }
       
   822 
       
   823                 if (ec_slave_write_sii(slave,
       
   824                             data.offset, data.nwords, words))
       
   825                     retval = -EIO;
       
   826 
       
   827                 kfree(words);
       
   828                 break;
       
   829             }
       
   830 
       
   831         case EC_IOCTL_CONFIG:
  1273         case EC_IOCTL_CONFIG:
   832             {
  1274             return ec_cdev_ioctl_config(master, arg);
   833                 ec_ioctl_config_t data;
       
   834                 const ec_slave_config_t *sc;
       
   835                 uint8_t i;
       
   836 
       
   837                 if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
       
   838                     retval = -EFAULT;
       
   839                     break;
       
   840                 }
       
   841                 
       
   842                 if (!(sc = ec_master_get_config_const(
       
   843                                 master, data.config_index))) {
       
   844                     EC_ERR("Slave config %u does not exist!\n",
       
   845                             data.config_index);
       
   846                     retval = -EINVAL;
       
   847                     break;
       
   848                 }
       
   849 
       
   850                 data.alias = sc->alias;
       
   851                 data.position = sc->position;
       
   852                 data.vendor_id = sc->vendor_id;
       
   853                 data.product_code = sc->product_code;
       
   854                 for (i = 0; i < EC_MAX_SYNCS; i++) {
       
   855                     data.syncs[i].dir = sc->sync_configs[i].dir;
       
   856                     data.syncs[i].pdo_count =
       
   857                         ec_pdo_list_count(&sc->sync_configs[i].pdos);
       
   858                 }
       
   859                 data.sdo_count = ec_slave_config_sdo_count(sc);
       
   860                 data.attached = sc->slave != NULL;
       
   861                 data.operational = sc->slave &&
       
   862                     sc->slave->current_state == EC_SLAVE_STATE_OP;
       
   863 
       
   864                 if (copy_to_user((void __user *) arg, &data, sizeof(data)))
       
   865                     retval = -EFAULT;
       
   866                 break;
       
   867             }
       
   868 
       
   869         case EC_IOCTL_CONFIG_PDO:
  1275         case EC_IOCTL_CONFIG_PDO:
   870             {
  1276             return ec_cdev_ioctl_config_pdo(master, arg);
   871                 ec_ioctl_config_pdo_t data;
       
   872                 const ec_slave_config_t *sc;
       
   873                 const ec_pdo_t *pdo;
       
   874 
       
   875                 if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
       
   876                     retval = -EFAULT;
       
   877                     break;
       
   878                 }
       
   879                 
       
   880                 if (!(sc = ec_master_get_config_const(
       
   881                                 master, data.config_index))) {
       
   882                     EC_ERR("Slave config %u does not exist!\n",
       
   883                             data.config_index);
       
   884                     retval = -EINVAL;
       
   885                     break;
       
   886                 }
       
   887 
       
   888                 if (data.sync_index >= EC_MAX_SYNCS) {
       
   889                     EC_ERR("Invalid sync manager index %u!\n",
       
   890                             data.sync_index);
       
   891                     retval = -EINVAL;
       
   892                     break;
       
   893                 }
       
   894                 
       
   895                 if (!(pdo = ec_pdo_list_find_pdo_by_pos_const(
       
   896                                 &sc->sync_configs[data.sync_index].pdos,
       
   897                                 data.pdo_pos))) {
       
   898                     EC_ERR("Invalid Pdo position!\n");
       
   899                     retval = -EINVAL;
       
   900                     break;
       
   901                 }
       
   902 
       
   903                 data.index = pdo->index;
       
   904                 data.entry_count = ec_pdo_entry_count(pdo);
       
   905 
       
   906                 if (pdo->name) {
       
   907                     strncpy(data.name, pdo->name, EC_IOCTL_STRING_SIZE);
       
   908                     data.name[EC_IOCTL_STRING_SIZE - 1] = 0;
       
   909                 } else {
       
   910                     data.name[0] = 0;
       
   911                 }
       
   912 
       
   913                 if (copy_to_user((void __user *) arg, &data, sizeof(data)))
       
   914                     retval = -EFAULT;
       
   915                 break;
       
   916             }
       
   917 
       
   918         case EC_IOCTL_CONFIG_PDO_ENTRY:
  1277         case EC_IOCTL_CONFIG_PDO_ENTRY:
   919             {
  1278             return ec_cdev_ioctl_config_pdo_entry(master, arg);
   920                 ec_ioctl_config_pdo_entry_t data;
       
   921                 const ec_slave_config_t *sc;
       
   922                 const ec_pdo_t *pdo;
       
   923                 const ec_pdo_entry_t *entry;
       
   924 
       
   925                 if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
       
   926                     retval = -EFAULT;
       
   927                     break;
       
   928                 }
       
   929                 
       
   930                 if (!(sc = ec_master_get_config_const(
       
   931                                 master, data.config_index))) {
       
   932                     EC_ERR("Slave config %u does not exist!\n",
       
   933                             data.config_index);
       
   934                     retval = -EINVAL;
       
   935                     break;
       
   936                 }
       
   937 
       
   938                 if (data.sync_index >= EC_MAX_SYNCS) {
       
   939                     EC_ERR("Invalid sync manager index %u!\n",
       
   940                             data.sync_index);
       
   941                     retval = -EINVAL;
       
   942                     break;
       
   943                 }
       
   944                 
       
   945                 if (!(pdo = ec_pdo_list_find_pdo_by_pos_const(
       
   946                                 &sc->sync_configs[data.sync_index].pdos,
       
   947                                 data.pdo_pos))) {
       
   948                     EC_ERR("Invalid Pdo position!\n");
       
   949                     retval = -EINVAL;
       
   950                     break;
       
   951                 }
       
   952 
       
   953                 if (!(entry = ec_pdo_find_entry_by_pos_const(
       
   954                                 pdo, data.entry_pos))) {
       
   955                     EC_ERR("Entry not found!\n");
       
   956                     retval = -EINVAL;
       
   957                     break;
       
   958                 }
       
   959 
       
   960                 data.index = entry->index;
       
   961                 data.subindex = entry->subindex;
       
   962                 data.bit_length = entry->bit_length;
       
   963                 if (entry->name) {
       
   964                     strncpy(data.name, entry->name, EC_IOCTL_STRING_SIZE);
       
   965                     data.name[EC_IOCTL_STRING_SIZE - 1] = 0;
       
   966                 } else {
       
   967                     data.name[0] = 0;
       
   968                 }
       
   969 
       
   970                 if (copy_to_user((void __user *) arg, &data, sizeof(data)))
       
   971                     retval = -EFAULT;
       
   972                 break;
       
   973             }
       
   974 
       
   975         case EC_IOCTL_CONFIG_SDO:
  1279         case EC_IOCTL_CONFIG_SDO:
   976             {
  1280             return ec_cdev_ioctl_config_sdo(master, arg);
   977                 ec_ioctl_config_sdo_t data;
       
   978                 const ec_slave_config_t *sc;
       
   979                 const ec_sdo_request_t *req;
       
   980 
       
   981                 if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
       
   982                     retval = -EFAULT;
       
   983                     break;
       
   984                 }
       
   985                 
       
   986                 if (!(sc = ec_master_get_config_const(
       
   987                                 master, data.config_index))) {
       
   988                     EC_ERR("Slave config %u does not exist!\n",
       
   989                             data.config_index);
       
   990                     retval = -EINVAL;
       
   991                     break;
       
   992                 }
       
   993 
       
   994                 if (!(req = ec_slave_config_get_sdo_by_pos_const(
       
   995                                 sc, data.sdo_pos))) {
       
   996                     EC_ERR("Invalid Sdo position!\n");
       
   997                     retval = -EINVAL;
       
   998                     break;
       
   999                 }
       
  1000 
       
  1001                 data.index = req->index;
       
  1002                 data.subindex = req->subindex;
       
  1003                 data.size = req->data_size;
       
  1004                 memcpy(&data.data, req->data, min((u32) data.size, (u32) 4));
       
  1005 
       
  1006                 if (copy_to_user((void __user *) arg, &data, sizeof(data)))
       
  1007                     retval = -EFAULT;
       
  1008                 break;
       
  1009             }
       
  1010 
       
  1011         default:
  1281         default:
  1012             retval = -ENOTTY;
  1282             return -ENOTTY;
  1013     }
  1283     }
  1014 
  1284 }
  1015     up(&master->master_sem);
  1285 
  1016     return retval;
  1286 /*****************************************************************************/
  1017 }
       
  1018 
       
  1019 /*****************************************************************************/