diff -Nru -X create_patch-2526-c_dc_helpers.exclude etherlabmaster-1.5.2-2526/include/ecrt.h etherlabmaster-1.5.2-2526-c_dc_helpers/include/ecrt.h
--- etherlabmaster-1.5.2-2526/include/ecrt.h	2013-04-03 13:46:38.000000000 +1300
+++ etherlabmaster-1.5.2-2526-c_dc_helpers/include/ecrt.h	2013-04-04 18:41:14.000000000 +1300
@@ -662,6 +662,20 @@
         ec_master_t *master /**< EtherCAT master. */
         );
 
+/** setup the domain's process data memory.
+ *
+ * Call this after all PDO entries have been registered and before activating
+ * the master.
+ *
+ * Call this if you need to access the domain memory before activating the 
+ * master
+ *
+ * \return 0 on success, else non-zero.
+ */
+int ecrt_master_setup_domain_memory(
+        ec_master_t *master /**< EtherCAT master. */
+        );
+
 /** Obtains a slave configuration.
  *
  * Creates a slave configuration object for the given \a alias and \a position
@@ -920,6 +934,19 @@
         ec_master_t *master /**< EtherCAT master. */
         );
 
+/** Deactivates the slaves distributed clocks and sends the slaves into PREOP.
+ * 
+ * This can be called prior to ecrt_master_deactivate to avoid the slaves 
+ * getting sync errors.
+ *
+ * This method should be called in realtime context.
+ * 
+ * Note: EoE slaves will not be changed to PREOP.
+ */
+void ecrt_master_deactivate_slaves(
+        ec_master_t *master /**< EtherCAT master. */
+        );
+
 /** Deactivates the master.
  *
  * Removes the bus configuration. All objects created by
diff -Nru -X create_patch-2526-c_dc_helpers.exclude etherlabmaster-1.5.2-2526/lib/master.c etherlabmaster-1.5.2-2526-c_dc_helpers/lib/master.c
--- etherlabmaster-1.5.2-2526/lib/master.c	2013-04-03 13:46:38.000000000 +1300
+++ etherlabmaster-1.5.2-2526-c_dc_helpers/lib/master.c	2013-04-04 19:55:32.000000000 +1300
@@ -532,6 +532,48 @@
 
 /****************************************************************************/
 
+int ecrt_master_setup_domain_memory(ec_master_t *master)
+{
+    ec_ioctl_master_activate_t io;
+    int ret;
+
+    ret = ioctl(master->fd, EC_IOCTL_SETUP_DOMAIN_MEMORY, &io);
+    if (EC_IOCTL_IS_ERROR(ret)) {
+        fprintf(stderr, "Failed to activate master: %s\n",
+                strerror(EC_IOCTL_ERRNO(ret)));
+        return -EC_IOCTL_ERRNO(ret);
+    }
+
+    // will return 0 process_data_size if domain data has already been set up
+    if (io.process_data_size) {
+        master->process_data_size = io.process_data_size;
+
+#ifdef USE_RTDM
+        /* memory-mapping was already done in kernel. The user-space addess is
+         * provided in the ioctl data.
+         */
+        master->process_data = io.process_data;
+#else
+        master->process_data = mmap(0, master->process_data_size,
+                PROT_READ | PROT_WRITE, MAP_SHARED, master->fd, 0);
+        if (master->process_data == MAP_FAILED) {
+            fprintf(stderr, "Failed to map process data: %s\n",
+                    strerror(errno));
+            master->process_data = NULL;
+            master->process_data_size = 0;
+            return -errno;
+        }
+#endif
+
+        // Access the mapped region to cause the initial page fault
+        master->process_data[0] = 0x00;
+    }
+
+    return 0;
+}
+
+/*****************************************************************************/
+
 int ecrt_master_activate(ec_master_t *master)
 {
     ec_ioctl_master_activate_t io;
@@ -544,9 +586,10 @@
         return -EC_IOCTL_ERRNO(ret);
     }
 
