1 /****************************************************************************** |
|
2 * |
|
3 * ec_module.c |
|
4 * |
|
5 * EtherCAT-Master-Treiber |
|
6 * |
|
7 * Autoren: Wilhelm Hagemeister, Florian Pose |
|
8 * |
|
9 * $Id$ |
|
10 * |
|
11 * (C) Copyright IgH 2005 |
|
12 * Ingenieurgemeinschaft IgH |
|
13 * Heinz-Bäcker Str. 34 |
|
14 * D-45356 Essen |
|
15 * Tel.: +49 201/61 99 31 |
|
16 * Fax.: +49 201/61 98 36 |
|
17 * E-mail: sp@igh-essen.com |
|
18 * |
|
19 *****************************************************************************/ |
|
20 |
|
21 #include <linux/module.h> |
|
22 #include <linux/kernel.h> |
|
23 #include <linux/init.h> |
|
24 |
|
25 #include "ec_module.h" |
|
26 |
|
27 int __init ecat_init_module(void); |
|
28 void __exit ecat_cleanup_module(void); |
|
29 |
|
30 /*****************************************************************************/ |
|
31 |
|
32 #define LIT(X) #X |
|
33 #define STR(X) LIT(X) |
|
34 |
|
35 #define COMPILE_INFO "Revision " STR(EC_REV) \ |
|
36 ", compiled by " STR(EC_USER) \ |
|
37 " at " STR(EC_DATE) |
|
38 |
|
39 /*****************************************************************************/ |
|
40 |
|
41 int ecat_master_count = 1; |
|
42 EtherCAT_master_t *ecat_masters = NULL; |
|
43 int *ecat_masters_reserved = NULL; |
|
44 |
|
45 /*****************************************************************************/ |
|
46 |
|
47 MODULE_AUTHOR ("Wilhelm Hagemeister <hm@igh-essen.com>," |
|
48 "Florian Pose <fp@igh-essen.com>"); |
|
49 MODULE_DESCRIPTION ("EtherCAT master driver module"); |
|
50 MODULE_LICENSE("GPL"); |
|
51 MODULE_VERSION(COMPILE_INFO); |
|
52 |
|
53 module_param(ecat_master_count, int, 1); |
|
54 MODULE_PARM_DESC(ecat_master_count, |
|
55 "Number of EtherCAT master to initialize."); |
|
56 |
|
57 module_init(ecat_init_module); |
|
58 module_exit(ecat_cleanup_module); |
|
59 |
|
60 EXPORT_SYMBOL(EtherCAT_register_device); |
|
61 EXPORT_SYMBOL(EtherCAT_unregister_device); |
|
62 EXPORT_SYMBOL(EtherCAT_request); |
|
63 EXPORT_SYMBOL(EtherCAT_release); |
|
64 |
|
65 /*****************************************************************************/ |
|
66 |
|
67 /** |
|
68 Init-Funktion des EtherCAT-Master-Treibermodules |
|
69 |
|
70 Initialisiert soviele Master, wie im Parameter ecat_master_count |
|
71 angegeben wurde (Default ist 1). |
|
72 |
|
73 @returns 0, wenn alles o.k., -1 bei ungueltiger Anzahl Master |
|
74 oder zu wenig Speicher. |
|
75 */ |
|
76 |
|
77 int __init ecat_init_module(void) |
|
78 { |
|
79 unsigned int i; |
|
80 |
|
81 printk(KERN_ERR "EtherCAT: Master driver, %s\n", COMPILE_INFO); |
|
82 |
|
83 if (ecat_master_count < 1) { |
|
84 printk(KERN_ERR "EtherCAT: Error - Illegal" |
|
85 " ecat_master_count: %i\n", ecat_master_count); |
|
86 return -1; |
|
87 } |
|
88 |
|
89 printk(KERN_ERR "EtherCAT: Initializing %i EtherCAT master(s)...\n", |
|
90 ecat_master_count); |
|
91 |
|
92 if ((ecat_masters = |
|
93 (EtherCAT_master_t *) kmalloc(sizeof(EtherCAT_master_t) |
|
94 * ecat_master_count, |
|
95 GFP_KERNEL)) == NULL) { |
|
96 printk(KERN_ERR "EtherCAT: Could not allocate" |
|
97 " memory for EtherCAT master(s)!\n"); |
|
98 return -1; |
|
99 } |
|
100 |
|
101 if ((ecat_masters_reserved = |
|
102 (int *) kmalloc(sizeof(int) * ecat_master_count, |
|
103 GFP_KERNEL)) == NULL) { |
|
104 printk(KERN_ERR "EtherCAT: Could not allocate" |
|
105 " memory for reservation flags!\n"); |
|
106 kfree(ecat_masters); |
|
107 return -1; |
|
108 } |
|
109 |
|
110 for (i = 0; i < ecat_master_count; i++) |
|
111 { |
|
112 EtherCAT_master_init(&ecat_masters[i]); |
|
113 ecat_masters_reserved[i] = 0; |
|
114 } |
|
115 |
|
116 printk(KERN_ERR "EtherCAT: Master driver initialized.\n"); |
|
117 |
|
118 return 0; |
|
119 } |
|
120 |
|
121 /*****************************************************************************/ |
|
122 |
|
123 /** |
|
124 Cleanup-Funktion des EtherCAT-Master-Treibermoduls |
|
125 |
|
126 Entfernt alle Master-Instanzen. |
|
127 */ |
|
128 |
|
129 void __exit ecat_cleanup_module(void) |
|
130 { |
|
131 unsigned int i; |
|
132 |
|
133 printk(KERN_ERR "EtherCAT: Cleaning up master driver...\n"); |
|
134 |
|
135 if (ecat_masters) |
|
136 { |
|
137 for (i = 0; i < ecat_master_count; i++) |
|
138 { |
|
139 if (ecat_masters_reserved[i]) { |
|
140 printk(KERN_WARNING "EtherCAT: Warning -" |
|
141 " Master %i is still in use!\n", i); |
|
142 } |
|
143 |
|
144 EtherCAT_master_clear(&ecat_masters[i]); |
|
145 } |
|
146 |
|
147 kfree(ecat_masters); |
|
148 } |
|
149 |
|
150 printk(KERN_ERR "EtherCAT: Master driver cleaned up.\n"); |
|
151 } |
|
152 |
|
153 /*****************************************************************************/ |
|
154 |
|
155 /** |
|
156 Setzt das EtherCAT-Geraet, auf dem der Master arbeitet. |
|
157 |
|
158 Registriert das Geraet beim Master, der es daraufhin oeffnet. |
|
159 |
|
160 @param master Der EtherCAT-Master |
|
161 @param device Das EtherCAT-Geraet |
|
162 @return 0, wenn alles o.k., |
|
163 < 0, wenn bereits ein Geraet registriert |
|
164 oder das Geraet nicht geoeffnet werden konnte. |
|
165 */ |
|
166 |
|
167 int EtherCAT_register_device(int index, EtherCAT_device_t *device) |
|
168 { |
|
169 if (index < 0 || index >= ecat_master_count) { |
|
170 printk(KERN_ERR "EtherCAT: Master %i does not exist!\n", index); |
|
171 return -1; |
|
172 } |
|
173 |
|
174 return EtherCAT_master_open(&ecat_masters[index], device); |
|
175 } |
|
176 |
|
177 /*****************************************************************************/ |
|
178 |
|
179 /** |
|
180 Loescht das EtherCAT-Geraet, auf dem der Master arbeitet. |
|
181 |
|
182 @param master Der EtherCAT-Master |
|
183 @param device Das EtherCAT-Geraet |
|
184 */ |
|
185 |
|
186 void EtherCAT_unregister_device(int index, EtherCAT_device_t *device) |
|
187 { |
|
188 if (index < 0 || index >= ecat_master_count) { |
|
189 printk(KERN_WARNING "EtherCAT: Master %i does not exist!\n", index); |
|
190 return; |
|
191 } |
|
192 |
|
193 EtherCAT_master_close(&ecat_masters[index], device); |
|
194 } |
|
195 |
|
196 /*****************************************************************************/ |
|
197 |
|
198 /** |
|
199 Reserviert einen bestimmten EtherCAT-Master und das zugehörige Gerät. |
|
200 |
|
201 Gibt einen Zeiger auf den reservierten EtherCAT-Master zurueck. |
|
202 |
|
203 @param index Index des gewuenschten Masters |
|
204 @returns Zeiger auf EtherCAT-Master oder NULL, wenn Parameter ungueltig. |
|
205 */ |
|
206 |
|
207 EtherCAT_master_t *EtherCAT_request(int index) |
|
208 { |
|
209 if (index < 0 || index >= ecat_master_count) { |
|
210 printk(KERN_ERR "EtherCAT: Master %i does not exist!\n", index); |
|
211 return NULL; |
|
212 } |
|
213 |
|
214 if (ecat_masters_reserved[index]) { |
|
215 printk(KERN_ERR "EtherCAT: Master %i already in use!\n", index); |
|
216 return NULL; |
|
217 } |
|
218 |
|
219 if (!ecat_masters[index].dev) { |
|
220 printk(KERN_ERR "EtherCAT: Master %i has no device assigned yet!\n", |
|
221 index); |
|
222 return NULL; |
|
223 } |
|
224 |
|
225 if (!ecat_masters[index].dev->module) { |
|
226 printk(KERN_ERR "EtherCAT: Master %i device module is not set!\n", index); |
|
227 return NULL; |
|
228 } |
|
229 |
|
230 if (!try_module_get(ecat_masters[index].dev->module)) { |
|
231 printk(KERN_ERR "EtherCAT: Could not reserve device module!\n"); |
|
232 return NULL; |
|
233 } |
|
234 |
|
235 if (EtherCAT_scan_for_slaves(&ecat_masters[index]) != 0) { |
|
236 printk(KERN_ERR "EtherCAT: Could not scan for slaves!\n"); |
|
237 return NULL; |
|
238 } |
|
239 |
|
240 ecat_masters_reserved[index] = 1; |
|
241 |
|
242 printk(KERN_INFO "EtherCAT: Reserved master %i.\n", index); |
|
243 |
|
244 return &ecat_masters[index]; |
|
245 } |
|
246 |
|
247 /*****************************************************************************/ |
|
248 |
|
249 /** |
|
250 Gibt einen zuvor angeforderten EtherCAT-Master wieder frei. |
|
251 |
|
252 @param master Zeiger auf den freizugebenden EtherCAT-Master. |
|
253 */ |
|
254 |
|
255 void EtherCAT_release(EtherCAT_master_t *master) |
|
256 { |
|
257 unsigned int i; |
|
258 |
|
259 for (i = 0; i < ecat_master_count; i++) |
|
260 { |
|
261 if (&ecat_masters[i] == master) |
|
262 { |
|
263 if (!ecat_masters[i].dev) { |
|
264 printk(KERN_WARNING "EtherCAT: Could not release device" |
|
265 "module because of no device!\n"); |
|
266 return; |
|
267 } |
|
268 |
|
269 module_put(ecat_masters[i].dev->module); |
|
270 ecat_masters_reserved[i] = 0; |
|
271 |
|
272 printk(KERN_INFO "EtherCAT: Released master %i.\n", i); |
|
273 |
|
274 return; |
|
275 } |
|
276 } |
|
277 |
|
278 printk(KERN_WARNING "EtherCAT: Master %X was never requested!\n", |
|
279 (unsigned int) master); |
|
280 } |
|
281 |
|
282 /*****************************************************************************/ |
|