Included ecrt_voe_handler_read_nosync()-Patch by Mathias Weber.

This commit is contained in:
Florian Pose 2008-11-18 11:13:49 +00:00
parent 8d46a283f6
commit fae8df09b0
5 changed files with 192 additions and 3 deletions

View File

@ -1049,6 +1049,25 @@ void ecrt_voe_handler_read(
ec_voe_handler_t *voe /**< VoE handler. */
);
/** Start a VoE read operation without querying the sync manager status.
*
* After this function has been called, the ecrt_voe_handler_execute() method
* must be called in every bus cycle as long as it returns EC_REQUEST_BUSY. No
* other operation may be started while the handler is busy.
*
* The state machine queries the slave by sending an empty mailbox. The slave
* fills its data to the master in this mailbox. If no data appear within the
* EC_VOE_RESPONSE_TIMEOUT (defined in master/voe_handler.c), the operation
* fails.
*
* On success, the size of the read data can be determined via
* ecrt_voe_handler_data_size(), while the VoE header of the received data
* can be retrieved with ecrt_voe_handler_received_header().
*/
void ecrt_voe_handler_read_nosync(
ec_voe_handler_t *voe /**< VoE handler. */
);
/** Execute the handler.
*
* This method executes the VoE handler. It has to be called in every bus cycle

View File

@ -111,6 +111,20 @@ void ecrt_voe_handler_read(ec_voe_handler_t *voe)
/*****************************************************************************/
void ecrt_voe_handler_read_nosync(ec_voe_handler_t *voe)
{
ec_ioctl_voe_t data;
data.config_index = voe->config->index;
data.voe_index = voe->index;
if (ioctl(voe->config->master->fd, EC_IOCTL_VOE_READ_NOSYNC, &data) == -1)
fprintf(stderr, "Failed to initiate VoE reading: %s\n",
strerror(errno));
}
/*****************************************************************************/
void ecrt_voe_handler_write(ec_voe_handler_t *voe, size_t size)
{
ec_ioctl_voe_t data;

View File

@ -2227,6 +2227,45 @@ int ec_cdev_ioctl_voe_read(
/*****************************************************************************/
/** Starts a VoE read operation without sending a sync message first.
*/
int ec_cdev_ioctl_voe_read_nosync(
ec_master_t *master, /**< EtherCAT master. */
unsigned long arg, /**< ioctl() argument. */
ec_cdev_priv_t *priv /**< Private data structure of file handle. */
)
{
ec_ioctl_voe_t data;
ec_slave_config_t *sc;
ec_voe_handler_t *voe;
if (unlikely(!priv->requested))
return -EPERM;
if (copy_from_user(&data, (void __user *) arg, sizeof(data)))
return -EFAULT;
if (down_interruptible(&master->master_sem))
return -EINTR;
if (!(sc = ec_master_get_config(master, data.config_index))) {
up(&master->master_sem);
return -ENOENT;
}
if (!(voe = ec_slave_config_find_voe_handler(sc, data.voe_index))) {
up(&master->master_sem);
return -ENOENT;
}
up(&master->master_sem);
ecrt_voe_handler_read_nosync(voe);
return 0;
}
/*****************************************************************************/
/** Starts a VoE write operation.
*/
int ec_cdev_ioctl_voe_write(
@ -2559,6 +2598,10 @@ long eccdev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
case EC_IOCTL_VOE_READ:
if (!(filp->f_mode & FMODE_WRITE))
return -EPERM;
case EC_IOCTL_VOE_READ_NOSYNC:
if (!(filp->f_mode & FMODE_WRITE))
return -EPERM;
return ec_cdev_ioctl_voe_read_nosync(master, arg, priv);
return ec_cdev_ioctl_voe_read(master, arg, priv);
case EC_IOCTL_VOE_WRITE:
if (!(filp->f_mode & FMODE_WRITE))

View File

@ -104,9 +104,10 @@
#define EC_IOCTL_VOE_SEND_HEADER EC_IOW(0x2a, ec_ioctl_voe_t)
#define EC_IOCTL_VOE_REC_HEADER EC_IOWR(0x2b, ec_ioctl_voe_t)
#define EC_IOCTL_VOE_READ EC_IOW(0x2c, ec_ioctl_voe_t)
#define EC_IOCTL_VOE_WRITE EC_IOWR(0x2d, ec_ioctl_voe_t)
#define EC_IOCTL_VOE_EXEC EC_IOWR(0x2e, ec_ioctl_voe_t)
#define EC_IOCTL_VOE_DATA EC_IOWR(0x2f, ec_ioctl_voe_t)
#define EC_IOCTL_VOE_READ_NOSYNC EC_IOW(0x2d, ec_ioctl_voe_t)
#define EC_IOCTL_VOE_WRITE EC_IOWR(0x2e, ec_ioctl_voe_t)
#define EC_IOCTL_VOE_EXEC EC_IOWR(0x2f, ec_ioctl_voe_t)
#define EC_IOCTL_VOE_DATA EC_IOWR(0x30, ec_ioctl_voe_t)
/*****************************************************************************/

View File

@ -65,6 +65,9 @@ void ec_voe_handler_state_read_start(ec_voe_handler_t *);
void ec_voe_handler_state_read_check(ec_voe_handler_t *);
void ec_voe_handler_state_read_response(ec_voe_handler_t *);
void ec_voe_handler_state_read_nosync_start(ec_voe_handler_t *);
void ec_voe_handler_state_read_nosync_response(ec_voe_handler_t *);
void ec_voe_handler_state_end(ec_voe_handler_t *);
void ec_voe_handler_state_error(ec_voe_handler_t *);
@ -168,6 +171,15 @@ void ecrt_voe_handler_read(ec_voe_handler_t *voe)
/*****************************************************************************/
void ecrt_voe_handler_read_nosync(ec_voe_handler_t *voe)
{
voe->dir = EC_DIR_INPUT;
voe->state = ec_voe_handler_state_read_nosync_start;
voe->request_state = EC_INT_REQUEST_QUEUED;
}
/*****************************************************************************/
void ecrt_voe_handler_write(ec_voe_handler_t *voe, size_t size)
{
voe->dir = EC_DIR_OUTPUT;
@ -427,6 +439,106 @@ void ec_voe_handler_state_read_response(ec_voe_handler_t *voe)
/*****************************************************************************/
/** Start reading VoE data without sending a sync message before.
*/
void ec_voe_handler_state_read_nosync_start(ec_voe_handler_t *voe)
{
ec_datagram_t *datagram = &voe->datagram;
ec_slave_t *slave = voe->config->slave;
if (slave->master->debug_level)
EC_DBG("Reading VoE data to slave %u.\n", slave->ring_position);
if (!(slave->sii.mailbox_protocols & EC_MBOX_VOE)) {
EC_ERR("Slave %u does not support VoE!\n", slave->ring_position);
voe->state = ec_voe_handler_state_error;
voe->request_state = EC_INT_REQUEST_FAILURE;
return;
}
ec_slave_mbox_prepare_fetch(slave, datagram); // can not fail.
voe->jiffies_start = jiffies;
voe->retries = EC_FSM_RETRIES;
voe->state = ec_voe_handler_state_read_nosync_response;
}
/*****************************************************************************/
/** Read the pending mailbox data without sending a sync message before. This
* might lead to an empty reponse from the client.
*/
void ec_voe_handler_state_read_nosync_response(ec_voe_handler_t *voe)
{
ec_datagram_t *datagram = &voe->datagram;
ec_slave_t *slave = voe->config->slave;
ec_master_t *master = voe->config->master;
uint8_t *data, mbox_prot;
size_t rec_size;
if (datagram->state == EC_DATAGRAM_TIMED_OUT && voe->retries--)
return;
if (datagram->state != EC_DATAGRAM_RECEIVED) {
voe->state = ec_voe_handler_state_error;
voe->request_state = EC_INT_REQUEST_FAILURE;
EC_ERR("Failed to receive VoE read datagram for"
" slave %u (datagram state %u).\n",
slave->ring_position, datagram->state);
return;
}
if (datagram->working_counter == 0) {
voe->state = ec_voe_handler_state_error;
voe->request_state = EC_INT_REQUEST_FAILURE;
EC_DBG("Slave (%u) did not send data with Mailbox.",
slave->ring_position);
return;
}
if (datagram->working_counter != 1) {
voe->state = ec_voe_handler_state_error;
voe->request_state = EC_INT_REQUEST_FAILURE;
EC_WARN("Reception of VoE read response failed on slave %u: ",
slave->ring_position);
ec_datagram_print_wc_error(datagram);
return;
}
if (!(data = ec_slave_mbox_fetch(slave, datagram,
&mbox_prot, &rec_size))) {
voe->state = ec_voe_handler_state_error;
voe->request_state = EC_INT_REQUEST_FAILURE;
return;
}
if (mbox_prot != EC_MBOX_TYPE_VOE) {
voe->state = ec_voe_handler_state_error;
voe->request_state = EC_INT_REQUEST_FAILURE;
EC_WARN("Received mailbox protocol 0x%02X as response.\n", mbox_prot);
ec_print_data(data, rec_size);
return;
}
if (rec_size < EC_VOE_HEADER_SIZE) {
voe->state = ec_voe_handler_state_error;
voe->request_state = EC_INT_REQUEST_FAILURE;
EC_ERR("Received VoE header is incomplete (%u bytes)!\n", rec_size);
return;
}
if (master->debug_level) {
EC_DBG("VoE data:\n");
ec_print_data(data, rec_size);
}
voe->data_size = rec_size - EC_VOE_HEADER_SIZE;
voe->request_state = EC_INT_REQUEST_SUCCESS;
voe->state = ec_voe_handler_state_end; // success
}
/*****************************************************************************/
/** Successful termination state function.
*/
void ec_voe_handler_state_end(ec_voe_handler_t *voe)