00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00033 #include <linux/module.h>
00034 #include <linux/slab.h>
00035 #include <linux/mman.h>
00036
00037 #include <rtdm/rtdm_driver.h>
00038
00039 #include "master.h"
00040 #include "ioctl.h"
00041 #include "rtdm.h"
00042
00045 #define DEBUG 0
00046
00047
00048
00051 typedef struct {
00052 rtdm_user_info_t *user_info;
00053 ec_ioctl_context_t ioctl_ctx;
00054 } ec_rtdm_context_t;
00055
00056
00057
00058 int ec_rtdm_open(struct rtdm_dev_context *, rtdm_user_info_t *, int);
00059 int ec_rtdm_close(struct rtdm_dev_context *, rtdm_user_info_t *);
00060 int ec_rtdm_ioctl(struct rtdm_dev_context *, rtdm_user_info_t *,
00061 unsigned int, void __user *);
00062
00063
00064
00069 int ec_rtdm_dev_init(
00070 ec_rtdm_dev_t *rtdm_dev,
00071 ec_master_t *master
00072 )
00073 {
00074 int ret;
00075
00076 rtdm_dev->master = master;
00077
00078 rtdm_dev->dev = kzalloc(sizeof(struct rtdm_device), GFP_KERNEL);
00079 if (!rtdm_dev->dev) {
00080 EC_MASTER_ERR(master, "Failed to reserve memory for RTDM device.\n");
00081 return -ENOMEM;
00082 }
00083
00084 rtdm_dev->dev->struct_version = RTDM_DEVICE_STRUCT_VER;
00085 rtdm_dev->dev->device_flags = RTDM_NAMED_DEVICE;
00086 rtdm_dev->dev->context_size = sizeof(ec_rtdm_context_t);
00087 snprintf(rtdm_dev->dev->device_name, RTDM_MAX_DEVNAME_LEN,
00088 "EtherCAT%u", master->index);
00089 rtdm_dev->dev->open_nrt = ec_rtdm_open;
00090 rtdm_dev->dev->ops.close_nrt = ec_rtdm_close;
00091 rtdm_dev->dev->ops.ioctl_rt = ec_rtdm_ioctl;
00092 rtdm_dev->dev->ops.ioctl_nrt = ec_rtdm_ioctl;
00093 rtdm_dev->dev->device_class = RTDM_CLASS_EXPERIMENTAL;
00094 rtdm_dev->dev->device_sub_class = 222;
00095 rtdm_dev->dev->driver_name = "EtherCAT";
00096 rtdm_dev->dev->driver_version = RTDM_DRIVER_VER(1, 0, 2);
00097 rtdm_dev->dev->peripheral_name = rtdm_dev->dev->device_name;
00098 rtdm_dev->dev->provider_name = "EtherLab Community";
00099 rtdm_dev->dev->proc_name = rtdm_dev->dev->device_name;
00100 rtdm_dev->dev->device_data = rtdm_dev;
00101
00102 EC_MASTER_INFO(master, "Registering RTDM device %s.\n",
00103 rtdm_dev->dev->driver_name);
00104 ret = rtdm_dev_register(rtdm_dev->dev);
00105 if (ret) {
00106 EC_MASTER_ERR(master, "Initialization of RTDM interface failed"
00107 " (return value %i).\n", ret);
00108 kfree(rtdm_dev->dev);
00109 }
00110
00111 return ret;
00112 }
00113
00114
00115
00118 void ec_rtdm_dev_clear(
00119 ec_rtdm_dev_t *rtdm_dev
00120 )
00121 {
00122 int ret;
00123
00124 EC_MASTER_INFO(rtdm_dev->master, "Unregistering RTDM device %s.\n",
00125 rtdm_dev->dev->driver_name);
00126 ret = rtdm_dev_unregister(rtdm_dev->dev, 1000 );
00127 if (ret < 0) {
00128 EC_MASTER_WARN(rtdm_dev->master,
00129 "Failed to unregister RTDM device (code %i).\n", ret);
00130 }
00131
00132 kfree(rtdm_dev->dev);
00133 }
00134
00135
00136
00141 int ec_rtdm_open(
00142 struct rtdm_dev_context *context,
00143 rtdm_user_info_t *user_info,
00144 int oflags
00145 )
00146 {
00147 ec_rtdm_context_t *ctx = (ec_rtdm_context_t *) context->dev_private;
00148 #if DEBUG
00149 ec_rtdm_dev_t *rtdm_dev = (ec_rtdm_dev_t *) context->device->device_data;
00150 #endif
00151
00152 ctx->user_info = user_info;
00153 ctx->ioctl_ctx.writable = oflags & O_WRONLY || oflags & O_RDWR;
00154 ctx->ioctl_ctx.requested = 0;
00155 ctx->ioctl_ctx.process_data = NULL;
00156 ctx->ioctl_ctx.process_data_size = 0;
00157
00158 #if DEBUG
00159 EC_MASTER_INFO(rtdm_dev->master, "RTDM device %s opened.\n",
00160 context->device->device_name);
00161 #endif
00162 return 0;
00163 }
00164
00165
00166
00171 int ec_rtdm_close(
00172 struct rtdm_dev_context *context,
00173 rtdm_user_info_t *user_info
00174 )
00175 {
00176 ec_rtdm_context_t *ctx = (ec_rtdm_context_t *) context->dev_private;
00177 ec_rtdm_dev_t *rtdm_dev = (ec_rtdm_dev_t *) context->device->device_data;
00178
00179 if (ctx->ioctl_ctx.requested) {
00180 ecrt_release_master(rtdm_dev->master);
00181 }
00182
00183 #if DEBUG
00184 EC_MASTER_INFO(rtdm_dev->master, "RTDM device %s closed.\n",
00185 context->device->device_name);
00186 #endif
00187 return 0;
00188 }
00189
00190
00191
00196 int ec_rtdm_ioctl(
00197 struct rtdm_dev_context *context,
00198 rtdm_user_info_t *user_info,
00199 unsigned int request,
00200 void __user *arg
00201 )
00202 {
00203 ec_rtdm_context_t *ctx = (ec_rtdm_context_t *) context->dev_private;
00204 ec_rtdm_dev_t *rtdm_dev = (ec_rtdm_dev_t *) context->device->device_data;
00205
00206 #if DEBUG
00207 EC_MASTER_INFO(rtdm_dev->master, "ioctl(request = %u, ctl = %02x)"
00208 " on RTDM device %s.\n", request, _IOC_NR(request),
00209 context->device->device_name);
00210 #endif
00211 return ec_ioctl_rtdm(rtdm_dev->master, &ctx->ioctl_ctx, request, arg);
00212 }
00213
00214
00215
00220 int ec_rtdm_mmap(
00221 ec_ioctl_context_t *ioctl_ctx,
00222 void **user_address
00223 )
00224 {
00225 ec_rtdm_context_t *ctx =
00226 container_of(ioctl_ctx, ec_rtdm_context_t, ioctl_ctx);
00227 int ret;
00228
00229 ret = rtdm_mmap_to_user(ctx->user_info,
00230 ioctl_ctx->process_data, ioctl_ctx->process_data_size,
00231 PROT_READ | PROT_WRITE,
00232 user_address,
00233 NULL, NULL);
00234 if (ret < 0) {
00235 return ret;
00236 }
00237
00238 return 0;
00239 }
00240
00241