682 |
682 |
683 ec_sdo_request_clear(&request.req); |
683 ec_sdo_request_clear(&request.req); |
684 break; |
684 break; |
685 } |
685 } |
686 |
686 |
|
687 case EC_IOCTL_SDO_DOWNLOAD: |
|
688 { |
|
689 ec_ioctl_sdo_download_t data; |
|
690 ec_master_sdo_request_t request; |
|
691 |
|
692 if (!(filp->f_mode & FMODE_WRITE)) |
|
693 return -EPERM; |
|
694 |
|
695 if (copy_from_user(&data, (void __user *) arg, sizeof(data))) { |
|
696 retval = -EFAULT; |
|
697 break; |
|
698 } |
|
699 |
|
700 if (!(request.slave = ec_master_find_slave( |
|
701 master, 0, data.slave_position))) { |
|
702 EC_ERR("Slave %u does not exist!\n", data.slave_position); |
|
703 retval = -EINVAL; |
|
704 break; |
|
705 } |
|
706 |
|
707 // copy data to download |
|
708 if (!data.data_size) { |
|
709 EC_ERR("Zero data size!\n"); |
|
710 retval = -EINVAL; |
|
711 break; |
|
712 } |
|
713 |
|
714 ec_sdo_request_init(&request.req); |
|
715 ec_sdo_request_address(&request.req, |
|
716 data.sdo_index, data.sdo_entry_subindex); |
|
717 if (ec_sdo_request_alloc(&request.req, data.data_size)) { |
|
718 ec_sdo_request_clear(&request.req); |
|
719 retval = -ENOMEM; |
|
720 break; |
|
721 } |
|
722 if (copy_from_user(request.req.data, |
|
723 (void __user *) data.data, data.data_size)) { |
|
724 ec_sdo_request_clear(&request.req); |
|
725 retval = -EFAULT; |
|
726 break; |
|
727 } |
|
728 request.req.data_size = data.data_size; |
|
729 ecrt_sdo_request_write(&request.req); |
|
730 |
|
731 // schedule request. |
|
732 down(&master->sdo_sem); |
|
733 list_add_tail(&request.list, &master->slave_sdo_requests); |
|
734 up(&master->sdo_sem); |
|
735 |
|
736 // wait for processing through FSM |
|
737 if (wait_event_interruptible(master->sdo_queue, |
|
738 request.req.state != EC_REQUEST_QUEUED)) { |
|
739 // interrupted by signal |
|
740 down(&master->sdo_sem); |
|
741 if (request.req.state == EC_REQUEST_QUEUED) { |
|
742 list_del(&request.req.list); |
|
743 up(&master->sdo_sem); |
|
744 retval = -EINTR; |
|
745 break; |
|
746 } |
|
747 // request already processing: interrupt not possible. |
|
748 up(&master->sdo_sem); |
|
749 } |
|
750 |
|
751 // wait until master FSM has finished processing |
|
752 wait_event(master->sdo_queue, request.req.state != EC_REQUEST_BUSY); |
|
753 |
|
754 if (request.req.state != EC_REQUEST_SUCCESS) { |
|
755 retval = -EIO; |
|
756 break; |
|
757 } |
|
758 |
|
759 ec_sdo_request_clear(&request.req); |
|
760 break; |
|
761 } |
|
762 |
687 default: |
763 default: |
688 retval = -ENOTTY; |
764 retval = -ENOTTY; |
689 } |
765 } |
690 |
766 |
691 return retval; |
767 return retval; |