42 |
42 |
43 /** Set to 1 to enable device operations debugging. |
43 /** Set to 1 to enable device operations debugging. |
44 */ |
44 */ |
45 #define DEBUG 0 |
45 #define DEBUG 0 |
46 |
46 |
47 /****************************************************************************/ |
47 |
48 |
48 /****************************************************************************/ |
49 /** Context structure for an open RTDM file handle. |
49 |
50 */ |
50 int ec_rtdm_open(struct rtdm_fd *, int); |
51 typedef struct { |
51 void ec_rtdm_close(struct rtdm_fd *); |
52 struct rtdm_fd *fd; /**< RTDM user data. */ |
52 int ec_rtdm_ioctl(struct rtdm_fd *, |
53 ec_ioctl_context_t ioctl_ctx; /**< Context structure. */ |
|
54 } ec_rtdm_context_t; |
|
55 |
|
56 /****************************************************************************/ |
|
57 |
|
58 int ec_rtdm_open(struct rtdm_dev_context *, struct rtdm_fd *, int); |
|
59 int ec_rtdm_close(struct rtdm_dev_context *, struct rtdm_fd *); |
|
60 int ec_rtdm_ioctl(struct rtdm_dev_context *, struct rtdm_fd *, |
|
61 unsigned int, void __user *); |
53 unsigned int, void __user *); |
62 |
54 |
63 /****************************************************************************/ |
55 /****************************************************************************/ |
64 |
56 |
65 static struct rtdm_driver ec_rtdm_driver = { |
57 static struct rtdm_driver ec_rtdm_driver = { |
67 RTDM_CLASS_EXPERIMENTAL, |
59 RTDM_CLASS_EXPERIMENTAL, |
68 222, |
60 222, |
69 1), |
61 1), |
70 .device_flags = RTDM_NAMED_DEVICE, |
62 .device_flags = RTDM_NAMED_DEVICE, |
71 .device_count = 1, |
63 .device_count = 1, |
72 .context_size = sizeof(ec_rtdm_context_t), |
64 .context_size = sizeof(ec_ioctl_context_t), |
73 .ops = { |
65 .ops = { |
74 .open = ec_rtdm_open; |
66 .open = ec_rtdm_open, |
75 .close_nrt = ec_rtdm_close, |
67 .close = ec_rtdm_close, |
76 .ioctl_rt = ec_rtdm_ioctl, |
68 .ioctl_rt = ec_rtdm_ioctl, |
77 .ioctl_nrt = ec_rtdm_ioctl |
69 .ioctl_nrt = ec_rtdm_ioctl |
78 }, |
70 }, |
79 }; |
71 }; |
80 |
72 |
86 ec_rtdm_dev_t *rtdm_dev, /**< EtherCAT RTDM device. */ |
78 ec_rtdm_dev_t *rtdm_dev, /**< EtherCAT RTDM device. */ |
87 ec_master_t *master /**< EtherCAT master. */ |
79 ec_master_t *master /**< EtherCAT master. */ |
88 ) |
80 ) |
89 { |
81 { |
90 int ret; |
82 int ret; |
91 |
83 char* devlabel; |
92 MODULE_VERSION |
|
93 |
84 |
94 rtdm_dev->master = master; |
85 rtdm_dev->master = master; |
95 |
86 |
96 rtdm_dev->dev = kzalloc(sizeof(struct rtdm_device), GFP_KERNEL); |
87 rtdm_dev->dev = kzalloc(sizeof(struct rtdm_device), GFP_KERNEL); |
97 if (!rtdm_dev->dev) { |
88 if (!rtdm_dev->dev) { |
98 EC_MASTER_ERR(master, "Failed to reserve memory for RTDM device.\n"); |
89 EC_MASTER_ERR(master, "Failed to reserve memory for RTDM device.\n"); |
99 return -ENOMEM; |
90 return -ENOMEM; |
100 } |
91 } |
101 |
92 |
102 rtdm_dev->dev->label = kzalloc(RTDM_MAX_DEVNAME_LEN+1, GFP_KERNEL); |
93 devlabel = kzalloc(RTDM_MAX_DEVNAME_LEN+1, GFP_KERNEL); |
103 if (!rtdm_dev->dev->label) { |
94 if (!devlabel) { |
104 EC_MASTER_ERR(master, "Failed to reserve memory for RTDM device name.\n"); |
95 EC_MASTER_ERR(master, "Failed to reserve memory for RTDM device name.\n"); |
105 return -ENOMEM; |
96 return -ENOMEM; |
106 kfree(rtdm_dev->dev); |
97 kfree(rtdm_dev->dev); |
107 } |
98 } |
108 |
99 snprintf(devlabel, RTDM_MAX_DEVNAME_LEN, |
109 |
100 "EtherCAT%u", master->index); |
|
101 |
|
102 rtdm_dev->dev->label = devlabel; |
110 rtdm_dev->dev->driver = &ec_rtdm_driver; |
103 rtdm_dev->dev->driver = &ec_rtdm_driver; |
111 snprintf(rtdm_dev->dev->label, RTDM_MAX_DEVNAME_LEN, |
|
112 "EtherCAT%u", master->index); |
|
113 rtdm_dev->dev->device_data = rtdm_dev; /* pointer to parent */ |
104 rtdm_dev->dev->device_data = rtdm_dev; /* pointer to parent */ |
114 |
105 |
115 |
106 |
116 EC_MASTER_INFO(master, "Registering RTDM device %s.\n", |
107 EC_MASTER_INFO(master, "Registering RTDM device %s.\n", |
117 rtdm_dev->dev->driver_name); |
108 devlabel); |
118 ret = rtdm_dev_register(rtdm_dev->dev); |
109 ret = rtdm_dev_register(rtdm_dev->dev); |
119 if (ret) { |
110 if (ret) { |
120 EC_MASTER_ERR(master, "Initialization of RTDM interface failed" |
111 EC_MASTER_ERR(master, "Initialization of RTDM interface failed" |
121 " (return value %i).\n", ret); |
112 " (return value %i).\n", ret); |
122 kfree(rtdm_dev->dev->label); |
113 kfree(rtdm_dev->dev->label); |
132 */ |
123 */ |
133 void ec_rtdm_dev_clear( |
124 void ec_rtdm_dev_clear( |
134 ec_rtdm_dev_t *rtdm_dev /**< EtherCAT RTDM device. */ |
125 ec_rtdm_dev_t *rtdm_dev /**< EtherCAT RTDM device. */ |
135 ) |
126 ) |
136 { |
127 { |
137 int ret; |
|
138 |
|
139 EC_MASTER_INFO(rtdm_dev->master, "Unregistering RTDM device %s.\n", |
128 EC_MASTER_INFO(rtdm_dev->master, "Unregistering RTDM device %s.\n", |
140 rtdm_dev->dev->label); |
129 rtdm_dev->dev->label); |
141 ret = rtdm_dev_unregister(rtdm_dev->dev, 1000 /* poll delay [ms] */); |
130 rtdm_dev_unregister(rtdm_dev->dev); |
142 if (ret < 0) { |
|
143 EC_MASTER_WARN(rtdm_dev->master, |
|
144 "Failed to unregister RTDM device (code %i).\n", ret); |
|
145 } |
|
146 |
131 |
147 kfree(rtdm_dev->dev->label); |
132 kfree(rtdm_dev->dev->label); |
148 kfree(rtdm_dev->dev); |
133 kfree(rtdm_dev->dev); |
149 } |
134 } |
150 |
135 |
153 /** Driver open. |
138 /** Driver open. |
154 * |
139 * |
155 * \return Always zero (success). |
140 * \return Always zero (success). |
156 */ |
141 */ |
157 int ec_rtdm_open( |
142 int ec_rtdm_open( |
158 struct rtdm_dev_context *context, /**< Context. */ |
|
159 struct rtdm_fd *fd, /**< User data. */ |
143 struct rtdm_fd *fd, /**< User data. */ |
160 int oflags /**< Open flags. */ |
144 int oflags /**< Open flags. */ |
161 ) |
145 ) |
162 { |
146 { |
163 ec_rtdm_context_t *ctx = (ec_rtdm_context_t *) context->dev_private; |
147 ec_ioctl_context_t *ctx = (ec_ioctl_context_t *) rtdm_fd_to_private(fd); |
164 #if DEBUG |
148 #if DEBUG |
165 ec_rtdm_dev_t *rtdm_dev = (ec_rtdm_dev_t *) context->device->device_data; |
149 ec_rtdm_dev_t *rtdm_dev = (ec_rtdm_dev_t *) rtdm_fd_device(fd)->device_data; |
166 #endif |
150 #endif |
167 |
151 |
168 ctx->fd = fd; |
152 ctx->writable = oflags & O_WRONLY || oflags & O_RDWR; |
169 ctx->ioctl_ctx.writable = oflags & O_WRONLY || oflags & O_RDWR; |
153 ctx->requested = 0; |
170 ctx->ioctl_ctx.requested = 0; |
154 ctx->process_data = NULL; |
171 ctx->ioctl_ctx.process_data = NULL; |
155 ctx->process_data_size = 0; |
172 ctx->ioctl_ctx.process_data_size = 0; |
|
173 |
156 |
174 #if DEBUG |
157 #if DEBUG |
175 EC_MASTER_INFO(rtdm_dev->master, "RTDM device %s opened.\n", |
158 EC_MASTER_INFO(rtdm_dev->master, "RTDM device %s opened.\n", |
176 context->device->device_name); |
159 context->device->device_name); |
177 #endif |
160 #endif |
182 |
165 |
183 /** Driver close. |
166 /** Driver close. |
184 * |
167 * |
185 * \return Always zero (success). |
168 * \return Always zero (success). |
186 */ |
169 */ |
187 int ec_rtdm_close( |
170 void ec_rtdm_close( |
188 struct rtdm_dev_context *context, /**< Context. */ |
|
189 struct rtdm_fd *fd /**< User data. */ |
171 struct rtdm_fd *fd /**< User data. */ |
190 ) |
172 ) |
191 { |
173 { |
192 ec_rtdm_context_t *ctx = (ec_rtdm_context_t *) context->dev_private; |
174 ec_ioctl_context_t *ctx = (ec_ioctl_context_t *) rtdm_fd_to_private(fd); |
193 ec_rtdm_dev_t *rtdm_dev = (ec_rtdm_dev_t *) context->device->device_data; |
175 ec_rtdm_dev_t *rtdm_dev = (ec_rtdm_dev_t *) rtdm_fd_device(fd)->device_data; |
194 |
176 |
195 if (ctx->ioctl_ctx.requested) { |
177 if (ctx->requested) { |
196 ecrt_release_master(rtdm_dev->master); |
178 ecrt_release_master(rtdm_dev->master); |
197 } |
179 } |
198 |
180 |
199 #if DEBUG |
181 #if DEBUG |
200 EC_MASTER_INFO(rtdm_dev->master, "RTDM device %s closed.\n", |
182 EC_MASTER_INFO(rtdm_dev->master, "RTDM device %s closed.\n", |
201 context->device->device_name); |
183 context->device->device_name); |
202 #endif |
184 #endif |
203 return 0; |
|
204 } |
185 } |
205 |
186 |
206 /****************************************************************************/ |
187 /****************************************************************************/ |
207 |
188 |
208 /** Driver ioctl. |
189 /** Driver ioctl. |
209 * |
190 * |
210 * \return ioctl() return code. |
191 * \return ioctl() return code. |
211 */ |
192 */ |
212 int ec_rtdm_ioctl( |
193 int ec_rtdm_ioctl( |
213 struct rtdm_dev_context *context, /**< Context. */ |
|
214 struct rtdm_fd *fd, /**< User data. */ |
194 struct rtdm_fd *fd, /**< User data. */ |
215 unsigned int request, /**< Request. */ |
195 unsigned int request, /**< Request. */ |
216 void __user *arg /**< Argument. */ |
196 void __user *arg /**< Argument. */ |
217 ) |
197 ) |
218 { |
198 { |
219 ec_rtdm_context_t *ctx = (ec_rtdm_context_t *) context->dev_private; |
199 ec_ioctl_context_t *ctx = (ec_ioctl_context_t *) rtdm_fd_to_private(fd); |
220 ec_rtdm_dev_t *rtdm_dev = (ec_rtdm_dev_t *) context->device->device_data; |
200 ec_rtdm_dev_t *rtdm_dev = (ec_rtdm_dev_t *) rtdm_fd_device(fd)->device_data; |
221 |
201 |
222 #if DEBUG |
202 #if DEBUG |
223 EC_MASTER_INFO(rtdm_dev->master, "ioctl(request = %u, ctl = %02x)" |
203 EC_MASTER_INFO(rtdm_dev->master, "ioctl(request = %u, ctl = %02x)" |
224 " on RTDM device %s.\n", request, _IOC_NR(request), |
204 " on RTDM device %s.\n", request, _IOC_NR(request), |
225 context->device->device_name); |
205 context->device->device_name); |
226 #endif |
206 #endif |
227 return ec_ioctl_rtdm(rtdm_dev->master, &ctx->ioctl_ctx, request, arg); |
207 return ec_ioctl_rtdm(rtdm_dev->master, ctx, request, arg); |
228 } |
208 } |
229 |
209 |
230 /****************************************************************************/ |
210 /****************************************************************************/ |
231 |
211 |
232 /** Memory-map process data to user space. |
212 /** Memory-map process data to user space. |
233 * |
213 * |
234 * \return Zero on success, otherwise a negative error code. |
214 * \return Zero on success, otherwise a negative error code. |
235 */ |
215 */ |
236 int ec_rtdm_mmap( |
216 int ec_rtdm_mmap( |
237 ec_ioctl_context_t *ioctl_ctx, /**< Context. */ |
217 ec_ioctl_context_t *ctx, /**< Context. */ |
238 void **user_address /**< Userspace address. */ |
218 void **user_address /**< Userspace address. */ |
239 ) |
219 ) |
240 { |
220 { |
241 ec_rtdm_context_t *ctx = |
|
242 container_of(ioctl_ctx, ec_rtdm_context_t, ioctl_ctx); |
|
243 int ret; |
221 int ret; |
244 |
222 |
245 ret = rtdm_mmap_to_user(ctx->fd, |
223 ret = rtdm_mmap_to_user(rtdm_private_to_fd(ctx), |
246 ioctl_ctx->process_data, ioctl_ctx->process_data_size, |
224 ctx->process_data, ctx->process_data_size, |
247 PROT_READ | PROT_WRITE, |
225 PROT_READ | PROT_WRITE, |
248 user_address, |
226 user_address, |
249 NULL, NULL); |
227 NULL, NULL); |
250 if (ret < 0) { |
228 if (ret < 0) { |
251 return ret; |
229 return ret; |