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; |
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; |
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 |
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 */ |