IgH EtherCAT Master  1.5.2
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
51typedef struct {
52 rtdm_user_info_t *user_info;
53 ec_ioctl_context_t ioctl_ctx;
55
56/****************************************************************************/
57
58int ec_rtdm_open(struct rtdm_dev_context *, rtdm_user_info_t *, int);
59int ec_rtdm_close(struct rtdm_dev_context *, rtdm_user_info_t *);
60int 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/****************************************************************************/
void ecrt_release_master(ec_master_t *master)
Releases a requested EtherCAT master.
Definition: module.c:625
EtherCAT master character device IOCTL commands.
EtherCAT master structure.
#define EC_MASTER_INFO(master, fmt, args...)
Convenience macro for printing master-specific information to syslog.
Definition: master.h:73
#define EC_MASTER_ERR(master, fmt, args...)
Convenience macro for printing master-specific errors to syslog.
Definition: master.h:85
#define EC_MASTER_WARN(master, fmt, args...)
Convenience macro for printing master-specific warnings to syslog.
Definition: master.h:97
int ec_rtdm_open(struct rtdm_dev_context *, rtdm_user_info_t *, int)
Driver open.
Definition: rtdm.c:141
int ec_rtdm_close(struct rtdm_dev_context *, rtdm_user_info_t *)
Driver close.
Definition: rtdm.c:171
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
int ec_rtdm_dev_init(ec_rtdm_dev_t *rtdm_dev, ec_master_t *master)
Initialize an RTDM device.
Definition: rtdm.c:69
int ec_rtdm_ioctl(struct rtdm_dev_context *, rtdm_user_info_t *, unsigned int, void __user *)
Driver ioctl.
Definition: rtdm.c:196
#define DEBUG
Set to 1 to enable device operations debugging.
Definition: rtdm.c:45
RTDM interface.
EtherCAT master.
Definition: master.h:194
unsigned int index
Index.
Definition: master.h:195
Context structure for an open RTDM file handle.
Definition: rtdm.c:51
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
EtherCAT RTDM device.
Definition: rtdm.h:44
ec_master_t * master
Master pointer.
Definition: rtdm.h:45
struct rtdm_device * dev
RTDM device.
Definition: rtdm.h:46