IgH EtherCAT Master  1.5.3
rtdm.c
Go to the documentation of this file.
1 /*****************************************************************************
2  *
3  * $Id$
4  *
5  * Copyright (C) 2009-2010 Moehwald GmbH B. Benner
6  * 2011 IgH Andreas Stewering-Bone
7  * 2012 Florian Pose <fp@igh-essen.com>
8  *
9  * This file is part of the IgH EtherCAT master.
10  *
11  * The IgH EtherCAT master is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License as published
13  * by the Free Software Foundation; version 2 of the License.
14  *
15  * The IgH EtherCAT master is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
18  * Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License along
21  * with the IgH EtherCAT master. If not, see <http://www.gnu.org/licenses/>.
22  *
23  * The license mentioned above concerns the source code only. Using the
24  * EtherCAT technology and brand is only permitted in compliance with the
25  * industrial property and similar rights of Beckhoff Automation GmbH.
26  *
27  ****************************************************************************/
28 
33 #include <linux/module.h>
34 #include <linux/slab.h>
35 #include <linux/mman.h>
36 
37 #include <rtdm/rtdm_driver.h>
38 
39 #include "master.h"
40 #include "ioctl.h"
41 #include "rtdm.h"
42 
45 #define DEBUG 0
46 
47 /****************************************************************************/
48 
51 typedef struct {
52  rtdm_user_info_t *user_info;
53  ec_ioctl_context_t ioctl_ctx;
55 
56 /****************************************************************************/
57 
58 int ec_rtdm_open(struct rtdm_dev_context *, rtdm_user_info_t *, int);
59 int ec_rtdm_close(struct rtdm_dev_context *, rtdm_user_info_t *);
60 int ec_rtdm_ioctl(struct rtdm_dev_context *, rtdm_user_info_t *,
61  unsigned int, void __user *);
62 
63 /****************************************************************************/
64 
70  ec_rtdm_dev_t *rtdm_dev,
71  ec_master_t *master
72  )
73 {
74  int ret;
75 
76  rtdm_dev->master = master;
77 
78  rtdm_dev->dev = kzalloc(sizeof(struct rtdm_device), GFP_KERNEL);
79  if (!rtdm_dev->dev) {
80  EC_MASTER_ERR(master, "Failed to reserve memory for RTDM device.\n");
81  return -ENOMEM;
82  }
83 
84  rtdm_dev->dev->struct_version = RTDM_DEVICE_STRUCT_VER;
85  rtdm_dev->dev->device_flags = RTDM_NAMED_DEVICE;
86  rtdm_dev->dev->context_size = sizeof(ec_rtdm_context_t);
87  snprintf(rtdm_dev->dev->device_name, RTDM_MAX_DEVNAME_LEN,
88  "EtherCAT%u", master->index);
89  rtdm_dev->dev->open_nrt = ec_rtdm_open;
90  rtdm_dev->dev->ops.close_nrt = ec_rtdm_close;
91  rtdm_dev->dev->ops.ioctl_rt = ec_rtdm_ioctl;
92  rtdm_dev->dev->ops.ioctl_nrt = ec_rtdm_ioctl;
93  rtdm_dev->dev->device_class = RTDM_CLASS_EXPERIMENTAL;
94  rtdm_dev->dev->device_sub_class = 222;
95  rtdm_dev->dev->driver_name = "EtherCAT";
96  rtdm_dev->dev->driver_version = RTDM_DRIVER_VER(1, 0, 2);
97  rtdm_dev->dev->peripheral_name = rtdm_dev->dev->device_name;
98  rtdm_dev->dev->provider_name = "EtherLab Community";
99  rtdm_dev->dev->proc_name = rtdm_dev->dev->device_name;
100  rtdm_dev->dev->device_data = rtdm_dev; /* pointer to parent */
101 
102  EC_MASTER_INFO(master, "Registering RTDM device %s.\n",
103  rtdm_dev->dev->driver_name);
104  ret = rtdm_dev_register(rtdm_dev->dev);
105  if (ret) {
106  EC_MASTER_ERR(master, "Initialization of RTDM interface failed"
107  " (return value %i).\n", ret);
108  kfree(rtdm_dev->dev);
109  }
110 
111  return ret;
112 }
113 
114 /****************************************************************************/
115 
119  ec_rtdm_dev_t *rtdm_dev
120  )
121 {
122  int ret;
123 
124  EC_MASTER_INFO(rtdm_dev->master, "Unregistering RTDM device %s.\n",
125  rtdm_dev->dev->driver_name);
126  ret = rtdm_dev_unregister(rtdm_dev->dev, 1000 /* poll delay [ms] */);
127  if (ret < 0) {
128  EC_MASTER_WARN(rtdm_dev->master,
129  "Failed to unregister RTDM device (code %i).\n", ret);
130  }
131 
132  kfree(rtdm_dev->dev);
133 }
134 
135 /****************************************************************************/
136 
142  struct rtdm_dev_context *context,
143  rtdm_user_info_t *user_info,
144  int oflags
145  )
146 {
147  ec_rtdm_context_t *ctx = (ec_rtdm_context_t *) context->dev_private;
148 #if DEBUG
149  ec_rtdm_dev_t *rtdm_dev = (ec_rtdm_dev_t *) context->device->device_data;
150 #endif
151 
152  ctx->user_info = user_info;
153  ctx->ioctl_ctx.writable = oflags & O_WRONLY || oflags & O_RDWR;
154  ctx->ioctl_ctx.requested = 0;
155  ctx->ioctl_ctx.process_data = NULL;
156  ctx->ioctl_ctx.process_data_size = 0;
157 
158 #if DEBUG
159  EC_MASTER_INFO(rtdm_dev->master, "RTDM device %s opened.\n",
160  context->device->device_name);
161 #endif
162  return 0;
163 }
164 
165 /****************************************************************************/
166 
172  struct rtdm_dev_context *context,
173  rtdm_user_info_t *user_info
174  )
175 {
176  ec_rtdm_context_t *ctx = (ec_rtdm_context_t *) context->dev_private;
177  ec_rtdm_dev_t *rtdm_dev = (ec_rtdm_dev_t *) context->device->device_data;
178 
179  if (ctx->ioctl_ctx.requested) {
180  ecrt_release_master(rtdm_dev->master);
181  }
182 
183 #if DEBUG
184  EC_MASTER_INFO(rtdm_dev->master, "RTDM device %s closed.\n",
185  context->device->device_name);
186 #endif
187  return 0;
188 }
189 
190 /****************************************************************************/
191 
197  struct rtdm_dev_context *context,
198  rtdm_user_info_t *user_info,
199  unsigned int request,
200  void __user *arg
201  )
202 {
203  ec_rtdm_context_t *ctx = (ec_rtdm_context_t *) context->dev_private;
204  ec_rtdm_dev_t *rtdm_dev = (ec_rtdm_dev_t *) context->device->device_data;
205 
206 #if DEBUG
207  EC_MASTER_INFO(rtdm_dev->master, "ioctl(request = %u, ctl = %02x)"
208  " on RTDM device %s.\n", request, _IOC_NR(request),
209  context->device->device_name);
210 #endif
211  return ec_ioctl_rtdm(rtdm_dev->master, &ctx->ioctl_ctx, request, arg);
212 }
213 
214 /****************************************************************************/
215 
221  ec_ioctl_context_t *ioctl_ctx,
222  void **user_address
223  )
224 {
225  ec_rtdm_context_t *ctx =
226  container_of(ioctl_ctx, ec_rtdm_context_t, ioctl_ctx);
227  int ret;
228 
229  ret = rtdm_mmap_to_user(ctx->user_info,
230  ioctl_ctx->process_data, ioctl_ctx->process_data_size,
231  PROT_READ | PROT_WRITE,
232  user_address,
233  NULL, NULL);
234  if (ret < 0) {
235  return ret;
236  }
237 
238  return 0;
239 }
240 
241 /****************************************************************************/
int ec_rtdm_dev_init(ec_rtdm_dev_t *rtdm_dev, ec_master_t *master)
Initialize an RTDM device.
Definition: rtdm.c:69
void ecrt_release_master(ec_master_t *master)
Releases a requested EtherCAT master.
Definition: module.c:625
struct rtdm_device * dev
RTDM device.
Definition: rtdm.h:46
ec_master_t * master
Master pointer.
Definition: rtdm.h:45
EtherCAT RTDM device.
Definition: rtdm.h:44
int ec_rtdm_close(struct rtdm_dev_context *, rtdm_user_info_t *)
Driver close.
Definition: rtdm.c:171
#define DEBUG
Set to 1 to enable device operations debugging.
Definition: rtdm.c:45
EtherCAT master structure.
rtdm_user_info_t * user_info
RTDM user data.
Definition: rtdm.c:52
ec_ioctl_context_t ioctl_ctx
Context structure.
Definition: rtdm.c:53
int ec_rtdm_ioctl(struct rtdm_dev_context *, rtdm_user_info_t *, unsigned int, void __user *)
Driver ioctl.
Definition: rtdm.c:196
#define EC_MASTER_WARN(master, fmt, args...)
Convenience macro for printing master-specific warnings to syslog.
Definition: master.h:97
#define EC_MASTER_ERR(master, fmt, args...)
Convenience macro for printing master-specific errors to syslog.
Definition: master.h:85
int ec_rtdm_mmap(ec_ioctl_context_t *ioctl_ctx, void **user_address)
Memory-map process data to user space.
Definition: rtdm.c:220
void ec_rtdm_dev_clear(ec_rtdm_dev_t *rtdm_dev)
Clear an RTDM device.
Definition: rtdm.c:118
Context structure for an open RTDM file handle.
Definition: rtdm.c:51
EtherCAT master character device IOCTL commands.
unsigned int index
Index.
Definition: master.h:195
int ec_rtdm_open(struct rtdm_dev_context *, rtdm_user_info_t *, int)
Driver open.
Definition: rtdm.c:141
#define EC_MASTER_INFO(master, fmt, args...)
Convenience macro for printing master-specific information to syslog.
Definition: master.h:73
EtherCAT master.
Definition: master.h:194
RTDM interface.