diff --git a/tool/Makefile.am b/tool/Makefile.am
index b235d2fca3805ca4064e9871f6f71c9c9461da33..41a68e35ea9a0aee22acf0ec4fcb8fe12d493ae3 100644
--- a/tool/Makefile.am
+++ b/tool/Makefile.am
@@ -34,7 +34,9 @@
 bin_PROGRAMS = ethercat
 
 ethercat_SOURCES = \
-    Master.cpp Master.h \
+    MasterDevice.cpp MasterDevice.h \
+    cmd_alias.cpp \
+    cmd_config.cpp \
     main.cpp
 
 ethercat_CXXFLAGS = -I../master -Wall
diff --git a/tool/Master.cpp b/tool/MasterDevice.cpp
similarity index 87%
rename from tool/Master.cpp
rename to tool/MasterDevice.cpp
index d0172f6612defb3a70d3c9055d6dd9526a71486a..df1ffdf107d028168eb97ff2dbaca01897753e32 100644
--- a/tool/Master.cpp
+++ b/tool/MasterDevice.cpp
@@ -4,51 +4,23 @@
  *
  ****************************************************************************/
 
-#include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
 #include <errno.h>
 #include <sys/ioctl.h>
 
-#include <iostream>
-#include <iomanip>
 #include <sstream>
+using namespace std;
+
+#if 0
+#include <iostream>
 #include <fstream>
 #include <cctype> // toupper()
 #include <list>
-using namespace std;
-
-#include "Master.h"
-
-#define swap16(x) \
-        ((uint16_t)( \
-        (((uint16_t)(x) & 0x00ffU) << 8) | \
-        (((uint16_t)(x) & 0xff00U) >> 8) ))
-#define swap32(x) \
-        ((uint32_t)( \
-        (((uint32_t)(x) & 0x000000ffUL) << 24) | \
-        (((uint32_t)(x) & 0x0000ff00UL) <<  8) | \
-        (((uint32_t)(x) & 0x00ff0000UL) >>  8) | \
-        (((uint32_t)(x) & 0xff000000UL) >> 24) ))
-
-#if __BYTE_ORDER == __LITTLE_ENDIAN
-
-#define le16tocpu(x) x
-#define le32tocpu(x) x
-
-#define cputole16(x) x
-#define cputole32(x) x
-
-#elif __BYTE_ORDER == __BIG_ENDIAN
-
-#define le16tocpu(x) swap16(x)
-#define le32tocpu(x) swap32(x)
-
-#define cputole16(x) swap16(x)
-#define cputole32(x) swap32(x)
-
 #endif
 
+#include "MasterDevice.h"
+
 /****************************************************************************/
 
 struct CoEDataType {
@@ -97,86 +69,27 @@ const CoEDataType *findDataType(uint16_t code)
 
 /****************************************************************************/
 
-Master::Master()
+MasterDevice::MasterDevice()
 {
     index = 0;
-    verbosity = Normal;
     fd = -1;
 }
 
 /****************************************************************************/
 
-Master::~Master()
+MasterDevice::~MasterDevice()
 {
     close();
 }
 
 /****************************************************************************/
 
-void Master::setIndex(unsigned int i)
+void MasterDevice::setIndex(unsigned int i)
 {
     index = i;
 }
 
-/****************************************************************************/
-
-void Master::setVerbosity(Verbosity v)
-{
-    verbosity = v;
-}
-
-/*****************************************************************************/
-
-/**
- * Writes the Secondary slave address (alias) to the slave's SII.
- */
-void Master::writeAlias(
-        int slavePosition,
-        bool force,
-        const vector<string> &commandArgs
-        )
-{
-    uint16_t alias;
-    stringstream err, strAlias;
-    int number;
-
-    if (commandArgs.size() != 1) {
-        stringstream err;
-        err << "'alias' takes exactly one argument!";
-        throw MasterException(err.str());
-    }
-
-    strAlias << commandArgs[0];
-    strAlias
-        >> resetiosflags(ios::basefield) // guess base from prefix
-        >> number;
-    if (strAlias.fail() || number < 0x0000 || number > 0xffff) {
-        err << "Invalid alias '" << commandArgs[0] << "'!";
-        throw MasterException(err.str());
-    }
-    alias = number;
-
-    if (slavePosition == -1) {
-        unsigned int numSlaves, i;
-
-        if (!force) {
-            err << "This will write the alias addresses of all slaves to "
-                << alias << "! Please specify --force to proceed.";
-            throw MasterException(err.str());
-        }
-
-        open(ReadWrite);
-        numSlaves = slaveCount();
-
-        for (i = 0; i < numSlaves; i++) {
-            writeSlaveAlias(i, alias);
-        }
-    } else {
-        open(ReadWrite);
-        writeSlaveAlias(slavePosition, alias);
-    }
-}
-
+#if 0
 /*****************************************************************************/
 
 bool operator<(const ec_ioctl_config_t &a, const ec_ioctl_config_t &b)
@@ -241,7 +154,7 @@ void Master::setDebug(const vector<string> &commandArgs)
     if (commandArgs.size() != 1) {
         stringstream err;
         err << "'debug' takes exactly one argument!";
-        throw MasterException(err.str());
+        throw MasterDeviceException(err.str());
     }
 
     str << commandArgs[0];
@@ -251,7 +164,7 @@ void Master::setDebug(const vector<string> &commandArgs)
     if (str.fail()) {
         stringstream err;
         err << "Invalid debug level '" << commandArgs[0] << "'!";
-        throw MasterException(err.str());
+        throw MasterDeviceException(err.str());
     }
 
     open(ReadWrite);
@@ -259,7 +172,7 @@ void Master::setDebug(const vector<string> &commandArgs)
     if (ioctl(fd, EC_IOCTL_MASTER_DEBUG, debugLevel) < 0) {
         stringstream err;
         err << "Failed to set debug level: " << strerror(errno);
-        throw MasterException(err.str());
+        throw MasterDeviceException(err.str());
     }
 }
 
@@ -304,7 +217,7 @@ void Master::showMaster()
         case 2: cout << "Operation"; break;
         default:
                 err << "Invalid master phase " << data.phase;
-                throw MasterException(err.str());
+                throw MasterDeviceException(err.str());
     }
 
     cout << endl
