merged
authorMartin Troxler <ch1010277@ch10lt194>
Mon, 14 Mar 2011 16:57:47 +0100
changeset 2046 4cf0161c445a
parent 2042 8b358effa78b (diff)
parent 2045 ff2a13a4603c (current diff)
child 2047 f4266c6fce7c
merged
master/master.c
--- a/TODO	Mon Mar 14 16:55:09 2011 +0100
+++ b/TODO	Mon Mar 14 16:57:47 2011 +0100
@@ -13,17 +13,12 @@
 * Ethernet drivers:
     - Fix link detection in generic driver.
     - Add native drivers from 2.6.24 up to 2.6.31.
-* ethercat tool:
-    - Implement ranges for slaves and domains.
 
 Future issues:
 
 * Remove allow_scanning flag.
-* Output skipped datagrams again.
 * Check for Enable SDO Complete Access flag.
 * Do not output 'SDO does not exist' when querying data type.
-* Always write down PDO assignment/mapping in doubt? If not, add an interface
-  for enforcing this.
 * Read AL status code on spontaneous state change.
 * recompile tool/CommandVersion.cpp if revision changes.
 * Log SoE IDNs with real name ([SP]-x-yyyy).
--- a/include/ecrt.h	Mon Mar 14 16:55:09 2011 +0100
+++ b/include/ecrt.h	Mon Mar 14 16:57:47 2011 +0100
@@ -76,6 +76,7 @@
  * - Added ecrt_slave_config_idn() method for storing SoE IDN configurations,
  *   and ecrt_master_read_idn() and ecrt_master_write_idn() to read/write IDNs
  *   ad-hoc via the user-space library.
+ * - Added ecrt_master_reset() to initiate retrying to configure slaves.
  * - Added support for overlapping PDOs which allows inputs to use the same
  *   space as outputs on the frame. This reduces the frame length.
  *
@@ -885,6 +886,17 @@
         ec_master_t *master /**< EtherCAT master. */
         );
 
+/** Retry configuring slaves.
+ *
+ * Via this method, the application can tell the master to bring all slaves to
+ * OP state. In general, this is not necessary, because it is automatically
+ * done by the master. But with special slaves, that can be reconfigured by
+ * the vendor during runtime, it can be useful.
+ */
+void ecrt_master_reset(
+        ec_master_t *master /**< EtherCAT master. */
+        );
+
 /******************************************************************************
  * Slave configuration methods
  *****************************************************************************/
--- a/lib/master.c	Mon Mar 14 16:55:09 2011 +0100
+++ b/lib/master.c	Mon Mar 14 16:57:47 2011 +0100
@@ -591,3 +591,12 @@
 }
 
 /*****************************************************************************/
+
+void ecrt_master_reset(ec_master_t *master)
+{
+    if (ioctl(master->fd, EC_IOCTL_RESET, NULL) == -1) {
+        fprintf(stderr, "Failed to reset master: %s\n", strerror(errno));
+    }
+}
+
+/*****************************************************************************/
--- a/master/cdev.c	Mon Mar 14 16:55:09 2011 +0100
+++ b/master/cdev.c	Mon Mar 14 16:57:47 2011 +0100
@@ -2009,6 +2009,25 @@
 
 /*****************************************************************************/
 