-    master->process_data_size = io.process_data_size;
+    // will return 0 process_data_size if domain data has already been set up
+    if (io.process_data_size) {
+        master->process_data_size = io.process_data_size;
 
-    if (master->process_data_size) {
 #ifdef USE_RTDM
         /* memory-mapping was already done in kernel. The user-space addess is
          * provided in the ioctl data.
@@ -573,6 +616,20 @@
 
 /****************************************************************************/
 
+void ecrt_master_deactivate_slaves(ec_master_t *master)
+{
+    int ret;
+
+    ret = ioctl(master->fd, EC_IOCTL_DEACTIVATE_SLAVES, NULL);
+    if (EC_IOCTL_IS_ERROR(ret)) {
+        fprintf(stderr, "Failed to deactivate slaves: %s\n",
+                strerror(EC_IOCTL_IS_ERROR(ret)));
+        return;
+    }
+}
+
+/*****************************************************************************/
+
 void ecrt_master_deactivate(ec_master_t *master)
 {
     int ret;
diff -Nru -X create_patch-2526-c_dc_helpers.exclude etherlabmaster-1.5.2-2526/master/fsm_master.c etherlabmaster-1.5.2-2526-c_dc_helpers/master/fsm_master.c
--- etherlabmaster-1.5.2-2526/master/fsm_master.c	2013-04-03 13:46:38.000000000 +1300
+++ etherlabmaster-1.5.2-2526-c_dc_helpers/master/fsm_master.c	2013-06-13 11:21:16.000000000 +1200
@@ -48,7 +48,7 @@
 
 /** Time difference [ns] to tolerate without setting a new system time offset.
  */
-#define EC_SYSTEM_TIME_TOLERANCE_NS 1000000
+#define EC_SYSTEM_TIME_TOLERANCE_NS 10000
 
 /*****************************************************************************/
 
@@ -860,11 +860,14 @@
     master->scan_busy = 0;
     wake_up_interruptible(&master->scan_queue);
 
-    ec_master_calc_dc(master);
-
     // Attach slave configurations
     ec_master_attach_slave_configs(master);
 
+    // Set DC ref slave and clac topology and transmission delays
+    // Note: must come after attach_slave_configs for application
+    //       selected dc_ref_config to return its slave
+    ec_master_calc_dc(master);
+
 #ifdef EC_EOE
     // check if EoE processing has to be started
     ec_master_eoe_start(master);
diff -Nru -X create_patch-2526-c_dc_helpers.exclude etherlabmaster-1.5.2-2526/master/ioctl.c etherlabmaster-1.5.2-2526-c_dc_helpers/master/ioctl.c
--- etherlabmaster-1.5.2-2526/master/ioctl.c	2012-11-08 14:27:19.000000000 +1300
+++ etherlabmaster-1.5.2-2526-c_dc_helpers/master/ioctl.c	2013-04-04 20:02:02.000000000 +1300
@@ -1679,11 +1679,11 @@
 
 /*****************************************************************************/
 
-/** Activates the master.
+/** Sets up domain memory.
  *
  * \return Zero on success, otherwise a negative error code.
  */
-static ATTRIBUTES int ec_ioctl_activate(
+static ATTRIBUTES int ec_ioctl_setup_domain_memory(
         ec_master_t *master, /**< EtherCAT master. */
         void *arg, /**< ioctl() argument. */
         ec_ioctl_context_t *ctx /**< Private data structure of file handle. */
@@ -1697,52 +1697,145 @@
     if (unlikely(!ctx->requested))
         return -EPERM;
 
-    io.process_data = NULL;
 
-    /* Get the sum of the domains' process data sizes. */
+    if (!ctx->process_data)
+    {
+        io.process_data = NULL;
 
-    ctx->process_data_size = 0;
+        /* Get the sum of the domains' process data sizes. */
 
-    if (down_interruptible(&master->master_sem))
-        return -EINTR;
+        ctx->process_data_size = 0;
 
-    list_for_each_entry(domain, &master->domains, list) {
-        ctx->process_data_size += ecrt_domain_size(domain);
+        if (down_interruptible(&master->master_sem))
+            return -EINTR;
+    
+        list_for_each_entry(domain, &master->domains, list) {
+            ctx->process_data_size += ecrt_domain_size(domain);
+        }
+    
+        up(&master->master_sem);
+    
+        if (ctx->process_data_size) {
+            ctx->process_data = vmalloc(ctx->process_data_size);
+            if (!ctx->process_data) {
+                ctx->process_data_size = 0;
+                return -ENOMEM;
+            }
+    
+            /* Set the memory as external process data memory for the
+             * domains.
+             */
+            offset = 0;
+            list_for_each_entry(domain, &master->domains, list) {
+                ecrt_domain_external_memory(domain,
+                        ctx->process_data + offset);
+                offset += ecrt_domain_size(domain);
+            }
+
+#ifdef EC_IOCTL_RTDM
+            /* RTDM uses a different approach for memory-mapping, which has to be
+             * initiated by the kernel.
+             */
+            ret = ec_rtdm_mmap(ctx, &io.process_data);
+            if (ret < 0) {
+                EC_MASTER_ERR(master, "Failed to map process data"
+                        " memory to user space (code %i).\n", ret);
+                return ret;
+            }
+#endif
+        }
+
+        io.process_data_size = ctx->process_data_size;
+    }
+    else
+    {
+        io.process_data = NULL;
+        io.process_data_size = 0;
     }
 
-    up(&master->master_sem);
 
-    if (ctx->process_data_size) {
-        ctx->process_data = vmalloc(ctx->process_data_size);
-        if (!ctx->process_data) {
-            ctx->process_data_size = 0;
-            return -ENOMEM;
-        }
+    if (copy_to_user((void __user *) arg, &io,
+                sizeof(ec_ioctl_master_activate_t)))
+        return -EFAULT;
+
+    return 0;
+}
+
+/*****************************************************************************/
+
+/** Activates the master.
+ *
+ * \return Zero on success, otherwise a negative error code.
+ */
+static ATTRIBUTES int ec_ioctl_activate(
+        ec_master_t *master, /**< EtherCAT master. */
+        void *arg, /**< ioctl() argument. */
+        ec_ioctl_context_t *ctx /**< Private data structure of file handle. */
+        )
+{
+    ec_ioctl_master_activate_t io;
+    ec_domain_t *domain;
+    off_t offset;
+    int ret;
 
-        /* Set the memory as external process data memory for the
-         * domains.
-         */
-        offset = 0;
+    if (unlikely(!ctx->requested))
+        return -EPERM;
+
+
+    if (!ctx->process_data)
+    {
+        io.process_data = NULL;
+
+        /* Get the sum of the domains' process data sizes. */
+
+        ctx->process_data_size = 0;
+
+        if (down_interruptible(&master->master_sem))
+            return -EINTR;
+    
         list_for_each_entry(domain, &master->domains, list) {
-            ecrt_domain_external_memory(domain,
-                    ctx->process_data + offset);
-            offset += ecrt_domain_size(domain);
+            ctx->process_data_size += ecrt_domain_size(domain);
         }
+    
+        up(&master->master_sem);
+    
+        if (ctx->process_data_size) {
+            ctx->process_data = vmalloc(ctx->process_data_size);
+            if (!ctx->process_data) {
+                ctx->process_data_size = 0;
+                return -ENOMEM;
+            }
+    
+            /* Set the memory as external process data memory for the
+             * domains.
+             */
+            offset = 0;
+            list_for_each_entry(domain, &master->domains, list) {
+                ecrt_domain_external_memory(domain,
+                        ctx->process_data + offset);
+                offset += ecrt_domain_size(domain);
+            }
 
 #ifdef EC_IOCTL_RTDM
-        /* RTDM uses a different approach for memory-mapping, which has to be
-         * initiated by the kernel.
-         */
-        ret = ec_rtdm_mmap(ctx, &io.process_data);
-        if (ret < 0) {
-            EC_MASTER_ERR(master, "Failed to map process data"
-                    " memory to user space (code %i).\n", ret);
-            return ret;
-        }
+            /* RTDM uses a different approach for memory-mapping, which has to be
+             * initiated by the kernel.
+             */
+            ret = ec_rtdm_mmap(ctx, &io.process_data);
+            if (ret < 0) {
+                EC_MASTER_ERR(master, "Failed to map process data"
+                        " memory to user space (code %i).\n", ret);
+                return ret;
+            }
 #endif
-    }
+        }
 
-    io.process_data_size = ctx->process_data_size;
+        io.process_data_size = ctx->process_data_size;
+    }
+    else
+    {
+        io.process_data = NULL;
+        io.process_data_size = 0;
+    }
 
 #ifndef EC_IOCTL_RTDM
     ecrt_master_callbacks(master, ec_master_internal_send_cb,
@@ -1762,6 +1855,25 @@
 
 /*****************************************************************************/
 
+/** Deactivates the slaves.
+ *
+ * \return Zero on success, otherwise a negative error code.
+ */
+static ATTRIBUTES int ec_ioctl_deactivate_slaves(
+        ec_master_t *master, /**< EtherCAT master. */
+        void *arg, /**< ioctl() argument. */
+        ec_ioctl_context_t *ctx /**< Private data structure of file handle. */
+        )
+{
+    if (unlikely(!ctx->requested))
+        return -EPERM;
+
+    ecrt_master_deactivate_slaves(master);
+    return 0;
+}
+
+/*****************************************************************************/
+
 /** Deactivates the master.
  *
  * \return Zero on success, otherwise a negative error code.
@@ -4253,6 +4365,13 @@
             }
             ret = ec_ioctl_select_ref_clock(master, arg, ctx);
             break;
+        case EC_IOCTL_SETUP_DOMAIN_MEMORY:
+            if (!ctx->writable) {
+                ret = -EPERM;
+                break;
+            }
+            ret = ec_ioctl_setup_domain_memory(master, arg, ctx);
+            break;
         case EC_IOCTL_ACTIVATE:
             if (!ctx->writable) {
                 ret = -EPERM;
@@ -4260,6 +4379,13 @@
             }
             ret = ec_ioctl_activate(master, arg, ctx);
             break;
+        case EC_IOCTL_DEACTIVATE_SLAVES:
+            if (!ctx->writable) {
+                ret = -EPERM;
+                break;
+            }
+            ret = ec_ioctl_deactivate_slaves(master, arg, ctx);
+            break;
         case EC_IOCTL_DEACTIVATE:
             if (!ctx->writable) {
                 ret = -EPERM;
diff -Nru -X create_patch-2526-c_dc_helpers.exclude etherlabmaster-1.5.2-2526/master/ioctl.h etherlabmaster-1.5.2-2526-c_dc_helpers/master/ioctl.h
--- etherlabmaster-1.5.2-2526/master/ioctl.h	2013-04-03 13:46:38.000000000 +1300
+++ etherlabmaster-1.5.2-2526-c_dc_helpers/master/ioctl.h	2013-04-04 19:05:27.000000000 +1300
@@ -97,7 +97,9 @@
 #define EC_IOCTL_CREATE_DOMAIN          EC_IO(0x1f)
 #define EC_IOCTL_CREATE_SLAVE_CONFIG  EC_IOWR(0x20, ec_ioctl_config_t)
 #define EC_IOCTL_SELECT_REF_CLOCK      EC_IOW(0x21, uint32_t)
+#define EC_IOCTL_SETUP_DOMAIN_MEMORY   EC_IOR(0x60, ec_ioctl_master_activate_t)
 #define EC_IOCTL_ACTIVATE              EC_IOR(0x22, ec_ioctl_master_activate_t)
+#define EC_IOCTL_DEACTIVATE_SLAVES      EC_IO(0x61)
 #define EC_IOCTL_DEACTIVATE             EC_IO(0x23)
 #define EC_IOCTL_SEND                   EC_IO(0x24)
 #define EC_IOCTL_RECEIVE                EC_IO(0x25)
diff -Nru -X create_patch-2526-c_dc_helpers.exclude etherlabmaster-1.5.2-2526/master/master.c etherlabmaster-1.5.2-2526-c_dc_helpers/master/master.c
--- etherlabmaster-1.5.2-2526/master/master.c	2013-04-03 13:46:38.000000000 +1300
+++ etherlabmaster-1.5.2-2526-c_dc_helpers/master/master.c	2013-06-13 11:45:21.000000000 +1200
@@ -2026,25 +2026,29 @@
     ec_slave_t *slave, *ref = NULL;
 
     if (master->dc_ref_config) {
-        // Use application-selected reference clock
+        // Check application-selected reference clock
         slave = master->dc_ref_config->slave;
 
         if (slave) {
             if (slave->base_dc_supported && slave->has_dc_system_time) {
                 ref = slave;
+                EC_MASTER_INFO(master, "Using slave %u as application selected"
+                        " DC reference clock.\n", ref->ring_position);
             }
             else {
-                EC_MASTER_WARN(master, "Slave %u can not act as a"
-                        " DC reference clock!", slave->ring_position);
+                EC_MASTER_WARN(master, "Application selected slave %u can not"
+                        " act as a DC reference clock!", slave->ring_position);
             }
         }
         else {
-            EC_MASTER_WARN(master, "DC reference clock config (%u-%u)"
-                    " has no slave attached!\n", master->dc_ref_config->alias,
+            EC_MASTER_WARN(master, "Application selected DC reference clock"
+                    " config (%u-%u) has no slave attached!\n", 
+                    master->dc_ref_config->alias, 
                     master->dc_ref_config->position);
         }
     }
-    else {
+
+    if (!ref) {
         // Use first slave with DC support as reference clock
         for (slave = master->slaves;
                 slave < master->slaves + master->slave_count;
@@ -2261,6 +2265,14 @@
 
 /*****************************************************************************/
 
+int ecrt_master_setup_domain_memory(ec_master_t *master)
+{
+	// not currently supported
+    return -ENOMEM;  // FIXME
+}
+
+/*****************************************************************************/
+
 int ecrt_master_activate(ec_master_t *master)
 {
     uint32_t domain_offset;
@@ -2335,6 +2347,54 @@
 
 /*****************************************************************************/
 
+void ecrt_master_deactivate_slaves(ec_master_t *master)
+{
+    ec_slave_t *slave;
+    ec_slave_config_t *sc, *next;
+#ifdef EC_EOE
+    ec_eoe_t *eoe;
+#endif
+
+    EC_MASTER_DBG(master, 1, "%s(master = 0x%p)\n", __func__, master);
+
+    if (!master->active) {
+        EC_MASTER_WARN(master, "%s: Master not active.\n", __func__);
+        return;
+    }
+
+
+    // clear dc settings on all slaves
+    list_for_each_entry_safe(sc, next, &master->configs, list) {
+        if (sc->dc_assign_activate) {
+            ecrt_slave_config_dc(sc, 0x0000, 0, 0, 0, 0);
+        }
+    }
+    
+    
+    for (slave = master->slaves;
+            slave < master->slaves + master->slave_count;
+            slave++) {
+
+        // set states for all slaves
+        ec_slave_request_state(slave, EC_SLAVE_STATE_PREOP);
+
+        // mark for reconfiguration, because the master could have no
+        // possibility for a reconfiguration between two sequential operation
+        // phases.
+        slave->force_config = 1;
+    }
+
+#ifdef EC_EOE
+    // ... but leave EoE slaves in OP
+    list_for_each_entry(eoe, &master->eoe_handlers, list) {
+        if (ec_eoe_is_open(eoe))
+            ec_slave_request_state(eoe->slave, EC_SLAVE_STATE_OP);
+    }
+#endif
+}
+
+/*****************************************************************************/
+
 void ecrt_master_deactivate(ec_master_t *master)
 {
     ec_slave_t *slave;
@@ -2588,18 +2648,22 @@
 int ecrt_master_select_reference_clock(ec_master_t *master,
         ec_slave_config_t *sc)
 {
-    if (sc) {
-        ec_slave_t *slave = sc->slave;
+    master->dc_ref_config = sc;
 
-        // output an early warning
-        if (slave &&
-                (!slave->base_dc_supported || !slave->has_dc_system_time)) {
-            EC_MASTER_WARN(master, "Slave %u can not act as"
-                    " a reference clock!", slave->ring_position);
-        }
+    if (master->dc_ref_config) {
+        EC_MASTER_INFO(master, "Application selected DC reference clock"
+                " config (%u-%u) set by application.\n",
+                master->dc_ref_config->alias,
+                master->dc_ref_config->position);
+    }
+    else {
+        EC_MASTER_INFO(master, "Application selected DC reference clock"
+                " config cleared by application.\n");
     }
 
-    master->dc_ref_config = sc;
+    // update dc datagrams
+    ec_master_find_dc_ref_clock(master);
+
     return 0;
 }
 
@@ -3226,7 +3290,9 @@
 /** \cond */
 
 EXPORT_SYMBOL(ecrt_master_create_domain);
+EXPORT_SYMBOL(ecrt_master_setup_domain_memory);
 EXPORT_SYMBOL(ecrt_master_activate);
+EXPORT_SYMBOL(ecrt_master_deactivate_slaves);
 EXPORT_SYMBOL(ecrt_master_deactivate);
 EXPORT_SYMBOL(ecrt_master_send);
 EXPORT_SYMBOL(ecrt_master_send_ext);
