master/cdev.c
changeset 1352 275d2fdeab48
parent 1350 cd278db5a872
child 1361 9c16b62326fa
--- a/master/cdev.c	Mon Feb 02 13:34:01 2009 +0000
+++ b/master/cdev.c	Mon Feb 02 13:37:00 2009 +0000
@@ -1874,6 +1874,55 @@
 
 /*****************************************************************************/
 
+/** Create an SDO request.
+ */
+int ec_cdev_ioctl_sc_create_sdo_request(
+        ec_master_t *master, /**< EtherCAT master. */
+        unsigned long arg, /**< ioctl() argument. */
+        ec_cdev_priv_t *priv /**< Private data structure of file handle. */
+        )
+{
+    ec_ioctl_sdo_request_t data;
+    ec_slave_config_t *sc;
+    ec_sdo_request_t *req;
+
+	if (unlikely(!priv->requested))
+		return -EPERM;
+
+    if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
+        return -EFAULT;
+    }
+
+    data.request_index = 0;
+
+    if (down_interruptible(&master->master_sem))
+        return -EINTR;
+
+    sc = ec_master_get_config(master, data.config_index);
+    if (!sc) {
+        up(&master->master_sem);
+        return -ENOENT;
+    }
+
+    list_for_each_entry(req, &sc->sdo_requests, list) {
+        data.request_index++;
+    }
+
+    up(&master->master_sem);
+
+    req = ecrt_slave_config_create_sdo_request_err(sc, data.sdo_index,
+            data.sdo_subindex, data.size);
+    if (IS_ERR(req))
+        return PTR_ERR(req);
+
+    if (copy_to_user((void __user *) arg, &data, sizeof(data)))
+        return -EFAULT;
+
+    return 0;
+}
+
+/*****************************************************************************/
+
 /** Create a VoE handler.
  */
 int ec_cdev_ioctl_sc_create_voe_handler(
@@ -2088,6 +2137,209 @@
 
 /*****************************************************************************/
 
+/** Sets an SDO request's timeout.
+ */
+int ec_cdev_ioctl_sdo_request_timeout(
+        ec_master_t *master, /**< EtherCAT master. */
+        unsigned long arg, /**< ioctl() argument. */
+        ec_cdev_priv_t *priv /**< Private data structure of file handle. */
+        )
+{
+    ec_ioctl_sdo_request_t data;
+    ec_slave_config_t *sc;
+    ec_sdo_request_t *req;
+
+	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 (!(req = ec_slave_config_find_sdo_request(sc, data.request_index))) {
+        up(&master->master_sem);
+        return -ENOENT;
+    }
+
+    up(&master->master_sem);
+
+    ecrt_sdo_request_timeout(req, data.timeout);
+    return 0;
+}
+
+/*****************************************************************************/
+
+/** Gets an SDO request's state.
+ */
+int ec_cdev_ioctl_sdo_request_state(
+        ec_master_t *master, /**< EtherCAT master. */
+        unsigned long arg, /**< ioctl() argument. */
+        ec_cdev_priv_t *priv /**< Private data structure of file handle. */
+        )
+{
+    ec_ioctl_sdo_request_t data;
+    ec_slave_config_t *sc;
+    ec_sdo_request_t *req;
+
+	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 (!(req = ec_slave_config_find_sdo_request(sc, data.request_index))) {
+        up(&master->master_sem);
+        return -ENOENT;
+    }
+
+    data.state = ecrt_sdo_request_state(req);
+    if (data.state == EC_REQUEST_SUCCESS && req->dir == EC_DIR_INPUT)
+        data.size = ecrt_sdo_request_data_size(req);
+    else
+        data.size = 0;
+
+    up(&master->master_sem);
+
+    if (copy_to_user((void __user *) arg, &data, sizeof(data)))
+        return -EFAULT;
+
+    return 0;
+}
+
+/*****************************************************************************/
+
+/** Starts an SDO read operation.
+ */
+int ec_cdev_ioctl_sdo_request_read(
+        ec_master_t *master, /**< EtherCAT master. */
+        unsigned long arg, /**< ioctl() argument. */
+        ec_cdev_priv_t *priv /**< Private data structure of file handle. */
+        )
+{
+    ec_ioctl_sdo_request_t data;
+    ec_slave_config_t *sc;
+    ec_sdo_request_t *req;
+
+	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 (!(req = ec_slave_config_find_sdo_request(sc, data.request_index))) {
+        up(&master->master_sem);
+        return -ENOENT;
+    }
+
+    up(&master->master_sem);
+
+    ecrt_sdo_request_read(req);
+    return 0;
+}
+
+/*****************************************************************************/
+
+/** Starts an SDO write operation.
+ */
+int ec_cdev_ioctl_sdo_request_write(
+        ec_master_t *master, /**< EtherCAT master. */
+        unsigned long arg, /**< ioctl() argument. */
+        ec_cdev_priv_t *priv /**< Private data structure of file handle. */
+        )
+{
+    ec_ioctl_sdo_request_t data;
+    ec_slave_config_t *sc;
+    ec_sdo_request_t *req;
+
+	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 (!(req = ec_slave_config_find_sdo_request(sc, data.request_index))) {
+        up(&master->master_sem);
+        return -ENOENT;
+    }
+
+    up(&master->master_sem);
+
+    ecrt_sdo_request_write(req);
+    return 0;
+}
+
+/*****************************************************************************/
+
+/** Read SDO data.
+ */
+int ec_cdev_ioctl_sdo_request_data(
+        ec_master_t *master, /**< EtherCAT master. */
+        unsigned long arg, /**< ioctl() argument. */
+        ec_cdev_priv_t *priv /**< Private data structure of file handle. */
+        )
+{
+    ec_ioctl_sdo_request_t data;
+    ec_slave_config_t *sc;
+    ec_sdo_request_t *req;
+
+	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 (!(req = ec_slave_config_find_sdo_request(sc, data.request_index))) {
+        up(&master->master_sem);
+        return -ENOENT;
+    }
+
+    up(&master->master_sem);
+
+    ecrt_sdo_request_timeout(req, data.timeout);
+    return 0;
+}
+
+/*****************************************************************************/
+
 /** Sets the VoE send header.
  */
 int ec_cdev_ioctl_voe_send_header(
@@ -2646,7 +2898,7 @@
     ec_master_t *master = priv->cdev->master;
 
     if (master->debug_level)
-        EC_DBG("ioctl(filp = 0x%x, cmd = 0x%x (0x%x), arg = 0x%x)\n",
+        EC_DBG("ioctl(filp = 0x%x, cmd = 0x%08x (0x%02x), arg = 0x%x)\n",
                 (u32) filp, (u32) cmd, (u32) _IOC_NR(cmd), (u32) arg);
 
     switch (cmd) {
@@ -2764,6 +3016,10 @@
             if (!(filp->f_mode & FMODE_WRITE))
 				return -EPERM;
 			return ec_cdev_ioctl_sc_sdo(master, arg, priv);
+        case EC_IOCTL_SC_SDO_REQUEST:
+            if (!(filp->f_mode & FMODE_WRITE))
+				return -EPERM;
+			return ec_cdev_ioctl_sc_create_sdo_request(master, arg, priv);
         case EC_IOCTL_SC_VOE:
             if (!(filp->f_mode & FMODE_WRITE))
 				return -EPERM;
@@ -2782,6 +3038,22 @@
 			return ec_cdev_ioctl_domain_queue(master, arg, priv);
         case EC_IOCTL_DOMAIN_STATE:
 			return ec_cdev_ioctl_domain_state(master, arg, priv);
+        case EC_IOCTL_SDO_REQUEST_TIMEOUT:
+            if (!(filp->f_mode & FMODE_WRITE))
+				return -EPERM;
+			return ec_cdev_ioctl_sdo_request_timeout(master, arg, priv);
+        case EC_IOCTL_SDO_REQUEST_STATE:
+			return ec_cdev_ioctl_sdo_request_state(master, arg, priv);
+        case EC_IOCTL_SDO_REQUEST_READ:
+            if (!(filp->f_mode & FMODE_WRITE))
+				return -EPERM;
+			return ec_cdev_ioctl_sdo_request_read(master, arg, priv);
+        case EC_IOCTL_SDO_REQUEST_WRITE:
+            if (!(filp->f_mode & FMODE_WRITE))
+				return -EPERM;
+			return ec_cdev_ioctl_sdo_request_write(master, arg, priv);
+        case EC_IOCTL_SDO_REQUEST_DATA:
+			return ec_cdev_ioctl_sdo_request_data(master, arg, priv);
         case EC_IOCTL_VOE_SEND_HEADER:
             if (!(filp->f_mode & FMODE_WRITE))
 				return -EPERM;