@@ -385,13 +298,13 @@ void Master::sdoDownload(
 
     if (slavePosition < 0) {
         err << "'sdo_download' requires a slave! Please specify --slave.";
-        throw MasterException(err.str());
+        throw MasterDeviceException(err.str());
     }
     data.slave_position = slavePosition;
 
     if (commandArgs.size() != 3) {
         err << "'sdo_download' takes 3 arguments!";
-        throw MasterException(err.str());
+        throw MasterDeviceException(err.str());
     }
 
     strIndex << commandArgs[0];
@@ -400,7 +313,7 @@ void Master::sdoDownload(
         >> data.sdo_index;
     if (strIndex.fail()) {
         err << "Invalid Sdo index '" << commandArgs[0] << "'!";
-        throw MasterException(err.str());
+        throw MasterDeviceException(err.str());
     }
 
     strSubIndex << commandArgs[1];
@@ -409,14 +322,14 @@ void Master::sdoDownload(
         >> number;
     if (strSubIndex.fail() || number > 0xff) {
         err << "Invalid Sdo subindex '" << commandArgs[1] << "'!";
-        throw MasterException(err.str());
+        throw MasterDeviceException(err.str());
     }
     data.sdo_entry_subindex = number;
 
     if (dataTypeStr != "") { // data type specified
         if (!(dataType = findDataType(dataTypeStr))) {
             err << "Invalid data type '" << dataTypeStr << "'!";
-            throw MasterException(err.str());
+            throw MasterDeviceException(err.str());
         }
     } else { // no data type specified: fetch from dictionary
         ec_ioctl_slave_sdo_entry_t entry;
@@ -426,16 +339,16 @@ void Master::sdoDownload(
         try {
             getSdoEntry(&entry, slavePosition,
                     data.sdo_index, data.sdo_entry_subindex);
-        } catch (MasterException &e) {
+        } catch (MasterDeviceException &e) {
             err << "Failed to determine Sdo entry data type. "
                 << "Please specify --type.";
-            throw MasterException(err.str());
+            throw MasterDeviceException(err.str());
         }
         if (!(dataType = findDataType(entry.data_type))) {
             err << "Pdo entry has unknown data type 0x"
                 << hex << setfill('0') << setw(4) << entry.data_type << "!"
                 << " Please specify --type.";
-            throw MasterException(err.str());
+            throw MasterDeviceException(err.str());
         }
     }
 
@@ -502,7 +415,7 @@ void Master::sdoDownload(
             case 0x0009: // string
                 if (strValue.str().size() >= data.data_size) {
                     err << "String too large";
-                    throw MasterException(err.str());
+                    throw MasterDeviceException(err.str());
                 }
                 data.data_size = strValue.str().size();
                 strValue >> (char *) data.data;
@@ -511,13 +424,13 @@ void Master::sdoDownload(
             default:
                 delete [] data.data;
                 err << "Unknown data type 0x" << hex << dataType->coeCode;
-                throw MasterException(err.str());
+                throw MasterDeviceException(err.str());
         }
     } catch (ios::failure &e) {
         delete [] data.data;
         err << "Invalid value argument '" << commandArgs[2]
             << "' for type '" << dataType->name << "'!";
-        throw MasterException(err.str());
+        throw MasterDeviceException(err.str());
     }
 
     open(ReadWrite);
@@ -532,7 +445,7 @@ void Master::sdoDownload(
             err << strerror(errno);
         }
         delete [] data.data;
-        throw MasterException(err.str());
+        throw MasterDeviceException(err.str());
     }
 
     delete [] data.data;
@@ -555,14 +468,14 @@ void Master::sdoUpload(
     if (slavePosition < 0) {
         stringstream err;
         err << "'sdo_upload' requires a slave! Please specify --slave.";
-        throw MasterException(err.str());
+        throw MasterDeviceException(err.str());
     }
     data.slave_position = slavePosition;
 
     if (commandArgs.size() != 2) {
         stringstream err;
         err << "'sdo_upload' takes two arguments!";
-        throw MasterException(err.str());
+        throw MasterDeviceException(err.str());
     }
 
     strIndex << commandArgs[0];
@@ -572,7 +485,7 @@ void Master::sdoUpload(
     if (strIndex.fail()) {
         stringstream err;
         err << "Invalid Sdo index '" << commandArgs[0] << "'!";
-        throw MasterException(err.str());
+        throw MasterDeviceException(err.str());
     }
 
     strSubIndex << commandArgs[1];
@@ -582,7 +495,7 @@ void Master::sdoUpload(
     if (strSubIndex.fail() || uval > 0xff) {
         stringstream err;
         err << "Invalid Sdo subindex '" << commandArgs[1] << "'!";
-        throw MasterException(err.str());
+        throw MasterDeviceException(err.str());
     }
     data.sdo_entry_subindex = uval;
 
@@ -590,7 +503,7 @@ void Master::sdoUpload(
         if (!(dataType = findDataType(dataTypeStr))) {
             stringstream err;
             err << "Invalid data type '" << dataTypeStr << "'!";
-            throw MasterException(err.str());
+            throw MasterDeviceException(err.str());
         }
     } else { // no data type specified: fetch from dictionary
         ec_ioctl_slave_sdo_entry_t entry;
@@ -600,18 +513,18 @@ void Master::sdoUpload(
         try {
             getSdoEntry(&entry, slavePosition,
                     data.sdo_index, data.sdo_entry_subindex);
-        } catch (MasterException &e) {
+        } catch (MasterDeviceException &e) {
             stringstream err;
             err << "Failed to determine Sdo entry data type. "
                 << "Please specify --type.";
-            throw MasterException(err.str());
+            throw MasterDeviceException(err.str());
         }
         if (!(dataType = findDataType(entry.data_type))) {
             stringstream err;
             err << "Pdo entry has unknown data type 0x"
                 << hex << setfill('0') << setw(4) << entry.data_type << "!"
                 << " Please specify --type.";
-            throw MasterException(err.str());
+            throw MasterDeviceException(err.str());
         }
     }
 
@@ -636,7 +549,7 @@ void Master::sdoUpload(
         }
         delete [] data.target;
         close();
-        throw MasterException(err.str());
+        throw MasterDeviceException(err.str());
     }
 
     close();
@@ -646,7 +559,7 @@ void Master::sdoUpload(
         err << "Data type mismatch. Expected " << dataType->name
             << " with " << dataType->byteSize << " byte, but got "
             << data.data_size << " byte.";
-        throw MasterException(err.str());
+        throw MasterDeviceException(err.str());
     }
 
     cout << setfill('0');
@@ -753,7 +666,7 @@ void Master::siiRead(int slavePosition)
     if (slavePosition < 0) {
         stringstream err;
         err << "'sii_read' requires a slave! Please specify --slave.";
-        throw MasterException(err.str());
+        throw MasterDeviceException(err.str());
     }
     data.slave_position = slavePosition;
 
@@ -772,7 +685,7 @@ void Master::siiRead(int slavePosition)
         stringstream err;
         delete [] data.words;
         err << "Failed to read SII: " << strerror(errno);
-        throw MasterException(err.str());
+        throw MasterDeviceException(err.str());
     }
 
     if (verbosity == Verbose) {
@@ -798,7 +711,7 @@ void Master::siiRead(int slavePosition)
 
                 if (categoryHeader + 1 > data.words + data.nwords) {
                     err << "SII data seem to be corrupted!";
-                    throw MasterException(err.str());
+                    throw MasterDeviceException(err.str());
                 }
                 categorySize = le16tocpu(*(categoryHeader + 1));
                 cout << ", " << dec << categorySize << " words" << flush;
@@ -806,7 +719,7 @@ void Master::siiRead(int slavePosition)
                 if (categoryHeader + 2 + categorySize
                         > data.words + data.nwords) {
                     err << "SII data seem to be corrupted!";
-                    throw MasterException(err.str());
+                    throw MasterDeviceException(err.str());
                 }
 
                 cout << hex;
@@ -824,7 +737,7 @@ void Master::siiRead(int slavePosition)
                 if (categoryHeader + 2 + categorySize + 1
                         > data.words + data.nwords) {
                     err << "SII data seem to be corrupted!"; 
-                    throw MasterException(err.str());
+                    throw MasterDeviceException(err.str());
                 }
                 categoryHeader += 2 + categorySize;
                 categoryType = le16tocpu(*categoryHeader);
@@ -858,19 +771,19 @@ void Master::siiWrite(
 
     if (slavePosition < 0) {
         err << "'sii_write' requires a slave! Please specify --slave.";
-        throw MasterException(err.str());
+        throw MasterDeviceException(err.str());
     }
     data.slave_position = slavePosition;
 
     if (commandArgs.size() != 1) {
         err << "'ssi_write' takes exactly one argument!";
-        throw MasterException(err.str());
+        throw MasterDeviceException(err.str());
     }
 
     file.open(commandArgs[0].c_str(), ifstream::in | ifstream::binary);
     if (file.fail()) {
         err << "Failed to open '" << commandArgs[0] << "'!";
-        throw MasterException(err.str());
+        throw MasterDeviceException(err.str());
     }
 
     // get length of file
@@ -881,14 +794,14 @@ void Master::siiWrite(
     if (!byte_size || byte_size % 2) {
         stringstream err;
         err << "Invalid file size! Must be non-zero and even.";
-        throw MasterException(err.str());
+        throw MasterDeviceException(err.str());
     }
 
     data.nwords = byte_size / 2;
     if (data.nwords < 0x0041 && !force) {
         err << "SII data too short (" << data.nwords << " words)! Mimimum is"
                 " 40 fixed words + 1 delimiter. Use --force to write anyway.";
-        throw MasterException(err.str());
+        throw MasterDeviceException(err.str());
     }
 
     // allocate buffer and read file into buffer
@@ -903,7 +816,7 @@ void Master::siiWrite(
             err << "CRC incorrect. Must be 0x"
                 << hex << setfill('0') << setw(2) << (unsigned int) crc
                 << ". Use --force to write anyway.";
-            throw MasterException(err.str());
+            throw MasterDeviceException(err.str());
         }
 
         // cycle through categories to detect corruption
@@ -913,14 +826,14 @@ void Master::siiWrite(
             if (categoryHeader + 1 > data.words + data.nwords) {
                 err << "SII data seem to be corrupted! "
                     << "Use --force to write anyway.";
-                throw MasterException(err.str());
+                throw MasterDeviceException(err.str());
             }
             categorySize = le16tocpu(*(categoryHeader + 1));
             if (categoryHeader + 2 + categorySize + 1
                     > data.words + data.nwords) {
                 err << "SII data seem to be corrupted! "
                     "Use --force to write anyway.";
-                throw MasterException(err.str());
+                throw MasterDeviceException(err.str());
             }
             categoryHeader += 2 + categorySize;
             categoryType = le16tocpu(*categoryHeader);
@@ -933,7 +846,7 @@ void Master::siiWrite(
     if (ioctl(fd, EC_IOCTL_SLAVE_SII_WRITE, &data) < 0) {
         stringstream err;
         err << "Failed to write SII: " << strerror(errno);
-        throw MasterException(err.str());
+        throw MasterDeviceException(err.str());
     }
 }
 
@@ -950,7 +863,7 @@ void Master::requestStates(
     if (commandArgs.size() != 1) {
         stringstream err;
         err << "'state' takes exactly one argument!";
-        throw MasterException(err.str());
+        throw MasterDeviceException(err.str());
     }
 
     stateStr = commandArgs[0];
@@ -968,7 +881,7 @@ void Master::requestStates(
     } else {
         stringstream err;
         err << "Invalid state '" << commandArgs[0] << "'!";
-        throw MasterException(err.str());
+        throw MasterDeviceException(err.str());
     }
 
     open(ReadWrite);
@@ -999,9 +912,10 @@ void Master::generateXml(int slavePosition)
     }
 }
 
+#endif
 /****************************************************************************/
 
-void Master::open(Permissions perm)
+void MasterDevice::open(Permissions perm)
 {
     stringstream deviceName;
 
@@ -1016,13 +930,13 @@ void Master::open(Permissions perm)
         stringstream err;
         err << "Failed to open master device " << deviceName.str() << ": "
             << strerror(errno);
-        throw MasterException(err.str());
+        throw MasterDeviceException(err.str());
     }
 }
 
 /****************************************************************************/
 
-void Master::close()
+void MasterDevice::close()
 {
     if (fd == -1)
         return;
@@ -1031,61 +945,7 @@ void Master::close()
     fd = -1;
 }
 
-/*****************************************************************************/
-
-/**
- * Writes the Secondary slave address (alias) to the slave's SII.
- */
-void Master::writeSlaveAlias(
-        uint16_t slavePosition,
-        uint16_t alias
-        )
-{
-    ec_ioctl_slave_sii_t data;
-    ec_ioctl_slave_t slave;
-    stringstream err;
-    uint8_t crc;
-
-    open(ReadWrite);
-
-    getSlave(&slave, slavePosition);
-
-    if (slave.sii_nwords < 8) {
-        err << "Current SII contents are too small to set an alias "
-            << "(" << slave.sii_nwords << " words)!";
-        throw MasterException(err.str());
-    }
-
-    data.slave_position = slavePosition;
-    data.offset = 0;
-    data.nwords = 8;
-    data.words = new uint16_t[data.nwords];
-
-    // read first 8 SII words
-    if (ioctl(fd, EC_IOCTL_SLAVE_SII_READ, &data) < 0) {
-        delete [] data.words;
-        err << "Failed to read SII: " << strerror(errno);
-        throw MasterException(err.str());
-    }
-
-    // write new alias address in word 4
-    data.words[4] = cputole16(alias);
-
-    // calculate checksum over words 0 to 6
-    crc = calcSiiCrc((const uint8_t *) data.words, 14);
-
-    // write new checksum into first byte of word 7
-    *(uint8_t *) (data.words + 7) = crc;
-
-    // write first 8 words with new alias and checksum
-    if (ioctl(fd, EC_IOCTL_SLAVE_SII_WRITE, &data) < 0) {
-        delete [] data.words;
-        err << "Failed to write SII: " << strerror(errno);
-        throw MasterException(err.str());
-    }
-
-    delete [] data.words;
-}
+#if 0
 
 /*****************************************************************************/
 
@@ -1275,7 +1135,7 @@ void Master::outputDomainData(unsigned int domainIndex)
 
     try {
         getData(&data, domainIndex, domain.data_size, processData);
-    } catch (MasterException &e) {
+    } catch (MasterDeviceException &e) {
         delete [] processData;
         throw e;
     }
@@ -1317,7 +1177,7 @@ void Master::showDomain(unsigned int domainIndex)
 
     try {
         getData(&data, domainIndex, domain.data_size, processData);
-    } catch (MasterException &e) {
+    } catch (MasterDeviceException &e) {
         delete [] processData;
         throw e;
     }
@@ -1341,7 +1201,7 @@ void Master::showDomain(unsigned int domainIndex)
             stringstream err;
             err << "Fmmu information corrupted!";
             delete [] processData;
-            throw MasterException(err.str());
+            throw MasterDeviceException(err.str());
         }
 
         cout << "    " << hex << setfill('0');
@@ -1781,10 +1641,10 @@ void Master::generateSlaveXml(uint16_t slavePosition)
         << "  </Descriptions>" << endl
         << "</EtherCATInfo>" << endl;
 }
-
+#endif
 /****************************************************************************/
 
-unsigned int Master::slaveCount()
+unsigned int MasterDevice::slaveCount()
 {
     ec_ioctl_master_t data;
 
@@ -1794,31 +1654,31 @@ unsigned int Master::slaveCount()
 
 /****************************************************************************/
 
-void Master::getMaster(ec_ioctl_master_t *data)
+void MasterDevice::getMaster(ec_ioctl_master_t *data)
 {
     if (ioctl(fd, EC_IOCTL_MASTER, data) < 0) {
         stringstream err;
         err << "Failed to get master information: " << strerror(errno);
-        throw MasterException(err.str());
+        throw MasterDeviceException(err.str());
     }
 }
 
 /****************************************************************************/
 
-void Master::getConfig(ec_ioctl_config_t *data, unsigned int index)
+void MasterDevice::getConfig(ec_ioctl_config_t *data, unsigned int index)
 {
     data->config_index = index;
 
     if (ioctl(fd, EC_IOCTL_CONFIG, data) < 0) {
         stringstream err;
         err << "Failed to get slave configuration: " << strerror(errno);
-        throw MasterException(err.str());
+        throw MasterDeviceException(err.str());
     }
 }
 
 /****************************************************************************/
 
-void Master::getConfigPdo(
+void MasterDevice::getConfigPdo(
         ec_ioctl_config_pdo_t *data,
         unsigned int index,
         uint8_t sync_index,
@@ -1832,13 +1692,13 @@ void Master::getConfigPdo(
     if (ioctl(fd, EC_IOCTL_CONFIG_PDO, data) < 0) {
         stringstream err;
         err << "Failed to get slave config Pdo: " << strerror(errno);
-        throw MasterException(err.str());
+        throw MasterDeviceException(err.str());
     }
 }
 
 /****************************************************************************/
 
-void Master::getConfigPdoEntry(
+void MasterDevice::getConfigPdoEntry(
         ec_ioctl_config_pdo_entry_t *data,
         unsigned int index,
         uint8_t sync_index,
@@ -1854,13 +1714,13 @@ void Master::getConfigPdoEntry(
     if (ioctl(fd, EC_IOCTL_CONFIG_PDO_ENTRY, data) < 0) {
         stringstream err;
         err << "Failed to get slave config Pdo entry: " << strerror(errno);
-        throw MasterException(err.str());
+        throw MasterDeviceException(err.str());
     }
 }
 
 /****************************************************************************/
 
-void Master::getConfigSdo(
+void MasterDevice::getConfigSdo(
         ec_ioctl_config_sdo_t *data,
         unsigned int index,
         unsigned int sdo_pos
@@ -1872,13 +1732,13 @@ void Master::getConfigSdo(
     if (ioctl(fd, EC_IOCTL_CONFIG_SDO, data) < 0) {
         stringstream err;
         err << "Failed to get slave config Sdo: " << strerror(errno);
-        throw MasterException(err.str());
+        throw MasterDeviceException(err.str());
     }
 }
 
 /****************************************************************************/
 
-void Master::getDomain(ec_ioctl_domain_t *data, unsigned int index)
+void MasterDevice::getDomain(ec_ioctl_domain_t *data, unsigned int index)
 {
     data->index = index;
 
@@ -1889,13 +1749,13 @@ void Master::getDomain(ec_ioctl_domain_t *data, unsigned int index)
             err << "Domain " << index << " does not exist!";
         else
             err << strerror(errno);
-        throw MasterException(err.str());
+        throw MasterDeviceException(err.str());
     }
 }
 
 /****************************************************************************/
 
-void Master::getData(ec_ioctl_domain_data_t *data, unsigned int domainIndex,
+void MasterDevice::getData(ec_ioctl_domain_data_t *data, unsigned int domainIndex,
         unsigned int dataSize, unsigned char *mem)
 {
     data->domain_index = domainIndex;
@@ -1905,13 +1765,13 @@ void Master::getData(ec_ioctl_domain_data_t *data, unsigned int domainIndex,
     if (ioctl(fd, EC_IOCTL_DOMAIN_DATA, data) < 0) {
         stringstream err;
         err << "Failed to get domain data: " << strerror(errno);
-        throw MasterException(err.str());
+        throw MasterDeviceException(err.str());
     }
 }
 
 /****************************************************************************/
 
-void Master::getSlave(ec_ioctl_slave_t *slave, uint16_t slaveIndex)
+void MasterDevice::getSlave(ec_ioctl_slave_t *slave, uint16_t slaveIndex)
 {
     slave->position = slaveIndex;
 
@@ -1922,13 +1782,13 @@ void Master::getSlave(ec_ioctl_slave_t *slave, uint16_t slaveIndex)
             err << "Slave " << slaveIndex << " does not exist!";
         else
             err << strerror(errno);
-        throw MasterException(err.str());
+        throw MasterDeviceException(err.str());
     }
 }
 
 /****************************************************************************/
 
-void Master::getFmmu(
+void MasterDevice::getFmmu(
         ec_ioctl_domain_fmmu_t *fmmu,
         unsigned int domainIndex,
         unsigned int fmmuIndex
@@ -1946,13 +1806,13 @@ void Master::getFmmu(
                 << " FMMus!";
         else
             err << strerror(errno);
-        throw MasterException(err.str());
+        throw MasterDeviceException(err.str());
     }
 }
 
 /****************************************************************************/
 
-void Master::getSync(
+void MasterDevice::getSync(
         ec_ioctl_slave_sync_t *sync,
         uint16_t slaveIndex,
         uint8_t syncIndex
@@ -1970,13 +1830,13 @@ void Master::getSync(
                 << " sync managers!";
         else
             err << strerror(errno);
-        throw MasterException(err.str());
+        throw MasterDeviceException(err.str());
     }
 }
 
 /****************************************************************************/
 
-void Master::getPdo(
+void MasterDevice::getPdo(
         ec_ioctl_slave_sync_pdo_t *pdo,
         uint16_t slaveIndex,
         uint8_t syncIndex,
@@ -1998,13 +1858,13 @@ void Master::getPdo(
                 << pdoPos + 1 << " Pdos!" << endl;
         else
             err << strerror(errno);
-        throw MasterException(err.str());
+        throw MasterDeviceException(err.str());
     }
 }
 
 /****************************************************************************/
 
-void Master::getPdoEntry(
+void MasterDevice::getPdoEntry(
         ec_ioctl_slave_sync_pdo_entry_t *entry,
         uint16_t slaveIndex,
         uint8_t syncIndex,
@@ -2030,13 +1890,13 @@ void Master::getPdoEntry(
                 << " entries!" << endl;
         else
             err << strerror(errno);
-        throw MasterException(err.str());
+        throw MasterDeviceException(err.str());
     }
 }
 
 /****************************************************************************/
 
-void Master::getSdo(
+void MasterDevice::getSdo(
         ec_ioctl_slave_sdo_t *sdo,
         uint16_t slaveIndex,
         uint16_t sdoPosition
@@ -2054,13 +1914,13 @@ void Master::getSdo(
                 << endl;
         else
             err << strerror(errno);
-        throw MasterException(err.str());
+        throw MasterDeviceException(err.str());
     }
 }
 
 /****************************************************************************/
 
-void Master::getSdoEntry(
+void MasterDevice::getSdoEntry(
         ec_ioctl_slave_sdo_entry_t *entry,
         uint16_t slaveIndex,
         int sdoSpec,
@@ -2075,13 +1935,40 @@ void Master::getSdoEntry(
         stringstream err;
         err << "Failed to get Sdo entry: ";
         err << strerror(errno);
-        throw MasterException(err.str());
+        throw MasterDeviceException(err.str());
+    }
+}
+
+/****************************************************************************/
+
+void MasterDevice::readSii(
+        ec_ioctl_slave_sii_t *data
+        )
+{
+    if (ioctl(fd, EC_IOCTL_SLAVE_SII_READ, data) < 0) {
+        stringstream err;
+        err << "Failed to read SII: " << strerror(errno);
+        throw MasterDeviceException(err.str());
+    }
+}
+
+/****************************************************************************/
+
+void MasterDevice::writeSii(
+        ec_ioctl_slave_sii_t *data
+        )
+{
+    if (ioctl(fd, EC_IOCTL_SLAVE_SII_WRITE, data) < 0) {
+        stringstream err;
+        err << "Failed to write SII: " << strerror(errno);
+        throw MasterDeviceException(err.str());
     }
 }
 
 /****************************************************************************/
 
-void Master::requestState(
+#if 0
+void MasterDevice::requestState(
         uint16_t slavePosition,
         uint8_t state
         )
@@ -2098,7 +1985,7 @@ void Master::requestState(
             err << "Slave " << slavePosition << " does not exist!";
         else
             err << strerror(errno);
-        throw MasterException(err.str());
+        throw MasterDeviceException(err.str());
     }
 }
 
@@ -2130,46 +2017,5 @@ void Master::printRawData(
     cout << endl;
 }
 
-/*****************************************************************************/
-
-/**
- * Calculates the SII checksum field.
- *
- * The checksum is generated with the polynom x^8+x^2+x+1 (0x07) and an
- * initial value of 0xff (see IEC 61158-6-12 ch. 5.4).
- *
- * The below code was originally generated with PYCRC
- * http://www.tty1.net/pycrc
- *
- * ./pycrc.py --width=8 --poly=0x07 --reflect-in=0 --xor-in=0xff
- *   --reflect-out=0 --xor-out=0 --generate c --algorithm=bit-by-bit
- *
- * \return CRC8
- */
-uint8_t Master::calcSiiCrc(
-        const uint8_t *data, /**< pointer to data */
-        size_t length /**< number of bytes in \a data */
-        )
-{
-    unsigned int i;
-    uint8_t bit, byte, crc = 0x48;
-
-    while (length--) {
-        byte = *data++;
-        for (i = 0; i < 8; i++) {
-            bit = crc & 0x80;
-            crc = (crc << 1) | ((byte >> (7 - i)) & 0x01);
-            if (bit) crc ^= 0x07;
-        }
-    }
-
-    for (i = 0; i < 8; i++) {
-        bit = crc & 0x80;
-        crc <<= 1;
-        if (bit) crc ^= 0x07;
-    }
-
-    return crc;
-}
-
+#endif
 /*****************************************************************************/
diff --git a/tool/Master.h b/tool/MasterDevice.h
similarity index 67%
rename from tool/Master.h
rename to tool/MasterDevice.h
index 9ba2327900838c85fd407487cfcfd2421e89fc71..a6e844d0f8009e91ba15c064b474970c681b3457 100644
--- a/tool/Master.h
+++ b/tool/MasterDevice.h
@@ -18,72 +18,32 @@ using namespace std;
 
 /****************************************************************************/
 
-class MasterException:
+class MasterDeviceException:
     public runtime_error
 {
     public:
         /** Constructor with std::string parameter. */
-        MasterException(
+        MasterDeviceException(
                 const string &s /**< Message. */
                 ): runtime_error(s) {}
-
-        /** Constructor with const char pointer parameter. */
-        MasterException(
-                const char *s /**< Message. */
-                ): runtime_error(s) {}
 };
 
 /****************************************************************************/
 
-class Master
+class MasterDevice
 {
     public:
-        Master();
-        ~Master();
+        MasterDevice();
+        ~MasterDevice();
 
         void setIndex(unsigned int);
 
-        enum Verbosity {
-            Quiet,
-            Normal,
-            Verbose
-        };
-        void setVerbosity(Verbosity);
-
-        void writeAlias(int, bool, const vector<string> &);
-        void showConfigs();
-        void outputData(int);
-        void setDebug(const vector<string> &);
-        void showDomains(int);
-        void showMaster();
-        void listPdos(int);
-        void listSdos(int);
-        void sdoDownload(int, const string &, const vector<string> &);
-        void sdoUpload(int, const string &, const vector<string> &);
-        void showSlaves(int);
-        void siiRead(int);
-        void siiWrite(int, bool, const vector<string> &);
-        void requestStates(int, const vector<string> &);
-        void generateXml(int);
-
-    protected:
         enum Permissions {Read, ReadWrite};
         void open(Permissions);
         void close();
 
-        void writeSlaveAlias(uint16_t, uint16_t);
-        typedef list<ec_ioctl_config_t> ConfigList;
-        void showDetailedConfigs(const ConfigList &);
-        void listConfigs(const ConfigList &);
-        void outputDomainData(unsigned int);
-        enum {BreakAfterBytes = 16};
-        void showDomain(unsigned int);
-        void listSlavePdos(uint16_t, bool = false);
-        void listSlaveSdos(uint16_t, bool = false);
-        void listSlaves(int);
-        void showSlave(uint16_t);
-        void generateSlaveXml(uint16_t);
         unsigned int slaveCount();
+
         void getMaster(ec_ioctl_master_t *);
         void getConfig(ec_ioctl_config_t *, unsigned int);
         void getConfigPdo(ec_ioctl_config_pdo_t *, unsigned int, uint8_t,
@@ -102,17 +62,30 @@ class Master
                 uint8_t, uint8_t);
         void getSdo(ec_ioctl_slave_sdo_t *, uint16_t, uint16_t);
         void getSdoEntry(ec_ioctl_slave_sdo_entry_t *, uint16_t, int, uint8_t);
+        void readSii(ec_ioctl_slave_sii_t *);
+        void writeSii(ec_ioctl_slave_sii_t *);
+
+    protected:
+#if 0
+        void outputDomainData(unsigned int);
+        enum {BreakAfterBytes = 16};
+        void showDomain(unsigned int);
+        void listSlavePdos(uint16_t, bool = false);
+        void listSlaveSdos(uint16_t, bool = false);
+        void listSlaves(int);
+        void showSlave(uint16_t);
+        void generateSlaveXml(uint16_t);
         void requestState(uint16_t, uint8_t);
 
         static string slaveState(uint8_t);
         static void printRawData(const uint8_t *, unsigned int);
         static uint8_t calcSiiCrc(const uint8_t *, unsigned int);
+#endif
         
     private:
-        enum {DefaultBufferSize = 1024};
+        //enum {DefaultBufferSize = 1024};
 
         unsigned int index;
-        Verbosity verbosity;
         int fd;
 };
 
diff --git a/tool/cmd_alias.cpp b/tool/cmd_alias.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..9b821845b1570ff0a05d076c4a36b1f24e3a006b
--- /dev/null
+++ b/tool/cmd_alias.cpp
@@ -0,0 +1,181 @@
+/*****************************************************************************
+ *
+ * $Id$
+ *
+ ****************************************************************************/
+
+#include <iostream>
+#include <iomanip>
+#include <sstream>
+using namespace std;
+
+#include "globals.h"
+
+/*****************************************************************************/
+
+const char *help_alias =
+    "[OPTIONS] <ALIAS>\n"
+    "\n"
+    "Write the secondary slave address (alias) for either\n"
+    "one or for multiple slaves.\n"
+    "\n"
+    "Arguments:\n"
+    "  ALIAS must be a 16 bit unsigned integer, specified\n"
+    "        either in decimal (no prefix), octal (prefix '0')\n"
+    "        or hexadecimal (prefix '0x').\n"
+    "\n"
+    "Command-specific options:\n"
+    "  -s <SLAVE>  Write the alias of the slave with the given\n"
+    "              ring position. If this option is not\n"
+    "              specified, the alias of all slaves is set.\n"
+    "              The --force option is required in this\n"
+    "              case.\n";
+
+/*****************************************************************************/
+
+void writeSlaveAlias(uint16_t, uint16_t);
+
+/*****************************************************************************/
+
+/** Writes the Secondary slave address (alias) to the slave's SII.
+ */
+void command_alias(void)
+{
+    uint16_t alias;
+    stringstream err, strAlias;
+    int number;
+    unsigned int numSlaves, i;
+
+    if (commandArgs.size() != 1) {
+        err << "'" << command << "' takes exactly one argument!";
+        throw InvalidUsageException(err);
+    }
+
+    strAlias << commandArgs[0];
+    strAlias
+        >> resetiosflags(ios::basefield) // guess base from prefix
+        >> number;
+    if (strAlias.fail() || number < 0x0000 || number > 0xffff) {
+        err << "Invalid alias '" << commandArgs[0] << "'!";
+        throw InvalidUsageException(err);
+    }
+    alias = number;
+
+    if (slavePosition == -1) {
+        if (!force) {
+            err << "This will write the alias addresses of all slaves to "
+                << alias << "! Please specify --force to proceed.";
+            throw ExecutionFailureException(err);
+        }
+
+        masterDev.open(MasterDevice::ReadWrite);
+        numSlaves = masterDev.slaveCount();
+
+        for (i = 0; i < numSlaves; i++) {
+            writeSlaveAlias(i, alias);
+        }
+    } else {
+        masterDev.open(MasterDevice::ReadWrite);
+        writeSlaveAlias(slavePosition, alias);
+    }
+}
+
+/*****************************************************************************/
+
+/** Calculates the SII checksum field.
+ *
+ * The checksum is generated with the polynom x^8+x^2+x+1 (0x07) and an
+ * initial value of 0xff (see IEC 61158-6-12 ch. 5.4).
+ *
+ * The below code was originally generated with PYCRC
+ * http://www.tty1.net/pycrc
+ *
+ * ./pycrc.py --width=8 --poly=0x07 --reflect-in=0 --xor-in=0xff
+ *   --reflect-out=0 --xor-out=0 --generate c --algorithm=bit-by-bit
+ *
+ * \return CRC8
+ */
+uint8_t calcSiiCrc(
+        const uint8_t *data, /**< pointer to data */
+        size_t length /**< number of bytes in \a data */
+        )
+{
+    unsigned int i;
+    uint8_t bit, byte, crc = 0x48;
+
+    while (length--) {
+        byte = *data++;
+        for (i = 0; i < 8; i++) {
+            bit = crc & 0x80;
+            crc = (crc << 1) | ((byte >> (7 - i)) & 0x01);
+            if (bit) crc ^= 0x07;
+        }
+    }
+
+    for (i = 0; i < 8; i++) {
+        bit = crc & 0x80;
+        crc <<= 1;
+        if (bit) crc ^= 0x07;
+    }
+
+    return crc;
+}
+
+/*****************************************************************************/
+
+/** Writes the Secondary slave address (alias) to the slave's SII.
+ */
+void writeSlaveAlias(
+        uint16_t slavePosition,
+        uint16_t alias
+        )
+{
+    ec_ioctl_slave_sii_t data;
+    ec_ioctl_slave_t slave;
+    stringstream err;
+    uint8_t crc;
+
+    masterDev.getSlave(&slave, slavePosition);
+
+    if (slave.sii_nwords < 8) {
+        err << "Current SII contents are too small to set an alias "
+            << "(" << slave.sii_nwords << " words)!";
+        throw ExecutionFailureException(err);
+    }
+
+    // read first 8 SII words
+    data.slave_position = slavePosition;
+    data.offset = 0;
+    data.nwords = 8;
+    data.words = new uint16_t[data.nwords];
+
+    try {
+        masterDev.readSii(&data);
+    } catch (MasterDeviceException &e) {
+        delete [] data.words;
+        err << "Failed to read SII: " << e.what();
+        throw ExecutionFailureException(err);
+    }
+
+    // write new alias address in word 4
+    data.words[4] = cputole16(alias);
+
+    // calculate checksum over words 0 to 6
+    crc = calcSiiCrc((const uint8_t *) data.words, 14);
+
+    // write new checksum into first byte of word 7
+    *(uint8_t *) (data.words + 7) = crc;
+
+    // write first 8 words with new alias and checksum
+    try {
+        masterDev.writeSii(&data);
+    } catch (MasterDeviceException &e) {
+        delete [] data.words;
+        err << "Failed to read SII: " << e.what();
+        throw ExecutionFailureException(err);
+    }
+
+    delete [] data.words;
+}
+
+/*****************************************************************************/
diff --git a/tool/cmd_config.cpp b/tool/cmd_config.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..ff0e6b716872e81bfcd016329c84f7f7a4c39d36
--- /dev/null
+++ b/tool/cmd_config.cpp
@@ -0,0 +1,237 @@
+/*****************************************************************************
+ *
+ * $Id$
+ *
+ ****************************************************************************/
+
+#include <list>
+#include <iostream>
+#include <iomanip>
+#include <sstream>
+using namespace std;
+
+#include "globals.h"
+
+/*****************************************************************************/
+
+const char *help_config =
+    "[OPTIONS]\n"
+    "\n"
+    "\n"
+    "Command-specific options:\n";
+
+/*****************************************************************************/
+
+struct ConfigInfo {
+    string alias;
+    string pos;
+    string ident;
+    string att;
+    string op;
+};
+
+typedef list<ec_ioctl_config_t> ConfigList;
+
+void showDetailedConfigs(const ConfigList &configList);
+void listConfigs(const ConfigList &configList);
+
+/*****************************************************************************/
+
+bool operator<(const ec_ioctl_config_t &a, const ec_ioctl_config_t &b)
+{
+    return a.alias < b.alias
+        || (a.alias == b.alias && a.position < b.position);
+}
+
+/*****************************************************************************/
+
+/** Lists the bus configuration.
+ */
+void command_config(void)
+{
+    ec_ioctl_master_t master;
+    unsigned int i;
+    ec_ioctl_config_t config;
+    ConfigList configList;
+
+    masterDev.open(MasterDevice::Read);
+    masterDev.getMaster(&master);
+
+    for (i = 0; i < master.config_count; i++) {
+        masterDev.getConfig(&config, i);
+        configList.push_back(config);
+    }
+
+    configList.sort();
+
+    if (verbosity == Verbose) {
+        showDetailedConfigs(configList);
+    } else {
+        listConfigs(configList);
+    }
+}
+
+/*****************************************************************************/
+
+/** Lists the complete bus configuration.
+ */
+void showDetailedConfigs(const ConfigList &configList)
+{
+    ConfigList::const_iterator configIter;
+    unsigned int j, k, l;
+    ec_ioctl_config_pdo_t pdo;
+    ec_ioctl_config_pdo_entry_t entry;
+    ec_ioctl_config_sdo_t sdo;
+
+    for (configIter = configList.begin();
+            configIter != configList.end();
+            configIter++) {
+
+        cout << "Alias: "
+            << dec << configIter->alias << endl
+            << "Position: " << configIter->position << endl
+            << "Vendor Id: 0x"
+            << hex << setfill('0')
+            << setw(8) << configIter->vendor_id << endl
+            << "Product code: 0x"
+            << setw(8) << configIter->product_code << endl
+            << "Attached: " << (configIter->attached ? "yes" : "no") << endl
+            << "Operational: " << (configIter->operational ? "yes" : "no") << endl;
+
+        for (j = 0; j < EC_MAX_SYNC_MANAGERS; j++) {
+            if (configIter->syncs[j].pdo_count) {
+                cout << "SM" << dec << j << " ("
+                    << (configIter->syncs[j].dir == EC_DIR_INPUT
+                            ? "Input" : "Output") << ")" << endl;
+                for (k = 0; k < configIter->syncs[j].pdo_count; k++) {
+                    masterDev.getConfigPdo(&pdo, configIter->config_index, j, k);
+
+                    cout << "  Pdo 0x" << hex
+                        << setw(4) << pdo.index
+                        << " \"" << pdo.name << "\"" << endl;
+
+                    for (l = 0; l < pdo.entry_count; l++) {
+                        masterDev.getConfigPdoEntry(&entry,
+                                configIter->config_index, j, k, l);
+
+                        cout << "    Pdo entry 0x" << hex
+                            << setw(4) << entry.index << ":"
+                            << setw(2) << (unsigned int) entry.subindex
+                            << ", " << dec << (unsigned int) entry.bit_length
+                            << " bit, \"" << entry.name << "\"" << endl;
+                    }
+                }
+            }
+        }
+
+        cout << "Sdo configuration:" << endl;
+        if (configIter->sdo_count) {
+            for (j = 0; j < configIter->sdo_count; j++) {
+                masterDev.getConfigSdo(&sdo, configIter->config_index, j);
+
+                cout << "  0x"
+                    << hex << setfill('0')
+                    << setw(4) << sdo.index << ":"
+                    << setw(2) << (unsigned int) sdo.subindex
+                    << ", " << dec << sdo.size << " byte: " << hex;
+
+                switch (sdo.size) {
+                    case 1:
+                        cout << "0x" << setw(2)
+                            << (unsigned int) *(uint8_t *) &sdo.data;
+                        break;
+                    case 2:
+                        cout << "0x" << setw(4)
+                            << le16tocpu(*(uint16_t *) &sdo.data);
+                        break;
+                    case 4:
+                        cout << "0x" << setw(8)
+                            << le32tocpu(*(uint32_t *) &sdo.data);
+                        break;
+                    default:
+                        cout << "???";
+                }
+
+                cout << endl;
+            }
+        } else {
+            cout << "  None." << endl;
+        }
+
+        cout << endl;
+    }
+}
+
+/*****************************************************************************/
+
+/** Lists the bus configuration.
+ */
+void listConfigs(const ConfigList &configList)
+{
+    ConfigList::const_iterator configIter;
+    stringstream str;
+    ConfigInfo info;
+    typedef list<ConfigInfo> ConfigInfoList;
+    ConfigInfoList list;
+    ConfigInfoList::const_iterator iter;
+    unsigned int maxAliasWidth = 0, maxPosWidth = 0,
+                 maxAttWidth = 0, maxOpWidth = 0;
+
+    for (configIter = configList.begin();
+            configIter != configList.end();
+            configIter++) {
+
+        str << dec << configIter->alias;
+        info.alias = str.str();
+        str.clear();
+        str.str("");
+
+        str << configIter->position;
+        info.pos = str.str();
+        str.clear();
+        str.str("");
+
+        str << hex << setfill('0')
+            << "0x" << setw(8) << configIter->vendor_id
+            << "/0x" << setw(8) << configIter->product_code;
+        info.ident = str.str();
+        str.clear();
+        str.str("");
+
+        str << (configIter->attached ? "attached" : "-");
+        info.att = str.str();
+        str.clear();
+        str.str("");
+
+        str << (configIter->operational ? "operational" : "-");
+        info.op = str.str();
+        str.clear();
+        str.str("");
+
+        list.push_back(info);
+
+        if (info.alias.length() > maxAliasWidth)
+            maxAliasWidth = info.alias.length();
+        if (info.pos.length() > maxPosWidth)
+            maxPosWidth = info.pos.length();
+        if (info.att.length() > maxAttWidth)
+            maxAttWidth = info.att.length();
+        if (info.op.length() > maxOpWidth)
+            maxOpWidth = info.op.length();
+    }
+
+    for (iter = list.begin(); iter != list.end(); iter++) {
+        cout << setfill(' ') << right
+            << setw(maxAliasWidth) << iter->alias
+            << ":" << left
+            << setw(maxPosWidth) << iter->pos
+            << "  "
+            << iter->ident
+            << "  "
+            << setw(maxAttWidth) << iter->att << "  "
+            << setw(maxOpWidth) << iter->op << "  "
+            << endl;
+    }
+}
+
+/*****************************************************************************/
diff --git a/tool/globals.h b/tool/globals.h
new file mode 100644
index 0000000000000000000000000000000000000000..31e0647646d147909aa8009a2b7ae36bd266bb16
--- /dev/null
+++ b/tool/globals.h
@@ -0,0 +1,89 @@
+/*****************************************************************************
+ *
+ * $Id$
+ *
+ ****************************************************************************/
+
+#include <sys/types.h>
+
+#include <string>
+#include <sstream>
+#include <vector>
+using namespace std;
+
+#include "MasterDevice.h"
+
+/*****************************************************************************/
+
+enum Verbosity {
+    Quiet,
+    Normal,
+    Verbose
+};
+
+extern string command;
+extern int slavePosition;
+extern int domainIndex;
+extern vector<string> commandArgs;
+extern Verbosity verbosity;
+extern string dataTypeStr;
+extern bool force;
+
+extern MasterDevice masterDev;
+
+/****************************************************************************/
+
+class InvalidUsageException:
+    public runtime_error
+{
+    public:
+        /** Constructor with std::string parameter. */
+        InvalidUsageException(
+                const stringstream &s /**< Message. */
+                ): runtime_error(s.str()) {}
+};
+
+/****************************************************************************/
+
+class ExecutionFailureException:
+    public runtime_error
+{
+    public:
+        /** Constructor with std::string parameter. */
+        ExecutionFailureException(
+                const stringstream &s /**< Message. */
+                ): runtime_error(s.str()) {}
+};
+
+/*****************************************************************************/
+
+#define swap16(x) \
+        ((uint16_t)( \
+        (((uint16_t)(x) & 0x00ffU) << 8) | \
+        (((uint16_t)(x) & 0xff00U) >> 8) ))
+#define swap32(x) \
+        ((uint32_t)( \
+        (((uint32_t)(x) & 0x000000ffUL) << 24) | \
+        (((uint32_t)(x) & 0x0000ff00UL) <<  8) | \
+        (((uint32_t)(x) & 0x00ff0000UL) >>  8) | \
+        (((uint32_t)(x) & 0xff000000UL) >> 24) ))
+
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+
+#define le16tocpu(x) x
+#define le32tocpu(x) x
+
+#define cputole16(x) x
+#define cputole32(x) x
+
+#elif __BYTE_ORDER == __BIG_ENDIAN
+
+#define le16tocpu(x) swap16(x)
+#define le32tocpu(x) swap32(x)
+
+#define cputole16(x) swap16(x)
+#define cputole32(x) swap32(x)
+
+#endif
+
+/****************************************************************************/
diff --git a/tool/main.cpp b/tool/main.cpp
index 4418ff6b4bda1ef59fb0d26176b74ce0751b6064..c9f73eaa4df6c8badf826a7b35ce06b0cfdbcd27 100644
--- a/tool/main.cpp
+++ b/tool/main.cpp
@@ -12,29 +12,93 @@
 #include <vector>
 using namespace std;
 
-#include "Master.h"
+#include "globals.h"
 
 /*****************************************************************************/
 
-#define DEFAULT_MASTER 0
-
-static string cmdName;
-static unsigned int masterIndex = DEFAULT_MASTER;
-static int slavePosition = -1;
-static int domainIndex = -1;
-static string command;
+string binaryBaseName;
+unsigned int masterIndex = 0;
+int slavePosition = -1;
+int domainIndex = -1;
+string command;
 vector<string> commandArgs;
-static Master::Verbosity verbosity = Master::Normal;
+Verbosity verbosity = Normal;
 string dataTypeStr;
 bool force = false;
+
 bool helpRequested = false;
 
+MasterDevice masterDev;
+
+/*****************************************************************************/
+
+struct Command {
+    void (*func)(void);
+    const char *helpString;
+
+    int execute(void) const;
+    void displayHelp(void) const;
+};
+
+struct CommandAlias {
+    const char *name;
+    const Command *command;
+};
+
+/*****************************************************************************/
+
+#define COMMAND(name) \
+    void command_##name(void); \
+    extern const char *help_##name; \
+    const Command cmd_##name = {command_##name, help_##name};
+
+COMMAND(alias);
+COMMAND(config);
+
+const CommandAlias commandAliases[] = {
+    {"alias",  &cmd_alias},
+
+    {"config", &cmd_config},
+    {"conf",   &cmd_config},
+    {"cf",     &cmd_config},
+};
+
+#if 0
+        } else if (command == "data") {
+            master.outputData(domainIndex);
+        } else if (command == "debug") {
+            master.setDebug(commandArgs);
+        } else if (command == "domain") {
+            master.showDomains(domainIndex);
+		} else if (command == "master") {
+            master.showMaster();
+        } else if (command == "pdos") {
+            master.listPdos(slavePosition);
+        } else if (command == "sdos") {
+            master.listSdos(slavePosition);
+        } else if (command == "sdo_download" || command == "sd") {
+            master.sdoDownload(slavePosition, dataTypeStr, commandArgs);
+        } else if (command == "sdo_upload" || command == "su") {
+            master.sdoUpload(slavePosition, dataTypeStr, commandArgs);
+		} else if (command == "slave" || command == "slaves"
+                || command == "list" || command == "ls") {
+            master.showSlaves(slavePosition);
+        } else if (command == "sii_read" || command == "sr") {
+            master.siiRead(slavePosition);
+        } else if (command == "sii_write" || command == "sw") {
+            master.siiWrite(slavePosition, force, commandArgs);
+        } else if (command == "state") {
+            master.requestStates(slavePosition, commandArgs);
+        } else if (command == "xml") {
+            master.generateXml(slavePosition);
+#endif
+
 /*****************************************************************************/
 
 void printUsage()
 {
     cerr
-        << "Usage: " << cmdName << " <COMMAND> [OPTIONS]" << endl
+        << "Usage: " << binaryBaseName << " <COMMAND> [OPTIONS]" << endl
 		<< "Commands:" << endl
         << "  alias         Write alias addresses." << endl
         << "  config        Show bus configuration." << endl
@@ -52,8 +116,8 @@ void printUsage()
         << "  state         Request slave states." << endl
         << "  xml           Generate slave information xmls." << endl
 		<< "Global options:" << endl
-        << "  --master  -m <master>  Index of the master to use. Default: "
-		<< DEFAULT_MASTER << endl
+        << "  --master  -m <master>  Index of the master to use. Default: 0"
+		<< endl
         << "  --slave   -s <index>   Positive numerical ring position,"
         << endl
         << "                         or 'all' for all slaves (default)."
@@ -67,8 +131,8 @@ void printUsage()
         << "  --quiet   -q           Output less information." << endl
         << "  --verbose -v           Output more information." << endl
         << "  --help    -h           Show this help." << endl
-        << "Call '" << cmdName << " <COMMAND> --help' for command-specific "
-        << "help." << endl
+        << "Call '" << binaryBaseName
+        << " <COMMAND> --help' for command-specific help." << endl
         << "Send bug reports to " << PACKAGE_BUGREPORT << "." << endl;
 }
 
@@ -146,11 +210,11 @@ void getOptions(int argc, char **argv)
                 break;
 
             case 'q':
-                verbosity = Master::Quiet;
+                verbosity = Quiet;
                 break;
 
             case 'v':
-                verbosity = Master::Verbose;
+                verbosity = Verbose;
                 break;
 
             case 'h':
@@ -184,60 +248,64 @@ void getOptions(int argc, char **argv)
 
 /****************************************************************************/
 
+int Command::execute() const
+{
+    try {
+        func();
+    } catch (InvalidUsageException &e) {
+        cerr << e.what() << endl << endl;
+        displayHelp();
+        return 1;
+    } catch (ExecutionFailureException &e) {
+        cerr << e.what() << endl;
+        return 1;
+    } catch (MasterDeviceException &e) {
+        cerr << e.what() << endl;
+        return 1;
+    }
+
+    return 0;
+}
+
+/****************************************************************************/
+
+void Command::displayHelp() const
+{
+    cerr << binaryBaseName << " " << command << " " << helpString;
+}
+
+/****************************************************************************/
+
 int main(int argc, char **argv)
 {
-    Master master;
+    int retval = 0;
+    const CommandAlias *alias;
+    const CommandAlias *endAlias =
+        commandAliases + sizeof(commandAliases) / sizeof(CommandAlias);
 
-    cmdName = basename(argv[0]);
-    
+    binaryBaseName = basename(argv[0]);
 	getOptions(argc, argv);
 
-    master.setIndex(masterIndex);
-    master.setVerbosity(verbosity);
+    // search command alias in alias map
+    for (alias = commandAliases; alias < endAlias; alias++) {
+        if (command == alias->name)
+            break;
+    }
 
-    try {
-        if (command == "alias") {
-            master.writeAlias(slavePosition, force, commandArgs);
-        } else if (command == "config") {
-            master.showConfigs();
-        } else if (command == "data") {
-            master.outputData(domainIndex);
-        } else if (command == "debug") {
-            master.setDebug(commandArgs);
-        } else if (command == "domain") {
-            master.showDomains(domainIndex);
-		} else if (command == "master") {
-            master.showMaster();
-        } else if (command == "pdos") {
-            master.listPdos(slavePosition);
-        } else if (command == "sdos") {
-            master.listSdos(slavePosition);
-        } else if (command == "sdo_download" || command == "sd") {
-            master.sdoDownload(slavePosition, dataTypeStr, commandArgs);
-        } else if (command == "sdo_upload" || command == "su") {
-            master.sdoUpload(slavePosition, dataTypeStr, commandArgs);
-		} else if (command == "slave" || command == "slaves"
-                || command == "list" || command == "ls") {
-            master.showSlaves(slavePosition);
-        } else if (command == "sii_read" || command == "sr") {
-            master.siiRead(slavePosition);
-        } else if (command == "sii_write" || command == "sw") {
-            master.siiWrite(slavePosition, force, commandArgs);
-        } else if (command == "state") {
-            master.requestStates(slavePosition, commandArgs);
-        } else if (command == "xml") {
-            master.generateXml(slavePosition);
+    if (alias < endAlias) { // command alias found
+        if (!helpRequested) {
+            masterDev.setIndex(masterIndex);
+            retval = alias->command->execute();
         } else {
-            cerr << "Unknown command " << command << "!" << endl;
-            printUsage();
-            exit(1);
+            alias->command->displayHelp();
         }
-    } catch (MasterException &e) {
-        cerr << e.what() << endl;
-        exit(1);
+    } else { // command not found
+        cerr << "Unknown command " << command << "!" << endl << endl;
+        printUsage();
+        retval = 1;
     }
 
-	return 0;
+	return retval;
 }
 
 /****************************************************************************/