+/** Reset configuration.
+ */
+int ec_cdev_ioctl_reset(
+        ec_master_t *master, /**< EtherCAT master. */
+        unsigned long arg, /**< ioctl() argument. */
+        ec_cdev_priv_t *priv /**< Private data structure of file handle. */
+        )
+{
+    if (unlikely(!priv->requested))
+        return -EPERM;
+
+    ec_mutex_lock(&master->master_mutex);
+    ecrt_master_reset(master);
+    ec_mutex_unlock(&master->master_mutex);
+    return 0;
+}
+
+/*****************************************************************************/
+
 /** Configure a sync manager.
  */
 int ec_cdev_ioctl_sc_sync(
@@ -3723,6 +3742,10 @@
             if (!(filp->f_mode & FMODE_WRITE))
                 return -EPERM;
             return ec_cdev_ioctl_sync_mon_process(master, arg, priv);
+        case EC_IOCTL_RESET:
+            if (!(filp->f_mode & FMODE_WRITE))
+                return -EPERM;
+            return ec_cdev_ioctl_reset(master, arg, priv);
         case EC_IOCTL_SC_SYNC:
             if (!(filp->f_mode & FMODE_WRITE))
                 return -EPERM;
--- a/master/ioctl.h	Mon Mar 14 16:55:09 2011 +0100
+++ b/master/ioctl.h	Mon Mar 14 16:57:47 2011 +0100
@@ -56,7 +56,7 @@
  *
  * Increment this when changing the ioctl interface!
  */
-#define EC_IOCTL_VERSION_MAGIC 11
+#define EC_IOCTL_VERSION_MAGIC 12
 
 // Command-line tool
 #define EC_IOCTL_MODULE                EC_IOR(0x00, ec_ioctl_module_t)
@@ -95,7 +95,7 @@
 // Application interface
 #define EC_IOCTL_REQUEST                EC_IO(0x1e)
 #define EC_IOCTL_CREATE_DOMAIN          EC_IO(0x1f)
-#define EC_IOCTL_CREATE_SLAVE_CONFIG  EC_IOWR(0x10, ec_ioctl_config_t)
+#define EC_IOCTL_CREATE_SLAVE_CONFIG  EC_IOWR(0x20, ec_ioctl_config_t)
 #define EC_IOCTL_ACTIVATE              EC_IOR(0x21, size_t)
 #define EC_IOCTL_DEACTIVATE             EC_IO(0x22)
 #define EC_IOCTL_SEND                   EC_IO(0x23)
@@ -106,38 +106,39 @@
 #define EC_IOCTL_SYNC_SLAVES            EC_IO(0x28)
 #define EC_IOCTL_SYNC_MON_QUEUE         EC_IO(0x29)
 #define EC_IOCTL_SYNC_MON_PROCESS      EC_IOR(0x2a, uint32_t)
-#define EC_IOCTL_SC_SYNC               EC_IOW(0x2b, ec_ioctl_config_t)
-#define EC_IOCTL_SC_WATCHDOG           EC_IOW(0x2c, ec_ioctl_config_t)
-#define EC_IOCTL_SC_ADD_PDO            EC_IOW(0x2d, ec_ioctl_config_pdo_t)
-#define EC_IOCTL_SC_CLEAR_PDOS         EC_IOW(0x2e, ec_ioctl_config_pdo_t)
-#define EC_IOCTL_SC_ADD_ENTRY          EC_IOW(0x2f, ec_ioctl_add_pdo_entry_t)
-#define EC_IOCTL_SC_CLEAR_ENTRIES      EC_IOW(0x20, ec_ioctl_config_pdo_t)
-#define EC_IOCTL_SC_REG_PDO_ENTRY     EC_IOWR(0x21, ec_ioctl_reg_pdo_entry_t)
-#define EC_IOCTL_SC_DC                 EC_IOW(0x32, ec_ioctl_config_t)
-#define EC_IOCTL_SC_SDO                EC_IOW(0x33, ec_ioctl_sc_sdo_t)
-#define EC_IOCTL_SC_SDO_REQUEST       EC_IOWR(0x34, ec_ioctl_sdo_request_t)
-#define EC_IOCTL_SC_VOE               EC_IOWR(0x35, ec_ioctl_voe_t)
-#define EC_IOCTL_SC_STATE             EC_IOWR(0x36, ec_ioctl_sc_state_t)
-#define EC_IOCTL_SC_IDN                EC_IOW(0x37, ec_ioctl_sc_idn_t)
-#define EC_IOCTL_DOMAIN_OFFSET          EC_IO(0x38)
-#define EC_IOCTL_DOMAIN_PROCESS         EC_IO(0x39)
-#define EC_IOCTL_DOMAIN_QUEUE           EC_IO(0x3a)
-#define EC_IOCTL_DOMAIN_STATE         EC_IOWR(0x3b, ec_ioctl_domain_state_t)
-#define EC_IOCTL_SDO_REQUEST_TIMEOUT  EC_IOWR(0x3c, ec_ioctl_sdo_request_t)
-#define EC_IOCTL_SDO_REQUEST_STATE    EC_IOWR(0x3d, ec_ioctl_sdo_request_t)
-#define EC_IOCTL_SDO_REQUEST_READ     EC_IOWR(0x3e, ec_ioctl_sdo_request_t)
-#define EC_IOCTL_SDO_REQUEST_WRITE    EC_IOWR(0x3f, ec_ioctl_sdo_request_t)
-#define EC_IOCTL_SDO_REQUEST_DATA     EC_IOWR(0x30, ec_ioctl_sdo_request_t)
-#define EC_IOCTL_VOE_SEND_HEADER       EC_IOW(0x41, ec_ioctl_voe_t)
-#define EC_IOCTL_VOE_REC_HEADER       EC_IOWR(0x42, ec_ioctl_voe_t)
-#define EC_IOCTL_VOE_READ              EC_IOW(0x43, ec_ioctl_voe_t)
-#define EC_IOCTL_VOE_READ_NOSYNC       EC_IOW(0x44, ec_ioctl_voe_t)
-#define EC_IOCTL_VOE_WRITE            EC_IOWR(0x45, ec_ioctl_voe_t)
-#define EC_IOCTL_VOE_EXEC             EC_IOWR(0x46, ec_ioctl_voe_t)
-#define EC_IOCTL_VOE_DATA             EC_IOWR(0x47, ec_ioctl_voe_t)
-#define EC_IOCTL_SET_SEND_INTERVAL     EC_IOW(0x48, size_t)
-#define EC_IOCTL_MASTER_SC_STATE        EC_IOR(0x49, ec_master_state_t)
-#define EC_IOCTL_SC_OVERLAPPING_IO      EC_IOW(0x50, ec_ioctl_config_t)
+#define EC_IOCTL_RESET                  EC_IO(0x2b)
+#define EC_IOCTL_SC_SYNC               EC_IOW(0x2c, ec_ioctl_config_t)
+#define EC_IOCTL_SC_WATCHDOG           EC_IOW(0x2d, ec_ioctl_config_t)
+#define EC_IOCTL_SC_ADD_PDO            EC_IOW(0x2e, ec_ioctl_config_pdo_t)
+#define EC_IOCTL_SC_CLEAR_PDOS         EC_IOW(0x2f, ec_ioctl_config_pdo_t)
+#define EC_IOCTL_SC_ADD_ENTRY          EC_IOW(0x30, ec_ioctl_add_pdo_entry_t)
+#define EC_IOCTL_SC_CLEAR_ENTRIES      EC_IOW(0x31, ec_ioctl_config_pdo_t)
+#define EC_IOCTL_SC_REG_PDO_ENTRY     EC_IOWR(0x32, ec_ioctl_reg_pdo_entry_t)
+#define EC_IOCTL_SC_DC                 EC_IOW(0x33, ec_ioctl_config_t)
+#define EC_IOCTL_SC_SDO                EC_IOW(0x34, ec_ioctl_sc_sdo_t)
+#define EC_IOCTL_SC_SDO_REQUEST       EC_IOWR(0x35, ec_ioctl_sdo_request_t)
+#define EC_IOCTL_SC_VOE               EC_IOWR(0x36, ec_ioctl_voe_t)
+#define EC_IOCTL_SC_STATE             EC_IOWR(0x37, ec_ioctl_sc_state_t)
+#define EC_IOCTL_SC_IDN                EC_IOW(0x38, ec_ioctl_sc_idn_t)
+#define EC_IOCTL_DOMAIN_OFFSET          EC_IO(0x39)
+#define EC_IOCTL_DOMAIN_PROCESS         EC_IO(0x3a)
+#define EC_IOCTL_DOMAIN_QUEUE           EC_IO(0x3b)
+#define EC_IOCTL_DOMAIN_STATE         EC_IOWR(0x3c, ec_ioctl_domain_state_t)
+#define EC_IOCTL_SDO_REQUEST_TIMEOUT  EC_IOWR(0x3d, ec_ioctl_sdo_request_t)
+#define EC_IOCTL_SDO_REQUEST_STATE    EC_IOWR(0x3e, ec_ioctl_sdo_request_t)
+#define EC_IOCTL_SDO_REQUEST_READ     EC_IOWR(0x3f, ec_ioctl_sdo_request_t)
+#define EC_IOCTL_SDO_REQUEST_WRITE    EC_IOWR(0x40, ec_ioctl_sdo_request_t)
+#define EC_IOCTL_SDO_REQUEST_DATA     EC_IOWR(0x41, ec_ioctl_sdo_request_t)
+#define EC_IOCTL_VOE_SEND_HEADER       EC_IOW(0x42, ec_ioctl_voe_t)
+#define EC_IOCTL_VOE_REC_HEADER       EC_IOWR(0x43, ec_ioctl_voe_t)
+#define EC_IOCTL_VOE_READ              EC_IOW(0x44, ec_ioctl_voe_t)
+#define EC_IOCTL_VOE_READ_NOSYNC       EC_IOW(0x45, ec_ioctl_voe_t)
+#define EC_IOCTL_VOE_WRITE            EC_IOWR(0x46, ec_ioctl_voe_t)
+#define EC_IOCTL_VOE_EXEC             EC_IOWR(0x47, ec_ioctl_voe_t)
+#define EC_IOCTL_VOE_DATA             EC_IOWR(0x48, ec_ioctl_voe_t)
+#define EC_IOCTL_SET_SEND_INTERVAL     EC_IOW(0x49, size_t)
+#define EC_IOCTL_MASTER_SC_STATE        EC_IOR(0x50, ec_master_state_t)
+#define EC_IOCTL_SC_OVERLAPPING_IO      EC_IOW(0x51, ec_ioctl_config_t)
 
 /*****************************************************************************/
 
--- a/master/master.c	Mon Mar 14 16:55:09 2011 +0100
+++ b/master/master.c	Mon Mar 14 16:57:47 2011 +0100
@@ -2477,6 +2477,19 @@
 
 /*****************************************************************************/
 
+void ecrt_master_reset(ec_master_t *master)
+{
+    ec_slave_config_t *sc;
+
+    list_for_each_entry(sc, &master->configs, list) {
+        if (sc->slave) {
+            ec_slave_request_state(sc->slave, EC_SLAVE_STATE_OP);
+        }
+    }
+}
+
+/*****************************************************************************/
+
 /** \cond */
 
 EXPORT_SYMBOL(ecrt_master_create_domain);
@@ -2496,6 +2509,7 @@
 EXPORT_SYMBOL(ecrt_master_sync_monitor_process);
 EXPORT_SYMBOL(ecrt_master_write_idn);
 EXPORT_SYMBOL(ecrt_master_read_idn);
+EXPORT_SYMBOL(ecrt_master_reset);
 
 /** \endcond */
 
--- a/tool/Command.cpp	Mon Mar 14 16:55:09 2011 +0100
+++ b/tool/Command.cpp	Mon Mar 14 16:57:47 2011 +0100
@@ -29,22 +29,120 @@
  *
  ****************************************************************************/
 
+#include <map>
+using namespace std;
+
 #include "Command.h"
 #include "MasterDevice.h"
 #include "NumberListParser.h"
 
 /*****************************************************************************/
 
+typedef map<uint16_t, ec_ioctl_config_t> AliasMap;
+typedef map<uint16_t, AliasMap> ConfigMap;
+
+/*****************************************************************************/
+
 class MasterIndexParser:
     public NumberListParser
 {
-    unsigned int getMax()
-    {
-        MasterDevice dev;
-        dev.setIndex(0U);
-        dev.open(MasterDevice::Read);
-        return dev.getMasterCount() - 1;
-    };
+    protected:
+        int getMax() {
+            MasterDevice dev;
+            dev.setIndex(0U);
+            dev.open(MasterDevice::Read);
+            return (int) dev.getMasterCount() - 1;
+        };
+};
+
+/*****************************************************************************/
+
+class SlaveAliasParser:
+    public NumberListParser
+{
+    public:
+        SlaveAliasParser(ec_ioctl_master_t &master, MasterDevice &dev):
+            master(master), dev(dev) {}
+
+    protected:
+        int getMax() {
+            unsigned int i;
+
+            uint16_t maxAlias = 0;
+            for (i = 0; i < master.slave_count; i++) {
+                ec_ioctl_slave_t slave;
+                dev.getSlave(&slave, i);
+                if (slave.alias > maxAlias) {
+                    maxAlias = slave.alias;
+                }
+            }
+            return maxAlias ? maxAlias : -1;
+        };
+
+    private:
+        ec_ioctl_master_t &master;
+        MasterDevice &dev;
+};
+
+/*****************************************************************************/
+
+class ConfigAliasParser:
+    public NumberListParser
+{
+    public:
+        ConfigAliasParser(unsigned int maxAlias):
+            maxAlias(maxAlias) {}
+
+    protected:
+        int getMax() { return maxAlias; };
+
+    private:
+        unsigned int maxAlias;
+};
+
+/*****************************************************************************/
+
+class PositionParser:
+    public NumberListParser
+{
+    public:
+        PositionParser(unsigned int count):
+            count(count) {}
+
+    protected:
+        int getMax() {
+            return count - 1;
+        };
+
+    private:
+        const unsigned int count;
+};
+
+/*****************************************************************************/
+
+class AliasPositionParser:
+    public NumberListParser
+{
+    public:
+        AliasPositionParser(const AliasMap &aliasMap):
+            aliasMap(aliasMap) {}
+
+    protected:
+        int getMax() {
+            AliasMap::const_iterator i;
+            int maxPos = -1;
+
+            for (i = aliasMap.begin(); i != aliasMap.end(); i++) {
+                if (i->first > maxPos) {
+                    maxPos = i->first;
+                }
+            }
+
+            return maxPos;
+        };
+
+    private:
+        const AliasMap &aliasMap;
 };
 
 /*****************************************************************************/
@@ -78,23 +176,23 @@
 
 /*****************************************************************************/
 
-void Command::setAlias(int a)
-{
-    alias = a;
-};
-
-/*****************************************************************************/
-
-void Command::setPosition(int p)
-{
-    position = p;
-};
-
-/*****************************************************************************/
-
-void Command::setDomain(int d)
-{
-    domain = d;
+void Command::setAliases(const string &a)
+{
+    aliases = a;
+};
+
+/*****************************************************************************/
+
+void Command::setPositions(const string &p)
+{
+    positions = p;
+};
+
+/*****************************************************************************/
+
+void Command::setDomains(const string &d)
+{
+    domains = d;
 };
 
 /*****************************************************************************/
@@ -214,11 +312,13 @@
 unsigned int Command::getSingleMasterIndex() const
 {
     MasterIndexList masterIndices = getMasterIndices();
+
     if (masterIndices.size() != 1) {
         stringstream err;
         err << getName() << " requires to select a single master!";
         throwInvalidUsageException(err);
     }
+
     return masterIndices.front();
 }
 
@@ -227,51 +327,57 @@
 Command::SlaveList Command::selectedSlaves(MasterDevice &m)
 {
     ec_ioctl_master_t master;
-    unsigned int i, aliasIndex;
-    uint16_t lastAlias;
+    unsigned int i;
     ec_ioctl_slave_t slave;
     SlaveList list;
 
     m.getMaster(&master);
 
-    if (alias == -1) { // no alias given
-        if (position == -1) { // no alias and position given
-            // all items
-            for (i = 0; i < master.slave_count; i++) {
-                m.getSlave(&slave, i);
+    if (aliases == "-") { // no alias given
+        PositionParser pp(master.slave_count);
+        NumberListParser::List posList = pp.parse(positions.c_str());
+        NumberListParser::List::const_iterator pi;
+
+        for (pi = posList.begin(); pi != posList.end(); pi++) {
+            if (*pi < master.slave_count) {
+                m.getSlave(&slave, *pi);
                 list.push_back(slave);
             }
-        } else { // no alias, but position given
-            // one item by position
-            m.getSlave(&slave, position);
-            list.push_back(slave);
         }
-    } else { // alias given
-        if (position == -1) { // alias, but no position given
-            // take all items with a given alias
-            lastAlias = 0;
+    } else { // aliases given
+        SlaveAliasParser ap(master, m);
+        NumberListParser::List aliasList = ap.parse(aliases.c_str());
+        NumberListParser::List::const_iterator ai;
+
+        for (ai = aliasList.begin(); ai != aliasList.end(); ai++) {
+
+            // gather slaves with that alias (and following)
+            uint16_t lastAlias = 0;
+            vector<ec_ioctl_slave_t> aliasSlaves;
+
             for (i = 0; i < master.slave_count; i++) {
                 m.getSlave(&slave, i);
                 if (slave.alias) {
+                    if (lastAlias && lastAlias == *ai && slave.alias != *ai) {
+                        // ignore multiple ocurrences of the same alias to
+                        // assure consistency for the position argument
+                        break;
+                    }
                     lastAlias = slave.alias;
                 }
-                if (lastAlias == (uint16_t) alias) {
-                    list.push_back(slave);
+                if (lastAlias == *ai) {
+                    aliasSlaves.push_back(slave);
                 }
             }
-        } else { // alias and position given
-            lastAlias = 0;
-            aliasIndex = 0;
-            for (i = 0; i < master.slave_count; i++) {
-                m.getSlave(&slave, i);
-                if (slave.alias && slave.alias == (uint16_t) alias) {
-                    lastAlias = slave.alias;
-                    aliasIndex = 0;
+
+            PositionParser pp(aliasSlaves.size());
+            NumberListParser::List posList = pp.parse(positions.c_str());
+            NumberListParser::List::const_iterator pi;
+
+            for (pi = posList.begin(); pi != posList.end(); pi++) {
+                if (*pi < aliasSlaves.size()) {
+                    list.push_back(aliasSlaves[*pi]);
                 }
-                if (lastAlias && aliasIndex == (unsigned int) position) {
-                    list.push_back(slave);
-                }
-                aliasIndex++;
             }
         }
     }
@@ -302,37 +408,47 @@
 
     m.getMaster(&master);
 
-    if (alias == -1) { // no alias given
-        if (position == -1) { // no alias and position given
-            // all items
-            for (i = 0; i < master.config_count; i++) {
-                m.getConfig(&config, i);
-                list.push_back(config);
-            }
-        } else { // no alias, but position given
-            for (i = 0; i < master.config_count; i++) {
-                m.getConfig(&config, i);
-                if (!config.alias && config.position == position) {
-                    list.push_back(config);
-                    break; // there can be at most one matching
-                }
-            }
+    if (aliases == "-" && positions == "-") { // shortcut
+        for (i = 0; i < master.config_count; i++) {
+            m.getConfig(&config, i);
+            list.push_back(config);
         }
-    } else { // alias given
-        if (position == -1) { // alias, but no position given
-            // take all items with a given alias
-            for (i = 0; i < master.config_count; i++) {
-                m.getConfig(&config, i);
-                if (config.alias == alias) {
-                    list.push_back(config);
-                }
-            }
-        } else { // alias and position given
-            for (i = 0; i < master.config_count; i++) {
-                m.getConfig(&config, i);
-                if (config.alias == alias && config.position == position) {
-                    list.push_back(config);
-                    break; // there can be at most one matching
+    } else { // take the long way home...
+        ConfigMap configs;
+        uint16_t maxAlias = 0;
+
+        // fill cascaded map structure with all configs
+        for (i = 0; i < master.config_count; i++) {
+            m.getConfig(&config, i);
+            AliasMap &aliasMap = configs[config.alias];
+            aliasMap[config.position] = config;
+            if (config.alias > maxAlias) {
+                maxAlias = config.alias;
+            }
+        }
+
+        ConfigAliasParser ap(maxAlias);
+        NumberListParser::List aliasList = ap.parse(aliases.c_str());
+        NumberListParser::List::const_iterator ai;
+
+        for (ai = aliasList.begin(); ai != aliasList.end(); ai++) {
+
+            ConfigMap::iterator ci = configs.find(*ai);
+            if (ci == configs.end()) {
+                continue;
+            }
+
+            AliasMap &aliasMap = configs[*ai];
+            AliasPositionParser pp(aliasMap);
+            NumberListParser::List posList = pp.parse(positions.c_str());
+            NumberListParser::List::const_iterator pi;
+
+            for (pi = posList.begin(); pi != posList.end(); pi++) {
+                AliasMap::const_iterator ci;
+
+                ci = aliasMap.find(*pi);
+                if (ci != aliasMap.end()) {
+                    list.push_back(ci->second);
                 }
             }
         }
@@ -346,22 +462,21 @@
 
 Command::DomainList Command::selectedDomains(MasterDevice &m)
 {
-    ec_ioctl_domain_t d;
+    ec_ioctl_master_t master;
     DomainList list;
 
-    if (domain == -1) {
-        ec_ioctl_master_t master;
-        unsigned int i;
-
-        m.getMaster(&master);
-
-        for (i = 0; i < master.domain_count; i++) {
-            m.getDomain(&d, i);
+    m.getMaster(&master);
+
+    PositionParser pp(master.domain_count);
+    NumberListParser::List domList = pp.parse(domains.c_str());
+    NumberListParser::List::const_iterator di;
+
+    for (di = domList.begin(); di != domList.end(); di++) {
+        if (*di < master.domain_count) {
+            ec_ioctl_domain_t d;
+            m.getDomain(&d, *di);
             list.push_back(d);
         }
-    } else {
-        m.getDomain(&d, domain);
-        list.push_back(d);
     }
 
     return list;
--- a/tool/Command.h	Mon Mar 14 16:55:09 2011 +0100
+++ b/tool/Command.h	Mon Mar 14 16:57:47 2011 +0100
@@ -96,16 +96,20 @@
         };
         void setVerbosity(Verbosity);
         Verbosity getVerbosity() const;
-        void setAlias(int);
-        int getAlias() const;
-        void setPosition(int);
-        int getPosition() const;
-        void setDomain(int);
-        int getDomain() const;
+
+        void setAliases(const string &);
+        void setPositions(const string &);
+
+        void setDomains(const string &);
+        typedef list<unsigned int> DomainIndexList;
+        DomainIndexList getDomainIndices() const;
+
         void setDataType(const string &);
         const string &getDataType() const;
+
         void setForce(bool);
         bool getForce() const;
+
         void setOutputFile(const string &);
         const string &getOutputFile() const;
 
@@ -141,9 +145,9 @@
         string briefDesc;
         string masters;
         Verbosity verbosity;
-        int alias;
-        int position;
-        int domain;
+        string aliases;
+        string positions;
+        string domains;
         string dataType;
         bool force;
         string outputFile;
@@ -174,27 +178,6 @@
 
 /****************************************************************************/
 
-inline int Command::getAlias() const
-{
-    return alias;
-}
-
-/****************************************************************************/
-
-inline int Command::getPosition() const
-{
-    return position;
-}
-
-/****************************************************************************/
-
-inline int Command::getDomain() const
-{
-    return domain;
-}
-
-/****************************************************************************/
-
 inline const string &Command::getDataType() const
 {
     return dataType;
--- a/tool/NumberListParser.cpp	Mon Mar 14 16:55:09 2011 +0100
+++ b/tool/NumberListParser.cpp	Mon Mar 14 16:57:47 2011 +0100
@@ -50,9 +50,9 @@
 
 /*****************************************************************************/
 
-NumberListParser::NumberList NumberListParser::parse(const char *data)
-{
-    NumberList ret;
+NumberListParser::List NumberListParser::parse(const char *data)
+{
+    List ret;
     unsigned int i = 0, size = strlen(data), firstNum = 0U, secondNum = 0U;
     typedef enum {
         SectionStart,
@@ -108,17 +108,41 @@
 
             case Range:
                 if (i >= size) {
-                    secondNum = maximum();
-                    NumberList r = range(firstNum, secondNum);
-                    ret.splice(ret.end(), r);
+                    int max = maximum();
+                    // only increasing ranges if second number omitted
+                    if (max >= 0 && firstNum <= (unsigned int) max) {
+                        List r = range(firstNum, max);
+                        ret.splice(ret.end(), r);
+                    }
                     state = Finished;
                 } else if (isNumeric(data[i])) {
                     secondNum = parseNumber(data, &i, size);
                     state = SecondNumber;
                 } else if (data[i] == ',') {
-                    i++;
-                    secondNum = maximum();
-                    NumberList r = range(firstNum, secondNum);
+                    int max = maximum();
+                    i++;
+                    if (max >= 0) {
+                        List r = range(firstNum, max);
+                        ret.splice(ret.end(), r);
+                    }
+                    state = SectionStart;
+                } else {
+                    stringstream err;
+                    err << "Invalid character " << data[i]
+                        << " at position " << i << "in state "
+                        << state << "." << endl;
+                    throw runtime_error(err.str());
+                }
+                break;
+
+            case SecondNumber:
+                if (i >= size) {
+                    List r = range(firstNum, secondNum);
+                    ret.splice(ret.end(), r);
+                    state = Finished;
+                } else if (data[i] == ',') {
+                    i++;
+                    List r = range(firstNum, secondNum);
                     ret.splice(ret.end(), r);
                     state = SectionStart;
                 } else {
@@ -130,25 +154,6 @@
                 }
                 break;
 
-            case SecondNumber:
-                if (i >= size) {
-                    NumberList r = range(firstNum, secondNum);
-                    ret.splice(ret.end(), r);
-                    state = Finished;
-                } else if (data[i] == ',') {
-                    i++;
-                    NumberList r = range(firstNum, secondNum);
-                    ret.splice(ret.end(), r);
-                    state = SectionStart;
-                } else {
-                    stringstream err;
-                    err << "Invalid character " << data[i]
-                        << " at position " << i << "in state "
-                        << state << "." << endl;
-                    throw runtime_error(err.str());
-                }
-                break;
-
             default:
                 {
                     stringstream err;
@@ -163,7 +168,7 @@
 
 /*****************************************************************************/
 
-unsigned int NumberListParser::maximum()
+int NumberListParser::maximum()
 {
     if (!hasMax) {
         max = getMax();
@@ -207,12 +212,12 @@
 
 /****************************************************************************/
 
-NumberListParser::NumberList NumberListParser::range(
+NumberListParser::List NumberListParser::range(
         unsigned int i,
         unsigned int j
         )
 {
-    NumberList ret;
+    List ret;
 
     if (i <= j) {
         for (; i <= j; i++) {
--- a/tool/NumberListParser.h	Mon Mar 14 16:55:09 2011 +0100
+++ b/tool/NumberListParser.h	Mon Mar 14 16:57:47 2011 +0100
@@ -38,22 +38,22 @@
         NumberListParser();
         virtual ~NumberListParser();
 
-        typedef list<unsigned int> NumberList;
+        typedef list<unsigned int> List;
 
-        NumberList parse(const char *);
+        List parse(const char *);
 
-        virtual unsigned int getMax() = 0;
+        virtual int getMax() = 0;
 
     private:
-        unsigned int max;
+        int max;
         bool hasMax;
 
-        unsigned int maximum();
+        int maximum();
 
         static bool isNumeric(char);
         static unsigned int parseNumber(const char *, unsigned int *,
                 unsigned int);
-        static NumberList range(unsigned int, unsigned int);
+        static List range(unsigned int, unsigned int);
 };
 
 /****************************************************************************/
--- a/tool/main.cpp	Mon Mar 14 16:55:09 2011 +0100
+++ b/tool/main.cpp	Mon Mar 14 16:57:47 2011 +0100
@@ -77,9 +77,9 @@
 
 // option variables
 string masters = "-"; // all masters
-int slavePosition = -1;
-int slaveAlias = -1;
-int domainIndex = -1;
+string positions = "-"; // all positions
+string aliases = "-"; // all aliases
+string domains = "-"; // all domains
 string dataTypeStr;
 Command::Verbosity verbosity = Command::Normal;
 bool force = false;
@@ -163,43 +163,15 @@
                 break;
 
             case 'a':
-                str.clear();
-                str.str("");
-                str << optarg;
-                str >> resetiosflags(ios::basefield) // guess base from prefix
-                    >> slaveAlias;
-                if (str.fail() || slaveAlias < 0 || slaveAlias > 0xFFFF) {
-                    cerr << "Invalid slave alias " << optarg << "!" << endl
-                        << endl << usage();
-                    exit(1);
-                }
+                aliases = optarg;
                 break;
 
             case 'p':
-                str.clear();
-                str.str("");
-                str << optarg;
-                str >> resetiosflags(ios::basefield) // guess base from prefix
-                    >> slavePosition;
-                if (str.fail()
-                        || slavePosition < 0 || slavePosition > 0xFFFF) {
-                    cerr << "Invalid slave position " << optarg << "!" << endl
-                        << endl << usage();
-                    exit(1);
-                }
+                positions = optarg;
                 break;
 
             case 'd':
-                str.clear();
-                str.str("");
-                str << optarg;
-                str >> resetiosflags(ios::basefield) // guess base from prefix
-                    >> domainIndex;
-                if (str.fail() || domainIndex < 0) {
-                    cerr << "Invalid domain index " << optarg << "!" << endl
-                        << endl << usage();
-                    exit(1);
-                }
+                domains = optarg;
                 break;
 
             case 't':
@@ -331,9 +303,9 @@
                 try {
                     cmd->setMasters(masters);
                     cmd->setVerbosity(verbosity);
-                    cmd->setAlias(slaveAlias);
-                    cmd->setPosition(slavePosition);
-                    cmd->setDomain(domainIndex);
+                    cmd->setAliases(aliases);
+                    cmd->setPositions(positions);
+                    cmd->setDomains(domains);
                     cmd->setDataType(dataTypeStr);
                     cmd->setOutputFile(outputFile);
                     cmd->setForce(force);