master/slave.c
changeset 992 50a44cbd30af
parent 980 c07dd38243ba
child 1000 5746fdd1ca2e
equal deleted inserted replaced
991:2548ca639b1f 992:50a44cbd30af
    52 
    52 
    53 extern const ec_code_msg_t al_status_messages[];
    53 extern const ec_code_msg_t al_status_messages[];
    54 
    54 
    55 /*****************************************************************************/
    55 /*****************************************************************************/
    56 
    56 
    57 void ec_slave_clear(struct kobject *);
       
    58 void ec_slave_sdos_clear(struct kobject *);
       
    59 ssize_t ec_show_slave_attribute(struct kobject *, struct attribute *, char *);
       
    60 char *ec_slave_sii_string(ec_slave_t *, unsigned int);
    57 char *ec_slave_sii_string(ec_slave_t *, unsigned int);
    61 
       
    62 /*****************************************************************************/
       
    63 
       
    64 /** \cond */
       
    65 
       
    66 EC_SYSFS_READ_ATTR(info);
       
    67 
       
    68 static struct attribute *def_attrs[] = {
       
    69     &attr_info,
       
    70     NULL,
       
    71 };
       
    72 
       
    73 static struct sysfs_ops sysfs_ops = {
       
    74     .show = ec_show_slave_attribute,
       
    75 };
       
    76 
       
    77 static struct kobj_type ktype_ec_slave = {
       
    78     .release = ec_slave_clear,
       
    79     .sysfs_ops = &sysfs_ops,
       
    80     .default_attrs = def_attrs
       
    81 };
       
    82 
       
    83 static struct kobj_type ktype_ec_slave_sdos = {
       
    84     .release = ec_slave_sdos_clear
       
    85 };
       
    86 
       
    87 /** \endcond */
       
    88 
    58 
    89 /*****************************************************************************/
    59 /*****************************************************************************/
    90 
    60 
    91 /**
    61 /**
    92    Slave constructor.
    62    Slave constructor.
    93    \return 0 in case of success, else < 0
    63    \return 0 in case of success, else < 0
    94 */
    64 */
    95 
    65 
    96 int ec_slave_init(ec_slave_t *slave, /**< EtherCAT slave */
    66 void ec_slave_init(
    97                   ec_master_t *master, /**< EtherCAT master */
    67         ec_slave_t *slave, /**< EtherCAT slave */
    98                   uint16_t ring_position, /**< ring position */
    68         ec_master_t *master, /**< EtherCAT master */
    99                   uint16_t station_address /**< station address to configure */
    69         uint16_t ring_position, /**< ring position */
   100                   )
    70         uint16_t station_address /**< station address to configure */
       
    71         )
   101 {
    72 {
   102     unsigned int i;
    73     unsigned int i;
   103 
    74 
   104     slave->ring_position = ring_position;
    75     slave->ring_position = ring_position;
   105     slave->station_address = station_address;
    76     slave->station_address = station_address;
   157         slave->dl_link[i] = 0;
   128         slave->dl_link[i] = 0;
   158         slave->dl_loop[i] = 0;
   129         slave->dl_loop[i] = 0;
   159         slave->dl_signal[i] = 0;
   130         slave->dl_signal[i] = 0;
   160         slave->sii.physical_layer[i] = 0xFF;
   131         slave->sii.physical_layer[i] = 0xFF;
   161     }
   132     }
   162 
       
   163     // init kobject and add it to the hierarchy
       
   164     memset(&slave->kobj, 0x00, sizeof(struct kobject));
       
   165     kobject_init(&slave->kobj);
       
   166     slave->kobj.ktype = &ktype_ec_slave;
       
   167     slave->kobj.parent = &master->kobj;
       
   168     if (kobject_set_name(&slave->kobj, "slave%03i", slave->ring_position)) {
       
   169         EC_ERR("Failed to set kobject name.\n");
       
   170         goto out_slave_put;
       
   171     }
       
   172     if (kobject_add(&slave->kobj)) {
       
   173         EC_ERR("Failed to add slave's kobject.\n");
       
   174         goto out_slave_put;
       
   175     }
       
   176 
       
   177     // init Sdo kobject and add it to the hierarchy
       
   178     memset(&slave->sdo_kobj, 0x00, sizeof(struct kobject));
       
   179     kobject_init(&slave->sdo_kobj);
       
   180     slave->sdo_kobj.ktype = &ktype_ec_slave_sdos;
       
   181     slave->sdo_kobj.parent = &slave->kobj;
       
   182     if (kobject_set_name(&slave->sdo_kobj, "sdos")) {
       
   183         EC_ERR("Failed to set kobject name.\n");
       
   184         goto out_sdo_put;
       
   185     }
       
   186     if (kobject_add(&slave->sdo_kobj)) {
       
   187         EC_ERR("Failed to add Sdos kobject.\n");
       
   188         goto out_sdo_put;
       
   189     }
       
   190 
       
   191     return 0;
       
   192 
       
   193  out_sdo_put:
       
   194     kobject_put(&slave->sdo_kobj);
       
   195     kobject_del(&slave->kobj);
       
   196  out_slave_put:
       
   197     kobject_put(&slave->kobj);
       
   198     return -1;
       
   199 }
   133 }
   200 
   134 
   201 /*****************************************************************************/
   135 /*****************************************************************************/
   202 
   136 
   203 /**
   137 /**
   204    Slave destructor.
   138    Slave destructor.
   205    Clears and frees a slave object.
   139    Clears and frees a slave object.
   206 */
   140 */
   207 
   141 
   208 void ec_slave_destroy(ec_slave_t *slave /**< EtherCAT slave */)
   142 void ec_slave_clear(ec_slave_t *slave /**< EtherCAT slave */)
   209 {
   143 {
   210     ec_sdo_t *sdo, *next_sdo;
   144     ec_sdo_t *sdo, *next_sdo;
       
   145     unsigned int i;
       
   146     ec_pdo_t *pdo, *next_pdo;
   211 
   147 
   212     if (slave->config)
   148     if (slave->config)
   213         ec_slave_config_detach(slave->config);
   149         ec_slave_config_detach(slave->config);
   214 
   150 
   215     // free all Sdos
   151     // free all Sdos
   216     list_for_each_entry_safe(sdo, next_sdo, &slave->sdo_dictionary, list) {
   152     list_for_each_entry_safe(sdo, next_sdo, &slave->sdo_dictionary, list) {
   217         list_del(&sdo->list);
   153         list_del(&sdo->list);
   218         ec_sdo_destroy(sdo);
   154         ec_sdo_clear(sdo);
   219     }
   155         kfree(sdo);
   220 
   156     }
   221     // free Sdo kobject
       
   222     kobject_del(&slave->sdo_kobj);
       
   223     kobject_put(&slave->sdo_kobj);
       
   224 
       
   225     // destroy self
       
   226     kobject_del(&slave->kobj);
       
   227     kobject_put(&slave->kobj);
       
   228 }
       
   229 
       
   230 /*****************************************************************************/
       
   231 
       
   232 /**
       
   233    Clear and free slave.
       
   234    This method is called by the kobject,
       
   235    once there are no more references to it.
       
   236 */
       
   237 
       
   238 void ec_slave_clear(struct kobject *kobj /**< kobject of the slave */)
       
   239 {
       
   240     ec_slave_t *slave;
       
   241     ec_pdo_t *pdo, *next_pdo;
       
   242     unsigned int i;
       
   243 
       
   244     slave = container_of(kobj, ec_slave_t, kobj);
       
   245 
   157 
   246     // free all strings
   158     // free all strings
   247     if (slave->sii.strings) {
   159     if (slave->sii.strings) {
   248         for (i = 0; i < slave->sii.string_count; i++)
   160         for (i = 0; i < slave->sii.string_count; i++)
   249             kfree(slave->sii.strings[i]);
   161             kfree(slave->sii.strings[i]);
   260         kfree(pdo);
   172         kfree(pdo);
   261     }
   173     }
   262 
   174 
   263     if (slave->sii_words)
   175     if (slave->sii_words)
   264         kfree(slave->sii_words);
   176         kfree(slave->sii_words);
   265 
       
   266     kfree(slave);
       
   267 }
       
   268 
       
   269 /*****************************************************************************/
       
   270 
       
   271 /**
       
   272  * Sdo kobject clear method.
       
   273  */
       
   274 
       
   275 void ec_slave_sdos_clear(struct kobject *kobj /**< kobject for Sdos */)
       
   276 {
       
   277 }
   177 }
   278 
   178 
   279 /*****************************************************************************/
   179 /*****************************************************************************/
   280 
   180 
   281 /** Clear the sync manager array. 
   181 /** Clear the sync manager array. 
   605     return slave->sii.strings[index];
   505     return slave->sii.strings[index];
   606 }
   506 }
   607 
   507 
   608 /*****************************************************************************/
   508 /*****************************************************************************/
   609 
   509 
   610 /** Outputs all information about a certain slave.
       
   611  */
       
   612 ssize_t ec_slave_info(const ec_slave_t *slave, /**< EtherCAT slave */
       
   613         char *buffer /**< Output buffer */
       
   614         )
       
   615 {
       
   616     const ec_sync_t *sync;
       
   617     const ec_pdo_t *pdo;
       
   618     const ec_pdo_entry_t *pdo_entry;
       
   619     int first, i;
       
   620     char *large_buffer, *buf;
       
   621     unsigned int size;
       
   622 
       
   623     if (!(large_buffer = (char *) kmalloc(PAGE_SIZE * 2, GFP_KERNEL))) {
       
   624         return -ENOMEM;
       
   625     }
       
   626 
       
   627     buf = large_buffer;
       
   628 
       
   629     buf += sprintf(buf, "Ring position: %u\n",
       
   630                    slave->ring_position);
       
   631     buf += sprintf(buf, "State: ");
       
   632     buf += ec_state_string(slave->current_state, buf);
       
   633     buf += sprintf(buf, " (");
       
   634     buf += ec_state_string(slave->requested_state, buf);
       
   635     buf += sprintf(buf, ")\n");
       
   636     buf += sprintf(buf, "Flags: %s\n\n", slave->error_flag ? "ERROR" : "ok");
       
   637 
       
   638     buf += sprintf(buf, "Data link status:\n");
       
   639     for (i = 0; i < 4; i++) {
       
   640         buf += sprintf(buf, "  Port %u: Phy %u (",
       
   641                 i, slave->sii.physical_layer[i]);
       
   642         switch (slave->sii.physical_layer[i]) {
       
   643             case 0x00:
       
   644                 buf += sprintf(buf, "EBUS");
       
   645                 break;
       
   646             case 0x01:
       
   647                 buf += sprintf(buf, "100BASE-TX");
       
   648                 break;
       
   649             case 0x02:
       
   650                 buf += sprintf(buf, "100BASE-FX");
       
   651                 break;
       
   652             default:
       
   653                 buf += sprintf(buf, "unknown");
       
   654         }
       
   655         buf += sprintf(buf, "), Link %s, Loop %s, %s\n",
       
   656                        slave->dl_link[i] ? "up" : "down",
       
   657                        slave->dl_loop[i] ? "closed" : "open",
       
   658                        slave->dl_signal[i] ? "Signal detected" : "No signal");
       
   659     }
       
   660     buf += sprintf(buf, "\n");
       
   661 
       
   662     if (slave->sii.alias)
       
   663         buf += sprintf(buf, "Configured station alias:"
       
   664                        " 0x%04X (%u)\n\n", slave->sii.alias, slave->sii.alias);
       
   665 
       
   666     buf += sprintf(buf, "Identity:\n");
       
   667     buf += sprintf(buf, "  Vendor ID: 0x%08X (%u)\n",
       
   668                    slave->sii.vendor_id, slave->sii.vendor_id);
       
   669     buf += sprintf(buf, "  Product code: 0x%08X (%u)\n",
       
   670                    slave->sii.product_code, slave->sii.product_code);
       
   671     buf += sprintf(buf, "  Revision number: 0x%08X (%u)\n",
       
   672                    slave->sii.revision_number, slave->sii.revision_number);
       
   673     buf += sprintf(buf, "  Serial number: 0x%08X (%u)\n\n",
       
   674                    slave->sii.serial_number, slave->sii.serial_number);
       
   675 
       
   676     if (slave->sii.mailbox_protocols) {
       
   677         buf += sprintf(buf, "Mailboxes:\n");
       
   678         buf += sprintf(buf, "  RX: 0x%04X/%u, TX: 0x%04X/%u\n",
       
   679                 slave->sii.rx_mailbox_offset, slave->sii.rx_mailbox_size,
       
   680                 slave->sii.tx_mailbox_offset, slave->sii.tx_mailbox_size);
       
   681         buf += sprintf(buf, "  Supported protocols: ");
       
   682 
       
   683         first = 1;
       
   684         if (slave->sii.mailbox_protocols & EC_MBOX_AOE) {
       
   685             buf += sprintf(buf, "AoE");
       
   686             first = 0;
       
   687         }
       
   688         if (slave->sii.mailbox_protocols & EC_MBOX_EOE) {
       
   689             if (!first) buf += sprintf(buf, ", ");
       
   690             buf += sprintf(buf, "EoE");
       
   691             first = 0;
       
   692         }
       
   693         if (slave->sii.mailbox_protocols & EC_MBOX_COE) {
       
   694             if (!first) buf += sprintf(buf, ", ");
       
   695             buf += sprintf(buf, "CoE");
       
   696             first = 0;
       
   697         }
       
   698         if (slave->sii.mailbox_protocols & EC_MBOX_FOE) {
       
   699             if (!first) buf += sprintf(buf, ", ");
       
   700             buf += sprintf(buf, "FoE");
       
   701             first = 0;
       
   702         }
       
   703         if (slave->sii.mailbox_protocols & EC_MBOX_SOE) {
       
   704             if (!first) buf += sprintf(buf, ", ");
       
   705             buf += sprintf(buf, "SoE");
       
   706             first = 0;
       
   707         }
       
   708         if (slave->sii.mailbox_protocols & EC_MBOX_VOE) {
       
   709             if (!first) buf += sprintf(buf, ", ");
       
   710             buf += sprintf(buf, "VoE");
       
   711         }
       
   712         buf += sprintf(buf, "\n\n");
       
   713     }
       
   714 
       
   715     if (slave->sii.has_general) {
       
   716         buf += sprintf(buf, "General:\n");
       
   717 
       
   718         if (slave->sii.group)
       
   719             buf += sprintf(buf, "  Group: %s\n", slave->sii.group);
       
   720         if (slave->sii.image)
       
   721             buf += sprintf(buf, "  Image: %s\n", slave->sii.image);
       
   722         if (slave->sii.order)
       
   723             buf += sprintf(buf, "  Order number: %s\n",
       
   724                     slave->sii.order);
       
   725         if (slave->sii.name)
       
   726             buf += sprintf(buf, "  Name: %s\n", slave->sii.name);
       
   727         if (slave->sii.mailbox_protocols & EC_MBOX_COE) {
       
   728             buf += sprintf(buf, "  CoE details:\n");
       
   729             buf += sprintf(buf, "    Enable Sdo: %s\n",
       
   730                     slave->sii.coe_details.enable_sdo ? "yes" : "no");
       
   731             buf += sprintf(buf, "    Enable Sdo Info: %s\n",
       
   732                     slave->sii.coe_details.enable_sdo_info ? "yes" : "no");
       
   733             buf += sprintf(buf, "    Enable Pdo Assign: %s\n",
       
   734                     slave->sii.coe_details.enable_pdo_assign ? "yes" : "no");
       
   735             buf += sprintf(buf, "    Enable Pdo Configuration: %s\n",
       
   736                     slave->sii.coe_details.enable_pdo_configuration ?
       
   737                     "yes" : "no");
       
   738             buf += sprintf(buf, "    Enable Upload at startup: %s\n",
       
   739                     slave->sii.coe_details.enable_upload_at_startup ?
       
   740                     "yes" : "no");
       
   741             buf += sprintf(buf, "    Enable Sdo complete access: %s\n",
       
   742                     slave->sii.coe_details.enable_sdo_complete_access
       
   743                     ? "yes" : "no");
       
   744         }
       
   745 
       
   746         buf += sprintf(buf, "  Flags:\n");
       
   747         buf += sprintf(buf, "    Enable SafeOp: %s\n",
       
   748                 slave->sii.general_flags.enable_safeop ? "yes" : "no");
       
   749         buf += sprintf(buf, "    Enable notLRW: %s\n",
       
   750                 slave->sii.general_flags.enable_not_lrw ? "yes" : "no");
       
   751         buf += sprintf(buf, "  Current consumption: %i mA\n\n",
       
   752                 slave->sii.current_on_ebus);
       
   753     }
       
   754 
       
   755     if (slave->sii.sync_count) {
       
   756         buf += sprintf(buf, "Sync managers / assigned Pdos:\n");
       
   757 
       
   758         for (i = 0; i < slave->sii.sync_count; i++) {
       
   759             sync = &slave->sii.syncs[i];
       
   760             buf += sprintf(buf,
       
   761                     "  SM%u: addr 0x%04X, size %u, control 0x%02X, %s\n",
       
   762                     sync->index, sync->physical_start_address,
       
   763                     sync->length, sync->control_register,
       
   764                     sync->enable ? "enable" : "disable");
       
   765 
       
   766             if (list_empty(&sync->pdos.list)) {
       
   767                 buf += sprintf(buf, "    No Pdos assigned.\n");
       
   768             } else if (sync->assign_source != EC_ASSIGN_NONE) {
       
   769                 buf += sprintf(buf, "    Pdo assignment from ");
       
   770                 switch (sync->assign_source) {
       
   771                     case EC_ASSIGN_SII:
       
   772                         buf += sprintf(buf, "SII");
       
   773                         break;
       
   774                     case EC_ASSIGN_COE:
       
   775                         buf += sprintf(buf, "CoE");
       
   776                         break;
       
   777                     case EC_ASSIGN_CUSTOM:
       
   778                         buf += sprintf(buf, "application");
       
   779                         break;
       
   780                     default:
       
   781                         buf += sprintf(buf, "?");
       
   782                         break;
       
   783                 }
       
   784                 buf += sprintf(buf, ".\n");
       
   785             }
       
   786 
       
   787             list_for_each_entry(pdo, &sync->pdos.list, list) {
       
   788                 buf += sprintf(buf, "    %s 0x%04X \"%s\"\n",
       
   789                         pdo->dir == EC_DIR_OUTPUT ? "RxPdo" : "TxPdo",
       
   790                         pdo->index, pdo->name ? pdo->name : "???");
       
   791 
       
   792                 list_for_each_entry(pdo_entry, &pdo->entries, list) {
       
   793                     buf += sprintf(buf,
       
   794                             "      0x%04X:%02X, %u bit, \"%s\"\n",
       
   795                             pdo_entry->index, pdo_entry->subindex,
       
   796                             pdo_entry->bit_length,
       
   797                             pdo_entry->name ? pdo_entry->name : "???");
       
   798                 }
       
   799             }
       
   800         }
       
   801         buf += sprintf(buf, "\n");
       
   802     }
       
   803 
       
   804     // type-cast to avoid warnings on some compilers
       
   805     if (!list_empty((struct list_head *) &slave->sii.pdos)) {
       
   806         buf += sprintf(buf, "Available Pdos from SII:\n");
       
   807 
       
   808         list_for_each_entry(pdo, &slave->sii.pdos, list) {
       
   809             buf += sprintf(buf, "  %s 0x%04X \"%s\"",
       
   810                     pdo->dir == EC_DIR_OUTPUT ? "RxPdo" : "TxPdo",
       
   811                     pdo->index, pdo->name ? pdo->name : "???");
       
   812             if (pdo->sync_index >= 0)
       
   813                 buf += sprintf(buf, ", default assignment: SM%u.\n",
       
   814                         pdo->sync_index);
       
   815             else
       
   816                 buf += sprintf(buf, ", no default assignment.\n");
       
   817 
       
   818             list_for_each_entry(pdo_entry, &pdo->entries, list) {
       
   819                 buf += sprintf(buf, "    0x%04X:%02X, %u bit, \"%s\"\n",
       
   820                         pdo_entry->index, pdo_entry->subindex,
       
   821                         pdo_entry->bit_length,
       
   822                         pdo_entry->name ? pdo_entry->name : "???");
       
   823             }
       
   824         }
       
   825         buf += sprintf(buf, "\n");
       
   826     }
       
   827 
       
   828     size = buf - large_buffer;
       
   829     if (size >= PAGE_SIZE) {
       
   830         const char trunc[] = "\n---TRUNCATED---\n";
       
   831         unsigned int len = strlen(trunc);
       
   832         memcpy(large_buffer + PAGE_SIZE - len, trunc, len);
       
   833     }
       
   834 
       
   835     size = min(size, (unsigned int) PAGE_SIZE);
       
   836     memcpy(buffer, large_buffer, size);
       
   837     kfree(large_buffer);
       
   838     return size;
       
   839 }
       
   840 
       
   841 /*****************************************************************************/
       
   842 
       
   843 /**
   510 /**
   844  * Writes SII contents to a slave.
   511  * Writes SII contents to a slave.
   845  * \return Zero on success, otherwise error code.
   512  * \return Zero on success, otherwise error code.
   846  */
   513  */
   847 
   514 
   896     }
   563     }
   897 }
   564 }
   898 
   565 
   899 /*****************************************************************************/
   566 /*****************************************************************************/
   900 
   567 
   901 /**
       
   902    Formats attribute data for SysFS read access.
       
   903    \return number of bytes to read
       
   904 */
       
   905 
       
   906 ssize_t ec_show_slave_attribute(struct kobject *kobj, /**< slave's kobject */
       
   907                                 struct attribute *attr, /**< attribute */
       
   908                                 char *buffer /**< memory to store data */
       
   909                                 )
       
   910 {
       
   911     ec_slave_t *slave = container_of(kobj, ec_slave_t, kobj);
       
   912 
       
   913     if (attr == &attr_info) {
       
   914         return ec_slave_info(slave, buffer);
       
   915     }
       
   916 
       
   917     return 0;
       
   918 }
       
   919 
       
   920 /*****************************************************************************/
       
   921 
       
   922 /** Get the sync manager for either Rx- or Tx-Pdos.
   568 /** Get the sync manager for either Rx- or Tx-Pdos.
   923  *
   569  *
   924  * \todo This seems not to be correct in every case...
   570  * \todo This seems not to be correct in every case...
   925  * \return pointer to sync manager, or NULL.
   571  * \return pointer to sync manager, or NULL.
   926  */
   572  */