3564 static int ec_ioctl_slave_foe_read( |
3564 static int ec_ioctl_slave_foe_read( |
3565 ec_master_t *master, /**< EtherCAT master. */ |
3565 ec_master_t *master, /**< EtherCAT master. */ |
3566 void *arg /**< ioctl() argument. */ |
3566 void *arg /**< ioctl() argument. */ |
3567 ) |
3567 ) |
3568 { |
3568 { |
3569 ec_ioctl_slave_foe_t data; |
3569 ec_ioctl_slave_foe_t io; |
3570 ec_master_foe_request_t request; |
3570 ec_foe_request_t request; |
3571 int retval; |
3571 ec_slave_t *slave; |
3572 |
3572 int ret; |
3573 if (copy_from_user(&data, (void __user *) arg, sizeof(data))) { |
3573 |
3574 return -EFAULT; |
3574 if (copy_from_user(&io, (void __user *) arg, sizeof(io))) { |
3575 } |
3575 return -EFAULT; |
3576 |
3576 } |
3577 ec_foe_request_init(&request.req, data.file_name); |
3577 |
3578 ec_foe_request_read(&request.req); |
3578 ec_foe_request_init(&request, io.file_name); |
3579 ec_foe_request_alloc(&request.req, 10000); // FIXME |
3579 ret = ec_foe_request_alloc(&request, 10000); // FIXME |
|
3580 if (ret) { |
|
3581 ec_foe_request_clear(&request); |
|
3582 return ret; |
|
3583 } |
|
3584 |
|
3585 ec_foe_request_read(&request); |
3580 |
3586 |
3581 if (down_interruptible(&master->master_sem)) { |
3587 if (down_interruptible(&master->master_sem)) { |
3582 ec_foe_request_clear(&request.req); |
3588 ec_foe_request_clear(&request); |
3583 return -EINTR; |
3589 return -EINTR; |
3584 } |
3590 } |
3585 |
3591 |
3586 if (!(request.slave = ec_master_find_slave( |
3592 if (!(slave = ec_master_find_slave(master, 0, io.slave_position))) { |
3587 master, 0, data.slave_position))) { |
3593 up(&master->master_sem); |
3588 up(&master->master_sem); |
3594 ec_foe_request_clear(&request); |
3589 ec_foe_request_clear(&request.req); |
|
3590 EC_MASTER_ERR(master, "Slave %u does not exist!\n", |
3595 EC_MASTER_ERR(master, "Slave %u does not exist!\n", |
3591 data.slave_position); |
3596 io.slave_position); |
3592 return -EINVAL; |
3597 return -EINVAL; |
3593 } |
3598 } |
3594 |
3599 |
3595 // schedule request. |
3600 // schedule request. |
3596 list_add_tail(&request.list, &request.slave->foe_requests); |
3601 list_add_tail(&request.list, &slave->foe_requests); |
3597 |
3602 |
3598 up(&master->master_sem); |
3603 up(&master->master_sem); |
3599 |
3604 |
3600 EC_SLAVE_DBG(request.slave, 1, "Scheduled FoE read request.\n"); |
3605 EC_SLAVE_DBG(slave, 1, "Scheduled FoE read request.\n"); |
3601 |
3606 |
3602 // wait for processing through FSM |
3607 // wait for processing through FSM |
3603 if (wait_event_interruptible(request.slave->foe_queue, |
3608 if (wait_event_interruptible(slave->foe_queue, |
3604 request.req.state != EC_INT_REQUEST_QUEUED)) { |
3609 request.state != EC_INT_REQUEST_QUEUED)) { |
3605 // interrupted by signal |
3610 // interrupted by signal |
3606 down(&master->master_sem); |
3611 down(&master->master_sem); |
3607 if (request.req.state == EC_INT_REQUEST_QUEUED) { |
3612 if (request.state == EC_INT_REQUEST_QUEUED) { |
3608 list_del(&request.list); |
3613 list_del(&request.list); |
3609 up(&master->master_sem); |
3614 up(&master->master_sem); |
3610 ec_foe_request_clear(&request.req); |
3615 ec_foe_request_clear(&request); |
3611 return -EINTR; |
3616 return -EINTR; |
3612 } |
3617 } |
3613 // request already processing: interrupt not possible. |
3618 // request already processing: interrupt not possible. |
3614 up(&master->master_sem); |
3619 up(&master->master_sem); |
3615 } |
3620 } |
3616 |
3621 |
|
3622 // FIXME slave may become invalid |
|
3623 |
3617 // wait until master FSM has finished processing |
3624 // wait until master FSM has finished processing |
3618 wait_event(request.slave->foe_queue, |
3625 wait_event(slave->foe_queue, request.state != EC_INT_REQUEST_BUSY); |
3619 request.req.state != EC_INT_REQUEST_BUSY); |
3626 |
3620 |
3627 io.result = request.result; |
3621 data.result = request.req.result; |
3628 io.error_code = request.error_code; |
3622 data.error_code = request.req.error_code; |
3629 |
3623 |
3630 EC_SLAVE_DBG(slave, 1, "Read %zd bytes via FoE (result = 0x%x).\n", |
3624 EC_SLAVE_DBG(request.slave, 1, "Read %zd bytes via FoE" |
3631 request.data_size, request.result); |
3625 " (result = 0x%x).\n", request.req.data_size, request.req.result); |
3632 |
3626 |
3633 if (request.state != EC_INT_REQUEST_SUCCESS) { |
3627 if (request.req.state != EC_INT_REQUEST_SUCCESS) { |
3634 io.data_size = 0; |
3628 data.data_size = 0; |
3635 ret = -EIO; |
3629 retval = -EIO; |
|
3630 } else { |
3636 } else { |
3631 if (request.req.data_size > data.buffer_size) { |
3637 if (request.data_size > io.buffer_size) { |
3632 EC_MASTER_ERR(master, "Buffer too small.\n"); |
3638 EC_MASTER_ERR(master, "Buffer too small.\n"); |
3633 ec_foe_request_clear(&request.req); |
3639 ec_foe_request_clear(&request); |
3634 return -EOVERFLOW; |
3640 return -EOVERFLOW; |
3635 } |
3641 } |
3636 data.data_size = request.req.data_size; |
3642 io.data_size = request.data_size; |
3637 if (copy_to_user((void __user *) data.buffer, |
3643 if (copy_to_user((void __user *) io.buffer, |
3638 request.req.buffer, data.data_size)) { |
3644 request.buffer, io.data_size)) { |
3639 ec_foe_request_clear(&request.req); |
3645 ec_foe_request_clear(&request); |
3640 return -EFAULT; |
3646 return -EFAULT; |
3641 } |
3647 } |
3642 retval = 0; |
3648 ret = 0; |
3643 } |
3649 } |
3644 |
3650 |
3645 if (__copy_to_user((void __user *) arg, &data, sizeof(data))) { |
3651 if (__copy_to_user((void __user *) arg, &io, sizeof(io))) { |
3646 retval = -EFAULT; |
3652 ret = -EFAULT; |
3647 } |
3653 } |
3648 |
3654 |
3649 EC_SLAVE_DBG(request.slave, 1, "Finished FoE read request.\n"); |
3655 EC_SLAVE_DBG(slave, 1, "Finished FoE read request.\n"); |
3650 |
3656 |
3651 ec_foe_request_clear(&request.req); |
3657 ec_foe_request_clear(&request); |
3652 |
3658 |
3653 return retval; |
3659 return ret; |
3654 } |
3660 } |
3655 |
3661 |
3656 /*****************************************************************************/ |
3662 /*****************************************************************************/ |
3657 |
3663 |
3658 /** Write a file to a slave via FoE |
3664 /** Write a file to a slave via FoE |
3660 static int ec_ioctl_slave_foe_write( |
3666 static int ec_ioctl_slave_foe_write( |
3661 ec_master_t *master, /**< EtherCAT master. */ |
3667 ec_master_t *master, /**< EtherCAT master. */ |
3662 void *arg /**< ioctl() argument. */ |
3668 void *arg /**< ioctl() argument. */ |
3663 ) |
3669 ) |
3664 { |
3670 { |
3665 ec_ioctl_slave_foe_t data; |
3671 ec_ioctl_slave_foe_t io; |
3666 ec_master_foe_request_t request; |
3672 ec_foe_request_t request; |
3667 int retval; |
3673 ec_slave_t *slave; |
3668 |
3674 int ret; |
3669 if (copy_from_user(&data, (void __user *) arg, sizeof(data))) { |
3675 |
3670 return -EFAULT; |
3676 if (copy_from_user(&io, (void __user *) arg, sizeof(io))) { |
3671 } |
3677 return -EFAULT; |
3672 |
3678 } |
3673 INIT_LIST_HEAD(&request.list); |
3679 |
3674 |
3680 ec_foe_request_init(&request, io.file_name); |
3675 ec_foe_request_init(&request.req, data.file_name); |
3681 |
3676 |
3682 ret = ec_foe_request_alloc(&request, io.buffer_size); |
3677 if (ec_foe_request_alloc(&request.req, data.buffer_size)) { |
3683 if (ret) { |
3678 ec_foe_request_clear(&request.req); |
3684 ec_foe_request_clear(&request); |
3679 return -ENOMEM; |
3685 return ret; |
3680 } |
3686 } |
3681 if (copy_from_user(request.req.buffer, |
3687 |
3682 (void __user *) data.buffer, data.buffer_size)) { |
3688 if (copy_from_user(request.buffer, |
3683 ec_foe_request_clear(&request.req); |
3689 (void __user *) io.buffer, io.buffer_size)) { |
3684 return -EFAULT; |
3690 ec_foe_request_clear(&request); |
3685 } |
3691 return -EFAULT; |
3686 request.req.data_size = data.buffer_size; |
3692 } |
3687 ec_foe_request_write(&request.req); |
3693 |
|
3694 request.data_size = io.buffer_size; |
|
3695 ec_foe_request_write(&request); |
3688 |
3696 |
3689 if (down_interruptible(&master->master_sem)) { |
3697 if (down_interruptible(&master->master_sem)) { |
3690 ec_foe_request_clear(&request.req); |
3698 ec_foe_request_clear(&request); |
3691 return -EINTR; |
3699 return -EINTR; |
3692 } |
3700 } |
3693 |
3701 |
3694 if (!(request.slave = ec_master_find_slave( |
3702 if (!(slave = ec_master_find_slave(master, 0, io.slave_position))) { |
3695 master, 0, data.slave_position))) { |
|
3696 up(&master->master_sem); |
3703 up(&master->master_sem); |
3697 EC_MASTER_ERR(master, "Slave %u does not exist!\n", |
3704 EC_MASTER_ERR(master, "Slave %u does not exist!\n", |
3698 data.slave_position); |
3705 io.slave_position); |
3699 ec_foe_request_clear(&request.req); |
3706 ec_foe_request_clear(&request); |
3700 return -EINVAL; |
3707 return -EINVAL; |
3701 } |
3708 } |
3702 |
3709 |
3703 EC_SLAVE_DBG(request.slave, 1, "Scheduling FoE write request.\n"); |
3710 EC_SLAVE_DBG(slave, 1, "Scheduling FoE write request.\n"); |
3704 |
3711 |
3705 // schedule FoE write request. |
3712 // schedule FoE write request. |
3706 list_add_tail(&request.list, &request.slave->foe_requests); |
3713 list_add_tail(&request.list, &slave->foe_requests); |
3707 |
3714 |
3708 up(&master->master_sem); |
3715 up(&master->master_sem); |
3709 |
3716 |
3710 // wait for processing through FSM |
3717 // wait for processing through FSM |
3711 if (wait_event_interruptible(request.slave->foe_queue, |
3718 if (wait_event_interruptible(slave->foe_queue, |
3712 request.req.state != EC_INT_REQUEST_QUEUED)) { |
3719 request.state != EC_INT_REQUEST_QUEUED)) { |
3713 // interrupted by signal |
3720 // interrupted by signal |
3714 down(&master->master_sem); |
3721 down(&master->master_sem); |
3715 if (request.req.state == EC_INT_REQUEST_QUEUED) { |
3722 if (request.state == EC_INT_REQUEST_QUEUED) { |
3716 // abort request |
3723 // abort request |
3717 list_del(&request.list); |
3724 list_del(&request.list); |
3718 up(&master->master_sem); |
3725 up(&master->master_sem); |
3719 ec_foe_request_clear(&request.req); |
3726 ec_foe_request_clear(&request); |
3720 return -EINTR; |
3727 return -EINTR; |
3721 } |
3728 } |
3722 up(&master->master_sem); |
3729 up(&master->master_sem); |
3723 } |
3730 } |
3724 |
3731 |
|
3732 // FIXME slave may become invalid |
|
3733 |
3725 // wait until master FSM has finished processing |
3734 // wait until master FSM has finished processing |
3726 wait_event(request.slave->foe_queue, |
3735 wait_event(slave->foe_queue, request.state != EC_INT_REQUEST_BUSY); |
3727 request.req.state != EC_INT_REQUEST_BUSY); |
3736 |
3728 |
3737 io.result = request.result; |
3729 data.result = request.req.result; |
3738 io.error_code = request.error_code; |
3730 data.error_code = request.req.error_code; |
3739 |
3731 |
3740 ret = request.state == EC_INT_REQUEST_SUCCESS ? 0 : -EIO; |
3732 retval = request.req.state == EC_INT_REQUEST_SUCCESS ? 0 : -EIO; |
3741 |
3733 |
3742 if (__copy_to_user((void __user *) arg, &io, sizeof(io))) { |
3734 if (__copy_to_user((void __user *) arg, &data, sizeof(data))) { |
3743 ret = -EFAULT; |
3735 retval = -EFAULT; |
3744 } |
3736 } |
3745 |
3737 |
3746 ec_foe_request_clear(&request); |
3738 ec_foe_request_clear(&request.req); |
3747 |
3739 |
3748 EC_SLAVE_DBG(slave, 1, "Finished FoE write request.\n"); |
3740 EC_SLAVE_DBG(request.slave, 1, "Finished FoE write request.\n"); |
3749 |
3741 |
3750 return ret; |
3742 return retval; |
|
3743 } |
3751 } |
3744 |
3752 |
3745 /*****************************************************************************/ |
3753 /*****************************************************************************/ |
3746 |
3754 |
3747 /** Read an SoE IDN. |
3755 /** Read an SoE IDN. |