master/domain.c
changeset 809 ec4ef8911824
parent 807 f8bca95ab75d
child 817 118dea2fa505
equal deleted inserted replaced
808:1feddbd65608 809:ec4ef8911824
    47 #include "domain.h"
    47 #include "domain.h"
    48 
    48 
    49 /*****************************************************************************/
    49 /*****************************************************************************/
    50 
    50 
    51 void ec_domain_clear(struct kobject *);
    51 void ec_domain_clear(struct kobject *);
       
    52 void ec_domain_clear_data(ec_domain_t *);
    52 ssize_t ec_show_domain_attribute(struct kobject *, struct attribute *, char *);
    53 ssize_t ec_show_domain_attribute(struct kobject *, struct attribute *, char *);
    53 
    54 
    54 /*****************************************************************************/
    55 /*****************************************************************************/
    55 
    56 
    56 /** \cond */
    57 /** \cond */
    88         )
    89         )
    89 {
    90 {
    90     domain->master = master;
    91     domain->master = master;
    91     domain->index = index;
    92     domain->index = index;
    92     domain->data_size = 0;
    93     domain->data_size = 0;
    93     domain->base_address = 0;
    94     domain->data = NULL;
       
    95     domain->data_origin = EC_ORIG_INTERNAL;
       
    96     domain->logical_base_address = 0L;
    94     domain->working_counter = 0xFFFFFFFF;
    97     domain->working_counter = 0xFFFFFFFF;
    95     domain->notify_jiffies = 0;
    98     domain->notify_jiffies = 0;
    96     domain->working_counter_changes = 0;
    99     domain->working_counter_changes = 0;
    97 
   100 
    98     INIT_LIST_HEAD(&domain->datagrams);
   101     INIT_LIST_HEAD(&domain->datagrams);
   156     list_for_each_entry_safe(datagram, next, &domain->datagrams, list) {
   159     list_for_each_entry_safe(datagram, next, &domain->datagrams, list) {
   157         ec_datagram_clear(datagram);
   160         ec_datagram_clear(datagram);
   158         kfree(datagram);
   161         kfree(datagram);
   159     }
   162     }
   160 
   163 
       
   164     ec_domain_clear_data(domain);
       
   165 
   161     kfree(domain);
   166     kfree(domain);
       
   167 }
       
   168 
       
   169 /*****************************************************************************/
       
   170 
       
   171 /** Frees internally allocated memory.
       
   172  */
       
   173 void ec_domain_clear_data(
       
   174         ec_domain_t *domain /**< EtherCAT domain. */
       
   175         )
       
   176 {
       
   177     if (domain->data_origin == EC_ORIG_INTERNAL && domain->data)
       
   178         kfree(domain->data);
       
   179     domain->data = NULL;
       
   180     domain->data_origin = EC_ORIG_INTERNAL;
   162 }
   181 }
   163 
   182 
   164 /*****************************************************************************/
   183 /*****************************************************************************/
   165 
   184 
   166 /** Allocates a domain datagram and appends it to the list.
   185 /** Allocates a domain datagram and appends it to the list.
   167  *
   186  *
   168  * \return 0 in case of success, else < 0
   187  * \return 0 in case of success, else < 0
   169  */
   188  */
   170 int ec_domain_add_datagram(
   189 int ec_domain_add_datagram(
   171         ec_domain_t *domain, /**< EtherCAT domain. */
   190         ec_domain_t *domain, /**< EtherCAT domain. */
   172         uint32_t offset, /**< Logical offset. */
   191         uint32_t logical_offset, /**< Logical offset. */
   173         size_t data_size /**< Size of the data. */
   192         size_t data_size, /**< Size of the data. */
       
   193         uint8_t *data /**< Process data. */
   174         )
   194         )
   175 {
   195 {
   176     ec_datagram_t *datagram;
   196     ec_datagram_t *datagram;
   177 
   197 
   178     if (!(datagram = kmalloc(sizeof(ec_datagram_t), GFP_KERNEL))) {
   198     if (!(datagram = kmalloc(sizeof(ec_datagram_t), GFP_KERNEL))) {
   180         return -1;
   200         return -1;
   181     }
   201     }
   182 
   202 
   183     ec_datagram_init(datagram);
   203     ec_datagram_init(datagram);
   184     snprintf(datagram->name, EC_DATAGRAM_NAME_SIZE,
   204     snprintf(datagram->name, EC_DATAGRAM_NAME_SIZE,
   185             "domain%u-%u", domain->index, offset);
   205             "domain%u-%u", domain->index, logical_offset);
   186 
   206 
   187     if (ec_datagram_lrw(datagram, offset, data_size)) {
   207     if (ec_datagram_lrw(datagram, logical_offset, data_size, data)) {
   188         kfree(datagram);
   208         kfree(datagram);
   189         return -1;
   209         return -1;
   190     }
   210     }
   191 
   211 
   192     list_add_tail(&datagram->list, &domain->datagrams);
   212     list_add_tail(&datagram->list, &domain->datagrams);
   197 
   217 
   198 /** Finishes a domain.
   218 /** Finishes a domain.
   199  *
   219  *
   200  * This allocates the necessary datagrams and writes the correct logical
   220  * This allocates the necessary datagrams and writes the correct logical
   201  * addresses to every configured FMMU.
   221  * addresses to every configured FMMU.
       
   222  *
       
   223  * \todo Check for FMMUs that do not fit into any datagram.
   202  *
   224  *
   203  * \retval 0 in case of success
   225  * \retval 0 in case of success
   204  * \retval <0 on failure.
   226  * \retval <0 on failure.
   205  */
   227  */
   206 int ec_domain_finish(
   228 int ec_domain_finish(
   207         ec_domain_t *domain, /**< EtherCAT domain. */
   229         ec_domain_t *domain, /**< EtherCAT domain. */
   208         uint32_t base_address /**< Logical base address. */
   230         uint32_t base_address /**< Logical base address. */
   209         )
   231         )
   210 {
   232 {
   211     uint32_t datagram_offset;
   233     uint32_t datagram_offset;
   212     size_t datagram_data_size;
   234     size_t datagram_size;
   213     unsigned int datagram_count, i;
   235     unsigned int datagram_count, i;
   214     ec_slave_config_t *sc;
   236     ec_slave_config_t *sc;
   215     ec_fmmu_config_t *fmmu;
   237     ec_fmmu_config_t *fmmu;
   216 
   238 
   217     domain->base_address = base_address;
   239     domain->logical_base_address = base_address;
   218 
   240 
   219     // Cycle through all domain FMMUS, add the logical base address and assign
   241     if (domain->data_size && domain->data_origin == EC_ORIG_INTERNAL) {
   220     // as many PDO entries as possible to the datagrams.
   242         if (!(domain->data =
   221     datagram_offset = base_address;
   243                     (uint8_t *) kmalloc(domain->data_size, GFP_KERNEL))) {
   222     datagram_data_size = 0;
   244             EC_ERR("Failed to allocate %u bytes internal memory for"
       
   245                     " domain %u!\n", domain->data_size, domain->index);
       
   246             return -1;
       
   247         }
       
   248     }
       
   249 
       
   250     // Cycle through all domain FMMUS, correct the logical base addresses and
       
   251     // set up the datagrams to carry the process data.
       
   252     datagram_offset = 0;
       
   253     datagram_size = 0;
   223     datagram_count = 0;
   254     datagram_count = 0;
   224     list_for_each_entry(sc, &domain->master->configs, list) {
   255     list_for_each_entry(sc, &domain->master->configs, list) {
   225         for (i = 0; i < sc->used_fmmus; i++) {
   256         for (i = 0; i < sc->used_fmmus; i++) {
   226             fmmu = &sc->fmmu_configs[i];
   257             fmmu = &sc->fmmu_configs[i];
   227             if (fmmu->domain != domain)
   258             if (fmmu->domain != domain)
   228                 continue;
   259                 continue;
   229 
   260 
       
   261             // Correct logical FMMU address
   230             fmmu->logical_start_address += base_address;
   262             fmmu->logical_start_address += base_address;
   231             if (datagram_data_size + fmmu->data_size > EC_MAX_DATA_SIZE) {
   263 
   232                 if (ec_domain_add_datagram(domain, datagram_offset,
   264             // If the current FMMU's data do not fit in the current datagram,
   233                             datagram_data_size)) return -1;
   265             // allocate a new one.
   234                 datagram_offset += datagram_data_size;
   266             if (datagram_size + fmmu->data_size > EC_MAX_DATA_SIZE) {
   235                 datagram_data_size = 0;
   267                 if (ec_domain_add_datagram(domain,
       
   268                             domain->logical_base_address + datagram_offset,
       
   269                             datagram_size, domain->data + datagram_offset))
       
   270                     return -1;
       
   271                 datagram_offset += datagram_size;
       
   272                 datagram_size = 0;
   236                 datagram_count++;
   273                 datagram_count++;
   237             }
   274             }
   238             datagram_data_size += fmmu->data_size;
   275 
   239         }
   276             datagram_size += fmmu->data_size;
   240     }
   277         }
   241 
   278     }
   242     // allocate last datagram
   279 
   243     if (datagram_data_size) {
   280     // allocate last datagram, if data are left
   244         if (ec_domain_add_datagram(domain, datagram_offset,
   281     if (datagram_size) {
   245                                    datagram_data_size))
   282         if (ec_domain_add_datagram(domain,
       
   283                     domain->logical_base_address + datagram_offset,
       
   284                     datagram_size, domain->data + datagram_offset))
   246             return -1;
   285             return -1;
   247         datagram_count++;
   286         datagram_count++;
   248     }
   287     }
   249 
   288 
   250     EC_INFO("Domain %u with logical offset %u contains %u bytes in %u"
   289     EC_INFO("Domain %u with logical offset %u contains %u bytes in %u"
   251             " datagram%s.\n", domain->index, domain->base_address,
   290             " datagram%s.\n", domain->index, domain->logical_base_address,
   252             domain->data_size, datagram_count, datagram_count == 1 ? "" : "s");
   291             domain->data_size, datagram_count, datagram_count == 1 ? "" : "s");
   253     return 0;
   292     return 0;
   254 }
   293 }
   255 
   294 
   256 /*****************************************************************************/
   295 /*****************************************************************************/
   300     return 0;
   339     return 0;
   301 }
   340 }
   302 
   341 
   303 /*****************************************************************************/
   342 /*****************************************************************************/
   304 
   343 
       
   344 size_t ecrt_domain_size(ec_domain_t *domain)
       
   345 {
       
   346     return domain->data_size;
       
   347 }
       
   348 
       
   349 /*****************************************************************************/
       
   350 
       
   351 void ecrt_domain_external_memory(ec_domain_t *domain, uint8_t *mem)
       
   352 {
       
   353     ec_domain_clear_data(domain);
       
   354 
       
   355     domain->data = mem;
       
   356     domain->data_origin = EC_ORIG_EXTERNAL;
       
   357 }
       
   358 
       
   359 /*****************************************************************************/
       
   360 
       
   361 uint8_t *ecrt_domain_data(ec_domain_t *domain)
       
   362 {
       
   363     return domain->data;
       
   364 }
       
   365 
       
   366 /*****************************************************************************/
       
   367 
   305 void ecrt_domain_process(ec_domain_t *domain)
   368 void ecrt_domain_process(ec_domain_t *domain)
   306 {
   369 {
   307     unsigned int working_counter_sum;
   370     unsigned int working_counter_sum;
   308     ec_datagram_t *datagram;
   371     ec_datagram_t *datagram;
   309 
   372 
   362 /*****************************************************************************/
   425 /*****************************************************************************/
   363 
   426 
   364 /** \cond */
   427 /** \cond */
   365 
   428 
   366 EXPORT_SYMBOL(ecrt_domain_reg_pdo_entry_list);
   429 EXPORT_SYMBOL(ecrt_domain_reg_pdo_entry_list);
   367 //EXPORT_SYMBOL(ecrt_domain_size);
   430 EXPORT_SYMBOL(ecrt_domain_size);
   368 //EXPORT_SYMBOL(ecrt_domain_memory);
   431 EXPORT_SYMBOL(ecrt_domain_external_memory);
       
   432 EXPORT_SYMBOL(ecrt_domain_data);
   369 EXPORT_SYMBOL(ecrt_domain_process);
   433 EXPORT_SYMBOL(ecrt_domain_process);
   370 EXPORT_SYMBOL(ecrt_domain_queue);
   434 EXPORT_SYMBOL(ecrt_domain_queue);
   371 EXPORT_SYMBOL(ecrt_domain_state);
   435 EXPORT_SYMBOL(ecrt_domain_state);
   372 
   436 
   373 /** \endcond */
   437 /** \endcond */