IgH EtherCAT Master  1.6.9
rtdm_xenomai_v3.c
Go to the documentation of this file.
1/*****************************************************************************
2 *
3 * Copyright (C) 2009-2010 Moehwald GmbH B. Benner
4 * 2011 IgH Andreas Stewering-Bone
5 * 2012 Florian Pose <fp@igh.de>
6 *
7 * This file is part of the IgH EtherCAT master.
8 *
9 * The IgH EtherCAT master is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as published
11 * by the Free Software Foundation; version 2 of the License.
12 *
13 * The IgH EtherCAT master is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
16 * Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with the IgH EtherCAT master. If not, see <http://www.gnu.org/licenses/>.
20 *
21 ****************************************************************************/
22
26
27#include <linux/module.h>
28#include <linux/vmalloc.h>
29#include <rtdm/driver.h>
30
31#include "master.h"
32#include "ioctl.h"
33#include "rtdm.h"
34#include "rtdm_details.h"
35
38#define DEBUG_RTDM 0
39
40/****************************************************************************/
41
42static int ec_rtdm_open(struct rtdm_fd *fd, int oflags)
43{
44 struct ec_rtdm_context *ctx = rtdm_fd_to_private(fd);
45#if DEBUG_RTDM
46 struct rtdm_device *dev = rtdm_fd_device(fd);
47 ec_rtdm_dev_t *rtdm_dev = dev->device_data;
48#endif
49
50 ctx->user_fd = fd;
51
52 ctx->ioctl_ctx.writable = oflags & O_WRONLY || oflags & O_RDWR;
53 ctx->ioctl_ctx.requested = 0;
54 ctx->ioctl_ctx.process_data = NULL;
55 ctx->ioctl_ctx.process_data_size = 0;
56
57#if DEBUG_RTDM
58 EC_MASTER_INFO(rtdm_dev->master, "RTDM device %s opened.\n",
59 dev->name);
60#endif
61
62 return 0;
63}
64
65/****************************************************************************/
66
67static void ec_rtdm_close(struct rtdm_fd *fd)
68{
69 struct ec_rtdm_context *ctx = rtdm_fd_to_private(fd);
70 struct rtdm_device *dev = rtdm_fd_device(fd);
71 ec_rtdm_dev_t *rtdm_dev = dev->device_data;
72
73 if (ctx->ioctl_ctx.requested)
74 ecrt_release_master(rtdm_dev->master);
75
76 if (ctx->ioctl_ctx.process_data)
77 vfree(ctx->ioctl_ctx.process_data);
78
79#if DEBUG_RTDM
80 EC_MASTER_INFO(rtdm_dev->master, "RTDM device %s closed.\n",
81 dev->name);
82#endif
83}
84
85/****************************************************************************/
86
87static int ec_rtdm_ioctl_rt_handler(struct rtdm_fd *fd, unsigned int request,
88 void __user *arg)
89{
90 int result;
91 struct ec_rtdm_context *ctx = rtdm_fd_to_private(fd);
92 struct rtdm_device *dev = rtdm_fd_device(fd);
93 ec_rtdm_dev_t *rtdm_dev = dev->device_data;
94
95 result =
96 ec_ioctl_rtdm_rt(rtdm_dev->master, &ctx->ioctl_ctx, request, arg);
97
98 if (result == -ENOTTY)
99 /* Try again with nrt ioctl handler below in secondary mode. */
100 return -ENOSYS;
101
102 return result;
103}
104
105/****************************************************************************/
106
107static int ec_rtdm_ioctl_nrt_handler(struct rtdm_fd *fd, unsigned int request,
108 void __user *arg)
109{
110 struct ec_rtdm_context *ctx = rtdm_fd_to_private(fd);
111 struct rtdm_device *dev = rtdm_fd_device(fd);
112 ec_rtdm_dev_t *rtdm_dev = dev->device_data;
113
114 return ec_ioctl_rtdm_nrt(rtdm_dev->master, &ctx->ioctl_ctx, request, arg);
115}
116
117/****************************************************************************/
118
119static int ec_rtdm_mmap(struct rtdm_fd *fd, struct vm_area_struct *vma)
120{
121 struct ec_rtdm_context *ctx =
122 (struct ec_rtdm_context *) rtdm_fd_to_private(fd);
123 return rtdm_mmap_kmem(vma, (void *)ctx->ioctl_ctx.process_data);
124}
125
126/****************************************************************************/
127
128static struct rtdm_driver ec_rtdm_driver = {
129 .profile_info = RTDM_PROFILE_INFO(ec_rtdm,
130 RTDM_CLASS_EXPERIMENTAL,
131 222,
132 0),
133 .device_flags = RTDM_NAMED_DEVICE,
134 .device_count = EC_MAX_MASTERS,
135 .context_size = sizeof(struct ec_rtdm_context),
136 .ops = {
137 .open = ec_rtdm_open,
138 .close = ec_rtdm_close,
139 .ioctl_rt = ec_rtdm_ioctl_rt_handler,
140 .ioctl_nrt = ec_rtdm_ioctl_nrt_handler,
141 .mmap = ec_rtdm_mmap,
142 },
143};
144
145/****************************************************************************/
146
148{
149 struct rtdm_device *dev;
150 int ret;
151
152 rtdm_dev->master = master;
153
154 rtdm_dev->dev = kzalloc(sizeof(struct rtdm_device), GFP_KERNEL);
155 if (!rtdm_dev->dev) {
156 EC_MASTER_ERR(master,
157 "Failed to reserve memory for RTDM device.\n");
158 return -ENOMEM;
159 }
160
161 dev = rtdm_dev->dev;
162
163 dev->driver = &ec_rtdm_driver;
164 dev->device_data = rtdm_dev;
165 dev->label = "EtherCAT%u";
166 dev->minor = master->index;
167
168 ret = rtdm_dev_register(dev);
169 if (ret) {
170 EC_MASTER_ERR(master, "Initialization of RTDM interface failed"
171 " (return value %i).\n", ret);
172 kfree(dev);
173 return ret;
174 }
175
176 EC_MASTER_INFO(master, "Registered RTDM device %s.\n", dev->name);
177
178 return 0;
179}
180
181/****************************************************************************/
182
184{
185 rtdm_dev_unregister(rtdm_dev->dev);
186
187 EC_MASTER_INFO(rtdm_dev->master, "Unregistered RTDM device %s.\n",
188 rtdm_dev->dev->name);
189
190 kfree(rtdm_dev->dev);
191}
192
193/****************************************************************************/
void ecrt_release_master(ec_master_t *master)
Releases a requested EtherCAT master.
Definition module.c:621
struct ec_master ec_master_t
Definition ecrt.h:300
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:62
#define EC_MAX_MASTERS
Maximum number of masters.
Definition master.h:117
#define EC_MASTER_ERR(master, fmt, args...)
Convenience macro for printing master-specific errors to syslog.
Definition master.h:74
int ec_rtdm_mmap(ec_ioctl_context_t *ioctl_ctx, void **user_address)
Memory-map process data to user space.
Definition rtdm.c:238
static int ec_rtdm_close(struct rtdm_dev_context *, rtdm_user_info_t *)
Driver close.
Definition rtdm.c:161
static int ec_rtdm_ioctl_nrt_handler(struct rtdm_dev_context *, rtdm_user_info_t *, unsigned int, void __user *)
Driver ioctl.
Definition rtdm.c:186
static int ec_rtdm_open(struct rtdm_dev_context *, rtdm_user_info_t *, int)
Driver open.
Definition rtdm.c:131
static int ec_rtdm_ioctl_rt_handler(struct rtdm_dev_context *, rtdm_user_info_t *, unsigned int, void __user *)
Definition rtdm.c:206
RTDM interface.
struct ec_rtdm_dev ec_rtdm_dev_t
EtherCAT RTDM device.
void ec_rtdm_dev_clear(ec_rtdm_dev_t *rtdm_dev)
Clear an RTDM device.
int ec_rtdm_dev_init(ec_rtdm_dev_t *rtdm_dev, ec_master_t *master)
Initialize an RTDM device.
unsigned int index
Index.
Definition master.h:188
Context structure for an open RTDM file handle.
ec_ioctl_context_t ioctl_ctx
Context structure.
EC_RTDM_USERFD_T * user_fd
RTDM user data.
ec_master_t * master
Master pointer.
Definition rtdm.h:39
struct rtdm_device * dev
RTDM device.
Definition rtdm.h:40