master/domain.c
changeset 792 3778920f61e4
parent 783 0e16f97cf752
child 807 f8bca95ab75d
equal deleted inserted replaced
791:3b81d074735c 792:3778920f61e4
    39 /*****************************************************************************/
    39 /*****************************************************************************/
    40 
    40 
    41 #include <linux/module.h>
    41 #include <linux/module.h>
    42 
    42 
    43 #include "globals.h"
    43 #include "globals.h"
       
    44 #include "master.h"
       
    45 #include "slave_config.h"
       
    46 
    44 #include "domain.h"
    47 #include "domain.h"
    45 #include "master.h"
       
    46 
       
    47 /*****************************************************************************/
       
    48 
       
    49 /**
       
    50    Data registration type.
       
    51 */
       
    52 
       
    53 typedef struct
       
    54 {
       
    55     struct list_head list; /**< list item */
       
    56     ec_slave_t *slave; /**< slave */
       
    57     const ec_sync_t *sync; /**< sync manager */
       
    58     off_t sync_offset; /**< pdo offset */
       
    59     void **data_ptr; /**< pointer to process data pointer(s) */
       
    60 }
       
    61 ec_data_reg_t;
       
    62 
    48 
    63 /*****************************************************************************/
    49 /*****************************************************************************/
    64 
    50 
    65 void ec_domain_clear(struct kobject *);
    51 void ec_domain_clear(struct kobject *);
    66 void ec_domain_clear_data_regs(ec_domain_t *);
       
    67 ssize_t ec_show_domain_attribute(struct kobject *, struct attribute *, char *);
    52 ssize_t ec_show_domain_attribute(struct kobject *, struct attribute *, char *);
    68 
    53 
    69 /*****************************************************************************/
    54 /*****************************************************************************/
    70 
    55 
    71 /** \cond */
    56 /** \cond */
    90 
    75 
    91 /** \endcond */
    76 /** \endcond */
    92 
    77 
    93 /*****************************************************************************/
    78 /*****************************************************************************/
    94 
    79 
    95 /**
    80 /** Domain constructor.
    96    Domain constructor.
    81  *
    97    \return 0 in case of success, else < 0
    82  * \return 0 in case of success, else < 0
    98 */
    83  */
    99 
    84 int ec_domain_init(
   100 int ec_domain_init(ec_domain_t *domain, /**< EtherCAT domain */
    85         ec_domain_t *domain, /**< EtherCAT domain. */
   101                    ec_master_t *master, /**< owning master */
    86         ec_master_t *master, /**< Parent master. */
   102                    unsigned int index /**< domain index */
    87         unsigned int index /**< Index. */
   103                    )
    88         )
   104 {
    89 {
   105     domain->master = master;
    90     domain->master = master;
   106     domain->index = index;
    91     domain->index = index;
   107     domain->data_size = 0;
    92     domain->data_size = 0;
   108     domain->base_address = 0;
    93     domain->base_address = 0;
   109     domain->response_count = 0xFFFFFFFF;
    94     domain->working_counter = 0xFFFFFFFF;
   110     domain->notify_jiffies = 0;
    95     domain->notify_jiffies = 0;
   111     domain->working_counter_changes = 0;
    96     domain->working_counter_changes = 0;
   112 
    97 
   113     INIT_LIST_HEAD(&domain->data_regs);
       
   114     INIT_LIST_HEAD(&domain->datagrams);
    98     INIT_LIST_HEAD(&domain->datagrams);
   115 
    99 
   116     // init kobject and add it to the hierarchy
   100     // init kobject and add it to the hierarchy
   117     memset(&domain->kobj, 0x00, sizeof(struct kobject));
   101     memset(&domain->kobj, 0x00, sizeof(struct kobject));
   118     kobject_init(&domain->kobj);
   102     kobject_init(&domain->kobj);
   162    once there are no more references to it.
   146    once there are no more references to it.
   163 */
   147 */
   164 
   148 
   165 void ec_domain_clear(struct kobject *kobj /**< kobject of the domain */)
   149 void ec_domain_clear(struct kobject *kobj /**< kobject of the domain */)
   166 {
   150 {
       
   151     ec_domain_t *domain;
   167     ec_datagram_t *datagram, *next;
   152     ec_datagram_t *datagram, *next;
   168     ec_domain_t *domain;
       
   169 
   153 
   170     domain = container_of(kobj, ec_domain_t, kobj);
   154     domain = container_of(kobj, ec_domain_t, kobj);
   171 
   155 
   172     list_for_each_entry_safe(datagram, next, &domain->datagrams, list) {
   156     list_for_each_entry_safe(datagram, next, &domain->datagrams, list) {
   173         ec_datagram_clear(datagram);
   157         ec_datagram_clear(datagram);
   174         kfree(datagram);
   158         kfree(datagram);
   175     }
   159     }
   176 
   160 
   177     ec_domain_clear_data_regs(domain);
       
   178 
       
   179     kfree(domain);
   161     kfree(domain);
   180 }
   162 }
   181 
   163 
   182 /*****************************************************************************/
   164 /*****************************************************************************/
   183 
   165 
   184 /**
   166 /** Allocates a domain datagram and appends it to the list.
   185  * Registers a PDO entry.
   167  *
   186  * \return 0 in case of success, else < 0
   168  * \return 0 in case of success, else < 0
   187  */
   169  */
   188 
   170 int ec_domain_add_datagram(
   189 int ec_domain_reg_pdo_entry(
   171         ec_domain_t *domain, /**< EtherCAT domain. */
   190         ec_domain_t *domain, /**< EtherCAT domain */
   172         uint32_t offset, /**< Logical offset. */
   191         ec_sync_t *sync, /**< sync manager */
   173         size_t data_size /**< Size of the data. */
   192         const ec_pdo_entry_t *entry, /**< PDO entry to register */
       
   193         void **data_ptr /**< pointer to the process data pointer */
       
   194         )
   174         )
   195 {
       
   196     ec_data_reg_t *data_reg;
       
   197     const ec_pdo_t *other_pdo;
       
   198     const ec_pdo_entry_t *other_entry;
       
   199     unsigned int bit_offset, byte_offset;
       
   200 
       
   201     // Calculate offset (in sync manager) for process data pointer
       
   202     bit_offset = 0;
       
   203     list_for_each_entry(other_pdo, &sync->pdos, list) {
       
   204         list_for_each_entry(other_entry, &other_pdo->entries, list) {
       
   205             if (other_entry == entry)
       
   206                 goto out;
       
   207             bit_offset += other_entry->bit_length;
       
   208         }
       
   209     }
       
   210 out:
       
   211     byte_offset = bit_offset / 8;
       
   212 
       
   213     // Allocate memory for data registration object
       
   214     if (!(data_reg =
       
   215           (ec_data_reg_t *) kmalloc(sizeof(ec_data_reg_t), GFP_KERNEL))) {
       
   216         EC_ERR("Failed to allocate data registration.\n");
       
   217         return -1;
       
   218     }
       
   219 
       
   220     if (ec_slave_prepare_fmmu(sync->slave, domain, sync)) {
       
   221         EC_ERR("FMMU configuration failed.\n");
       
   222         kfree(data_reg);
       
   223         return -1;
       
   224     }
       
   225 
       
   226     data_reg->slave = sync->slave;
       
   227     data_reg->sync = sync;
       
   228     data_reg->sync_offset = byte_offset;
       
   229     data_reg->data_ptr = data_ptr;
       
   230     list_add_tail(&data_reg->list, &domain->data_regs);
       
   231     return 0;
       
   232 }
       
   233 
       
   234 /*****************************************************************************/
       
   235 
       
   236 /**
       
   237    Clears the list of the data registrations.
       
   238 */
       
   239 
       
   240 void ec_domain_clear_data_regs(ec_domain_t *domain /**< EtherCAT domain */)
       
   241 {
       
   242     ec_data_reg_t *data_reg, *next;
       
   243 
       
   244     list_for_each_entry_safe(data_reg, next, &domain->data_regs, list) {
       
   245         list_del(&data_reg->list);
       
   246         kfree(data_reg);
       
   247     }
       
   248 }
       
   249 
       
   250 /*****************************************************************************/
       
   251 
       
   252 /**
       
   253    Allocates a process data datagram and appends it to the list.
       
   254    \return 0 in case of success, else < 0
       
   255 */
       
   256 
       
   257 int ec_domain_add_datagram(ec_domain_t *domain, /**< EtherCAT domain */
       
   258                            uint32_t offset, /**< logical offset */
       
   259                            size_t data_size /**< size of the datagram data */
       
   260                            )
       
   261 {
   175 {
   262     ec_datagram_t *datagram;
   176     ec_datagram_t *datagram;
   263 
   177 
   264     if (!(datagram = kmalloc(sizeof(ec_datagram_t), GFP_KERNEL))) {
   178     if (!(datagram = kmalloc(sizeof(ec_datagram_t), GFP_KERNEL))) {
   265         EC_ERR("Failed to allocate domain datagram!\n");
   179         EC_ERR("Failed to allocate domain datagram!\n");
   279     return 0;
   193     return 0;
   280 }
   194 }
   281 
   195 
   282 /*****************************************************************************/
   196 /*****************************************************************************/
   283 
   197 
   284 /**
   198 /** Finishes a domain.
   285    Creates a domain.
   199  *
   286    Reserves domain memory, calculates the logical addresses of the
   200  * This allocates the necessary datagrams and writes the correct logical
   287    corresponding FMMUs and sets the process data pointer of the registered
   201  * addresses to every configured FMMU.
   288    process data.
   202  *
   289    \return 0 in case of success, else < 0
   203  * \retval 0 in case of success
   290 */
   204  * \retval <0 on failure.
   291 
   205  */
   292 int ec_domain_alloc(ec_domain_t *domain, /**< EtherCAT domain */
   206 int ec_domain_finish(
   293                     uint32_t base_address /**< logical base address */
   207         ec_domain_t *domain, /**< EtherCAT domain. */
   294                     )
   208         uint32_t base_address /**< Logical base address. */
   295 {
   209         )
   296     ec_data_reg_t *data_reg;
   210 {
   297     ec_slave_t *slave;
   211     uint32_t datagram_offset;
   298     ec_fmmu_t *fmmu;
   212     size_t datagram_data_size;
   299     unsigned int i, j, datagram_count;
   213     unsigned int datagram_count, i;
   300     uint32_t pdo_off, pdo_off_datagram;
   214     ec_slave_config_t *sc;
   301     uint32_t datagram_offset, log_addr;
   215     ec_fmmu_config_t *fmmu;
   302     size_t datagram_data_size, sync_size;
       
   303     ec_datagram_t *datagram;
       
   304 
   216 
   305     domain->base_address = base_address;
   217     domain->base_address = base_address;
   306 
   218 
   307     // calculate size of process data and allocate memory
   219     // Cycle through all domain FMMUS, add the logical base address and assign
   308     domain->data_size = 0;
   220     // as many PDO entries as possible to the datagrams.
   309     datagram_offset = base_address;
   221     datagram_offset = base_address;
   310     datagram_data_size = 0;
   222     datagram_data_size = 0;
   311     datagram_count = 0;
   223     datagram_count = 0;
   312     list_for_each_entry(slave, &domain->master->slaves, list) {
   224     list_for_each_entry(sc, &domain->master->configs, list) {
   313         for (j = 0; j < slave->fmmu_count; j++) {
   225         for (i = 0; i < sc->used_fmmus; i++) {
   314             fmmu = &slave->fmmus[j];
   226             fmmu = &sc->fmmu_configs[i];
   315             if (fmmu->domain == domain) {
   227             if (fmmu->domain != domain)
   316                 fmmu->logical_start_address = base_address + domain->data_size;
   228                 continue;
   317                 sync_size = ec_sync_size(fmmu->sync);
   229 
   318                 domain->data_size += sync_size;
   230             fmmu->logical_start_address += base_address;
   319                 if (datagram_data_size + sync_size > EC_MAX_DATA_SIZE) {
   231             if (datagram_data_size + fmmu->data_size > EC_MAX_DATA_SIZE) {
   320                     if (ec_domain_add_datagram(domain, datagram_offset,
   232                 if (ec_domain_add_datagram(domain, datagram_offset,
   321                                                datagram_data_size)) return -1;
   233                             datagram_data_size)) return -1;
   322                     datagram_offset += datagram_data_size;
   234                 datagram_offset += datagram_data_size;
   323                     datagram_data_size = 0;
   235                 datagram_data_size = 0;
   324                     datagram_count++;
   236                 datagram_count++;
   325                 }
       
   326                 datagram_data_size += sync_size;
       
   327             }
   237             }
       
   238             datagram_data_size += fmmu->data_size;
   328         }
   239         }
   329     }
   240     }
   330 
   241 
   331     // allocate last datagram
   242     // allocate last datagram
   332     if (datagram_data_size) {
   243     if (datagram_data_size) {
   334                                    datagram_data_size))
   245                                    datagram_data_size))
   335             return -1;
   246             return -1;
   336         datagram_count++;
   247         datagram_count++;
   337     }
   248     }
   338 
   249 
   339     if (datagram_count) {
   250     EC_INFO("Domain %u with logical offset %u contains %u bytes in %u"
   340         // set all process data pointers
   251             " datagram%s.\n", domain->index, domain->base_address,
   341         list_for_each_entry(data_reg, &domain->data_regs, list) {
   252             domain->data_size, datagram_count, datagram_count == 1 ? "" : "s");
   342             for (i = 0; i < data_reg->slave->fmmu_count; i++) {
       
   343                 fmmu = &data_reg->slave->fmmus[i];
       
   344                 if (fmmu->domain == domain && fmmu->sync == data_reg->sync) {
       
   345                     pdo_off =
       
   346                         fmmu->logical_start_address + data_reg->sync_offset;
       
   347                     // search datagram
       
   348                     list_for_each_entry(datagram, &domain->datagrams, list) {
       
   349                         log_addr = EC_READ_U32(datagram->address);
       
   350                         pdo_off_datagram = pdo_off - log_addr;
       
   351                         if (pdo_off >= log_addr &&
       
   352                                 pdo_off_datagram < datagram->mem_size) {
       
   353                             *data_reg->data_ptr = datagram->data +
       
   354                                 pdo_off_datagram;
       
   355                         }
       
   356                     }
       
   357                     if (!data_reg->data_ptr) {
       
   358                         EC_ERR("Failed to assign data pointer!\n");
       
   359                         return -1;
       
   360                     }
       
   361                     break;
       
   362                 }
       
   363             }
       
   364         }
       
   365 
       
   366         EC_INFO("Domain %u - Allocated %u bytes in %u datagram%s.\n",
       
   367                 domain->index, domain->data_size, datagram_count,
       
   368                 datagram_count == 1 ? "" : "s");
       
   369     } else { // !datagram_count
       
   370         EC_WARN("Domain %u contains no data!\n", domain->index);
       
   371     }
       
   372 
       
   373     ec_domain_clear_data_regs(domain);
       
   374     return 0;
   253     return 0;
   375 }
   254 }
   376 
   255 
   377 /*****************************************************************************/
   256 /*****************************************************************************/
   378 
   257 
   397 
   276 
   398 /******************************************************************************
   277 /******************************************************************************
   399  *  Realtime interface
   278  *  Realtime interface
   400  *****************************************************************************/
   279  *****************************************************************************/
   401 
   280 
   402 /**
   281 int ecrt_domain_reg_pdo_entry(ec_domain_t *domain, ec_slave_config_t *sc,
   403  * Registers a PDO for a domain.
   282         uint16_t index, uint8_t subindex)
   404  * \return 0 on success, else non-zero
   283 {
   405  * \ingroup RealtimeInterface
   284     return ec_slave_config_reg_pdo_entry(sc, domain, index, subindex);
   406  */
   285 }
   407 
   286 
   408 int ecrt_domain_register_pdo(
   287 /*****************************************************************************/
   409         ec_domain_t *domain, /**< EtherCAT domain */
   288 
   410         ec_slave_t *slave, /**< EtherCAT slave */
   289 int ecrt_domain_reg_pdo_entry_list(ec_domain_t *domain,
   411         uint16_t pdo_entry_index, /**< PDO entry index */
   290         const ec_pdo_entry_reg_t *regs)
   412         uint8_t pdo_entry_subindex, /**< PDO entry subindex */
   291 {
   413         void **data_ptr /**< address of the process data pointer */
   292     const ec_pdo_entry_reg_t *reg;
   414         )
   293     ec_slave_config_t *sc;
   415 {
   294     int ret;
   416     ec_sync_t *sync;
       
   417     const ec_pdo_t *pdo;
       
   418     const ec_pdo_entry_t *entry;
       
   419     unsigned int i;
       
   420 
       
   421     // search for PDO entry
       
   422     for (i = 0; i < slave->sii_sync_count; i++) {
       
   423         sync = &slave->sii_syncs[i];
       
   424         list_for_each_entry(pdo, &sync->pdos, list) {
       
   425             list_for_each_entry(entry, &pdo->entries, list) {
       
   426                 if (entry->index != pdo_entry_index ||
       
   427                         entry->subindex != pdo_entry_subindex) continue;
       
   428                 // PDO entry found
       
   429                 if (ec_domain_reg_pdo_entry(domain, sync, entry, data_ptr)) {
       
   430                     return -1;
       
   431                 }
       
   432                 return 0;
       
   433             }
       
   434         }
       
   435     }
       
   436 
       
   437     EC_ERR("PDO entry 0x%04X:%u is not mapped in slave %u.\n",
       
   438            pdo_entry_index, pdo_entry_subindex, slave->ring_position);
       
   439     return -1;
       
   440 }
       
   441 
       
   442 /*****************************************************************************/
       
   443 
       
   444 /**
       
   445  * Registers a bunch of data fields.
       
   446  * \attention The list has to be terminated with a NULL structure ({})!
       
   447  * \return 0 in case of success, else < 0
       
   448  * \ingroup RealtimeInterface
       
   449  */
       
   450 
       
   451 int ecrt_domain_register_pdo_list(
       
   452         ec_domain_t *domain, /**< EtherCAT domain */
       
   453         const ec_pdo_reg_t *pdo_regs /**< array of PDO registrations */
       
   454         )
       
   455 {
       
   456     const ec_pdo_reg_t *reg;
       
   457     ec_slave_t *slave;
       
   458     
   295     
   459     for (reg = pdo_regs; reg->slave_address; reg++) {
   296     for (reg = regs; reg->index; reg++) {
   460         if (!(slave = ecrt_master_get_slave(domain->master,
   297         if (!(sc = ecrt_master_slave_config(domain->master, reg->alias,
   461                         reg->slave_address, reg->vendor_id,
   298                         reg->position, reg->vendor_id, reg->product_code)))
   462                         reg->product_code)))
       
   463             return -1;
   299             return -1;
   464 
   300 
   465         if (ecrt_domain_register_pdo(domain, slave, reg->pdo_entry_index,
   301         if ((ret = ecrt_domain_reg_pdo_entry(domain, sc, reg->index,
   466                     reg->pdo_entry_subindex, reg->data_ptr))
   302                         reg->subindex)) < 0)
   467             return -1;
   303             return -1;
   468     }
   304 
   469 
   305         *reg->offset = ret;
   470     return 0;
   306     }
   471 }
   307 
   472 
   308     return 0;
   473 /*****************************************************************************/
   309 }
   474 
   310 
   475 /**
   311 /*****************************************************************************/
   476  * Registers a PDO range in a domain.
   312 
   477  * \return 0 on success, else non-zero
   313 void ecrt_domain_process(ec_domain_t *domain)
   478  * \ingroup RealtimeInterface
       
   479  */
       
   480 
       
   481 int ecrt_domain_register_pdo_range(
       
   482         ec_domain_t *domain, /**< EtherCAT domain */
       
   483         ec_slave_t *slave, /**< EtherCAT slave */
       
   484         ec_direction_t dir, /**< data direction */
       
   485         uint16_t offset, /**< offset in slave's PDO range */
       
   486         uint16_t length, /**< length of this range */
       
   487         void **data_ptr /**< address of the process data pointer */
       
   488         )
       
   489 {
       
   490     ec_data_reg_t *data_reg;
       
   491     ec_sync_t *sync;
       
   492     uint16_t sync_length;
       
   493 
       
   494     if (!(sync = ec_slave_get_pdo_sync(slave, dir))) {
       
   495         EC_ERR("No sync manager found for PDO range.\n");
       
   496         return -1;
       
   497     }
       
   498 
       
   499     // Allocate memory for data registration object
       
   500     if (!(data_reg =
       
   501           (ec_data_reg_t *) kmalloc(sizeof(ec_data_reg_t), GFP_KERNEL))) {
       
   502         EC_ERR("Failed to allocate data registration.\n");
       
   503         return -1;
       
   504     }
       
   505 
       
   506     if (ec_slave_prepare_fmmu(slave, domain, sync)) {
       
   507         EC_ERR("FMMU configuration failed.\n");
       
   508         kfree(data_reg);
       
   509         return -1;
       
   510     }
       
   511 
       
   512     data_reg->slave = slave;
       
   513     data_reg->sync = sync;
       
   514     data_reg->sync_offset = offset;
       
   515     data_reg->data_ptr = data_ptr;
       
   516 
       
   517     // estimate sync manager length
       
   518     sync_length = offset + length;
       
   519     if (sync->est_length < sync_length) {
       
   520         sync->est_length = sync_length;
       
   521         if (domain->master->debug_level) {
       
   522             EC_DBG("Estimating length of sync manager %u of slave %u to %u.\n",
       
   523                    sync->index, slave->ring_position, sync_length);
       
   524         }
       
   525     }
       
   526 
       
   527     list_add_tail(&data_reg->list, &domain->data_regs);
       
   528     return 0;
       
   529 }
       
   530 
       
   531 /*****************************************************************************/
       
   532 
       
   533 /**
       
   534    Processes received process data and requeues the domain datagram(s).
       
   535    \ingroup RealtimeInterface
       
   536 */
       
   537 
       
   538 void ecrt_domain_process(ec_domain_t *domain /**< EtherCAT domain */)
       
   539 {
   314 {
   540     unsigned int working_counter_sum;
   315     unsigned int working_counter_sum;
   541     ec_datagram_t *datagram;
   316     ec_datagram_t *datagram;
   542 
   317 
   543     working_counter_sum = 0;
   318     working_counter_sum = 0;
   550         else {
   325         else {
   551             domain->state = -1;
   326             domain->state = -1;
   552         }
   327         }
   553     }
   328     }
   554 
   329 
   555     if (working_counter_sum != domain->response_count) {
   330     if (working_counter_sum != domain->working_counter) {
   556         domain->working_counter_changes++;
   331         domain->working_counter_changes++;
   557         domain->response_count = working_counter_sum;
   332         domain->working_counter = working_counter_sum;
   558     }
   333     }
   559 
   334 
   560     if (domain->working_counter_changes &&
   335     if (domain->working_counter_changes &&
   561         jiffies - domain->notify_jiffies > HZ) {
   336         jiffies - domain->notify_jiffies > HZ) {
   562         domain->notify_jiffies = jiffies;
   337         domain->notify_jiffies = jiffies;
   563         if (domain->working_counter_changes == 1) {
   338         if (domain->working_counter_changes == 1) {
   564             EC_INFO("Domain %u working counter change: %u\n", domain->index,
   339             EC_INFO("Domain %u working counter change: %u\n", domain->index,
   565                     domain->response_count);
   340                     domain->working_counter);
   566         }
   341         }
   567         else {
   342         else {
   568             EC_INFO("Domain %u: %u WC changes. Current response count: %u\n",
   343             EC_INFO("Domain %u: %u working counter changes. Currently %u\n",
   569                     domain->index, domain->working_counter_changes,
   344                     domain->index, domain->working_counter_changes,
   570                     domain->response_count);
   345                     domain->working_counter);
   571         }
   346         }
   572         domain->working_counter_changes = 0;
   347         domain->working_counter_changes = 0;
   573     }
   348     }
   574 }
   349 }
   575 
   350 
   576 /*****************************************************************************/
   351 /*****************************************************************************/
   577 
   352 
   578 /**
   353 void ecrt_domain_queue(ec_domain_t *domain)
   579    Places all process data datagrams in the masters datagram queue.
       
   580    \ingroup RealtimeInterface
       
   581 */
       
   582 
       
   583 void ecrt_domain_queue(ec_domain_t *domain /**< EtherCAT domain */)
       
   584 {
   354 {
   585     ec_datagram_t *datagram;
   355     ec_datagram_t *datagram;
   586 
   356 
   587     list_for_each_entry(datagram, &domain->datagrams, list) {
   357     list_for_each_entry(datagram, &domain->datagrams, list) {
   588         ec_master_queue_datagram(domain->master, datagram);
   358         ec_master_queue_datagram(domain->master, datagram);
   589     }
   359     }
   590 }
   360 }
   591 
   361 
   592 /*****************************************************************************/
   362 /*****************************************************************************/
   593 
   363 
   594 /**
   364 void ecrt_domain_state(const ec_domain_t *domain, ec_domain_state_t *state)
   595    Returns the state of a domain.
   365 {
   596    \return 0 if all datagrams were received, else -1.
   366     state->working_counter = domain->working_counter;
   597    \ingroup RealtimeInterface
   367     state->wc_state = EC_WC_ZERO; // FIXME
   598 */
       
   599 
       
   600 int ecrt_domain_state(const ec_domain_t *domain /**< EtherCAT domain */)
       
   601 {
       
   602     return domain->state;
       
   603 }
   368 }
   604 
   369 
   605 /*****************************************************************************/
   370 /*****************************************************************************/
   606 
   371 
   607 /** \cond */
   372 /** \cond */
   608 
   373 
   609 EXPORT_SYMBOL(ecrt_domain_register_pdo);
   374 EXPORT_SYMBOL(ecrt_domain_reg_pdo_entry);
   610 EXPORT_SYMBOL(ecrt_domain_register_pdo_list);
   375 EXPORT_SYMBOL(ecrt_domain_reg_pdo_entry_list);
   611 EXPORT_SYMBOL(ecrt_domain_register_pdo_range);
   376 //EXPORT_SYMBOL(ecrt_domain_size);
       
   377 //EXPORT_SYMBOL(ecrt_domain_memory);
   612 EXPORT_SYMBOL(ecrt_domain_process);
   378 EXPORT_SYMBOL(ecrt_domain_process);
   613 EXPORT_SYMBOL(ecrt_domain_queue);
   379 EXPORT_SYMBOL(ecrt_domain_queue);
   614 EXPORT_SYMBOL(ecrt_domain_state);
   380 EXPORT_SYMBOL(ecrt_domain_state);
   615 
   381 
   616 /** \endcond */
   382 /** \endcond */