12 #include <linux/kernel.h> |
12 #include <linux/kernel.h> |
13 #include <linux/string.h> |
13 #include <linux/string.h> |
14 #include <linux/slab.h> |
14 #include <linux/slab.h> |
15 #include <linux/delay.h> |
15 #include <linux/delay.h> |
16 |
16 |
|
17 #include "../include/EtherCAT_rt.h" |
17 #include "globals.h" |
18 #include "globals.h" |
18 #include "master.h" |
19 #include "master.h" |
|
20 #include "slave.h" |
|
21 #include "types.h" |
19 #include "device.h" |
22 #include "device.h" |
20 #include "command.h" |
23 #include "command.h" |
21 |
24 |
22 /*****************************************************************************/ |
25 /*****************************************************************************/ |
23 |
26 |
24 // Prototypen |
27 // Prototypen |
25 |
28 |
26 int ec_simple_send(ec_master_t *, ec_command_t *); |
29 int ec_simple_send(ec_master_t *, ec_command_t *); |
27 int ec_simple_receive(ec_master_t *, ec_command_t *); |
30 int ec_simple_receive(ec_master_t *, ec_command_t *); |
28 void ec_output_debug_data(const ec_master_t *); |
31 void ec_output_debug_data(const ec_master_t *); |
29 int ec_read_slave_information(ec_master_t *, unsigned short, unsigned short, |
32 int ec_sii_read(ec_master_t *, unsigned short, unsigned short, unsigned int *); |
30 unsigned int *); |
|
31 void ec_output_lost_frames(ec_master_t *); |
33 void ec_output_lost_frames(ec_master_t *); |
32 |
34 |
33 /*****************************************************************************/ |
35 /*****************************************************************************/ |
34 |
36 |
35 /** |
37 /** |
378 } |
380 } |
379 |
381 |
380 // For every slave in the list |
382 // For every slave in the list |
381 for (i = 0; i < master->bus_slaves_count; i++) |
383 for (i = 0; i < master->bus_slaves_count; i++) |
382 { |
384 { |
383 cur = master->bus_slaves + i; |
385 slave = master->bus_slaves + i; |
384 |
386 |
385 ec_slave_init(cur); |
387 ec_slave_init(slave); |
|
388 |
|
389 // Set ring position |
|
390 slave->ring_position = -i; |
|
391 slave->station_address = i + 1; |
|
392 |
|
393 // Write station address |
|
394 |
|
395 data[0] = slave->station_address & 0x00FF; |
|
396 data[1] = (slave->station_address & 0xFF00) >> 8; |
|
397 |
|
398 ec_command_position_write(&cmd, slave->ring_position, 0x0010, 2, data); |
|
399 |
|
400 if (unlikely(ec_simple_send_receive(master, &cmd) < 0)) |
|
401 return -1; |
|
402 |
|
403 if (unlikely(cmd.working_counter != 1)) { |
|
404 printk(KERN_ERR "EtherCAT: Slave %i did not repond while writing" |
|
405 " station address!\n", i); |
|
406 return -1; |
|
407 } |
386 |
408 |
387 // Read base data |
409 // Read base data |
388 |
410 |
389 ec_command_read(&cmd, cur->station_address, 0x0000, 4); |
411 ec_command_read(&cmd, slave->station_address, 0x0000, 4); |
390 |
412 |
391 if (unlikely(ec_simple_send_receive(master, &cmd) < 0)) |
413 if (unlikely(ec_simple_send_receive(master, &cmd) < 0)) |
392 return -1; |
414 return -1; |
393 |
415 |
394 if (unlikely(cmd.working_counter != 1)) { |
416 if (unlikely(cmd.working_counter != 1)) { |
395 printk(KERN_ERR "EtherCAT: Slave %i did not respond" |
417 printk(KERN_ERR "EtherCAT: Slave %i did not respond while reading base" |
396 " while reading base data!\n", i); |
418 " data!\n", i); |
397 return -1; |
419 return -1; |
398 } |
420 } |
399 |
421 |
400 // Get base data |
422 // Get base data |
401 |
423 |
402 cur->type = cmd.data[0]; |
424 slave->base_type = cmd.data[0]; |
403 cur->revision = cmd.data[1]; |
425 slave->base_revision = cmd.data[1]; |
404 cur->build = cmd.data[2] | (cmd.data[3] << 8); |
426 slave->base_build = cmd.data[2] | (cmd.data[3] << 8); |
405 |
427 |
406 // Read identification from "Slave Information Interface" (SII) |
428 // Read identification from "Slave Information Interface" (SII) |
407 |
429 |
408 if (unlikely(ec_read_slave_information(master, cur->station_address, |
430 if (unlikely(ec_sii_read(master, slave->station_address, 0x0008, |
409 0x0008, &cur->vendor_id) != 0)) { |
431 &slave->sii_vendor_id) != 0)) { |
410 printk(KERN_ERR "EtherCAT: Could not read SII vendor id!\n"); |
432 printk(KERN_ERR "EtherCAT: Could not read SII vendor id!\n"); |
411 return -1; |
433 return -1; |
412 } |
434 } |
413 |
435 |
414 if (unlikely(ec_read_slave_information(master, cur->station_address, |
436 if (unlikely(ec_sii_read(master, slave->station_address, 0x000A, |
415 0x000A, &cur->product_code) != 0)) { |
437 &slave->sii_product_code) != 0)) { |
416 printk(KERN_ERR "EtherCAT: Could not read SII product code!\n"); |
438 printk(KERN_ERR "EtherCAT: Could not read SII product code!\n"); |
417 return -1; |
439 return -1; |
418 } |
440 } |
419 |
441 |
420 if (unlikely(ec_read_slave_information(master, cur->station_address, |
442 if (unlikely(ec_sii_read(master, slave->station_address, 0x000C, |
421 0x000C, |
443 &slave->sii_revision_number) != 0)) { |
422 &cur->revision_number) != 0)) { |
|
423 printk(KERN_ERR "EtherCAT: Could not read SII revision number!\n"); |
444 printk(KERN_ERR "EtherCAT: Could not read SII revision number!\n"); |
424 return -1; |
445 return -1; |
425 } |
446 } |
426 |
447 |
427 if (unlikely(ec_read_slave_information(master, cur->station_address, |
448 if (unlikely(ec_sii_read(master, slave->station_address, 0x000E, |
428 0x000E, |
449 &slave->sii_serial_number) != 0)) { |
429 &cur->serial_number) != 0)) { |
|
430 printk(KERN_ERR "EtherCAT: Could not read SII serial number!\n"); |
450 printk(KERN_ERR "EtherCAT: Could not read SII serial number!\n"); |
431 return -1; |
451 return -1; |
432 } |
452 } |
433 |
453 |
434 // Search for identification in "database" |
454 // Search for identification in "database" |
435 |
455 |
436 for (j = 0; j < slave_ident_count; j++) |
456 for (j = 0; j < slave_ident_count; j++) |
437 { |
457 { |
438 if (unlikely(slave_idents[j].vendor_id == cur->vendor_id |
458 if (unlikely(slave_idents[j].vendor_id == slave->sii_vendor_id |
439 && slave_idents[j].product_code == cur->product_code)) |
459 && slave_idents[j].product_code == slave->sii_product_code)) |
440 { |
460 { |
441 cur->desc = slave_idents[j].desc; |
461 slave->type = slave_idents[j].type; |
442 break; |
462 break; |
443 } |
463 } |
444 } |
464 } |
445 |
465 |
446 if (unlikely(!cur->desc)) { |
466 if (unlikely(!slave->type)) { |
447 printk(KERN_ERR "EtherCAT: Unknown slave device (vendor %X, code %X) at " |
467 printk(KERN_ERR "EtherCAT: Unknown slave device (vendor %X, code %X) at " |
448 " position %i.\n", cur->vendor_id, cur->product_code, i); |
468 " position %i.\n", slave->sii_vendor_id, slave->sii_product_code, |
449 return -1; |
469 i); |
450 } |
|
451 |
|
452 // Set ring position |
|
453 cur->ring_position = -i; |
|
454 cur->station_address = i + 1; |
|
455 |
|
456 // Write station address |
|
457 |
|
458 data[0] = cur->station_address & 0x00FF; |
|
459 data[1] = (cur->station_address & 0xFF00) >> 8; |
|
460 |
|
461 ec_command_position_write(&cmd, cur->ring_position, 0x0010, 2, data); |
|
462 |
|
463 if (unlikely(ec_simple_send_receive(master, &cmd) < 0)) |
|
464 return -1; |
|
465 |
|
466 if (unlikely(cmd.working_counter != 1)) { |
|
467 printk(KERN_ERR "EtherCAT: Slave %i did not repond" |
|
468 " while writing station address!\n", i); |
|
469 return -1; |
470 return -1; |
470 } |
471 } |
471 } |
472 } |
472 |
473 |
473 return 0; |
474 return 0; |
709 @param master Der EtherCAT-Master |
704 @param master Der EtherCAT-Master |
710 |
705 |
711 @return 0 bei Erfolg, sonst < 0 |
706 @return 0 bei Erfolg, sonst < 0 |
712 */ |
707 */ |
713 |
708 |
714 void *EtherCAT_rt_register_slave(ec_master_t *master, unsigned int bus_index, |
709 ec_slave_t *EtherCAT_rt_register_slave(ec_master_t *master, |
715 const char *vendor_name, |
710 unsigned int bus_index, |
716 const char *product_name, unsigned int domain) |
711 const char *vendor_name, |
|
712 const char *product_name, |
|
713 unsigned int domain) |
717 { |
714 { |
718 ec_slave_t *slave; |
715 ec_slave_t *slave; |
|
716 const ec_slave_type_t *type; |
719 ec_domain_t *dom; |
717 ec_domain_t *dom; |
720 unsigned int j; |
718 unsigned int j; |
721 |
719 |
722 if (bus_index >= master->bus_slaves_count) { |
720 if (bus_index >= master->bus_slaves_count) { |
723 printk(KERN_ERR "EtherCAT: Illegal bus index! (%i / %i)\n", bus_index, |
721 printk(KERN_ERR "EtherCAT: Illegal bus index! (%i / %i)\n", bus_index, |
725 return NULL; |
723 return NULL; |
726 } |
724 } |
727 |
725 |
728 slave = master->bus_slaves + bus_index; |
726 slave = master->bus_slaves + bus_index; |
729 |
727 |
730 if (slave->process_data) { |
728 if (slave->registered) { |
731 printk(KERN_ERR "EtherCAT: Slave %i is already registered!\n", bus_index); |
729 printk(KERN_ERR "EtherCAT: Slave %i is already registered!\n", bus_index); |
732 return NULL; |
730 return NULL; |
733 } |
731 } |
734 |
732 |
735 if (strcmp(vendor_name, slave->desc->vendor_name) || |
733 type = slave->type; |
736 strcmp(product_name, slave->desc->product_name)) { |
734 |
|
735 if (strcmp(vendor_name, type->vendor_name) || |
|
736 strcmp(product_name, type->product_name)) { |
737 printk(KERN_ERR "Invalid Slave Type! Requested: \"%s %s\", present: \"%s" |
737 printk(KERN_ERR "Invalid Slave Type! Requested: \"%s %s\", present: \"%s" |
738 "%s\".\n", vendor_name, product_name, slave->desc->vendor_name, |
738 " %s\".\n", vendor_name, product_name, type->vendor_name, |
739 slave->desc->product_name); |
739 type->product_name); |
740 return NULL; |
740 return NULL; |
741 } |
741 } |
742 |
742 |
743 // Check, if process data domain already exists... |
743 // Check, if process data domain already exists... |
744 dom = NULL; |
744 dom = NULL; |
760 dom->number = domain; |
760 dom->number = domain; |
761 dom->logical_offset = master->domain_count * EC_FRAME_SIZE; |
761 dom->logical_offset = master->domain_count * EC_FRAME_SIZE; |
762 master->domain_count++; |
762 master->domain_count++; |
763 } |
763 } |
764 |
764 |
765 if (dom->data_size + slave->desc->process_data_size > EC_FRAME_SIZE - 14) { |
765 if (dom->data_size + type->process_data_size > EC_FRAME_SIZE - 14) { |
766 printk(KERN_ERR "EtherCAT: Oversized domain %i: %i / %i Bytes!\n", |
766 printk(KERN_ERR "EtherCAT: Oversized domain %i: %i / %i Bytes!\n", |
767 dom->number, dom->data_size + slave->desc->process_data_size, |
767 dom->number, dom->data_size + type->process_data_size, |
768 EC_FRAME_SIZE - 14); |
768 EC_FRAME_SIZE - 14); |
769 return NULL; |
769 return NULL; |
770 } |
770 } |
771 |
771 |
772 slave->process_data = dom->data + dom->data_size; |
772 slave->process_data = dom->data + dom->data_size; |
773 dom->data_size += slave->desc->process_data_size; |
773 dom->data_size += type->process_data_size; |
774 |
774 slave->registered = 1; |
775 return slave->process_data; |
775 |
|
776 return slave; |
776 } |
777 } |
777 |
778 |
778 /*****************************************************************************/ |
779 /*****************************************************************************/ |
779 |
780 |
780 /** |
781 /** |
838 " respond!\n", slave->station_address); |
839 " respond!\n", slave->station_address); |
839 return -1; |
840 return -1; |
840 } |
841 } |
841 } |
842 } |
842 |
843 |
|
844 // Check if slave was registered... |
|
845 |
|
846 if (!slave->registered) { |
|
847 printk(KERN_INFO "EtherCAT: Slave %i (%s %s) was not registered.\n", |
|
848 i, type->vendor_name, type->product_name); |
|
849 continue; |
|
850 } |
|
851 |
843 // Init Mailbox communication |
852 // Init Mailbox communication |
844 |
853 |
845 if (desc->type == EC_MAILBOX_SLAVE) |
854 if (type->features == EC_MAILBOX_SLAVE) |
846 { |
855 { |
847 if (desc->sm0) |
856 if (type->sm0) |
848 { |
857 { |
849 ec_command_write(&cmd, slave->station_address, 0x0800, 8, |
858 ec_command_write(&cmd, slave->station_address, 0x0800, 8, type->sm0); |
850 desc->sm0); |
|
851 |
859 |
852 if (unlikely(ec_simple_send_receive(master, &cmd) < 0)) |
860 if (unlikely(ec_simple_send_receive(master, &cmd) < 0)) |
853 return -1; |
861 return -1; |
854 |
862 |
855 if (unlikely(cmd.working_counter != 1)) { |
863 if (unlikely(cmd.working_counter != 1)) { |
881 if (unlikely(ec_state_change(master, slave, EC_SLAVE_STATE_PREOP) != 0)) |
888 if (unlikely(ec_state_change(master, slave, EC_SLAVE_STATE_PREOP) != 0)) |
882 return -1; |
889 return -1; |
883 |
890 |
884 // Set FMMU's |
891 // Set FMMU's |
885 |
892 |
886 if (desc->fmmu0) |
893 if (type->fmmu0) |
887 { |
894 { |
888 if (unlikely(!slave->process_data)) { |
895 if (unlikely(!slave->process_data)) { |
889 printk(KERN_ERR "EtherCAT: Warning - Slave %04X is not assigned to any" |
896 printk(KERN_ERR "EtherCAT: Warning - Slave %04X is not assigned to any" |
890 " process data object!\n", slave->station_address); |
897 " process data object!\n", slave->station_address); |
891 return -1; |
898 return -1; |
892 } |
899 } |
893 |
900 |
894 memcpy(fmmu, desc->fmmu0, 16); |
901 memcpy(fmmu, type->fmmu0, 16); |
895 |
902 |
896 fmmu[0] = slave->logical_address & 0x000000FF; |
903 fmmu[0] = slave->logical_address & 0x000000FF; |
897 fmmu[1] = (slave->logical_address & 0x0000FF00) >> 8; |
904 fmmu[1] = (slave->logical_address & 0x0000FF00) >> 8; |
898 fmmu[2] = (slave->logical_address & 0x00FF0000) >> 16; |
905 fmmu[2] = (slave->logical_address & 0x00FF0000) >> 16; |
899 fmmu[3] = (slave->logical_address & 0xFF000000) >> 24; |
906 fmmu[3] = (slave->logical_address & 0xFF000000) >> 24; |