109 const uint8_t *backup_mac, /**< MAC address of backup device */ |
109 const uint8_t *backup_mac, /**< MAC address of backup device */ |
110 dev_t device_number, /**< Character device number. */ |
110 dev_t device_number, /**< Character device number. */ |
111 struct class *class /**< Device class. */ |
111 struct class *class /**< Device class. */ |
112 ) |
112 ) |
113 { |
113 { |
|
114 int ret; |
|
115 |
114 master->index = index; |
116 master->index = index; |
115 master->reserved = 0; |
117 master->reserved = 0; |
116 |
118 |
117 init_MUTEX(&master->master_sem); |
119 init_MUTEX(&master->master_sem); |
118 |
120 |
174 |
176 |
175 INIT_LIST_HEAD(&master->phy_requests); |
177 INIT_LIST_HEAD(&master->phy_requests); |
176 init_waitqueue_head(&master->phy_queue); |
178 init_waitqueue_head(&master->phy_queue); |
177 |
179 |
178 // init devices |
180 // init devices |
179 if (ec_device_init(&master->main_device, master)) |
181 ret = ec_device_init(&master->main_device, master); |
|
182 if (ret < 0) |
180 goto out_return; |
183 goto out_return; |
181 |
184 |
182 if (ec_device_init(&master->backup_device, master)) |
185 ret = ec_device_init(&master->backup_device, master); |
|
186 if (ret < 0) |
183 goto out_clear_main; |
187 goto out_clear_main; |
184 |
188 |
185 // init state machine datagram |
189 // init state machine datagram |
186 ec_datagram_init(&master->fsm_datagram); |
190 ec_datagram_init(&master->fsm_datagram); |
187 snprintf(master->fsm_datagram.name, EC_DATAGRAM_NAME_SIZE, "master-fsm"); |
191 snprintf(master->fsm_datagram.name, EC_DATAGRAM_NAME_SIZE, "master-fsm"); |
188 if (ec_datagram_prealloc(&master->fsm_datagram, EC_MAX_DATA_SIZE)) { |
192 ret = ec_datagram_prealloc(&master->fsm_datagram, EC_MAX_DATA_SIZE); |
|
193 if (ret < 0) { |
189 EC_ERR("Failed to allocate FSM datagram.\n"); |
194 EC_ERR("Failed to allocate FSM datagram.\n"); |
190 goto out_clear_backup; |
195 goto out_clear_backup; |
191 } |
196 } |
192 |
197 |
193 // create state machine object |
198 // create state machine object |
194 ec_fsm_master_init(&master->fsm, master, &master->fsm_datagram); |
199 ec_fsm_master_init(&master->fsm, master, &master->fsm_datagram); |
195 |
200 |
196 // init character device |
201 // init character device |
197 if (ec_cdev_init(&master->cdev, master, device_number)) |
202 ret = ec_cdev_init(&master->cdev, master, device_number); |
|
203 if (ret) |
198 goto out_clear_fsm; |
204 goto out_clear_fsm; |
199 |
205 |
200 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) |
206 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) |
201 master->class_device = device_create(class, NULL, |
207 master->class_device = device_create(class, NULL, |
202 MKDEV(MAJOR(device_number), master->index), |
208 MKDEV(MAJOR(device_number), master->index), |
210 MKDEV(MAJOR(device_number), master->index), |
216 MKDEV(MAJOR(device_number), master->index), |
211 NULL, "EtherCAT%u", master->index); |
217 NULL, "EtherCAT%u", master->index); |
212 #endif |
218 #endif |
213 if (IS_ERR(master->class_device)) { |
219 if (IS_ERR(master->class_device)) { |
214 EC_ERR("Failed to create class device!\n"); |
220 EC_ERR("Failed to create class device!\n"); |
|
221 ret = PTR_ERR(master->class_device); |
215 goto out_clear_cdev; |
222 goto out_clear_cdev; |
216 } |
223 } |
217 |
224 |
218 return 0; |
225 return 0; |
219 |
226 |
347 } |
354 } |
348 |
355 |
349 /*****************************************************************************/ |
356 /*****************************************************************************/ |
350 |
357 |
351 /** Starts the master thread. |
358 /** Starts the master thread. |
|
359 * |
|
360 * \retval 0 Success. |
|
361 * \retval <0 Error code. |
352 */ |
362 */ |
353 int ec_master_thread_start( |
363 int ec_master_thread_start( |
354 ec_master_t *master, /**< EtherCAT master */ |
364 ec_master_t *master, /**< EtherCAT master */ |
355 int (*thread_func)(void *), /**< thread function to start */ |
365 int (*thread_func)(void *), /**< thread function to start */ |
356 const char *name /**< Thread name. */ |
366 const char *name /**< Thread name. */ |
357 ) |
367 ) |
358 { |
368 { |
359 EC_INFO("Starting %s thread.\n", name); |
369 EC_INFO("Starting %s thread.\n", name); |
360 master->thread = kthread_run(thread_func, master, name); |
370 master->thread = kthread_run(thread_func, master, name); |
361 if (IS_ERR(master->thread)) { |
371 if (IS_ERR(master->thread)) { |
362 EC_ERR("Failed to start master thread (error %i)!\n", |
372 int err = (int) PTR_ERR(master->thread); |
363 (int) PTR_ERR(master->thread)); |
373 EC_ERR("Failed to start master thread (error %i)!\n", err); |
364 master->thread = NULL; |
374 master->thread = NULL; |
365 return -1; |
375 return err; |
366 } |
376 } |
367 |
377 |
368 return 0; |
378 return 0; |
369 } |
379 } |
370 |
380 |
404 */ |
414 */ |
405 int ec_master_enter_idle_phase( |
415 int ec_master_enter_idle_phase( |
406 ec_master_t *master /**< EtherCAT master */ |
416 ec_master_t *master /**< EtherCAT master */ |
407 ) |
417 ) |
408 { |
418 { |
|
419 int ret; |
|
420 |
409 if (master->debug_level) |
421 if (master->debug_level) |
410 EC_DBG("ORPHANED -> IDLE.\n"); |
422 EC_DBG("ORPHANED -> IDLE.\n"); |
411 |
423 |
412 master->request_cb = ec_master_request_cb; |
424 master->request_cb = ec_master_request_cb; |
413 master->release_cb = ec_master_release_cb; |
425 master->release_cb = ec_master_release_cb; |
414 master->cb_data = master; |
426 master->cb_data = master; |
415 |
427 |
416 master->phase = EC_IDLE; |
428 master->phase = EC_IDLE; |
417 if (ec_master_thread_start(master, ec_master_idle_thread, |
429 ret = ec_master_thread_start(master, ec_master_idle_thread, |
418 "EtherCAT-IDLE")) { |
430 "EtherCAT-IDLE"); |
|
431 if (ret) |
419 master->phase = EC_ORPHANED; |
432 master->phase = EC_ORPHANED; |
420 return -1; |
433 |
421 } |
434 return ret; |
422 |
|
423 return 0; |
|
424 } |
435 } |
425 |
436 |
426 /*****************************************************************************/ |
437 /*****************************************************************************/ |
427 |
438 |
428 /** Transition function from IDLE to ORPHANED phase. |
439 /** Transition function from IDLE to ORPHANED phase. |
462 master->allow_config = 0; // temporarily disable slave configuration |
474 master->allow_config = 0; // temporarily disable slave configuration |
463 if (master->config_busy) { |
475 if (master->config_busy) { |
464 up(&master->config_sem); |
476 up(&master->config_sem); |
465 |
477 |
466 // wait for slave configuration to complete |
478 // wait for slave configuration to complete |
467 if (wait_event_interruptible(master->config_queue, |
479 ret = wait_event_interruptible(master->config_queue, |
468 !master->config_busy)) { |
480 !master->config_busy); |
|
481 if (ret) { |
469 EC_INFO("Finishing slave configuration interrupted by signal.\n"); |
482 EC_INFO("Finishing slave configuration interrupted by signal.\n"); |
470 goto out_allow; |
483 goto out_allow; |
471 } |
484 } |
472 |
485 |
473 if (master->debug_level) |
486 if (master->debug_level) |
482 up(&master->scan_sem); |
495 up(&master->scan_sem); |
483 } else { |
496 } else { |
484 up(&master->scan_sem); |
497 up(&master->scan_sem); |
485 |
498 |
486 // wait for slave scan to complete |
499 // wait for slave scan to complete |
487 if (wait_event_interruptible(master->scan_queue, !master->scan_busy)) { |
500 ret = wait_event_interruptible(master->scan_queue, !master->scan_busy); |
|
501 if (ret) { |
488 EC_INFO("Waiting for slave scan interrupted by signal.\n"); |
502 EC_INFO("Waiting for slave scan interrupted by signal.\n"); |
489 goto out_allow; |
503 goto out_allow; |
490 } |
504 } |
491 |
505 |
492 if (master->debug_level) |
506 if (master->debug_level) |
509 |
523 |
510 master->phase = EC_OPERATION; |
524 master->phase = EC_OPERATION; |
511 master->ext_request_cb = NULL; |
525 master->ext_request_cb = NULL; |
512 master->ext_release_cb = NULL; |
526 master->ext_release_cb = NULL; |
513 master->ext_cb_data = NULL; |
527 master->ext_cb_data = NULL; |
514 return 0; |
528 return ret; |
515 |
529 |
516 out_allow: |
530 out_allow: |
517 master->allow_scan = 1; |
531 master->allow_scan = 1; |
518 master->allow_config = 1; |
532 master->allow_config = 1; |
519 return -1; |
533 return ret; |
520 } |
534 } |
521 |
535 |
522 /*****************************************************************************/ |
536 /*****************************************************************************/ |
523 |
537 |
524 /** Transition function from OPERATION to IDLE phase. |
538 /** Transition function from OPERATION to IDLE phase. |
1273 |
1287 |
1274 /*****************************************************************************/ |
1288 /*****************************************************************************/ |
1275 |
1289 |
1276 /** Set the debug level. |
1290 /** Set the debug level. |
1277 * |
1291 * |
1278 * \retval 0 Success. |
1292 * \retval 0 Success. |
1279 * \retval -1 Invalid debug level. |
1293 * \retval -EINVAL Invalid debug level. |
1280 */ |
1294 */ |
1281 int ec_master_debug_level( |
1295 int ec_master_debug_level( |
1282 ec_master_t *master, /**< EtherCAT master. */ |
1296 ec_master_t *master, /**< EtherCAT master. */ |
1283 int level /**< Debug level. May be 0, 1 or 2. */ |
1297 int level /**< Debug level. May be 0, 1 or 2. */ |
1284 ) |
1298 ) |
1285 { |
1299 { |
1286 if (level < 0 || level > 2) { |
1300 if (level < 0 || level > 2) { |
1287 EC_ERR("Invalid debug level %i!\n", level); |
1301 EC_ERR("Invalid debug level %i!\n", level); |
1288 return -1; |
1302 return -EINVAL; |
1289 } |
1303 } |
1290 |
1304 |
1291 if (level != master->debug_level) { |
1305 if (level != master->debug_level) { |
1292 master->debug_level = level; |
1306 master->debug_level = level; |
1293 EC_INFO("Master debug level set to %i.\n", master->debug_level); |
1307 EC_INFO("Master debug level set to %i.\n", master->debug_level); |
1349 |
1363 |
1350 int ecrt_master_activate(ec_master_t *master) |
1364 int ecrt_master_activate(ec_master_t *master) |
1351 { |
1365 { |
1352 uint32_t domain_offset; |
1366 uint32_t domain_offset; |
1353 ec_domain_t *domain; |
1367 ec_domain_t *domain; |
|
1368 int ret; |
1354 |
1369 |
1355 if (master->debug_level) |
1370 if (master->debug_level) |
1356 EC_DBG("ecrt_master_activate(master = 0x%x)\n", (u32) master); |
1371 EC_DBG("ecrt_master_activate(master = 0x%x)\n", (u32) master); |
1357 |
1372 |
1358 down(&master->master_sem); |
1373 down(&master->master_sem); |
1359 |
1374 |
1360 // finish all domains |
1375 // finish all domains |
1361 domain_offset = 0; |
1376 domain_offset = 0; |
1362 list_for_each_entry(domain, &master->domains, list) { |
1377 list_for_each_entry(domain, &master->domains, list) { |
1363 if (ec_domain_finish(domain, domain_offset)) { |
1378 ret = ec_domain_finish(domain, domain_offset); |
|
1379 if (ret < 0) { |
1364 up(&master->master_sem); |
1380 up(&master->master_sem); |
1365 EC_ERR("Failed to finish domain 0x%08X!\n", (u32) domain); |
1381 EC_ERR("Failed to finish domain 0x%08X!\n", (u32) domain); |
1366 return -1; |
1382 return ret; |
1367 } |
1383 } |
1368 domain_offset += domain->data_size; |
1384 domain_offset += domain->data_size; |
1369 } |
1385 } |
1370 |
1386 |
1371 up(&master->master_sem); |
1387 up(&master->master_sem); |
1383 master->injection_seq_rt = 0; |
1399 master->injection_seq_rt = 0; |
1384 master->request_cb = master->ext_request_cb; |
1400 master->request_cb = master->ext_request_cb; |
1385 master->release_cb = master->ext_release_cb; |
1401 master->release_cb = master->ext_release_cb; |
1386 master->cb_data = master->ext_cb_data; |
1402 master->cb_data = master->ext_cb_data; |
1387 |
1403 |
1388 if (ec_master_thread_start(master, ec_master_operation_thread, |
1404 ret = ec_master_thread_start(master, ec_master_operation_thread, |
1389 "EtherCAT-OP")) { |
1405 "EtherCAT-OP"); |
|
1406 if (ret < 0) { |
1390 EC_ERR("Failed to start master thread!\n"); |
1407 EC_ERR("Failed to start master thread!\n"); |
1391 return -1; |
1408 return ret; |
1392 } |
1409 } |
1393 #ifdef EC_EOE |
1410 #ifdef EC_EOE |
1394 ec_master_eoe_start(master); |
1411 ec_master_eoe_start(master); |
1395 #endif |
1412 #endif |
1396 |
1413 |