master/master.c
changeset 792 3778920f61e4
parent 758 8fa6f825eb7d
child 794 684dea874956
equal deleted inserted replaced
791:3b81d074735c 792:3778920f61e4
    44 #include <linux/slab.h>
    44 #include <linux/slab.h>
    45 #include <linux/delay.h>
    45 #include <linux/delay.h>
    46 
    46 
    47 #include "../include/ecrt.h"
    47 #include "../include/ecrt.h"
    48 #include "globals.h"
    48 #include "globals.h"
    49 #include "master.h"
       
    50 #include "slave.h"
    49 #include "slave.h"
       
    50 #include "slave_config.h"
    51 #include "device.h"
    51 #include "device.h"
    52 #include "datagram.h"
    52 #include "datagram.h"
    53 #ifdef EC_EOE
    53 #ifdef EC_EOE
    54 #include "ethernet.h"
    54 #include "ethernet.h"
    55 #endif
    55 #endif
    56 
    56 #include "master.h"
    57 /*****************************************************************************/
    57 
    58 
    58 /*****************************************************************************/
       
    59 
       
    60 void ec_master_destroy_slave_configs(ec_master_t *);
    59 void ec_master_destroy_domains(ec_master_t *);
    61 void ec_master_destroy_domains(ec_master_t *);
    60 static int ec_master_idle_thread(ec_master_t *);
    62 static int ec_master_idle_thread(ec_master_t *);
    61 static int ec_master_operation_thread(ec_master_t *);
    63 static int ec_master_operation_thread(ec_master_t *);
    62 #ifdef EC_EOE
    64 #ifdef EC_EOE
    63 void ec_master_eoe_run(unsigned long);
    65 void ec_master_eoe_run(unsigned long);
   120     master->injection_seq_rt = 0;
   122     master->injection_seq_rt = 0;
   121 
   123 
   122     INIT_LIST_HEAD(&master->slaves);
   124     INIT_LIST_HEAD(&master->slaves);
   123     master->slave_count = 0;
   125     master->slave_count = 0;
   124     
   126     
       
   127     INIT_LIST_HEAD(&master->configs);
       
   128 
   125     master->scan_state = EC_REQUEST_IN_PROGRESS;
   129     master->scan_state = EC_REQUEST_IN_PROGRESS;
   126     master->allow_scan = 1;
   130     master->allow_scan = 1;
   127     init_MUTEX(&master->scan_sem);
   131     init_MUTEX(&master->scan_sem);
   128     init_waitqueue_head(&master->scan_queue);
   132     init_waitqueue_head(&master->scan_queue);
   129 
   133 
   134     
   138     
   135     INIT_LIST_HEAD(&master->datagram_queue);
   139     INIT_LIST_HEAD(&master->datagram_queue);
   136     master->datagram_index = 0;
   140     master->datagram_index = 0;
   137 
   141 
   138     INIT_LIST_HEAD(&master->domains);
   142     INIT_LIST_HEAD(&master->domains);
       
   143 
   139     master->debug_level = 0;
   144     master->debug_level = 0;
   140 
       
   141     master->stats.timeouts = 0;
   145     master->stats.timeouts = 0;
   142     master->stats.corrupted = 0;
   146     master->stats.corrupted = 0;
   143     master->stats.unmatched = 0;
   147     master->stats.unmatched = 0;
   144     master->stats.output_jiffies = 0;
   148     master->stats.output_jiffies = 0;
       
   149     master->pdo_slaves_offline = 0; // assume all PDO slaves online
       
   150     master->frames_timed_out = 0;
   145 
   151 
   146     for (i = 0; i < HZ; i++) {
   152     for (i = 0; i < HZ; i++) {
   147         master->idle_cycle_times[i] = 0;
   153         master->idle_cycle_times[i] = 0;
   148 #ifdef EC_EOE
   154 #ifdef EC_EOE
   149         master->eoe_cycle_times[i] = 0;
   155         master->eoe_cycle_times[i] = 0;
   234         )
   240         )
   235 {
   241 {
   236 #ifdef EC_EOE
   242 #ifdef EC_EOE
   237     ec_master_clear_eoe_handlers(master);
   243     ec_master_clear_eoe_handlers(master);
   238 #endif
   244 #endif
       
   245     ec_master_destroy_slave_configs(master);
   239     ec_master_destroy_slaves(master);
   246     ec_master_destroy_slaves(master);
   240     ec_master_destroy_domains(master);
   247     ec_master_destroy_domains(master);
   241     ec_fsm_master_clear(&master->fsm);
   248     ec_fsm_master_clear(&master->fsm);
   242     ec_datagram_clear(&master->fsm_datagram);
   249     ec_datagram_clear(&master->fsm_datagram);
   243     ec_device_clear(&master->backup_device);
   250     ec_device_clear(&master->backup_device);
   249 }
   256 }
   250 
   257 
   251 /*****************************************************************************/
   258 /*****************************************************************************/
   252 
   259 
   253 #ifdef EC_EOE
   260 #ifdef EC_EOE
   254 /**
   261 /** Clear and free all EoE handlers.
   255  * Clear and free all EoE handlers.
       
   256  */
   262  */
   257 
       
   258 void ec_master_clear_eoe_handlers(
   263 void ec_master_clear_eoe_handlers(
   259         ec_master_t *master /**< EtherCAT master */
   264         ec_master_t *master /**< EtherCAT master */
   260         )
   265         )
   261 {
   266 {
   262     ec_eoe_t *eoe, *next;
   267     ec_eoe_t *eoe, *next;
   269 }
   274 }
   270 #endif
   275 #endif
   271 
   276 
   272 /*****************************************************************************/
   277 /*****************************************************************************/
   273 
   278 
   274 /**
   279 /** Destroy all slave configurations.
   275    Destroy all slaves.
   280  */
   276 */
   281 void ec_master_destroy_slave_configs(ec_master_t *master)
   277 
   282 {
       
   283     ec_slave_config_t *sc, *next;
       
   284 
       
   285     list_for_each_entry_safe(sc, next, &master->configs, list) {
       
   286         list_del(&sc->list);
       
   287         ec_slave_config_destroy(sc);
       
   288     }
       
   289 }
       
   290 
       
   291 /*****************************************************************************/
       
   292 
       
   293 /** Destroy all slaves.
       
   294  */
   278 void ec_master_destroy_slaves(ec_master_t *master)
   295 void ec_master_destroy_slaves(ec_master_t *master)
   279 {
   296 {
   280     ec_slave_t *slave, *next_slave;
   297     ec_slave_t *slave, *next;
   281 
   298 
   282     list_for_each_entry_safe(slave, next_slave, &master->slaves, list) {
   299     list_for_each_entry_safe(slave, next, &master->slaves, list) {
   283         list_del(&slave->list);
   300         list_del(&slave->list);
   284         ec_slave_destroy(slave);
   301         ec_slave_destroy(slave);
   285     }
   302     }
   286 
   303 
   287     master->slave_count = 0;
   304     master->slave_count = 0;
   293    Destroy all domains.
   310    Destroy all domains.
   294 */
   311 */
   295 
   312 
   296 void ec_master_destroy_domains(ec_master_t *master)
   313 void ec_master_destroy_domains(ec_master_t *master)
   297 {
   314 {
   298     ec_domain_t *domain, *next_d;
   315     ec_domain_t *domain, *next;
   299 
   316 
   300     list_for_each_entry_safe(domain, next_d, &master->domains, list) {
   317     list_for_each_entry_safe(domain, next, &master->domains, list) {
   301         list_del(&domain->list);
   318         list_del(&domain->list);
   302         ec_domain_destroy(domain);
   319         ec_domain_destroy(domain);
   303     }
   320     }
   304 }
   321 }
   305 
   322 
   465 
   482 
   466     if (master->debug_level)
   483     if (master->debug_level)
   467         EC_DBG("Switching to operation mode.\n");
   484         EC_DBG("Switching to operation mode.\n");
   468 
   485 
   469     master->mode = EC_MASTER_MODE_OPERATION;
   486     master->mode = EC_MASTER_MODE_OPERATION;
   470     master->pdo_slaves_offline = 0; // assume all PDO slaves online
       
   471     master->frames_timed_out = 0;
       
   472     master->ext_request_cb = NULL;
   487     master->ext_request_cb = NULL;
   473     master->ext_release_cb = NULL;
   488     master->ext_release_cb = NULL;
   474     master->ext_cb_data = NULL;
   489     master->ext_cb_data = NULL;
   475     return 0;
   490     return 0;
   476     
   491     
   503     
   518     
   504     master->request_cb = ec_master_request_cb;
   519     master->request_cb = ec_master_request_cb;
   505     master->release_cb = ec_master_release_cb;
   520     master->release_cb = ec_master_release_cb;
   506     master->cb_data = master;
   521     master->cb_data = master;
   507     
   522     
       
   523     ec_master_destroy_slave_configs(master);
       
   524     ec_master_destroy_domains(master);
       
   525 
   508     // set states for all slaves
   526     // set states for all slaves
   509     list_for_each_entry(slave, &master->slaves, list) {
   527     list_for_each_entry(slave, &master->slaves, list) {
   510         ec_slave_reset(slave);
       
   511         ec_slave_request_state(slave, EC_SLAVE_STATE_PREOP);
   528         ec_slave_request_state(slave, EC_SLAVE_STATE_PREOP);
   512     }
   529     }
   513 #ifdef EC_EOE
   530 #ifdef EC_EOE
   514     // ... but leave EoE slaves in OP
   531     // ... but leave EoE slaves in OP
   515     list_for_each_entry(eoe, &master->eoe_handlers, list) {
   532     list_for_each_entry(eoe, &master->eoe_handlers, list) {
   516         if (ec_eoe_is_open(eoe))
   533         if (ec_eoe_is_open(eoe))
   517             ec_slave_request_state(eoe->slave, EC_SLAVE_STATE_OP);
   534             ec_slave_request_state(eoe->slave, EC_SLAVE_STATE_OP);
   518     }
   535     }
   519 #endif
   536 #endif
   520 
   537 
   521     ec_master_destroy_domains(master);
       
   522     
       
   523     if (ec_master_thread_start(master, ec_master_idle_thread))
   538     if (ec_master_thread_start(master, ec_master_idle_thread))
   524         EC_WARN("Failed to restart master thread!\n");
   539         EC_WARN("Failed to restart master thread!\n");
   525 #ifdef EC_EOE
   540 #ifdef EC_EOE
   526     ec_master_eoe_start(master);
   541     ec_master_eoe_start(master);
   527 #endif
   542 #endif
  1239     }
  1254     }
  1240 }
  1255 }
  1241 
  1256 
  1242 /*****************************************************************************/
  1257 /*****************************************************************************/
  1243 
  1258 
  1244 /**
  1259 /** Detaches the slave configurations from the slaves.
  1245  * Translates an ASCII coded bus-address to a slave pointer.
       
  1246  * These are the valid addressing schemes:
       
  1247  * - \a "X" = the Xth slave on the bus (ring position),
       
  1248  * - \a "#X" = the slave with alias X,
       
  1249  * - \a "#X:Y" = the Yth slave after the slave with alias X.
       
  1250  * X and Y are zero-based indices and may be provided in hexadecimal or octal
       
  1251  * notation (with appropriate prefix).
       
  1252  * \return pointer to the slave on success, else NULL
       
  1253  */
  1260  */
  1254 
  1261 void ec_master_detach_slave_configs(
  1255 ec_slave_t *ec_master_parse_slave_address(
  1262         ec_master_t *master /**< EtherCAT master. */
  1256         const ec_master_t *master, /**< EtherCAT master */
       
  1257         const char *address /**< address string */
       
  1258         )
  1263         )
  1259 {
  1264 {
  1260     unsigned long first, second;
  1265     ec_slave_config_t *sc;
  1261     char *remainder, *remainder2;
  1266 
  1262     const char *original;
  1267     if (!master->configs_attached)
  1263     unsigned int alias_requested = 0, alias_not_found = 1;
  1268         return;
  1264     ec_slave_t *alias_slave = NULL, *slave;
  1269 
  1265 
  1270     list_for_each_entry(sc, &master->configs, list) {
  1266     original = address;
  1271         ec_slave_config_detach(sc); 
  1267 
  1272     }
  1268     if (!address[0])
  1273 
  1269         goto out_invalid;
  1274     master->configs_attached = 0;
  1270 
  1275 }
  1271     if (address[0] == '#') {
  1276 
  1272         alias_requested = 1;
  1277 /*****************************************************************************/
  1273         address++;
  1278 
  1274     }
  1279 /** Attaches the slave configurations to the slaves.
  1275 
  1280  */
  1276     first = simple_strtoul(address, &remainder, 0);
  1281 int ec_master_attach_slave_configs(
  1277     if (remainder == address)
  1282         ec_master_t *master /**< EtherCAT master. */
  1278         goto out_invalid;
  1283         )
  1279 
  1284 {
  1280     if (alias_requested) {
  1285     ec_slave_config_t *sc;
  1281         list_for_each_entry(alias_slave, &master->slaves, list) {
  1286     unsigned int errors = 0;
  1282             if (alias_slave->sii_alias == first) {
  1287 
  1283                 alias_not_found = 0;
  1288     if (master->configs_attached)
  1284                 break;
  1289         return 0;
  1285             }
  1290 
  1286         }
  1291     list_for_each_entry(sc, &master->configs, list) {
  1287         if (alias_not_found) {
  1292         if (ec_slave_config_attach(sc))
  1288             EC_ERR("Alias not found!\n");
  1293             errors = 1;
  1289             goto out_invalid;
  1294     }
  1290         }
  1295 
  1291     }
  1296     master->configs_attached = !errors;
  1292 
  1297     return errors ? -1 : 0;
  1293     if (!remainder[0]) {
       
  1294         if (alias_requested) { // alias addressing
       
  1295             return alias_slave;
       
  1296         }
       
  1297         else { // position addressing
       
  1298             list_for_each_entry(slave, &master->slaves, list) {
       
  1299                 if (slave->ring_position == first) return slave;
       
  1300             }
       
  1301             EC_ERR("Slave index out of range!\n");
       
  1302             goto out_invalid;
       
  1303         }
       
  1304     }
       
  1305     else if (alias_requested && remainder[0] == ':') { // field addressing
       
  1306         struct list_head *list;
       
  1307         remainder++;
       
  1308         second = simple_strtoul(remainder, &remainder2, 0);
       
  1309 
       
  1310         if (remainder2 == remainder || remainder2[0])
       
  1311             goto out_invalid;
       
  1312 
       
  1313         list = &alias_slave->list;
       
  1314         while (second--) {
       
  1315             list = list->next;
       
  1316             if (list == &master->slaves) { // last slave exceeded
       
  1317                 EC_ERR("Slave index out of range!\n");
       
  1318                 goto out_invalid;
       
  1319             }
       
  1320         }
       
  1321         return list_entry(list, ec_slave_t, list);
       
  1322     }
       
  1323 
       
  1324 out_invalid:
       
  1325     EC_ERR("Invalid slave address string \"%s\"!\n", original);
       
  1326     return NULL;
       
  1327 }
  1298 }
  1328 
  1299 
  1329 /******************************************************************************
  1300 /******************************************************************************
  1330  *  Realtime interface
  1301  *  Realtime interface
  1331  *****************************************************************************/
  1302  *****************************************************************************/
  1332 
       
  1333 /**
       
  1334    Creates a domain.
       
  1335    \return pointer to new domain on success, else NULL
       
  1336    \ingroup RealtimeInterface
       
  1337 */
       
  1338 
  1303 
  1339 ec_domain_t *ecrt_master_create_domain(ec_master_t *master /**< master */)
  1304 ec_domain_t *ecrt_master_create_domain(ec_master_t *master /**< master */)
  1340 {
  1305 {
  1341     ec_domain_t *domain, *last_domain;
  1306     ec_domain_t *domain, *last_domain;
  1342     unsigned int index;
  1307     unsigned int index;
  1362     return domain;
  1327     return domain;
  1363 }
  1328 }
  1364 
  1329 
  1365 /*****************************************************************************/
  1330 /*****************************************************************************/
  1366 
  1331 
  1367 /**
  1332 int ecrt_master_activate(ec_master_t *master)
  1368    Configures all slaves and leads them to the OP state.
       
  1369    Does the complete configuration and activation for all slaves. Sets sync
       
  1370    managers and FMMUs, and does the appropriate transitions, until the slave
       
  1371    is operational.
       
  1372    \return 0 in case of success, else < 0
       
  1373    \ingroup RealtimeInterface
       
  1374 */
       
  1375 
       
  1376 int ecrt_master_activate(ec_master_t *master /**< EtherCAT master */)
       
  1377 {
  1333 {
  1378     uint32_t domain_offset;
  1334     uint32_t domain_offset;
  1379     ec_domain_t *domain;
  1335     ec_domain_t *domain;
  1380 
  1336 
  1381     // allocate all domains
  1337     // finish all domains
  1382     domain_offset = 0;
  1338     domain_offset = 0;
  1383     list_for_each_entry(domain, &master->domains, list) {
  1339     list_for_each_entry(domain, &master->domains, list) {
  1384         if (ec_domain_alloc(domain, domain_offset)) {
  1340         if (ec_domain_finish(domain, domain_offset)) {
  1385             EC_ERR("Failed to allocate domain %X!\n", (u32) domain);
  1341             EC_ERR("Failed to finish domain %X!\n", (u32) domain);
  1386             return -1;
  1342             return -1;
  1387         }
  1343         }
  1388         domain_offset += domain->data_size;
  1344         domain_offset += domain->data_size;
  1389     }
  1345     }
  1390 
  1346 
  1433     return 0;
  1389     return 0;
  1434 }
  1390 }
  1435 
  1391 
  1436 /*****************************************************************************/
  1392 /*****************************************************************************/
  1437 
  1393 
  1438 /**
  1394 void ecrt_master_send(ec_master_t *master)
  1439    Asynchronous sending of datagrams.
       
  1440    \ingroup RealtimeInterface
       
  1441 */
       
  1442 
       
  1443 void ecrt_master_send(ec_master_t *master /**< EtherCAT master */)
       
  1444 {
  1395 {
  1445     ec_datagram_t *datagram, *n;
  1396     ec_datagram_t *datagram, *n;
  1446 
  1397 
  1447     if (master->injection_seq_rt != master->injection_seq_fsm) {
  1398     if (master->injection_seq_rt != master->injection_seq_fsm) {
  1448         // inject datagram produced by master FSM
  1399         // inject datagram produced by master FSM
  1466     ec_master_send_datagrams(master);
  1417     ec_master_send_datagrams(master);
  1467 }
  1418 }
  1468 
  1419 
  1469 /*****************************************************************************/
  1420 /*****************************************************************************/
  1470 
  1421 
  1471 /**
  1422 void ecrt_master_receive(ec_master_t *master)
  1472    Asynchronous receiving of datagrams.
       
  1473    \ingroup RealtimeInterface
       
  1474 */
       
  1475 
       
  1476 void ecrt_master_receive(ec_master_t *master /**< EtherCAT master */)
       
  1477 {
  1423 {
  1478     ec_datagram_t *datagram, *next;
  1424     ec_datagram_t *datagram, *next;
  1479     cycles_t cycles_timeout;
  1425     cycles_t cycles_timeout;
  1480     unsigned int frames_timed_out = 0;
  1426     unsigned int frames_timed_out = 0;
  1481 
  1427 
  1508     master->frames_timed_out = frames_timed_out;
  1454     master->frames_timed_out = frames_timed_out;
  1509 }
  1455 }
  1510 
  1456 
  1511 /*****************************************************************************/
  1457 /*****************************************************************************/
  1512 
  1458 
  1513 /**
  1459 ec_slave_config_t *ecrt_master_slave_config(ec_master_t *master,
  1514  * Obtains a slave pointer by its bus address.
  1460         uint16_t alias, uint16_t position, uint32_t vendor_id,
  1515  * A valid slave pointer is only returned, if vendor ID and product code are
  1461         uint32_t product_code)
  1516  * matching.
  1462 {
  1517  * \return pointer to the slave on success, else NULL
  1463     ec_slave_config_t *sc;
  1518  * \ingroup RealtimeInterface
       
  1519  */
       
  1520 
       
  1521 ec_slave_t *ecrt_master_get_slave(
       
  1522         const ec_master_t *master, /**< EtherCAT master */
       
  1523         const char *address, /**< address string
       
  1524                                \see ec_master_parse_slave_address() */
       
  1525         uint32_t vendor_id, /**< vendor ID */
       
  1526         uint32_t product_code /**< product code */
       
  1527         )
       
  1528 {
       
  1529     ec_slave_t *slave = ec_master_parse_slave_address(master, address);
       
  1530 
       
  1531     if (!slave)
       
  1532         return NULL;
       
  1533 
       
  1534     return ec_slave_validate(slave, vendor_id, product_code) ? NULL : slave;
       
  1535 }
       
  1536 
       
  1537 /*****************************************************************************/
       
  1538 
       
  1539 /**
       
  1540  * Obtains a slave pointer by its ring position.
       
  1541  * A valid slave pointer is only returned, if vendor ID and product code are
       
  1542  * matching.
       
  1543  * \return pointer to the slave on success, else NULL
       
  1544  * \ingroup RealtimeInterface
       
  1545  */
       
  1546 
       
  1547 ec_slave_t *ecrt_master_get_slave_by_pos(
       
  1548         const ec_master_t *master, /**< EtherCAT master */
       
  1549         uint16_t ring_position, /**< ring position */
       
  1550         uint32_t vendor_id, /**< vendor ID */
       
  1551         uint32_t product_code /**< product code */
       
  1552         )
       
  1553 {
       
  1554     ec_slave_t *slave;
       
  1555     unsigned int found = 0;
  1464     unsigned int found = 0;
  1556 
  1465 
  1557     list_for_each_entry(slave, &master->slaves, list) {
  1466     list_for_each_entry(sc, &master->configs, list) {
  1558         if (slave->ring_position == ring_position) {
  1467         if (sc->alias == alias && sc->position == position) {
  1559             found = 1;
  1468             found = 1;
  1560             break;
  1469             break;
  1561         }
  1470         }
  1562     }
  1471     }
  1563 
  1472 
  1564     if (!found) {
  1473     if (found) {
  1565         EC_ERR("Slave index out of range!\n");
  1474         if (master->debug_level) {
  1566         return NULL;
  1475             EC_INFO("Using existing slave configuration for %u:%u\n",
  1567     }
  1476                     alias, position);
  1568 
  1477         }
  1569     return ec_slave_validate(slave, vendor_id, product_code) ? NULL : slave;
  1478         if (sc->vendor_id != vendor_id || sc->product_code != product_code) {
  1570 }
  1479             EC_ERR("Slave type mismatch. Slave was configured as"
  1571 
  1480                     " 0x%08X/0x%08X before. Now configuring with"
  1572 /*****************************************************************************/
  1481                     " 0x%08X/0x%08X.\n", sc->vendor_id, sc->product_code,
  1573 
  1482                     vendor_id, product_code);
  1574 /**
  1483             return NULL;
  1575    Sets the locking callbacks.
  1484         }
  1576    The request_cb function must return zero, to allow another instance
  1485     } else {
  1577    (the EoE process for example) to access the master. Non-zero means,
  1486         if (master->debug_level) {
  1578    that access is forbidden at this time.
  1487             EC_INFO("Creating slave configuration for %u:%u,"
  1579    \ingroup RealtimeInterface
  1488                     " 0x%08X/0x%08X.\n", alias, position, vendor_id,
  1580 */
  1489                     product_code);
  1581 
  1490         }
  1582 void ecrt_master_callbacks(ec_master_t *master, /**< EtherCAT master */
  1491 
  1583                            int (*request_cb)(void *), /**< request lock CB */
  1492         if (!(sc = (ec_slave_config_t *) kmalloc(sizeof(ec_slave_config_t),
  1584                            void (*release_cb)(void *), /**< release lock CB */
  1493                         GFP_KERNEL))) {
  1585                            void *cb_data /**< data parameter */
  1494             EC_ERR("Failed to allocate memory for slave configuration.\n");
  1586                            )
  1495             return NULL;
       
  1496         }
       
  1497 
       
  1498         if (ec_slave_config_init(sc, master, alias, position, vendor_id,
       
  1499                     product_code)) {
       
  1500             EC_ERR("Failed to init slave configuration.\n");
       
  1501             return NULL;
       
  1502         }
       
  1503 
       
  1504         // try to find the addressed slave
       
  1505         ec_slave_config_attach(sc);
       
  1506         ec_slave_config_load_default_mapping(sc);
       
  1507 
       
  1508         list_add_tail(&sc->list, &master->configs);
       
  1509     }
       
  1510 
       
  1511     return sc;
       
  1512 }
       
  1513 
       
  1514 /*****************************************************************************/
       
  1515 
       
  1516 void ecrt_master_callbacks(ec_master_t *master, int (*request_cb)(void *),
       
  1517         void (*release_cb)(void *), void *cb_data)
  1587 {
  1518 {
  1588     master->ext_request_cb = request_cb;
  1519     master->ext_request_cb = request_cb;
  1589     master->ext_release_cb = release_cb;
  1520     master->ext_release_cb = release_cb;
  1590     master->ext_cb_data = cb_data;
  1521     master->ext_cb_data = cb_data;
  1591 }
  1522 }
  1592 
  1523 
  1593 /*****************************************************************************/
  1524 /*****************************************************************************/
  1594 
  1525 
  1595 /**
  1526 void ecrt_master_state(const ec_master_t *master, ec_master_state_t *state)
  1596  * Reads the current master status.
  1527 {
  1597  */
  1528     state->bus_state =
  1598 
       
  1599 void ecrt_master_get_status(const ec_master_t *master, /**< EtherCAT master */
       
  1600         ec_master_status_t *status /**< target status object */
       
  1601         )
       
  1602 {
       
  1603     status->bus_status =
       
  1604         (master->pdo_slaves_offline || master->frames_timed_out)
  1529         (master->pdo_slaves_offline || master->frames_timed_out)
  1605         ? EC_BUS_FAILURE : EC_BUS_OK;
  1530         ? EC_BUS_FAILURE : EC_BUS_OK;
  1606     status->bus_tainted = master->fsm.tainted; 
  1531     state->bus_tainted = master->fsm.tainted; 
  1607     status->slaves_responding = master->fsm.slaves_responding;
  1532     state->slaves_responding = master->fsm.slaves_responding;
  1608 }
  1533 }
  1609 
  1534 
  1610 /*****************************************************************************/
  1535 /*****************************************************************************/
  1611 
  1536 
  1612 /** \cond */
  1537 /** \cond */
  1614 EXPORT_SYMBOL(ecrt_master_create_domain);
  1539 EXPORT_SYMBOL(ecrt_master_create_domain);
  1615 EXPORT_SYMBOL(ecrt_master_activate);
  1540 EXPORT_SYMBOL(ecrt_master_activate);
  1616 EXPORT_SYMBOL(ecrt_master_send);
  1541 EXPORT_SYMBOL(ecrt_master_send);
  1617 EXPORT_SYMBOL(ecrt_master_receive);
  1542 EXPORT_SYMBOL(ecrt_master_receive);
  1618 EXPORT_SYMBOL(ecrt_master_callbacks);
  1543 EXPORT_SYMBOL(ecrt_master_callbacks);
  1619 EXPORT_SYMBOL(ecrt_master_get_slave);
  1544 EXPORT_SYMBOL(ecrt_master_slave_config);
  1620 EXPORT_SYMBOL(ecrt_master_get_slave_by_pos);
  1545 EXPORT_SYMBOL(ecrt_master_state);
  1621 EXPORT_SYMBOL(ecrt_master_get_status);
       
  1622 
  1546 
  1623 /** \endcond */
  1547 /** \endcond */
  1624 
  1548 
  1625 /*****************************************************************************/
  1549 /*****************************************************************************/