From 5252df4e86f31c21367e5166cef01e02233f880f Mon Sep 17 00:00:00 2001
From: Rolf Bork <rolf.bork@ligo.org>
Date: Thu, 13 Sep 2018 17:42:35 +0000
Subject: [PATCH] Modifications to break up controller code to use common I/O
 functions added in drv area.

git-svn-id: https://redoubt.ligo-wa.caltech.edu/svn/advLigoRTS/trunk@4813 6dcd42c9-f523-4c6d-aada-af552506706e
---
 src/fe/controllerApp.c     |  809 ++++++++------------------
 src/fe/controllerAppUser.c |   70 +--
 src/fe/controllerIop.c     | 1107 +++++++++++-------------------------
 src/fe/controllerIopUser.c |   60 +-
 src/fe/moduleLoadApp.c     |   22 +-
 src/fe/moduleLoadCommon.c  |    3 +-
 src/fe/moduleLoadIop.c     |   84 +--
 src/fe/moduleLoadVirtual.c |  701 ++---------------------
 src/fe/rcguser.c           |   68 +--
 9 files changed, 754 insertions(+), 2170 deletions(-)

diff --git a/src/fe/controllerApp.c b/src/fe/controllerApp.c
index 0b9af087a..9f331b520 100644
--- a/src/fe/controllerApp.c
+++ b/src/fe/controllerApp.c
@@ -33,7 +33,6 @@
 #undef printf
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/proc_fs.h>
 #include <linux/kthread.h>
 #include <asm/delay.h>
 #include <asm/cacheflush.h>
@@ -69,16 +68,14 @@ int printk(const char *fmt, ...) {
 #include "fm10Gen.h"		// CDS filter module defs and C code
 #include "feComms.h"		// Lvea control RFM network defs.
 #include "daqmap.h"		// DAQ network layout
+#include "cds_types.h"
 #include "controller.h"
 
+
 #ifndef NO_DAQ
-#include "drv/fb.h"
-#ifdef USE_ZMQ
-	#include "drv/daqLibZmq.c"		// DAQ/GDS connection software
-#else
+	#include "drv/fb.h"
 	#include "drv/daqLib.c"		// DAQ/GDS connection software
 #endif
-#endif
 
 #include "drv/map.h"		// PCI hardware defs
 #include "drv/epicsXfer.c"	// User defined EPICS to/from FE data transfer function
@@ -119,9 +116,9 @@ unsigned int odcStateWord = 0xffff;
 int out_buf_size = 0; // test checking DAC buffer size
 unsigned int cycle_gps_time = 0; // Time at which ADCs triggered
 unsigned int cycle_gps_event_time = 0; // Time at which ADCs triggered
-unsigned int   cycle_gps_ns = 0;
-unsigned int   cycle_gps_event_ns = 0;
-unsigned int   gps_receiver_locked = 0; // Lock/unlock flag for GPS time card
+unsigned int cycle_gps_ns = 0;
+unsigned int cycle_gps_event_ns = 0;
+unsigned int gps_receiver_locked = 0; // Lock/unlock flag for GPS time card
 /// GPS time in GPS seconds
 unsigned int timeSec = 0;
 unsigned int timeSecDiag = 0;
@@ -146,14 +143,21 @@ int timeHoldWhenHold = 0;		///< Cycle number within last second when maximum rea
 struct rmIpcStr *daqPtr;
 
 int  getGpsTime(unsigned int *tsyncSec, unsigned int *tsyncUsec); 
+int dacOF[MAX_DAC_MODULES];
 
 // Include C code modules
 #include "moduleLoadApp.c"
 #include "map.c"
+#include <drv/app_adc_read.c>
+#include <drv/app_dac_functions.c>
+#include <drv/app_dio_routines.c>
 
 
 char daqArea[2*DAQ_DCU_SIZE];		// Space allocation for daqLib buffers
 int cpuId = 1;
+adcInfo_t adcInfo;
+dacInfo_t dacInfo;
+
 
 #ifdef DUAL_DAQ_DC
 	#define MX_OK	15
@@ -197,30 +201,19 @@ void deallocate_dac_channels(void) {
 ///	- 
 void *fe_start(void *arg)
 {
-  int ii,jj,kk,ll,mm;			// Dummy loop counter variables
+  int ii,jj,kk,ll;			// Dummy loop counter variables
   static int clock1Min = 0;		///  @param clockMin Minute counter (Not Used??)
   static int cpuClock[CPU_TIMER_CNT];	///  @param cpuClock[] Code timing diag variables
 
-  int adcData[MAX_ADC_MODULES][MAX_ADC_CHN_PER_MOD];	/// @param adcData[][]  ADC raw data
-  int adcChanErr[MAX_ADC_MODULES];
-  int adcWait = 0;
-  int adcOF[MAX_ADC_MODULES];		/// @param adcOF[]  ADC overrange counters
 
-  // int dacChanErr[MAX_DAC_MODULES];
-  int dacOF[MAX_DAC_MODULES];		/// @param dacOF[]  DAC overrange counters
   static int dacWriteEnable = 0;	/// @param dacWriteEnable  No DAC outputs until >4 times through code
   					///< Code runs longer for first few cycles on startup as it settles in,
 					///< so this helps prevent long cycles during that time.
-  int limit = OVERFLOW_LIMIT_16BIT;      /// @param limit ADC/DAC overflow test value
-  int mask = GSAI_DATA_MASK;            /// @param mask Bit mask for ADC/DAC read/writes
-  int num_outs = MAX_DAC_CHN_PER_MOD;   /// @param num_outs Number of DAC channels variable
   int dkiTrip = 0;
   RFM_FE_COMMS *pEpicsComms;		/// @param *pEpicsComms Pointer to EPICS shared memory space
   int timeHoldMax = 0;			/// @param timeHoldMax Max code cycle time since last diag reset
   int myGmError2 = 0;			/// @param myGmError2 Myrinet error variable
   int status;				/// @param status Typical function return value
-  float onePps;				/// @param onePps Value of 1PPS signal, if used, for diagnostics
-  int onePpsHi = 0;			/// @param onePpsHi One PPS diagnostic check
   int onePpsTime = 0;			/// @param onePpsTime One PPS diagnostic check
 #ifdef DIAG_TEST
   float onePpsTest;			/// @param onePpsTest Value of 1PPS signal, if used, for diagnostics
@@ -239,16 +232,14 @@ void *fe_start(void *arg)
   int ioClockDac = DAC_PRELOAD_CNT;
   int ioMemCntr = 0;
   int ioMemCntrDac = DAC_PRELOAD_CNT;
-  int memCtr = 0;
+  // int memCtr = 0;
   int ioClock = 0;
-  double dac_in =  0.0;			/// @param dac_in DAC value after upsample filtering
-  int dac_out = 0;			/// @param dac_out Integer value sent to DAC FIFO
+  // double dac_in =  0.0;			/// @param dac_in DAC value after upsample filtering
+  // int dac_out = 0;			/// @param dac_out Integer value sent to DAC FIFO
 
   int feStatus = 0;
 
-  int clk, clk1;			// Used only when run on timer enabled (test mode)
 
-  int cnt = 0;
   unsigned long cpc;
 
 /// **********************************************************************************************\n
@@ -288,9 +279,9 @@ void *fe_start(void *arg)
   /// - ---- V2.8 and later, code uses EPICS shared memory only. This was done to: \n
   /// - -------- Allow daqLib.c to retrieve filter module data directly from shared memory. \n
   /// - -------- Avoid copy of filter module data between to memory locations, which was slow. \n
-    pDsp[system] = (FILT_MOD *)(&pEpicsComms->dspSpace);
-    pCoeff[system] = (VME_COEF *)(&pEpicsComms->coeffSpace);
-    dspPtr[system] = (FILT_MOD *)(&pEpicsComms->dspSpace);
+  pDsp[system] = (FILT_MOD *)(&pEpicsComms->dspSpace);
+  pCoeff[system] = (VME_COEF *)(&pEpicsComms->coeffSpace);
+  dspPtr[system] = (FILT_MOD *)(&pEpicsComms->dspSpace);
 
   /// \> Clear the FE reset which comes from Epics
   pLocalEpics->epicsInput.vmeReset = 0;
@@ -300,27 +291,6 @@ void *fe_start(void *arg)
   pLocalEpics->epicsInput.dacDuoSet_mask = 0;
 
 
-/// \> Wait for BURT restore.\n
-/// - ---- Code will exit if BURT flag not set by EPICS sequencer.
-  // Do not proceed until EPICS has had a BURT restore *******************************
-  printf("Waiting for EPICS BURT Restore = %d\n", pLocalEpics->epicsInput.burtRestore);
-  cnt = 0;
-  do{
-#ifndef NO_CPU_SHUTDOWN
-	udelay(MAX_UDELAY);
-        udelay(MAX_UDELAY);
-        udelay(MAX_UDELAY);
-#else
-	msleep(80);
-#endif
-  	printf("Waiting for EPICS BURT %d\n", cnt++);
-	cpu_relax();
-  }while(!pLocalEpics->epicsInput.burtRestore);
-
-  printf("BURT Restore Complete\n");
-
-// BURT has completed *******************************************************************
-
 /// < Read in all Filter Module EPICS coeff settings
     for(ii=0;ii<MAX_MODULES;ii++)
     {
@@ -358,11 +328,12 @@ void *fe_start(void *arg)
 
   /// \> Initialize IIR filter bank values
     if (initVars(pDsp[0], pDsp[0], dspCoeff, MAX_MODULES, pCoeff[0])) {
-    	printf("Filter module init failed, exiting\n");
+    	// printf("Filter module init failed, exiting\n");
+		pLocalEpics->epicsOutput.fe_status = FILT_INIT_ERROR;
 	return 0;
     }
 
-  printf("Initialized servo control parameters.\n");
+  // printf("Initialized servo control parameters.\n");
 
 udelay(1000);
 
@@ -385,10 +356,16 @@ udelay(1000);
   daq.xTpMin = daq.filtTpMax;
   daq.xTpMax = daq.xTpMin + GDS_MAX_NFM_TP;
 
-  printf("DAQ Ex Min/Max = %d %d\n",daq.filtExMin,daq.filtExMax);
-  printf("DAQ XEx Min/Max = %d %d\n",daq.xExMin,daq.xExMax);
-  printf("DAQ Tp Min/Max = %d %d\n",daq.filtTpMin,daq.filtTpMax);
-  printf("DAQ XTp Min/Max = %d %d\n",daq.xTpMin,daq.xTpMax);
+  /// - ---- Initialize DAQ function
+  status = daqWrite(0,dcuId,daq,DAQ_RATE,testpoint,dspPtr[0],0, (int *)(pLocalEpics->epicsOutput.gdsMon),xExc,pEpicsDaq);
+  if(status == -1) 
+  {
+    // printf("DAQ init failed -- exiting\n");
+	pLocalEpics->epicsOutput.fe_status = DAQ_INIT_ERROR;
+    vmeDone = 1;
+    return(0);
+  }
+#endif
 
   /// - ---- Assign DAC testpoint pointers
   for (ii = 0; ii <  cdsPciModules.dacCount; ii++)
@@ -398,84 +375,31 @@ udelay(1000);
   // Zero out storage
   memset(floatDacOut, 0, sizeof(floatDacOut));
 
-#endif
   pLocalEpics->epicsOutput.ipcStat = 0;
   pLocalEpics->epicsOutput.fbNetStat = 0;
   pLocalEpics->epicsOutput.tpCnt = 0;
 
-#if !defined(NO_DAQ) && !defined(IOP_TASK)
-  /// - ---- Initialize DAQ function
-  status = daqWrite(0,dcuId,daq,DAQ_RATE,testpoint,dspPtr[0],0, (int *)(pLocalEpics->epicsOutput.gdsMon),xExc,pEpicsDaq);
-  if(status == -1) 
-  {
-    printf("DAQ init failed -- exiting\n");
-    vmeDone = 1;
-    return(0);
-  }
-#endif
 
 	/// \> Read Dio card initial values
 	/// - ---- SLAVE units read/write their own DIO \n
 	/// - ---- MASTER units ignore DIO for speed reasons \n 
-     for(kk=0;kk<cdsPciModules.doCount;kk++)
-     {
-	ii = cdsPciModules.doInstance[kk];
-	if(cdsPciModules.doType[kk] == ACS_8DIO)
-	{
-	  rioInputInput[ii] = accesIiro8ReadInputRegister(&cdsPciModules, kk) & 0xff;
-	  rioInputOutput[ii] = accesIiro8ReadOutputRegister(&cdsPciModules, kk) & 0xff;
-	  rioOutputHold[ii] = -1;
-	} else if(cdsPciModules.doType[kk] == ACS_16DIO) {
-  	  rioInput1[ii] = accesIiro16ReadInputRegister(&cdsPciModules, kk) & 0xffff;
-	  rioOutputHold1[ii] = -1;
-	} else if (cdsPciModules.doType[kk] == CON_32DO) {
-  	  CDO32Input[ii] = contec32ReadOutputRegister(&cdsPciModules, kk);
-	} else if (cdsPciModules.doType[kk] == CON_6464DIO) {
-  	  CDIO6464LastOutState[ii] = contec6464ReadOutputRegister(&cdsPciModules, kk);
-	  printf ("Initial state of contec6464 number %d = 0x%x \n",ii,CDIO6464LastOutState[ii]);
-	} else if (cdsPciModules.doType[kk] == CDI64) {
-  	  CDIO6464LastOutState[ii] = contec6464ReadOutputRegister(&cdsPciModules, kk);
-	  printf ("Initial state of contec6464 number %d = 0x%x \n",ii,CDIO6464LastOutState[ii]);
-	} else if(cdsPciModules.doType[kk] == ACS_24DIO) {
-  	  dioInput[ii] = accesDio24ReadInputRegister(&cdsPciModules, kk);
-	}
-     }
+	status = app_dio_init();	
 
 
   // Clear the code exit flag
   vmeDone = 0;
 
   /// \> Call user application software initialization routine.
-  printf("Calling feCode() to initialize\n");
+  // printf("Calling feCode() to initialize\n");
   iopDacEnable = feCode(cycleNum,dWord,dacOut,dspPtr[0],&dspCoeff[0], (struct CDS_EPICS *)pLocalEpics,1);
 
-/// \> Verify DAC channels defined for this app are not already in use. \n
-/// - ---- User apps are allowed to share DAC modules but not DAC channels.
-  // See if my DAC channel map overlaps with already running models
-  for (ii = 0; ii < cdsPciModules.dacCount; ii++) {
-    int pd = cdsPciModules.dacConfig[ii] - ioMemData->adcCount; // physical DAC number
-    for (jj = 0; jj < 16; jj++) {
-	if (dacOutUsed[ii][jj]) {
-	  if (ioMemData->dacOutUsed[pd][jj])  {
-    		vmeDone = 1;
-   		printf("Failed to allocate DAC channel.\n");
-		printf("DAC local %d global %d channel %d is already allocated.\n", ii, pd, jj);
-	  }
-    	}
-    }
-  }
-  if (vmeDone == 1) {
+  
+  pLocalEpics->epicsOutput.fe_status = INIT_DAC_MODS;
+  /// \> Initialize DAC channels.
+  status = app_dac_init();
+  if (status) {
+		pLocalEpics->epicsOutput.fe_status = DAC_INIT_ERROR;
      	return(0);
-  } else {
-    for (ii = 0; ii < cdsPciModules.dacCount; ii++) {
-      int pd = cdsPciModules.dacConfig[ii] - ioMemData->adcCount; // physical DAC number
-      for (jj = 0; jj < MAX_DAC_CHN_PER_MOD; jj++) {
-	if (dacOutUsed[ii][jj]) {
-	  	ioMemData->dacOutUsed[pd][jj] = 1;
-		printf("Setting card local=%d global = %d channel=%d dac usage\n", ii, pd, jj);
-	}
-      }
-    }
   }
 
   /// \> Initialize the ADC status
@@ -484,40 +408,42 @@ udelay(1000);
   	  pLocalEpics->epicsOutput.statAdc[jj] = 1;
   }
 
-	// SLAVE needs to sync with MASTER by looking for cycle 0 count in ipc memory
-	// Find memory buffer of first ADC to be used in SLAVE application.
-        ll = cdsPciModules.adcConfig[0];
-        printf("waiting to sync %d\n",ioMemData->iodata[ll][0].cycle);
-        rdtscl(cpuClock[CPU_TIME_CYCLE_START]);
+  // SLAVE needs to sync with MASTER by looking for cycle 0 count in ipc memory
+  // Find memory buffer of first ADC to be used in SLAVE application.
+  ll = cdsPciModules.adcConfig[0];
+  // printf("waiting to sync %d\n",ioMemData->iodata[ll][0].cycle);
+  rdtscl(cpuClock[CPU_TIME_CYCLE_START]);
 
- 	if (boot_cpu_has(X86_FEATURE_MWAIT)) {
+  pLocalEpics->epicsOutput.fe_status = INIT_SYNC;
+  if (boot_cpu_has(X86_FEATURE_MWAIT)) {
 	  for(;;) {
 	    if (ioMemData->iodata[ll][0].cycle == 0) break;
 	    __monitor((void *)&(ioMemData->iodata[ll][0].cycle), 0, 0);
 	    if (ioMemData->iodata[ll][0].cycle == 0) break;
 	    __mwait(0, 0);
 	  }
- 	} else {
-	  // Spin until cycle 0 detected in first ADC buffer location.
-          do {
-		udelay(1);
-          } while(ioMemData->iodata[ll][0].cycle != 0);
-	}
-        timeSec = ioMemData->iodata[ll][0].timeSec;
-
-        rdtscl(cpuClock[CPU_TIME_CYCLE_END]);
-        cycleTime = (cpuClock[CPU_TIME_CYCLE_END] - cpuClock[CPU_TIME_CYCLE_START])/CPURATE;
-        printf("Synched %d\n",cycleTime);
-	// Get GPS seconds from MASTER
-	timeSec = ioMemData->gpsSecond;
-        pLocalEpics->epicsOutput.timeDiag = timeSec;
-	// Decrement GPS seconds as it will be incremented on first read cycle.
-	timeSec --;
+  } else {
+    // Spin until cycle 0 detected in first ADC buffer location.
+	do {
+	udelay(1);
+    } while(ioMemData->iodata[ll][0].cycle != 0);
+  }
+  pLocalEpics->epicsOutput.fe_status = NORMAL_RUN;
+
+  timeSec = ioMemData->iodata[ll][0].timeSec;
+  rdtscl(cpuClock[CPU_TIME_CYCLE_END]);
+  cycleTime = (cpuClock[CPU_TIME_CYCLE_END] - cpuClock[CPU_TIME_CYCLE_START])/CPURATE;
+  // printf("Synched %d\n",cycleTime);
+  // Get GPS seconds from MASTER
+  timeSec = ioMemData->gpsSecond;
+  pLocalEpics->epicsOutput.timeDiag = timeSec;
+  // Decrement GPS seconds as it will be incremented on first read cycle.
+  timeSec --;
 
   onePpsTime = cycleNum;
 #ifdef REMOTE_GPS
   timeSec = remote_time((struct CDS_EPICS *)pLocalEpics);
-  printf ("Using remote GPS time %d \n",timeSec);
+  // printf ("Using remote GPS time %d \n",timeSec);
 #else
   timeSec = current_time() -1;
 #endif
@@ -536,11 +462,6 @@ udelay(1000);
 #endif
 
 
-#ifdef NO_CPU_SHUTDOWN
-  while(!kthread_should_stop()){
-#else
-  while(!vmeDone){ 	// Run forever until user hits reset
-#endif
 	// **********************************************************************************************************
 	// NORMAL OPERATION -- Wait for ADC data ready
 	// On startup, only want to read one sample such that first cycle
@@ -549,256 +470,120 @@ udelay(1000);
 	// code rate eg 32 samples each time thru before proceeding to match 2048 system.
 	// **********************************************************************************************************
 
+#ifdef NO_CPU_SHUTDOWN
+  while(!kthread_should_stop()){
+#else
+  while(!vmeDone){ 	// Run forever until user hits reset
+#endif
+
 /// \> On 1PPS mark \n
-        if(cycleNum == 0)
-        {
-	  /// - ---- Check awgtpman status.
-	  //printf("awgtpman gps = %d local = %d\n", pEpicsComms->padSpace.awgtpman_gps, timeSec);
-	  pLocalEpics->epicsOutput.awgStat = (pEpicsComms->padSpace.awgtpman_gps != timeSec);
-	  if(pLocalEpics->epicsOutput.awgStat) feStatus |= FE_ERROR_AWG;
-	  /// - ---- Check if DAC outputs are enabled, report error.
-	  if(!iopDacEnable || dkiTrip) feStatus |= FE_ERROR_DAC_ENABLE;
+	if(cycleNum == 0)
+    {
+	  	/// - ---- Check awgtpman status.
+	  	//printf("awgtpman gps = %d local = %d\n", pEpicsComms->padSpace.awgtpman_gps, timeSec);
+		pLocalEpics->epicsOutput.awgStat = (pEpicsComms->padSpace.awgtpman_gps != timeSec);
+	  	if(pLocalEpics->epicsOutput.awgStat) feStatus |= FE_ERROR_AWG;
+	  	/// - ---- Check if DAC outputs are enabled, report error.
+	  	if(!iopDacEnable || dkiTrip) feStatus |= FE_ERROR_DAC_ENABLE;
 
 	}
 #ifdef NO_CPU_SHUTDOWN
-        if(vmeDone)usleep_range(2,4);
+	if(vmeDone)usleep_range(2,4);
 #endif
-        for(ll=0;ll<sampleCount;ll++)
+	for(ll=0;ll<sampleCount;ll++)
+    {
+		status = app_adc_read(ioMemCntr,ioClock,&adcInfo,cpuClock);
+
+		// Return of non zero = ADC timeout error.
+		if(status)
         {
-		/// \> SLAVE gets its adc data from MASTER via ipc shared memory\n
-		/// \> For each ADC defined:
-		for(jj=0;jj<cdsPciModules.adcCount;jj++)
-		{
-        		mm = cdsPciModules.adcConfig[jj];
-	    		rdtscl(cpuClock[CPU_TIME_RDY_ADC]);
-			/// - ---- Wait for proper timestamp in shared memory, indicating data ready.
-                        do{
-		    		rdtscl(cpuClock[CPU_TIME_ADC_WAIT]);
-				adcWait = (cpuClock[CPU_TIME_ADC_WAIT] - cpuClock[CPU_TIME_RDY_ADC])/CPURATE;
-                        }while((ioMemData->iodata[mm][ioMemCntr].cycle != ioClock) && (adcWait < MAX_ADC_WAIT_SLAVE));
-			timeSec = ioMemData->iodata[mm][ioMemCntr].timeSec;
-			if (cycle_gps_time == 0) {
-				startGpsTime = timeSec;
-				pLocalEpics->epicsOutput.startgpstime = startGpsTime;
-			}
-			cycle_gps_time = timeSec;
-
-			/// - --------- If data not ready in time, set error, release DAC channel reservation and exit the code.
-                        if(adcWait >= MAX_ADC_WAIT_SLAVE)
-                        {
-                                printf ("ADC TIMEOUT %d %d %d %d\n",mm,ioMemData->iodata[mm][ioMemCntr].cycle, ioMemCntr,ioClock);
-	  			pLocalEpics->epicsOutput.stateWord = FE_ERROR_ADC;
-	  			pLocalEpics->epicsOutput.diagWord |= ADC_TIMEOUT_ERR;
-				deallocate_dac_channels();
-  				return (void *)-1;
-                        }
-                        for(ii=0;ii<MAX_ADC_CHN_PER_MOD;ii++)
-                        {
-				/// - ---- Read data from shared memory.
-                                adcData[jj][ii] = ioMemData->iodata[mm][ioMemCntr].data[ii];
-#ifdef FLIP_SIGNALS
-                                adcData[jj][ii] *= -1;
-#endif
-                                dWord[jj][ii] = adcData[jj][ii];
-#ifdef OVERSAMPLE
-				/// - ---- Downsample ADC data from 64K to rate of user application
-				if (dWordUsed[jj][ii]) {
-					dWord[jj][ii] = iir_filter_biquad(dWord[jj][ii],FE_OVERSAMPLE_COEFF,2,&dHistory[ii+jj*32][0]);
-				}
-			/// - ---- Check for ADC data over/under range
-			if((adcData[jj][ii] > limit) || (adcData[jj][ii] < -limit))
-			  {
-				overflowAdc[jj][ii] ++;
-				pLocalEpics->epicsOutput.overflowAdcAcc[jj][ii] ++;
-				overflowAcc ++;
-				adcOF[jj] = 1;
-				odcStateWord |= ODC_ADC_OVF;
-			  }
-#endif
-                        }
-                }
+	  		pLocalEpics->epicsOutput.stateWord = FE_ERROR_ADC;
+	  		pLocalEpics->epicsOutput.diagWord |= ADC_TIMEOUT_ERR;
+			deallocate_dac_channels();
+  			return (void *)-1;
+        }
+
 		/// \> Set counters for next read from ipc memory
-                ioClock = (ioClock + 1) % IOP_IO_RATE;
-                ioMemCntr = (ioMemCntr + 1) % IO_MEMORY_SLOTS;
-        	rdtscl(cpuClock[CPU_TIME_CYCLE_START]);
+        ioClock = (ioClock + 1) % IOP_IO_RATE;
+        ioMemCntr = (ioMemCntr + 1) % IO_MEMORY_SLOTS;
+       	rdtscl(cpuClock[CPU_TIME_CYCLE_START]);
 
 	}
 
-	// After first synced ADC read, must set to code to read number samples/cycle
-        sampleCount = OVERSAMPLE_TIMES;
-/// End of ADC Read **************************************************************************************
+	// After first synced ADC read, must set code to read number samples/cycle
+    sampleCount = OVERSAMPLE_TIMES;
 
 
 /// \> Call the front end specific application  ******************\n
 /// - -- This is where the user application produced by RCG gets called and executed. \n\n
-        rdtscl(cpuClock[CPU_TIME_USR_START]);
+    rdtscl(cpuClock[CPU_TIME_USR_START]);
  	iopDacEnable = feCode(cycleNum,dWord,dacOut,dspPtr[0],&dspCoeff[0],(struct CDS_EPICS *)pLocalEpics,0);
-        rdtscl(cpuClock[CPU_TIME_USR_END]);
-
+    rdtscl(cpuClock[CPU_TIME_USR_END]);
   	odcStateWord = 0;
-/// WRITE DAC OUTPUTS ***************************************** \n
 
-/// Writing of DAC outputs is dependent on code compile option: \n
-/// - -- IOP (ADC_MASTER) reads DAC output values from memory shared with user apps and writes to DAC hardware. \n
-/// - -- USER APP (ADC_SLAVE) sends output values to memory shared with IOP. \n
 
+// **********************************************************************
 /// START OF USER APP DAC WRITE *****************************************
-        // Write out data to DAC modules
-	/// \> Loop thru all DAC modules
-        for(jj=0;jj<cdsPciModules.dacCount;jj++)
-        {
-		/// - -- locate the proper DAC memory block
-           	mm = cdsPciModules.dacConfig[jj];
-		/// - -- Set overflow limits, data mask, and chan count based on DAC type
-                limit = OVERFLOW_LIMIT_16BIT;
-                mask = GSAO_16BIT_MASK;
-                num_outs = GSAO_16BIT_CHAN_COUNT;
-                if (cdsPciModules.dacType[jj] == GSC_18AO8) {
-                        limit = OVERFLOW_LIMIT_18BIT; // 18 bit limit
-                        mask = GSAO_18BIT_MASK;
-                        num_outs = GSAO_18BIT_CHAN_COUNT;
-                }
-				if (cdsPciModules.dacType[jj] == GSC_20AO8) {
-                        limit = OVERFLOW_LIMIT_20BIT; // 20 bit limit
-                        mask = GSAO_20BIT_MASK;
-                        num_outs = GSAO_20BIT_CHAN_COUNT;
-                }
-		/// - -- If user app < 64k rate (typical), need to upsample from code rate to IOP rate
-           	for (kk=0; kk < OVERSAMPLE_TIMES; kk++) {
-		     /// - -- For each DAC channel
-                    for (ii=0; ii < num_outs; ii++)
-                    {
-#ifdef FLIP_SIGNALS
-                        dacOut[jj][ii] *= -1;
-#endif
-			/// - ---- Read in DAC value, if channel is used by the application,  and run thru upsample filter\n
-                        if (dacOutUsed[jj][ii]) {
-#ifdef OVERSAMPLE_DAC
-#ifdef NO_ZERO_PAD
-				/// - --------- If set to NO_ZERO_PAD (not standard setting), then DAC output value is 
-				/// repeatedly run thru the filter OVERSAMPE_TIMES.\n
-                          	dac_in = dacOut[jj][ii];
-#ifdef CORE_BIQUAD
-                          	dac_in = iir_filter_biquad(dac_in,FE_OVERSAMPLE_COEFF,2,&dDacHistory[ii+jj*MAX_DAC_CHN_PER_MOD][0]);
-#else
-                          	dac_in = iir_filter(dac_in,FE_OVERSAMPLE_COEFF,2,&dDacHistory[ii+jj*MAX_DAC_CHN_PER_MOD][0]);
-#endif
-#else
-				/// - --------- Otherwise zero padding is used (standard), 
-				/// ie DAC output value is applied to filter on first
-				/// interation, thereafter zeros are applied.
-                          	dac_in =  kk == 0? (double)dacOut[jj][ii]: 0.0;
-#ifdef CORE_BIQUAD
-                          	dac_in = iir_filter_biquad(dac_in,FE_OVERSAMPLE_COEFF,2,&dDacHistory[ii+jj*MAX_DAC_CHN_PER_MOD][0]);
-#else
-                          	dac_in = iir_filter(dac_in,FE_OVERSAMPLE_COEFF,2,&dDacHistory[ii+jj*MAX_DAC_CHN_PER_MOD][0]);
-#endif
-                          	dac_in *= OVERSAMPLE_TIMES;
-#endif
-#else
-                          	dac_in = dacOut[jj][ii];
-#endif
-                        }
-			/// - ---- If channel is not used, then set value to zero.
-                        else 
-				dac_in = 0.0;
-                        /// - ---- Smooth out some of the double > short roundoff errors
-                        if(dac_in > 0.0) dac_in += 0.5;
-                        else dac_in -= 0.5;
-                        dac_out = dac_in;
-
-                        /// - ---- Check output values are within range of DAC \n
-                        /// - --------- If overflow, clip at DAC limits and report errors
-                        if(dac_out > limit || dac_out < -limit)
-                        {
-                                overflowDac[jj][ii] ++;
-				pLocalEpics->epicsOutput.overflowDacAcc[jj][ii] ++;
-                                overflowAcc ++;
-                                dacOF[jj] = 1;
-				odcStateWord |= ODC_DAC_OVF;;
-				if(dac_out > limit) dac_out = limit;
-				else dac_out = -limit;
-                        }
-			/// - ---- If DAQKILL tripped, set output to zero.
-                        if(!iopDacEnable) dac_out = 0;
-			/// - ---- Load last values to EPICS channels for monitoring on GDS_TP screen.
-                        dacOutEpics[jj][ii] = dac_out;
-
-                        /// - ---- Load DAC testpoints
-                        floatDacOut[16*jj + ii] = dac_out;
-                        /// - ---- Determine shared memory location for new DAC output data 
-                        memCtr = (ioMemCntrDac + kk) % IO_MEMORY_SLOTS;
-			/// - ---- Write DAC output to shared memory. \n
-                        /// - --------- Only write to DAC channels being used to allow two or more
-                        /// slaves to write to same DAC module.
-                        if (dacOutUsed[jj][ii])
-                                ioMemData->iodata[mm][memCtr].data[ii] = dac_out;
-		    }
-                /// - ---- Write cycle count to make DAC data complete
-                if(iopDacEnable)
-                ioMemData->iodata[mm][memCtr].cycle = (ioClockDac + kk) % IOP_IO_RATE;
-           }
-	}
-        /// \> Increment DAC memory block pointers for next cycle
-        ioClockDac = (ioClockDac + OVERSAMPLE_TIMES) % IOP_IO_RATE;
-        ioMemCntrDac = (ioMemCntrDac  + OVERSAMPLE_TIMES) % IO_MEMORY_SLOTS;
-        if(dacWriteEnable < 10) dacWriteEnable ++;
+ // Write out data to DAC modules
+// **********************************************************************
+	status = app_dac_write(ioMemCntrDac,ioClockDac, &dacInfo);
+    /// \> Increment DAC memory block pointers for next cycle
+    ioClockDac = (ioClockDac + OVERSAMPLE_TIMES) % IOP_IO_RATE;
+    ioMemCntrDac = (ioMemCntrDac  + OVERSAMPLE_TIMES) % IO_MEMORY_SLOTS;
+    if(dacWriteEnable < 10) dacWriteEnable ++;
 /// END OF USER APP DAC WRITE *************************************************
 
-/// END OF DAC WRITE *************************************************
-
 
+// **********************************************************************
 /// BEGIN HOUSEKEEPING ************************************************ \n
+// **********************************************************************
 
-        pLocalEpics->epicsOutput.cycle = cycleNum;
+    pLocalEpics->epicsOutput.cycle = cycleNum;
 
 /// \> Cycle 18, Send timing info to EPICS at 1Hz
 	if(cycleNum ==HKP_TIMING_UPDATES)	
-        {
-	  pLocalEpics->epicsOutput.cpuMeter = timeHold;
-	  pLocalEpics->epicsOutput.cpuMeterMax = timeHoldMax;
-          timeHoldHold = timeHold;
-          timeHold = 0;
-	  timeHoldWhenHold = timeHoldWhen;
-
-	  if (timeSec % 4 == 0) pLocalEpics->epicsOutput.adcWaitTime = adcHoldTimeMin;
-	  else if (timeSec % 4 == 1)
-		pLocalEpics->epicsOutput.adcWaitTime =  adcHoldTimeMax;
-	  else
-	  	pLocalEpics->epicsOutput.adcWaitTime = adcHoldTimeAvg/CYCLE_PER_SECOND;
-	  adcHoldTimeAvgPerSec = adcHoldTimeAvg/CYCLE_PER_SECOND;
-	  adcHoldTimeMax = 0;
-	  adcHoldTimeMin = 0xffff;
-	  adcHoldTimeAvg = 0;
-	  if((adcHoldTime > CYCLE_TIME_ALRM_HI) || (adcHoldTime < CYCLE_TIME_ALRM_LO)) 
-	  {
-	  	diagWord |= FE_ADC_HOLD_ERR;
-		feStatus |= FE_ERROR_TIMING;
-	  
-	  }
-	  if(timeHoldMax > CYCLE_TIME_ALRM) 
-	  {
-	  	diagWord |= FE_PROC_TIME_ERR;
-		feStatus |= FE_ERROR_TIMING;
-	  }
-	  pLocalEpics->epicsOutput.stateWord = feStatus;
-  	  feStatus = 0;
-  	  if(pLocalEpics->epicsInput.diagReset || initialDiagReset)
-	  {
-		initialDiagReset = 0;
-		pLocalEpics->epicsInput.diagReset = 0;
-		pLocalEpics->epicsInput.ipcDiagReset = 1;
-  		// pLocalEpics->epicsOutput.diags[1] = 0;
-		timeHoldMax = 0;
-	  	diagWord = 0;
-		ipcErrBits = 0;
+    {
+		pLocalEpics->epicsOutput.cpuMeter = timeHold;
+	  	pLocalEpics->epicsOutput.cpuMeterMax = timeHoldMax;
+        timeHoldHold = timeHold;
+        timeHold = 0;
+	  	timeHoldWhenHold = timeHoldWhen;
+
+	  	if (timeSec % 4 == 0) pLocalEpics->epicsOutput.adcWaitTime = adcHoldTimeMin;
+	  	else if (timeSec % 4 == 1)
+			pLocalEpics->epicsOutput.adcWaitTime =  adcHoldTimeMax;
+	  	else
+	  		pLocalEpics->epicsOutput.adcWaitTime = adcHoldTimeAvg/CYCLE_PER_SECOND;
+	  		adcHoldTimeAvgPerSec = adcHoldTimeAvg/CYCLE_PER_SECOND;
+	  		adcHoldTimeMax = 0;
+	  		adcHoldTimeMin = 0xffff;
+	  		adcHoldTimeAvg = 0;
+	  	if((adcHoldTime > CYCLE_TIME_ALRM_HI) || (adcHoldTime < CYCLE_TIME_ALRM_LO)) 
+	  	{
+	  		diagWord |= FE_ADC_HOLD_ERR;
+			feStatus |= FE_ERROR_TIMING;
+	  	}
+	  	if(timeHoldMax > CYCLE_TIME_ALRM) 
+	  	{
+	  		diagWord |= FE_PROC_TIME_ERR;
+			feStatus |= FE_ERROR_TIMING;
+	  	}
+	  	pLocalEpics->epicsOutput.stateWord = feStatus;
+  	  	feStatus = 0;
+  	  	if(pLocalEpics->epicsInput.diagReset || initialDiagReset)
+	  	{
+			initialDiagReset = 0;
+			pLocalEpics->epicsInput.diagReset = 0;
+			pLocalEpics->epicsInput.ipcDiagReset = 1;
+			timeHoldMax = 0;
+	  		diagWord = 0;
+			ipcErrBits = 0;
 		
-		// feStatus = 0;
-	  }
-	  // Flip the onePPS various once/sec as a watchdog monitor.
-	  // pLocalEpics->epicsOutput.onePps ^= 1;
-	  pLocalEpics->epicsOutput.diagWord = diagWord;
-        }
+	  	}
+	  	// Flip the onePPS various once/sec as a watchdog monitor.
+	  	// pLocalEpics->epicsOutput.onePps ^= 1;
+	  	pLocalEpics->epicsOutput.diagWord = diagWord;
+	}
 
 
 /// \> Check for requests for filter module clear history requests. This is spread out over a number of cycles.
@@ -820,211 +605,99 @@ udelay(1000);
 /// \> Cycle 10 to number of BIO cards:\n
  /// - ---- Read Dio cards once per second \n
 
-	if(cdsPciModules.doCount)
-        // if((cycleNum < (HKP_READ_DIO + cdsPciModules.doCount)) && (cycleNum >= HKP_READ_DIO))
-        {
-                // kk = cycleNum - HKP_READ_DIO;
-		kk = cycleNum % cdsPciModules.doCount;
-                ii = cdsPciModules.doInstance[kk];
-                if(cdsPciModules.doType[kk] == ACS_8DIO)
-                {
-	  		rioInputInput[ii] = accesIiro8ReadInputRegister(&cdsPciModules, kk) & 0xff;
-	  		rioInputOutput[ii] = accesIiro8ReadOutputRegister(&cdsPciModules, kk) & 0xff;
-                }
-                if(cdsPciModules.doType[kk] == ACS_16DIO)
-                {
-                        rioInput1[ii] = accesIiro16ReadInputRegister(&cdsPciModules, kk) & 0xffff;
-                }
-		if(cdsPciModules.doType[kk] == ACS_24DIO)
-		{
-		  dioInput[ii] = accesDio24ReadInputRegister(&cdsPciModules, kk);
-		}
-		if (cdsPciModules.doType[kk] == CON_6464DIO) {
-	 		CDIO6464InputInput[ii] = contec6464ReadInputRegister(&cdsPciModules, kk);
-		}
-		if (cdsPciModules.doType[kk] == CDI64) {
-	 		CDIO6464InputInput[ii] = contec6464ReadInputRegister(&cdsPciModules, kk);
-		}
-        }
-/// \> Write Dio cards only on change
-        for(kk=0;kk < cdsPciModules.doCount;kk++)
-        {
-                ii = cdsPciModules.doInstance[kk];
-                if((cdsPciModules.doType[kk] == ACS_8DIO) && (rioOutput[ii] != rioOutputHold[ii]))
-                {
-                        accesIiro8WriteOutputRegister(&cdsPciModules, kk, rioOutput[ii]);
-                        rioOutputHold[ii] = rioOutput[ii];
-                } else 
-                if((cdsPciModules.doType[kk] == ACS_16DIO) && (rioOutput1[ii] != rioOutputHold1[ii]))
-                {
-                        accesIiro16WriteOutputRegister(&cdsPciModules, kk, rioOutput1[ii]);
-                        rioOutputHold1[ii] = rioOutput1[ii];
-                } else 
-                if(cdsPciModules.doType[kk] == CON_32DO)
-                {
-                        if (CDO32Input[ii] != CDO32Output[ii]) {
-                          CDO32Input[ii] = contec32WriteOutputRegister(&cdsPciModules, kk, CDO32Output[ii]);
-                        }
-		} else if (cdsPciModules.doType[kk] == CON_6464DIO) {
-			if (CDIO6464LastOutState[ii] != CDIO6464Output[ii]) {
-			  CDIO6464LastOutState[ii] = contec6464WriteOutputRegister(&cdsPciModules, kk, CDIO6464Output[ii]);
-			}
-		} else if (cdsPciModules.doType[kk] == CDO64) {
-			if (CDIO6464LastOutState[ii] != CDIO6464Output[ii]) {
-			  CDIO6464LastOutState[ii] = contec6464WriteOutputRegister(&cdsPciModules, kk, CDIO6464Output[ii]);
-			}
-                } else
-                if((cdsPciModules.doType[kk] == ACS_24DIO) && (dioOutputHold[ii] != dioOutput[ii]))
-		{
-                        accesDio24WriteOutputRegister(&cdsPciModules, kk, dioOutput[ii]);
-			dioOutputHold[ii] = dioOutput[ii];
-		}
-        }
-
+	status = app_dio_read_write();
 
 /// \>  Write data to DAQ.
 #ifndef NO_DAQ
-		
-		// Call daqLib
-		pLocalEpics->epicsOutput.daqByteCnt = 
+	
+	// Call daqLib
+	pLocalEpics->epicsOutput.daqByteCnt = 
 			daqWrite(1,dcuId,daq,DAQ_RATE,testpoint,dspPtr[0],myGmError2,(int *)(pLocalEpics->epicsOutput.gdsMon),xExc,pEpicsDaq);
-		// Send the current DAQ block size to the awgtpman for TP number checking
-	  	pEpicsComms->padSpace.feDaqBlockSize = curDaqBlockSize;
-	  	pLocalEpics->epicsOutput.tpCnt = tpPtr->count & 0xff;
-		feStatus |= (FE_ERROR_EXC_SET & tpPtr->count);
-		if (FE_ERROR_EXC_SET & tpPtr->count) odcStateWord |= ODC_EXC_SET;
-		else odcStateWord &= ~(ODC_EXC_SET);
-		if(pLocalEpics->epicsOutput.daqByteCnt > DAQ_DCU_RATE_WARNING) 
-			feStatus |= FE_ERROR_DAQ;
+	// Send the current DAQ block size to the awgtpman for TP number checking
+  	pEpicsComms->padSpace.feDaqBlockSize = curDaqBlockSize;
+  	pLocalEpics->epicsOutput.tpCnt = tpPtr->count & 0xff;
+	feStatus |= (FE_ERROR_EXC_SET & tpPtr->count);
+	if (FE_ERROR_EXC_SET & tpPtr->count) odcStateWord |= ODC_EXC_SET;
+	else odcStateWord &= ~(ODC_EXC_SET);
+	if(pLocalEpics->epicsOutput.daqByteCnt > DAQ_DCU_RATE_WARNING) 
+		feStatus |= FE_ERROR_DAQ;
 #endif
 
 /// \> Cycle 19, write updated diag info to EPICS
 	if(cycleNum == HKP_DIAG_UPDATES)	
-        {
-	  pLocalEpics->epicsOutput.userTime = usrHoldTime;
-	  pLocalEpics->epicsOutput.ipcStat = ipcErrBits;
-	  if(ipcErrBits & 0xf) feStatus |= FE_ERROR_IPC;
-	  // Create FB status word for return to EPICS
-	  mxStat = 0;
-	  mxDiagR = daqPtr->reqAck;
-	  if((mxDiag & 1) != (mxDiagR & 1)) mxStat = 1;
-	  if((mxDiag & 2) != (mxDiagR & 2)) mxStat += 2;
+    {
+	  	pLocalEpics->epicsOutput.userTime = usrHoldTime;
+	  	pLocalEpics->epicsOutput.ipcStat = ipcErrBits;
+	  	if(ipcErrBits & 0xf) feStatus |= FE_ERROR_IPC;
+	  	// Create FB status word for return to EPICS
+	  	mxStat = 0;
+	  	mxDiagR = daqPtr->reqAck;
+	  	if((mxDiag & 1) != (mxDiagR & 1)) mxStat = 1;
+	  	if((mxDiag & 2) != (mxDiagR & 2)) mxStat += 2;
 #ifdef DUAL_DAQ_DC
-	  if((mxDiag & 4) != (mxDiagR & 4)) mxStat += 4;
-	  if((mxDiag & 8) != (mxDiagR & 8)) mxStat += 8;
+	  	if((mxDiag & 4) != (mxDiagR & 4)) mxStat += 4;
+	  	if((mxDiag & 8) != (mxDiagR & 8)) mxStat += 8;
 #endif
-	  pLocalEpics->epicsOutput.fbNetStat = mxStat;
-  	  mxDiag = mxDiagR;
-	  if(mxStat != MX_OK)
-		feStatus |= FE_ERROR_DAQ;;
-	  usrHoldTime = 0;
-  	  if(pLocalEpics->epicsInput.overflowReset)
-	  {
-                if (pLocalEpics->epicsInput.overflowReset) {
-                   for (ii = 0; ii < 16; ii++) {
-                      for (jj = 0; jj < cdsPciModules.adcCount; jj++) {
-                         overflowAdc[jj][ii] = 0;
-                         overflowAdc[jj][ii + 16] = 0;
-			pLocalEpics->epicsOutput.overflowAdcAcc[jj][ii] = 0;
-			pLocalEpics->epicsOutput.overflowAdcAcc[jj][ii + 16] = 0;
-                      }
-
-                      for (jj = 0; jj < cdsPciModules.dacCount; jj++) {
-                         pLocalEpics->epicsOutput.overflowDacAcc[jj][ii] = 0;
-                      }
-                   }
-                }
-	  }
-  	  if((pLocalEpics->epicsInput.overflowReset) || (overflowAcc > OVERFLOW_CNTR_LIMIT))
-	  {
-		pLocalEpics->epicsInput.overflowReset = 0;
-		pLocalEpics->epicsOutput.ovAccum = 0;
-		overflowAcc = 0;
-	  }
-        }
+	  	pLocalEpics->epicsOutput.fbNetStat = mxStat;
+  	  	mxDiag = mxDiagR;
+	  	if(mxStat != MX_OK)
+			feStatus |= FE_ERROR_DAQ;;
+	  	usrHoldTime = 0;
+  	  	if(pLocalEpics->epicsInput.overflowReset)
+	  	{
+        	if (pLocalEpics->epicsInput.overflowReset) {
+            	for (ii = 0; ii < 16; ii++) {
+                	for (jj = 0; jj < cdsPciModules.adcCount; jj++) {
+                    	adcInfo.overflowAdc[jj][ii] = 0;
+                        adcInfo.overflowAdc[jj][ii + 16] = 0;
+						pLocalEpics->epicsOutput.overflowAdcAcc[jj][ii] = 0;
+						pLocalEpics->epicsOutput.overflowAdcAcc[jj][ii + 16] = 0;
+                     }
+
+                     for (jj = 0; jj < cdsPciModules.dacCount; jj++) {
+                        pLocalEpics->epicsOutput.overflowDacAcc[jj][ii] = 0;
+                     }
+             	}
+          	}
+	  	}
+  	  	if((pLocalEpics->epicsInput.overflowReset) || (overflowAcc > OVERFLOW_CNTR_LIMIT))
+	  	{
+			pLocalEpics->epicsInput.overflowReset = 0;
+			pLocalEpics->epicsOutput.ovAccum = 0;
+			overflowAcc = 0;
+	  	}
+	}
 
-        if(cycleNum == 1)
+    if(cycleNum == 1)
 	{
           pLocalEpics->epicsOutput.timeDiag = timeSec;
 	}
 /// \> Cycle 20, Update latest DAC output values to EPICS
-        if(subcycle == HKP_DAC_EPICS_UPDATES)
+    if(subcycle == HKP_DAC_EPICS_UPDATES)
 	{
-	      // Send DAC output values at 16Hzfb
-	      for(jj=0;jj<cdsPciModules.dacCount;jj++)
-	      {
+		// Send DAC output values at 16Hzfb
+	    for(jj=0;jj<cdsPciModules.dacCount;jj++)
+	    {
 	    	for(ii=0;ii<MAX_DAC_CHN_PER_MOD;ii++)
 	    	{
-			pLocalEpics->epicsOutput.dacValue[jj][ii] = dacOutEpics[jj][ii];
-		}
-	      }
+				pLocalEpics->epicsOutput.dacValue[jj][ii] = dacInfo.dacOutEpics[jj][ii];
+			}
+	    }
 	}
 
 /// \> Cycle 21, Update ADC/DAC status to EPICS.
-        if(cycleNum == HKP_ADC_DAC_STAT_UPDATES)
-        {
-	  pLocalEpics->epicsOutput.ovAccum = overflowAcc;
-	  for(jj=0;jj<cdsPciModules.adcCount;jj++)
-	  {
-	    // SET/CLR Channel Hopping Error
-	    if(adcChanErr[jj]) 
-	    {
-	    	pLocalEpics->epicsOutput.statAdc[jj] &= ~(2);
-		feStatus |= FE_ERROR_ADC;;
-	    }
- 	    else pLocalEpics->epicsOutput.statAdc[jj] |= 2;
-	    adcChanErr[jj] = 0;
-	    // SET/CLR Overflow Error
-	    if(adcOF[jj]) 
-	    {
-	    	pLocalEpics->epicsOutput.statAdc[jj] &= ~(4);
-		feStatus |= FE_ERROR_OVERFLOW;;
-	    }
- 	    else pLocalEpics->epicsOutput.statAdc[jj] |= 4;
-	    adcOF[jj] = 0;
-	    for(ii=0;ii<32;ii++)
-	    {
-
-                if (pLocalEpics->epicsOutput.overflowAdcAcc[jj][ii] > OVERFLOW_CNTR_LIMIT) {
-		   pLocalEpics->epicsOutput.overflowAdcAcc[jj][ii] = 0;
-                }
-		pLocalEpics->epicsOutput.overflowAdc[jj][ii] = overflowAdc[jj][ii];
-		overflowAdc[jj][ii] = 0;
-
-	    }
-	  }
-	  for(jj=0;jj<cdsPciModules.dacCount;jj++)
-	  {
-	    if(dacOF[jj]) 
-	    {
-	    	pLocalEpics->epicsOutput.statDac[jj] &= ~(DAC_OVERFLOW_BIT);
-		feStatus |= FE_ERROR_OVERFLOW;;
-	    }
- 	    else pLocalEpics->epicsOutput.statDac[jj] |= DAC_OVERFLOW_BIT;
-	    dacOF[jj] = 0;
-	    if(dacChanErr[jj]) 
-	    {
-	    	pLocalEpics->epicsOutput.statDac[jj] &= ~(DAC_TIMING_BIT);
-	    }
- 	    else pLocalEpics->epicsOutput.statDac[jj] |= DAC_TIMING_BIT;
-	    dacChanErr[jj] = 0;
-	    for(ii=0;ii<MAX_DAC_CHN_PER_MOD;ii++)
-	    {
-
-                if (pLocalEpics->epicsOutput.overflowDacAcc[jj][ii] > OVERFLOW_CNTR_LIMIT) {
-		   pLocalEpics->epicsOutput.overflowDacAcc[jj][ii] = 0;
-                }
-		pLocalEpics->epicsOutput.overflowDac[jj][ii] = overflowDac[jj][ii];
-		overflowDac[jj][ii] = 0;
-
-	    }
-	  }
-        }
+    if(cycleNum == HKP_ADC_DAC_STAT_UPDATES)
+    {
+	  	pLocalEpics->epicsOutput.ovAccum = overflowAcc;
+		feStatus |= app_adc_status_update(&adcInfo);
+		feStatus |= app_dac_status_update(&dacInfo);
+	}
 	// Capture end of cycle time.
-        rdtscl(cpuClock[CPU_TIME_CYCLE_END]);
+    rdtscl(cpuClock[CPU_TIME_CYCLE_END]);
 
 	/// \> Compute code cycle time diag information.
 	cycleTime = (cpuClock[CPU_TIME_CYCLE_END] - cpuClock[CPU_TIME_CYCLE_START])/CPURATE;
+
 	// Hold the max cycle time over the last 1 second
 	if(cycleTime > timeHold) { 
 		timeHold = cycleTime;
@@ -1033,6 +706,7 @@ udelay(1000);
 	// Hold the max cycle time since last diag reset
 	if(cycleTime > timeHoldMax) timeHoldMax = cycleTime;
 	adcHoldTime = (cpuClock[CPU_TIME_CYCLE_START] - adcTime)/CPURATE;
+
 	// Avoid calculating the max hold time for the first few seconds
 	if (cycleNum != 0 && (startGpsTime+3) < cycle_gps_time) {
 		if(adcHoldTime > adcHoldTimeMax) adcHoldTimeMax = adcHoldTime;
@@ -1045,37 +719,36 @@ udelay(1000);
 	usrTime = (cpuClock[CPU_TIME_USR_END] - cpuClock[CPU_TIME_USR_START])/CPURATE;
 	if(usrTime > usrHoldTime) usrHoldTime = usrTime;
 
-        /// \> Update internal cycle counters
-          cycleNum += 1;
+    /// \> Update internal cycle counters
+    cycleNum += 1;
 #ifdef DIAG_TEST
-          if(pLocalEpics->epicsInput.bumpCycle != 0) {
+    if(pLocalEpics->epicsInput.bumpCycle != 0) {
 	  	cycleNum += pLocalEpics->epicsInput.bumpCycle;
 		pLocalEpics->epicsInput.bumpCycle = 0;
-	  }
+  	}
 #endif
-          cycleNum %= CYCLE_PER_SECOND;
-	  clock1Min += 1;
-	  clock1Min %= CYCLE_PER_MINUTE;
-          if(subcycle == DAQ_CYCLE_CHANGE) 
-	  {
+    cycleNum %= CYCLE_PER_SECOND;
+	clock1Min += 1;
+	clock1Min %= CYCLE_PER_MINUTE;
+    if(subcycle == DAQ_CYCLE_CHANGE) 
+	{
 		daqCycle = (daqCycle + 1) % DAQ_NUM_DATA_BLOCKS_PER_SECOND;
 		if(!(daqCycle % 2)) pLocalEpics->epicsOutput.epicsSync = daqCycle;
-	  }
-          if(subcycle == END_OF_DAQ_BLOCK) /*we have reached the 16Hz second barrier*/
-            {
-              /* Reset the data cycle counter */
-              subcycle = 0;
-  
-            }
-          else{
-            /* Increment the internal cycle counter */
-            subcycle ++;                                                
-          }
+  	}
+    if(subcycle == END_OF_DAQ_BLOCK) /*we have reached the 16Hz second barrier*/
+    {
+    	/* Reset the data cycle counter */
+        subcycle = 0;
+     }
+     else{
+   		/* Increment the internal cycle counter */
+        subcycle ++;                                                
+     }
 
 /// \> If not exit request, then continue INFINITE LOOP  *******
   }
 
-  printf("exiting from fe_code()\n");
+  // printf("exiting from fe_code()\n");
   pLocalEpics->epicsOutput.cpuMeter = 0;
 
   deallocate_dac_channels();
diff --git a/src/fe/controllerAppUser.c b/src/fe/controllerAppUser.c
index e72979966..97055b09d 100644
--- a/src/fe/controllerAppUser.c
+++ b/src/fe/controllerAppUser.c
@@ -41,6 +41,7 @@
 #include "fm10Gen.h"		// CDS filter module defs and C code
 #include "feComms.h"		// Lvea control RFM network defs.
 #include "daqmap.h"		// DAQ network layout
+#include "cds_types.h"
 #include "controller.h"
 
 #ifndef NO_DAQ
@@ -184,14 +185,11 @@ int fe_start()
   static int clock1Min = 0;		///  @param clockMin Minute counter (Not Used??)
   struct timespec tp;
   static struct timespec cpuClock[CPU_TIMER_CNT];	///  @param cpuClock[] Code timing diag variables
+int dacOF[MAX_DAC_MODULES]; 
 
-  int adcData[MAX_ADC_MODULES][MAX_ADC_CHN_PER_MOD];	/// @param adcData[][]  ADC raw data
-  int adcChanErr[MAX_ADC_MODULES];
-  int adcWait = 0;
-  int adcOF[MAX_ADC_MODULES];		/// @param adcOF[]  ADC overrange counters
+  adcInfo_t adcInfo;
+  dacInfo_t dacInfo;
 
-  // int dacChanErr[MAX_DAC_MODULES];
-  int dacOF[MAX_DAC_MODULES];		/// @param dacOF[]  DAC overrange counters
   static int dacWriteEnable = 0;	/// @param dacWriteEnable  No DAC outputs until >4 times through code
   					///< Code runs longer for first few cycles on startup as it settles in,
 					///< so this helps prevent long cycles during that time.
@@ -287,20 +285,6 @@ int fe_start()
   memset(proc_futures, 0, sizeof(proc_futures));
 
 
-/// \> Wait for BURT restore.\n
-/// - ---- Code will exit if BURT flag not set by EPICS sequencer.
-  // Do not proceed until EPICS has had a BURT restore *******************************
-  printf("Waiting for EPICS BURT Restore = %d\n", pLocalEpics->epicsInput.burtRestore);
-  cnt = 0;
-  do{
-	usleep(80000);
-  	printf("Waiting for EPICS BURT %d\n", cnt++);
-  }while(!pLocalEpics->epicsInput.burtRestore);
-
-  printf("BURT Restore Complete\n");
-
-// BURT has completed *******************************************************************
-
 /// < Read in all Filter Module EPICS coeff settings
     for(ii=0;ii<MAX_MODULES;ii++)
     {
@@ -512,11 +496,11 @@ usleep(1000);
                         do{
                                 // usleep(1);
 		    		clock_gettime(CLOCK_MONOTONIC, &cpuClock[CPU_TIME_ADC_WAIT]);
-				adcWait = BILLION * (cpuClock[CPU_TIME_ADC_WAIT].tv_sec - cpuClock[CPU_TIME_RDY_ADC].tv_sec) + 
+				adcInfo.adcWait = BILLION * (cpuClock[CPU_TIME_ADC_WAIT].tv_sec - cpuClock[CPU_TIME_RDY_ADC].tv_sec) + 
 	    	               			     cpuClock[CPU_TIME_ADC_WAIT].tv_nsec - cpuClock[CPU_TIME_RDY_ADC].tv_nsec;
-				adcWait /= 1000;
+				adcInfo.adcWait /= 1000;
                                 // kk++;
-                        }while((ioMemData->iodata[mm][ioMemCntr].cycle != ioClock) && (adcWait < MAX_ADC_WAIT_SLAVE));
+                        }while((ioMemData->iodata[mm][ioMemCntr].cycle != ioClock) && (adcInfo.adcWait < MAX_ADC_WAIT_SLAVE));
 			timeSec = ioMemData->iodata[mm][ioMemCntr].timeSec;
 			if (cycle_gps_time == 0) {
 				startGpsTime = timeSec;
@@ -525,7 +509,7 @@ usleep(1000);
 			cycle_gps_time = timeSec;
 
 			/// - --------- If data not ready in time, set error, release DAC channel reservation and exit the code.
-                        if(adcWait >= MAX_ADC_WAIT_SLAVE)
+                        if(adcInfo.adcWait >= MAX_ADC_WAIT_SLAVE)
                         {
                                 printf ("ADC TIMEOUT %d %d %d %d\n",mm,ioMemData->iodata[mm][ioMemCntr].cycle, ioMemCntr,ioClock);
 	  			pLocalEpics->epicsOutput.stateWord = FE_ERROR_ADC;
@@ -536,23 +520,23 @@ usleep(1000);
                         for(ii=0;ii<MAX_ADC_CHN_PER_MOD;ii++)
                         {
 				/// - ---- Read data from shared memory.
-                                adcData[jj][ii] = ioMemData->iodata[mm][ioMemCntr].data[ii];
+                                adcInfo.adcData[jj][ii] = ioMemData->iodata[mm][ioMemCntr].data[ii];
 #ifdef FLIP_SIGNALS
-                                adcData[jj][ii] *= -1;
+                                adcInfo.adcData[jj][ii] *= -1;
 #endif
-                                dWord[jj][ii] = adcData[jj][ii];
+                                dWord[jj][ii] = adcInfo.adcData[jj][ii];
 #ifdef OVERSAMPLE
 				/// - ---- Downsample ADC data from 64K to rate of user application
 				if (dWordUsed[jj][ii]) {
 					dWord[jj][ii] = iir_filter_biquad(dWord[jj][ii],FE_OVERSAMPLE_COEFF,2,&dHistory[ii+jj*32][0]);
 				}
 			/// - ---- Check for ADC data over/under range
-			if((adcData[jj][ii] > limit) || (adcData[jj][ii] < -limit))
+			if((adcInfo.adcData[jj][ii] > limit) || (adcInfo.adcData[jj][ii] < -limit))
 			  {
-				overflowAdc[jj][ii] ++;
+				adcInfo.overflowAdc[jj][ii] ++;
 				pLocalEpics->epicsOutput.overflowAdcAcc[jj][ii] ++;
 				overflowAcc ++;
-				adcOF[jj] = 1;
+				adcInfo.adcOF[jj] = 1;
 				odcStateWord |= ODC_ADC_OVF;
 			  }
 #endif
@@ -651,7 +635,7 @@ usleep(1000);
                         /// - --------- If overflow, clip at DAC limits and report errors
                         if(dac_out > limit || dac_out < -limit)
                         {
-                                overflowDac[jj][ii] ++;
+                                dacInfo.overflowDac[jj][ii] ++;
 				pLocalEpics->epicsOutput.overflowDacAcc[jj][ii] ++;
                                 overflowAcc ++;
                                 dacOF[jj] = 1;
@@ -662,7 +646,7 @@ usleep(1000);
 			/// - ---- If DAQKILL tripped, set output to zero.
                         if(!iopDacEnable) dac_out = 0;
 			/// - ---- Load last values to EPICS channels for monitoring on GDS_TP screen.
-                        dacOutEpics[jj][ii] = dac_out;
+                        dacInfo.dacOutEpics[jj][ii] = dac_out;
 
                         /// - ---- Load DAC testpoints
                         floatDacOut[16*jj + ii] = dac_out;
@@ -796,8 +780,8 @@ usleep(1000);
                 if (pLocalEpics->epicsInput.overflowReset) {
                    for (ii = 0; ii < 16; ii++) {
                       for (jj = 0; jj < cdsPciModules.adcCount; jj++) {
-                         overflowAdc[jj][ii] = 0;
-                         overflowAdc[jj][ii + 16] = 0;
+                         adcInfo.overflowAdc[jj][ii] = 0;
+                         adcInfo.overflowAdc[jj][ii + 16] = 0;
 			pLocalEpics->epicsOutput.overflowAdcAcc[jj][ii] = 0;
 			pLocalEpics->epicsOutput.overflowAdcAcc[jj][ii + 16] = 0;
                       }
@@ -828,7 +812,7 @@ usleep(1000);
 	      {
 	    	for(ii=0;ii<MAX_DAC_CHN_PER_MOD;ii++)
 	    	{
-			pLocalEpics->epicsOutput.dacValue[jj][ii] = dacOutEpics[jj][ii];
+			pLocalEpics->epicsOutput.dacValue[jj][ii] = dacInfo.dacOutEpics[jj][ii];
 		}
 	      }
 	}
@@ -840,29 +824,29 @@ usleep(1000);
 	  for(jj=0;jj<cdsPciModules.adcCount;jj++)
 	  {
 	    // SET/CLR Channel Hopping Error
-	    if(adcChanErr[jj]) 
+	    if(adcInfo.adcChanErr[jj]) 
 	    {
 	    	pLocalEpics->epicsOutput.statAdc[jj] &= ~(2);
 		feStatus |= FE_ERROR_ADC;;
 	    }
  	    else pLocalEpics->epicsOutput.statAdc[jj] |= 2;
-	    adcChanErr[jj] = 0;
+	    adcInfo.adcChanErr[jj] = 0;
 	    // SET/CLR Overflow Error
-	    if(adcOF[jj]) 
+	    if(adcInfo.adcOF[jj]) 
 	    {
 	    	pLocalEpics->epicsOutput.statAdc[jj] &= ~(4);
 		feStatus |= FE_ERROR_OVERFLOW;;
 	    }
  	    else pLocalEpics->epicsOutput.statAdc[jj] |= 4;
-	    adcOF[jj] = 0;
+	    adcInfo.adcOF[jj] = 0;
 	    for(ii=0;ii<32;ii++)
 	    {
 
                 if (pLocalEpics->epicsOutput.overflowAdcAcc[jj][ii] > OVERFLOW_CNTR_LIMIT) {
 		   pLocalEpics->epicsOutput.overflowAdcAcc[jj][ii] = 0;
                 }
-		pLocalEpics->epicsOutput.overflowAdc[jj][ii] = overflowAdc[jj][ii];
-		overflowAdc[jj][ii] = 0;
+		pLocalEpics->epicsOutput.overflowAdc[jj][ii] = adcInfo.overflowAdc[jj][ii];
+		adcInfo.overflowAdc[jj][ii] = 0;
 
 	    }
 	  }
@@ -887,8 +871,8 @@ usleep(1000);
                 if (pLocalEpics->epicsOutput.overflowDacAcc[jj][ii] > OVERFLOW_CNTR_LIMIT) {
 		   pLocalEpics->epicsOutput.overflowDacAcc[jj][ii] = 0;
                 }
-		pLocalEpics->epicsOutput.overflowDac[jj][ii] = overflowDac[jj][ii];
-		overflowDac[jj][ii] = 0;
+		pLocalEpics->epicsOutput.overflowDac[jj][ii] = dacInfo.overflowDac[jj][ii];
+		dacInfo.overflowDac[jj][ii] = 0;
 
 	    }
 	  }
diff --git a/src/fe/controllerIop.c b/src/fe/controllerIop.c
index 406570321..4b5d7b895 100644
--- a/src/fe/controllerIop.c
+++ b/src/fe/controllerIop.c
@@ -70,6 +70,7 @@ int printk(const char *fmt, ...) {
 #include "fm10Gen.h"		// CDS filter module defs and C code
 #include "feComms.h"		// Lvea control RFM network defs.
 #include "daqmap.h"		// DAQ network layout
+#include "cds_types.h"
 #include "controller.h"
 
 #ifndef NO_DAQ
@@ -92,11 +93,17 @@ int printk(const char *fmt, ...) {
 #include "dolphin.c"
 #endif
 
+
 #ifdef TIME_MASTER
 TIMING_SIGNAL *pcieTimer;
 #endif
 
 
+adcInfo_t adcinfo;
+dacInfo_t dacinfo;
+duotone_diag_t dt_diag;
+timing_diag_t timeinfo;
+
 // Contec 64 input bits plus 64 output bits (Standard for aLIGO)
 /// Contec6464 input register values
 unsigned int CDIO6464InputInput[MAX_DIO_MODULES]; // Binary input bits
@@ -133,39 +140,18 @@ unsigned int timeSec = 0;
 unsigned int timeSecDiag = 0;
 /* 1 - error occured on shmem; 2 - RFM; 3 - Dolphin */
 unsigned int ipcErrBits = 0;
-int adcTime;			///< Used in code cycle timing
-int adcHoldTime;		///< Stores time between code cycles
-int adcHoldTimeMax;		///< Stores time between code cycles
-int adcHoldTimeEverMax;		///< Maximum cycle time recorded
-int adcHoldTimeEverMaxWhen;
-int cpuTimeEverMax;		///< Maximum code cycle time recorded
-int cpuTimeEverMaxWhen;
-int startGpsTime;
-int adcHoldTimeMin;
-int adcHoldTimeAvg;
-int adcHoldTimeAvgPerSec;
-int usrTime;			///< Time spent in user app code
-int usrHoldTime;		///< Max time spent in user app code
 int cardCountErr = 0;
-int cycleTime;			///< Current cycle time
-int timeHold = 0;			///< Max code cycle time within 1 sec period
-int timeHoldHold = 0;			///< Max code cycle time within 1 sec period; hold for another sec
-int timeHoldWhen= 0;			///< Cycle number within last second when maximum reached; running
-int timeHoldWhenHold = 0;		///< Cycle number within last second when maximum reached
-
-// The following are for timing histograms written to /proc files
-#if defined(SERVO64K) || defined(SERVO32K)
-unsigned int cycleHist[32];
-unsigned int cycleHistMax[32];
-unsigned int cycleHistWhen[32];
-unsigned int cycleHistWhenHold[32];
-#elif defined(SERVO16K)
-unsigned int cycleHist[64];
-unsigned int cycleHistMax[64];
-unsigned int cycleHistWhen[64];
-unsigned int cycleHistWhenHold[64];
-#endif
 
+int ioClockDac = DAC_PRELOAD_CNT;
+int ioMemCntr = 0;
+int ioMemCntrDac = DAC_PRELOAD_CNT;
+int dac_out = 0;			/// @param dac_out Integer value sent to DAC FIFO
+int dacEnable = 0;
+int pBits[9] = {1,2,4,8,16,32,64,128,256};	/// @param pBits[] Lookup table for quick power of 2 calcs
+int dacOF[MAX_DAC_MODULES];		/// @param dacOF[]  DAC overrange counters
+int dacWriteEnable = 0;	/// @param dacWriteEnable  No DAC outputs until >4 times through code
+int dacTimingErrorPending[MAX_DAC_MODULES];
+static int dacTimingError = 0;
 
 struct rmIpcStr *daqPtr;
 int dacWatchDog = 0;
@@ -175,6 +161,8 @@ int  getGpsTime(unsigned int *tsyncSec, unsigned int *tsyncUsec);
 // Include C code modules
 #include "moduleLoadIop.c"
 #include "map.c"
+#include <drv/iop_adc_functions.c>
+#include <drv/iop_dac_functions.c>
 
 
 char daqArea[2*DAQ_DCU_SIZE];		// Space allocation for daqLib buffers
@@ -212,35 +200,24 @@ int initialDiagReset = 1;
 ///	- 
 void *fe_start(void *arg)
 {
-  int longestWrite2 = 0;
   int tempClock[4];
-  int ii,jj,kk,ll,mm;			// Dummy loop counter variables
+  int ii,jj,kk,ll;			// Dummy loop counter variables
+  // int mm;
   static int clock1Min = 0;		///  @param clockMin Minute counter (Not Used??)
   static int cpuClock[CPU_TIMER_CNT];	///  @param cpuClock[] Code timing diag variables
-  static int chanHop = 0;		/// @param chanHop Adc channel hopping status
 
-  int adcData[MAX_ADC_MODULES][MAX_ADC_CHN_PER_MOD];	/// @param adcData[][]  ADC raw data
-  int adcChanErr[MAX_ADC_MODULES];
-  int adcWait = 0;
-  int adcOF[MAX_ADC_MODULES];		/// @param adcOF[]  ADC overrange counters
 
-  // int dacChanErr[MAX_DAC_MODULES];
-  int dacOF[MAX_DAC_MODULES];		/// @param dacOF[]  DAC overrange counters
-  static int dacWriteEnable = 0;	/// @param dacWriteEnable  No DAC outputs until >4 times through code
   					///< Code runs longer for first few cycles on startup as it settles in,
 					///< so this helps prevent long cycles during that time.
-  int limit = OVERFLOW_LIMIT_16BIT;      /// @param limit ADC/DAC overflow test value
-  int mask = GSAI_DATA_MASK;            /// @param mask Bit mask for ADC/DAC read/writes
-  int num_outs = MAX_DAC_CHN_PER_MOD;   /// @param num_outs Number of DAC channels variable
-  volatile int *packedData;		/// @param *packedData Pointer to ADC PCI data space
-  volatile unsigned int *pDacData;	/// @param *pDacData Pointer to DAC PCI data space
-  int wtmin,wtmax;			/// @param wtmin Time window for startup on IRIG-B
-  int dacEnable = 0;
-  int pBits[9] = {1,2,4,8,16,32,64,128,256};	/// @param pBits[] Lookup table for quick power of 2 calcs
+  // int limit = OVERFLOW_LIMIT_16BIT;      /// @param limit ADC/DAC overflow test value
+  // int mask = GSAI_DATA_MASK;            /// @param mask Bit mask for ADC/DAC read/writes
+  // int num_outs = MAX_DAC_CHN_PER_MOD;   /// @param num_outs Number of DAC channels variable
+  // volatile unsigned int *pDacData;	/// @param *pDacData Pointer to DAC PCI data space
+  // int dacEnable = 0;
+  // int pBits[9] = {1,2,4,8,16,32,64,128,256};	/// @param pBits[] Lookup table for quick power of 2 calcs
   int sync21ppsCycles = 0;		/// @param sync32ppsCycles Number of attempts to sync to 1PPS
-  int dkiTrip = 0;
+  // int dkiTrip = 0;
   RFM_FE_COMMS *pEpicsComms;		/// @param *pEpicsComms Pointer to EPICS shared memory space
-  int timeHoldMax = 0;			/// @param timeHoldMax Max code cycle time since last diag reset
   int myGmError2 = 0;			/// @param myGmError2 Myrinet error variable
   int status;				/// @param status Typical function return value
   float onePps;				/// @param onePps Value of 1PPS signal, if used, for diagnostics
@@ -262,37 +239,35 @@ void *fe_start(void *arg)
   int mxDiag = 0;
   int mxDiagR = 0;
 // ****** Share data
+#if 0
   int ioClockDac = DAC_PRELOAD_CNT;
   int ioMemCntr = 0;
   int ioMemCntrDac = DAC_PRELOAD_CNT;
-  double dac_in =  0.0;			/// @param dac_in DAC value after upsample filtering
   int dac_out = 0;			/// @param dac_out Integer value sent to DAC FIFO
+#endif
 
   int feStatus = 0;
+  int dkiTrip = 0;
 
   int clk, clk1;			// Used only when run on timer enabled (test mode)
 
-  static float duotone[IOP_IO_RATE];		// Duotone timing diagnostic variables
-  static float duotoneDac[IOP_IO_RATE];
-  float duotoneTimeDac;
-  float duotoneTime;
-  static float duotoneTotal = 0.0;
-  static float duotoneMean = 0.0;
-  static float duotoneTotalDac = 0.0;
-  static float duotoneMeanDac = 0.0;
-  static int dacDuoEnable = 0;
-  static int dacTimingError = 0;
-  static int dacTimingErrorPending[MAX_DAC_MODULES];
-
-  volatile GSA_18BIT_DAC_REG *dac18bitPtr;	// Pointer to 16bit DAC memory area
-  volatile GSA_20BIT_DAC_REG *dac20bitPtr;  // Pointer to 20bit DAC memory area
-  volatile GSC_DAC_REG *dac16bitPtr;		// Pointer to 18bit DAC memory area
+
+  // volatile GSA_18BIT_DAC_REG *dac18bitPtr;	// Pointer to 16bit DAC memory area
+  // volatile GSA_20BIT_DAC_REG *dac20bitPtr;  // Pointer to 20bit DAC memory area
+  // volatile GSC_DAC_REG *dac16bitPtr;		// Pointer to 18bit DAC memory area
   unsigned int usec = 0;
-  unsigned int offset = 0;
 
 
-  int cnt = 0;
   unsigned long cpc;
+  float duotoneTimeDac;
+  float duotoneTime;
+
+  // static int dacTimingErrorPending[MAX_DAC_MODULES];
+  // static int dacTimingError = 0;
+  // int dacOF[MAX_DAC_MODULES];		/// @param dacOF[]  DAC overrange counters
+  // static int dacWriteEnable = 0;	/// @param dacWriteEnable  No DAC outputs until >4 times through code
+  // int dacChanErr[MAX_DAC_MODULES];
+
 
 /// **********************************************************************************************\n
 /// Start Initialization Process \n
@@ -306,40 +281,18 @@ void *fe_start(void *arg)
 
   fz_daz(); /// \> Kill the denorms!
 
-// Set memory for cycle time history diagnostics
-#if defined(SERVO64K) || defined(SERVO32K) || defined(SERVO16K)
-  memset(cycleHist, 0, sizeof(cycleHist));
-  memset(cycleHistMax, 0, sizeof(cycleHistMax));
-  memset(cycleHistWhen, 0, sizeof(cycleHistWhen));
-  memset(cycleHistWhenHold, 0, sizeof(cycleHistWhenHold));
-#endif
-
   /// \> Init comms with EPICS processor */
   pEpicsComms = (RFM_FE_COMMS *)_epics_shm;
   pLocalEpics = (CDS_EPICS *)&pEpicsComms->epicsSpace;
   pEpicsDaq = (char *)&(pLocalEpics->epicsOutput);
-// printf("Epics at 0x%x and DAQ at 0x%x  size = %d \n",pLocalEpics,pEpicsDaq,sizeof(CDS_EPICS_IN));
 
+adcInfo_t *padcinfo = (adcInfo_t *)&adcinfo;
 #ifdef OVERSAMPLE
   /// \> Zero out filter histories
   memset(dHistory, 0, sizeof(dHistory));
   memset(dDacHistory, 0, sizeof(dDacHistory));
 #endif
 
-  /// \> Zero out DAC outputs
-  for (ii = 0; ii < MAX_DAC_MODULES; ii++)
-  {
-    dacTimingErrorPending[ii] = 0;
-    for (jj = 0; jj < 16; jj++) {
- 	dacOut[ii][jj] = 0.0;
- 	dacOutUsed[ii][jj] = 0;
-	dacOutBufSize[ii] = 0;
-	// Zero out DAC channel map in the shared memory
-	// to be used to check on slaves' channel allocation
-	ioMemData->dacOutUsed[ii][jj] = 0;
-    }
-  }
-
   /// \> Set pointers to filter module data buffers. \n
   /// - ---- Prior to V2.8, separate local/shared memories for FILT_MOD data.\n
   /// - ---- V2.8 and later, code uses EPICS shared memory only. This was done to: \n
@@ -362,35 +315,12 @@ void *fe_start(void *arg)
   if(cdsPciModules.cDio1616lCount) syncSource = SYNC_SRC_TDS;
   else syncSource = SYNC_SRC_1PPS;
 
-printf("Sync source = %d\n",syncSource);
 
 #ifdef TIME_MASTER
 pcieTimer = (TIMING_SIGNAL *) ((volatile char *)(cdsPciModules.dolphinWrite[0]) + IPC_PCIE_TIME_OFFSET);
-printf("I am a TIMING MASTER **************\n");
+// printf("I am a TIMING MASTER **************\n");
 #endif
 
-
-/// \> Wait for BURT restore.\n
-/// - ---- Code will exit if BURT flag not set by EPICS sequencer.
-  // Do not proceed until EPICS has had a BURT restore *******************************
-  printf("Waiting for EPICS BURT Restore = %d\n", pLocalEpics->epicsInput.burtRestore);
-  cnt = 0;
-  do{
-#ifndef NO_CPU_SHUTDOWN
-	udelay(MAX_UDELAY);
-        udelay(MAX_UDELAY);
-        udelay(MAX_UDELAY);
-#else
-	msleep(80);
-#endif
-  	printf("Waiting for EPICS BURT %d\n", cnt++);
-	cpu_relax();
-  }while(!pLocalEpics->epicsInput.burtRestore);
-
-  printf("BURT Restore Complete\n");
-
-// BURT has completed *******************************************************************
-
 /// < Read in all Filter Module EPICS coeff settings
     for(ii=0;ii<MAX_MODULES;ii++)
     {
@@ -428,11 +358,11 @@ printf("I am a TIMING MASTER **************\n");
 
   /// \> Initialize IIR filter bank values
     if (initVars(pDsp[0], pDsp[0], dspCoeff, MAX_MODULES, pCoeff[0])) {
-    	printf("Filter module init failed, exiting\n");
+    	// printf("Filter module init failed, exiting\n");
+  		pLocalEpics->epicsOutput.fe_status = FILT_INIT_ERROR;
 	return 0;
     }
 
-  printf("Initialized servo control parameters.\n");
 
 udelay(1000);
 
@@ -454,11 +384,18 @@ udelay(1000);
   daq.filtTpSize = MAX_MODULES * 3;
   daq.xTpMin = daq.filtTpMax;
   daq.xTpMax = daq.xTpMin + GDS_MAX_NFM_TP;
+  
+  /// - ---- Initialize DAQ function
+  status = daqWrite(0,dcuId,daq,DAQ_RATE,testpoint,dspPtr[0],0, (int *)(pLocalEpics->epicsOutput.gdsMon),xExc,pEpicsDaq);
+  if(status == -1) 
+  {
+    // printf("DAQ init failed -- exiting\n");
+  	pLocalEpics->epicsOutput.fe_status = DAQ_INIT_ERROR;
+    vmeDone = 1;
+    return(0);
+  }
 
-  printf("DAQ Ex Min/Max = %d %d\n",daq.filtExMin,daq.filtExMax);
-  printf("DAQ XEx Min/Max = %d %d\n",daq.xExMin,daq.xExMax);
-  printf("DAQ Tp Min/Max = %d %d\n",daq.filtTpMin,daq.filtTpMax);
-  printf("DAQ XTp Min/Max = %d %d\n",daq.xTpMin,daq.xTpMax);
+#endif
 
   /// - ---- Assign DAC testpoint pointers
   for (ii = 0; ii <  cdsPciModules.dacCount; ii++)
@@ -468,83 +405,54 @@ udelay(1000);
   // Zero out storage
   memset(floatDacOut, 0, sizeof(floatDacOut));
 
-#endif
   pLocalEpics->epicsOutput.ipcStat = 0;
   pLocalEpics->epicsOutput.fbNetStat = 0;
   pLocalEpics->epicsOutput.tpCnt = 0;
 
-#if !defined(NO_DAQ) && !defined(IOP_TASK)
-  /// - ---- Initialize DAQ function
-  status = daqWrite(0,dcuId,daq,DAQ_RATE,testpoint,dspPtr[0],0, (int *)(pLocalEpics->epicsOutput.gdsMon),xExc,pEpicsDaq);
-  if(status == -1) 
-  {
-    printf("DAQ init failed -- exiting\n");
-    vmeDone = 1;
-    return(0);
-  }
-#endif
-
-
   // Clear the code exit flag
   vmeDone = 0;
 
   /// \> Call user application software initialization routine.
-  printf("Calling feCode() to initialize\n");
+  // printf("Calling feCode() to initialize\n");
   iopDacEnable = feCode(cycleNum,dWord,dacOut,dspPtr[0],&dspCoeff[0], (struct CDS_EPICS *)pLocalEpics,1);
 
-  // Clear timing diags.
-  adcHoldTime = 0;
-  adcHoldTimeMax = 0;
-  adcHoldTimeEverMax = 0;	
-  adcHoldTimeEverMaxWhen = 0;	
-  cpuTimeEverMax = 0;		
-  cpuTimeEverMaxWhen = 0;	
-  startGpsTime = 0;
-  adcHoldTimeMin = 0xffff;	
-  adcHoldTimeAvg = 0;		
-  usrHoldTime = 0;		
+  timeinfo.cpuTimeEverMax = 0;		
+  timeinfo.cpuTimeEverMaxWhen = 0;	
+  timeinfo.startGpsTime = 0;
+  timeinfo.usrHoldTime = 0;		
+  timeinfo.timeHold = 0;		
+  timeinfo.timeHoldHold = 0;		
+  timeinfo.timeHoldWhen = 0;		
+  timeinfo.timeHoldWhenHold = 0;		
+  timeinfo.usrTime = 0;		
+  timeinfo.cycleTime = 0;		
   missedCycle = 0;
 
-  /// \> If IOP,  Initialize the ADC modules
-  for(jj=0;jj<cdsPciModules.adcCount;jj++)
-  {
-	  // Setup the DMA registers
-	  status = gsc16ai64DmaSetup(jj);
-	  // Preload input memory with dummy variables to test that new ADC data has arrived.
-	  packedData = (int *)cdsPciModules.pci_adc[jj];
-	  // Write a dummy 0 to first ADC channel location
-	  // This location should never be zero when the ADC writes data as it should always
-	  // have an upper bit set indicating channel 0.
-          *packedData = 0x0;
-          if (cdsPciModules.adcType[jj] == GSC_18AISS6C)  packedData += 5;
-          else packedData += 31;
-	  // Write a number into the last channel which the ADC should never write ie no
-	  // upper bits should be set in channel 31.
-          *packedData = DUMMY_ADC_VAL;
-	  // Set ADC Present Flag
-  	  pLocalEpics->epicsOutput.statAdc[jj] = 1;
-	  adcRdTimeErr[jj] = 0;
-  }
-  printf("ADC setup complete \n");
-
-  /// \> If IOP, Initialize the DAC module variables
-  for(jj = 0; jj < cdsPciModules.dacCount; jj++) {
-  	pLocalEpics->epicsOutput.statDac[jj] = DAC_FOUND_BIT;
-        pDacData = (unsigned int *) cdsPciModules.pci_dac[jj];
-	// Arm DAC DMA for full data size
-	if(cdsPciModules.dacType[jj] == GSC_16AO16) {
-		status = gsc16ao16DmaSetup(jj);
-	} else if (cdsPciModules.dacType[jj] == GSC_20AO8){
-	         status = gsc20ao8DmaSetup(jj);
-	} else {
-		status = gsc18ao8DmaSetup(jj);
-	}
+  for(ii=0;ii<IOP_IO_RATE;ii++) {
+  	dt_diag.adc[ii] = 0;
+  	dt_diag.dac[ii] = 0;
   }
-  printf("DAC setup complete \n");
+  dt_diag.totalAdc = 0.0;
+  dt_diag.totalDac = 0.0;
+  dt_diag.meanAdc = 0.0;
+  dt_diag.meanDac = 0.0;
+  dt_diag.dacDuoEnable = 0.0;
+
+  /// \> Initialize the ADC modules *************************************
+  pLocalEpics->epicsOutput.fe_status = INIT_ADC_MODS;
+  status = iop_adc_init(padcinfo);
+  // printf("ADC setup complete \n");
+
+  pLocalEpics->epicsOutput.fe_status = INIT_DAC_MODS;
+  /// \> Initialize the DAC module variables  **********************************
+  status = iop_dac_init(dacTimingErrorPending);
+
+  // printf("DAC setup complete \n");
+  pLocalEpics->epicsOutput.fe_status = INIT_SYNC;
 
   
 
-/// \> If IOP, find the code syncrhonization source. \n
+/// \> Find the code syncrhonization source. \n
 /// - Standard aLIGO Sync source is the Timing Distribution System (TDS) (SYNC_SRC_TDS). 
   if (!run_on_timer) {
   switch(syncSource)
@@ -554,14 +462,13 @@ udelay(1000);
 		/// - ---- Turn off TDS slave unit timing clocks, in turn removing clocks from ADC/DAC modules.
 		for(ii=0;ii<tdsCount;ii++)
 		{
-		CDIO1616Output[ii] = TDS_STOP_CLOCKS;
-		CDIO1616Input[ii] = contec1616WriteOutputRegister(&cdsPciModules, tdsControl[ii], CDIO1616Output[ii]);
-		printf("writing BIO %d\n",tdsControl[ii]);
+			CDIO1616Output[ii] = TDS_STOP_CLOCKS;
+			CDIO1616Input[ii] = contec1616WriteOutputRegister(&cdsPciModules, tdsControl[ii], CDIO1616Output[ii]);
 		}
 		udelay(MAX_UDELAY);
 		udelay(MAX_UDELAY);
 		/// - ---- Arm ADC modules
-    		gsc16ai64Enable(cdsPciModules.adcCount);
+    	gsc16ai64Enable(cdsPciModules.adcCount);
 		/// - ----  Arm DAC outputs
 		gsc18ao8Enable(&cdsPciModules);
 		gsc16ao16Enable(&cdsPciModules);
@@ -574,21 +481,7 @@ udelay(1000);
 		/// values not written until a few cycle into run. \n
 		/// - --------- DAC timing diags will later check FIFO sizes to verify synchrounous timing.
 		#ifndef NO_DAC_PRELOAD
-		for(jj=0;jj<cdsPciModules.dacCount;jj++)
-		{       
-			if(cdsPciModules.dacType[jj] == GSC_18AO8)
-			{       
-				dac18bitPtr = (volatile GSA_18BIT_DAC_REG *)(dacPtr[jj]);
-				for(ii=0;ii<GSAO_18BIT_PRELOAD;ii++) dac18bitPtr->OUTPUT_BUF = 0;
-			} else if(cdsPciModules.dacType[jj] == GSC_20AO8) {
-		        dac20bitPtr = (volatile GSA_20BIT_DAC_REG *)(dacPtr[jj]);
-		        for(ii=0;ii<GSAO_20BIT_PRELOAD;ii++) dac20bitPtr->OUTPUT_BUF = 0;
-			}else{  
-				dac16bitPtr = dacPtr[jj];
-				printf("writing DAC %d\n",jj);
-				for(ii=0;ii<GSAO_16BIT_PRELOAD;ii++) dac16bitPtr->ODB = 0;
-			}       
-		}       
+		status = iop_dac_preload(dacPtr);
 		#endif
 		/// - ---- Start the timing clocks\n
 		/// - --------- Send start command to TDS slave.\n
@@ -596,62 +489,18 @@ udelay(1000);
 		// CDIO1616Output[tdsControl] = 0x7B00000;
 		for(ii=0;ii<tdsCount;ii++)
 		{
-		// CDIO1616Output[ii] = TDS_START_ADC_NEG_DAC_POS;
-		CDIO1616Output[ii] = TDS_START_ADC_NEG_DAC_POS | TDS_NO_DAC_DUOTONE;
-		CDIO1616Input[ii] = contec1616WriteOutputRegister(&cdsPciModules, tdsControl[ii], CDIO1616Output[ii]);
+			// CDIO1616Output[ii] = TDS_START_ADC_NEG_DAC_POS;
+			CDIO1616Output[ii] = TDS_START_ADC_NEG_DAC_POS | TDS_NO_DAC_DUOTONE;
+			CDIO1616Input[ii] = contec1616WriteOutputRegister(&cdsPciModules, tdsControl[ii], CDIO1616Output[ii]);
 		}
 		break;
 	case SYNC_SRC_1PPS:
-                printf("Sync src is 1PPS\n");
 #ifndef NO_DAC_PRELOAD
-		for(jj=0;jj<cdsPciModules.dacCount;jj++)
-		{       
-			if(cdsPciModules.dacType[jj] == GSC_18AO8)
-			{       
-				dac18bitPtr = (volatile GSA_18BIT_DAC_REG *)(dacPtr[jj]);
-				for(ii=0;ii<GSAO_18BIT_PRELOAD;ii++) dac18bitPtr->OUTPUT_BUF = 0;
-			} else if(cdsPciModules.dacType[jj] == GSC_20AO8) {
-                dac20bitPtr = (volatile GSA_20BIT_DAC_REG *)(dacPtr[jj]);
-                for(ii=0;ii<GSAO_20BIT_PRELOAD;ii++) dac20bitPtr->OUTPUT_BUF = 0;
-			}else{  
-				dac16bitPtr = dacPtr[jj];
-				printf("writing DAC %d\n",jj);
-				for(ii=0;ii<GSAO_16BIT_PRELOAD;ii++) dac16bitPtr->ODB = 0;
-			}       
-		}       
+		status = iop_dac_preload(dacPtr);
 #endif
 		// Arm ADC modules
 		// This has to be done sequentially, one at a time.
-                kk = 0;
-                for(jj=0;jj<cdsPciModules.adcCount;jj++)
-                {
-                    packedData = (int *)cdsPciModules.pci_adc[0];
-                    packedData += 31;
-                    gsc16ai64Enable1PPS(jj);
-                    rdtscl(cpuClock[jj]);
-                    status = gsc16ai64WaitDmaDone(0, packedData);
-                    kk ++;
-                    udelay(2);
-                    for(ii=0;ii<kk;ii++) {
-                          gsc16ai64DmaEnable(ii);
-                    }
-                }
-                // Need to do some dummy reads here to allow time for last ADC to arm
-                // as it takes two clock cycles past arm to actually deliver data.
-                for(ii=0;ii<cdsPciModules.adcCount;ii++)
-                {
-                    // Want to verify ADC FIFOs are empty to ensure they are in sync.
-                    status = gsc16ai64WaitDmaDone(0, packedData);
-                    cpuClock[ii] = gsc16ai64CheckAdcBuffer(ii);
-                    for(jj=0;jj<cdsPciModules.adcCount;jj++)
-                    {
-                         gsc16ai64DmaEnable(jj);
-                    }
-                }
-                // Print out the FIFO info to dmesg to verify sync.
-                for(jj=0;jj<cdsPciModules.adcCount;jj++) {
-                    printf("ADC buffer %d = %d\n",jj,cpuClock[jj]);
-                }
+		status = sync_adc_2_1pps();
 		break;
 	default: {
 		    // IRIG-B card not found, so use CPU time to get close to 1PPS on startup
@@ -663,11 +512,13 @@ udelay(1000);
 
 
   if (run_on_timer) {	// NOT normal operating mode; used for test systems without I/O cards/chassis
-    printf("*******************************\n");
-    printf("*     Running on timer!       *\n");
-    printf("*******************************\n");
+    // printf("*******************************\n");
+    // printf("*     Running on timer!       *\n");
+    // printf("*******************************\n");
+  				pLocalEpics->epicsOutput.fe_status = RUN_ON_TIMER;
   } else {
-    printf("Triggered the ADC\n");
+    // printf("Triggered the ADC\n");
+  				pLocalEpics->epicsOutput.fe_status = NORMAL_RUN;
   }
 
   onePpsTime = cycleNum;
@@ -678,7 +529,7 @@ udelay(1000);
   timeSec = current_time() -1;
 #endif
 
-  rdtscl(adcTime);
+  rdtscl(adcinfo.adcTime);
 
   /// ******************************************************************************\n
   /// Enter the infinite FE control loop  ******************************************\n
@@ -757,8 +608,8 @@ udelay(1000);
 #endif
 
 /// \> On 1PPS mark \n
-       if(cycleNum == 0)
-        {
+    if(cycleNum == 0)
+    {
 	  /// - ---- Check awgtpman status.
 	  //printf("awgtpman gps = %d local = %d\n", pEpicsComms->padSpace.awgtpman_gps, timeSec);
 	  pLocalEpics->epicsOutput.awgStat = (pEpicsComms->padSpace.awgtpman_gps != timeSec);
@@ -767,19 +618,17 @@ udelay(1000);
 	  if(!iopDacEnable || dkiTrip) feStatus |= FE_ERROR_DAC_ENABLE;
 
 	  /// - ---- If IOP, Increment GPS second
-          timeSec ++;
-          pLocalEpics->epicsOutput.timeDiag = timeSec;
+      timeSec ++;
+      pLocalEpics->epicsOutput.timeDiag = timeSec;
 	  if (cycle_gps_time == 0) {
-		startGpsTime = timeSec;
-		pLocalEpics->epicsOutput.startgpstime = startGpsTime;
+		timeinfo.startGpsTime = timeSec;
+		pLocalEpics->epicsOutput.startgpstime = timeinfo.startGpsTime;
 	  }
 	  cycle_gps_time = timeSec;
 	}
 #ifdef NO_CPU_SHUTDOWN
 	if((cycleNum % 2048) == 0) usleep_range(2,4);
 #endif
-        for(ll=0;ll<sampleCount;ll++)
-        {
 /// IF IOP *************************** \n
 // Start of ADC Read *************************************************************************************
 	/// \> IF IOP, Wait for ADC data ready
@@ -788,180 +637,20 @@ udelay(1000);
 	/// increased to appropriate number of 65536 s/sec to match desired
 	/// code rate eg 32 samples each time thru before proceeding to match 2048 system.
 		// Read ADC data
-        for(jj=0;jj<cdsPciModules.adcCount;jj++)
-		{
-		    /// - ---- ADC DATA RDY is detected when last channel in memory no longer contains the
-		    /// dummy variable written during initialization and reset after the read.
-		    packedData = (int *)cdsPciModules.pci_adc[jj];
-                    if (cdsPciModules.adcType[jj] == GSC_18AISS6C) packedData += 5;
-               	    else packedData += 31;
-		
-		    rdtscl(cpuClock[CPU_TIME_RDY_ADC]);
-                    do {
-			/// - ---- Need to delay if not ready as constant banging of the input register
-			/// will slow down the ADC DMA.
-			// if(*packedData == DUMMY_ADC_VAL) {
-		    		rdtscl(cpuClock[CPU_TIME_ADC_WAIT]);
-				adcWait = (cpuClock[CPU_TIME_ADC_WAIT] - cpuClock[CPU_TIME_RDY_ADC])/CPURATE;
-			// }
-			/// - ---- Allow 1sec for data to be ready (should never take that long).
-                    }while((*packedData == DUMMY_ADC_VAL) && (adcWait < MAX_ADC_WAIT));
-#ifdef TIME_MASTER
-            pcieTimer->gps_time = timeSec;
-            pcieTimer->cycle = cycleNum;
-#endif
-
-			/// - ---- Added ADC timing diagnostics to verify timing consistent and all rdy together.
-		    if(jj==0)
-			    adcRdTime[jj] = (cpuClock[CPU_TIME_ADC_WAIT] - cpuClock[CPU_TIME_CYCLE_START]) / CPURATE;
-		    else
-			    adcRdTime[jj] = adcWait;
-	
-		    if(adcRdTime[jj] > adcRdTimeMax[jj]) adcRdTimeMax[jj] = adcRdTime[jj];
-
-		    if((jj==0) && (adcRdTimeMax[jj] > MAX_ADC_WAIT_CARD_0)) 
-			adcRdTimeErr[jj] ++;
-		    if((jj!=0) && (adcRdTimeMax[jj] > MAX_ADC_WAIT_CARD_S)) 
-			adcRdTimeErr[jj] ++;
-
-		    /// - --------- If data not ready in time, abort.
-		    /// Either the clock is missing or code is running too slow and ADC FIFO
-		    /// is overflowing.
-		    if (adcWait >= MAX_ADC_WAIT) {
-	  		pLocalEpics->epicsOutput.stateWord = FE_ERROR_ADC;
-	  		pLocalEpics->epicsOutput.diagWord |= ADC_TIMEOUT_ERR;
-                        stop_working_threads = 1;
-			vmeDone = 1;
-                        printf("timeout %d %d \n",jj,adcWait);
-			continue;
-		    }
-		    if(jj == 0) 
-		    {
-			// Capture cpu clock for cpu meter diagnostics
-			rdtscl(cpuClock[CPU_TIME_CYCLE_START]);
-			/// \> If first cycle of a new second, capture IRIG-B time. Standard for aLIGO is
-			/// TSYNC_RCVR.
-			if(cycleNum == 0) 
-			{
-				// if SymCom type, just do write to lock current time and read later
-				// This save a couple three microseconds here
-				if(cdsPciModules.gpsType == SYMCOM_RCVR) lockGpsTime();
-				if(cdsPciModules.gpsType == TSYNC_RCVR) 
-				{
-					/// - ---- Reading second info will lock the time register, allowing
-					/// nanoseconds to be read later (on next cycle). Two step process used to 
-					/// save CPU time here, as each read can take 2usec or more.
-					timeSec = getGpsSecTsync();
-				}
-			}
-			
-		    }
-
-#ifndef RFM_DIRECT_READ
-#ifdef FUTURE_RFM_DMA_CHECK
-                    /// \> If RFM cards, verify DMA is complete
-                    if(jj == 0 && (cycleNum % 4) == 0 && cdsPciModules.pci_rfm[0])
-                                vmic5565DMAdone(0);
-                    if(jj == 0 && (cycleNum % 4) == 0 && cdsPciModules.pci_rfm[1])
-                                vmic5565DMAdone(1);
-#endif
-#endif
-
-                    /// \> Read adc data
-                    packedData = (int *)cdsPciModules.pci_adc[jj];
-		    /// - ---- First, and only first, channel should have upper bit marker set.
-		    /// If not, have a channel hopping error.
-                    if(!(*packedData & ADC_1ST_CHAN_MARKER)) 
-		    {
-  			 adcChanErr[jj] = 1;
-			 chanHop = 1;
-	  	 	 pLocalEpics->epicsOutput.stateWord |= FE_ERROR_ADC;
-	 	    }	
-
-                    limit = OVERFLOW_LIMIT_16BIT;
-                    if (cdsPciModules.adcType[jj] == GSC_18AISS6C) {
-			limit = OVERFLOW_LIMIT_18BIT; // 18 bit limit
-			offset = GSAF_DATA_CODE_OFFSET; // Data coding offset in 18-bit DAC
-			mask = GSAF_DATA_MASK;
-			num_outs = GSAF_CHAN_COUNT;
-                    } else {
-		    	// Various ADC models have different number of channels/data bits
-                    	offset = GSAI_DATA_CODE_OFFSET;
-                    	mask = GSAI_DATA_MASK;
-                    	num_outs = GSAI_CHAN_COUNT;
-		    }
-		    /// - ---- Determine next ipc memory location to load ADC data
-		    ioMemCntr = (cycleNum % IO_MEMORY_SLOTS);
-                    /// - ----  Read adc data from PCI mapped memory into local variables
-                    for(ii=0;ii<num_outs;ii++)
-                    {
-			// adcData is the integer representation of the ADC data
-			adcData[jj][ii] = (*packedData & mask);
-			adcData[jj][ii]  -= offset;
-#ifdef DEC_TEST
-			if(ii==0)
-			{
-				adcData[jj][ii] = dspPtr[0]->data[0].exciteInput;
-			}
-#endif
-			// dWord is the double representation of the ADC data
-			// This is the value used by the rest of the code calculations.
-			dWord[jj][ii] = adcData[jj][ii];
-			/// - ----  Load ADC value into ipc memory buffer
-			ioMemData->iodata[jj][ioMemCntr].data[ii] = adcData[jj][ii];
-			packedData ++;
-                    }
-		    /// - ---- Write GPS time and cycle count as indicator to slave that adc data is ready
-	  	    ioMemData->gpsSecond = timeSec;;
-		    ioMemData->iodata[jj][ioMemCntr].timeSec = timeSec;;
-		    ioMemData->iodata[jj][ioMemCntr].cycle = cycleNum;
-
-		    /// - ---- Check for ADC overflows
-                    for(ii=0;ii<num_outs;ii++)
-                    {
-			if((adcData[jj][ii] > limit) || (adcData[jj][ii] < -limit))
-			  {
-				overflowAdc[jj][ii] ++;
-				pLocalEpics->epicsOutput.overflowAdcAcc[jj][ii] ++;
-				overflowAcc ++;
-				adcOF[jj] = 1;
-				odcStateWord |= ODC_ADC_OVF;
-			  }
-                    }
-
-		   /// - ---- Clear out last ADC data read for test on next cycle
-                   packedData = (int *)cdsPciModules.pci_adc[jj];
-                   *packedData = 0x0;
-
-                   if (cdsPciModules.adcType[jj] == GSC_18AISS6C) packedData += GSAF_CHAN_COUNT_M1;
-                   else packedData += GSAI_CHAN_COUNT_M1;
-
-                   *packedData = DUMMY_ADC_VAL;
-
-#ifdef DIAG_TEST
-// For DIAGS ONLY !!!!!!!!
-// This will change ADC DMA BYTE count
-// -- Greater than normal will result in channel hopping.
-// -- Less than normal will result in ADC timeout.
-// In both cases, real-time kernel code should exit with errors to dmesg
-          	   if(pLocalEpics->epicsInput.bumpAdcRd != 0) {
-		   	gsc16ai64DmaBump(jj,pLocalEpics->epicsInput.bumpAdcRd);
-		   	pLocalEpics->epicsInput.bumpAdcRd = 0;
-		   }
-#endif
-		}
-
+    for(ll=0;ll<sampleCount;ll++)
+    {
+		status = iop_adc_read (padcinfo, cpuClock);
 
-		  // Try synching to 1PPS on ADC[0][31] if not using IRIG-B or TDS
-		  // Only try for 1 sec.
-                  if(!sync21pps)
-                  {
+		// Try synching to 1PPS on ADC[0][31] if not using IRIG-B or TDS
+		// Only try for 1 sec.
+        if(!sync21pps)
+        {
 			// 1PPS signal should rise above 4000 ADC counts if present.
-                        if((adcData[0][31] < ONE_PPS_THRESH) && (sync21ppsCycles < (CYCLE_PER_SECOND*OVERSAMPLE_TIMES))) 
+            if((adcinfo.adcData[0][31] < ONE_PPS_THRESH) && (sync21ppsCycles < (CYCLE_PER_SECOND*OVERSAMPLE_TIMES))) 
 			{
 				ll = -1;
 				sync21ppsCycles ++;
-                        }else {
+            }else {
 				// Need to start clocking the DAC outputs.
 				gsc18ao8Enable(&cdsPciModules);
 				gsc16ao16Enable(&cdsPciModules);
@@ -970,15 +659,15 @@ udelay(1000);
 				if(sync21ppsCycles >= (CYCLE_PER_SECOND*OVERSAMPLE_TIMES))
 				{
 					syncSource = SYNC_SRC_NONE;
-					printf("NO SYNC SOURCE FOUND %d %d\n",sync21ppsCycles,adcData[0][31]);
+					// printf("NO SYNC SOURCE FOUND %d %d\n",sync21ppsCycles,adcinfo.adcData[0][31]);
 				} else {
 				// 1PPS found and synched to
-					printf("GPS Trigg %d %d\n",adcData[0][31],sync21pps);
+					// printf("GPS Trigg %d %d\n",adcinfo.adcData[0][31],sync21pps);
 					syncSource = SYNC_SRC_1PPS;
 				}
 				pLocalEpics->epicsOutput.timeErr = syncSource;
-                        }
-                }
+       		}
+		}
 
 	}
 /// END IF IOP \n
@@ -1001,7 +690,10 @@ udelay(1000);
    		gsc16ai64DmaEnable(jj);
 
   	odcStateWord = 0;
+
+// ********************************************************************
 /// WRITE DAC OUTPUTS ***************************************** \n
+// ********************************************************************
 
 /// Writing of DAC outputs is dependent on code compile option: \n
 /// - -- IOP (ADC_MASTER) reads DAC output values from memory shared with user apps and writes to DAC hardware. \n
@@ -1012,120 +704,17 @@ udelay(1000);
         /// - -- Code will require restart to clear.
         // COMMENT OUT NEX LINE FOR TEST STAND w/bad DAC cards. 
 #ifndef DAC_WD_OVERRIDE
-        if(dacTimingError) iopDacEnable = 0;
-        // Write out data to DAC modules
+    if(dacTimingError) iopDacEnable = 0;
+    // Write out data to DAC modules
 	dkiTrip = 0;
-	/// \> Loop thru all DAC modules
-        for(jj=0;jj<cdsPciModules.dacCount;jj++)
-        {
-           	/// - -- Point to DAC memory buffer
-           	pDacData = (unsigned int *)(cdsPciModules.pci_dac[jj]);
-        	/// - -- locate the proper DAC memory block
-        	mm = cdsPciModules.dacConfig[jj];
-        	/// - -- Determine if memory block has been set with the correct cycle count by Slave app.
-		if(ioMemData->iodata[mm][ioMemCntrDac].cycle == ioClockDac)
-		{
-			dacEnable |= pBits[jj];
-		}else {
-			dacEnable &= ~(pBits[jj]);
-			dacChanErr[jj] += 1;
-		}
-		/// - -- Set overflow limits, data mask, and chan count based on DAC type
-                limit = OVERFLOW_LIMIT_16BIT;
-                mask = GSAO_16BIT_MASK;
-                num_outs = GSAO_16BIT_CHAN_COUNT;
-                if (cdsPciModules.dacType[jj] == GSC_18AO8) {
-                        limit = OVERFLOW_LIMIT_18BIT; // 18 bit limit
-                        mask = GSAO_18BIT_MASK;
-                        num_outs = GSAO_18BIT_CHAN_COUNT;
-                }
-				if (cdsPciModules.dacType[jj] == GSC_20AO8) {
-                        limit = OVERFLOW_LIMIT_20BIT; // 20 bit limit
-                        mask = GSAO_20BIT_MASK;
-                        num_outs = GSAO_20BIT_CHAN_COUNT;
-                }
-		/// - -- For each DAC channel
-                for (ii=0; ii < num_outs; ii++)
-                {
-#ifdef FLIP_SIGNALS
-                        dacOut[jj][ii] *= -1;
-#endif
-			/// - ---- Read DAC output value from shared memory and reset memory to zero
-                        if((!dacChanErr[jj]) && (iopDacEnable)) {
-                                dac_out = ioMemData->iodata[mm][ioMemCntrDac].data[ii];
-                                /// - --------- Zero out data in case user app dies by next cycle
-                                /// when two or more apps share same DAC module.
-                                ioMemData->iodata[mm][ioMemCntrDac].data[ii] = 0;
-                        } else {
-				dac_out = 0;
-				dkiTrip = 1;
-			}
-                        /// - ----  Write out ADC duotone signal to first DAC, last channel, 
-			/// if DAC duotone is enabled.
-                        if((dacDuoEnable) && (ii==(num_outs-1)) && (jj == 0))
-                        {
-                                dac_out = adcData[0][ADC_DUOTONE_CHAN];
-                        }
-// Code below is only for use in DAQ test system.
-#ifdef DIAG_TEST
-                        if((ii==0) && (jj == 0))
-                        {
-                                if(cycleNum < 100) dac_out = limit / 20;
-                                else dac_out = 0;
-                        }
-                        if((ii==0) && (jj == 2))
-                        {
-                                if(cycleNum < 100) dac_out = limit / 20;
-                                else dac_out = 0;
-                        }
-#endif
-                        /// - ---- Check output values are within range of DAC \n
-                        /// - --------- If overflow, clip at DAC limits and report errors
-                        if(dac_out > limit || dac_out < -limit)
-                        {
-                                overflowDac[jj][ii] ++;
-				pLocalEpics->epicsOutput.overflowDacAcc[jj][ii] ++;
-                                overflowAcc ++;
-                                dacOF[jj] = 1;
-				odcStateWord |= ODC_DAC_OVF;;
-				if(dac_out > limit) dac_out = limit;
-				else dac_out = -limit;
-                        }
-                        /// - ---- If DAQKILL tripped, set output to zero.
-                        if(!iopDacEnable) dac_out = 0;
-                        /// - ---- Load last values to EPICS channels for monitoring on GDS_TP screen.
-                        dacOutEpics[jj][ii] = dac_out;
-
-                        /// - ---- Load DAC testpoints
-                        floatDacOut[16*jj + ii] = dac_out;
-
-                        /// - ---- Write to DAC local memory area, for later xmit to DAC module
-                        *pDacData =  (unsigned int)(dac_out & mask);
-                        pDacData ++;
-		}
-                /// - -- Mark cycle count as having been used -1 \n
-                /// - --------- Forces slaves to mark this cycle or will not be used again by Master
-                ioMemData->iodata[mm][ioMemCntrDac].cycle = -1;
-                /// - -- DMA Write data to DAC module
-                if(dacWriteEnable > 4) {
-                        if(cdsPciModules.dacType[jj] == GSC_16AO16) {
-                                gsc16ao16DmaStart(jj);
-					 	} else if(cdsPciModules.dacType[jj] == GSC_20AO8) {
-					            gsc20ao8DmaStart(jj);
-                        } else {
-                                gsc18ao8DmaStart(jj);
-                        }
-                }
-	}
-        /// \> Increment DAC memory block pointers for next cycle
-        ioClockDac = (ioClockDac + 1) % IOP_IO_RATE;
-        ioMemCntrDac = (ioMemCntrDac + 1) % IO_MEMORY_SLOTS;
-        if(dacWriteEnable < 10) dacWriteEnable ++;
+	dkiTrip = iop_dac_write();
 /// END OF IOP DAC WRITE *************************************************
-
 #endif
 
+
+// ***********************************************************************
 /// BEGIN HOUSEKEEPING ************************************************ \n
+// ***********************************************************************
 
         pLocalEpics->epicsOutput.cycle = cycleNum;
 // The following, to endif, is all duotone timing diagnostics.
@@ -1145,10 +734,10 @@ udelay(1000);
 			feStatus |= FE_ERROR_TIMING;;
 	        }
 /// - ---- Calc duotone diagnostic mean values for past second and reset.
-                duotoneMean = duotoneTotal/CYCLE_PER_SECOND;
-                duotoneTotal = 0.0;
-                duotoneMeanDac = duotoneTotalDac/CYCLE_PER_SECOND;
-                duotoneTotalDac = 0.0;
+                dt_diag.meanAdc = dt_diag.totalAdc/CYCLE_PER_SECOND;
+                dt_diag.totalAdc = 0.0;
+                dt_diag.meanDac = dt_diag.totalDac/CYCLE_PER_SECOND;
+                dt_diag.totalDac = 0.0;
         }
 
 /// \> Cycle 1 and Spectricom IRIGB (standard), get IRIG-B time information.
@@ -1168,31 +757,30 @@ udelay(1000);
         }
 
 /// \> Update duotone diag information
-        duotoneDac[(cycleNum + DT_SAMPLE_OFFSET) % CYCLE_PER_SECOND] = dWord[ADC_DUOTONE_BRD][DAC_DUOTONE_CHAN];
-        duotoneTotalDac += dWord[ADC_DUOTONE_BRD][DAC_DUOTONE_CHAN];
-        duotone[(cycleNum + DT_SAMPLE_OFFSET) % CYCLE_PER_SECOND] = dWord[ADC_DUOTONE_BRD][ADC_DUOTONE_CHAN];
-        duotoneTotal += dWord[ADC_DUOTONE_BRD][ADC_DUOTONE_CHAN];
+        dt_diag.dac[(cycleNum + DT_SAMPLE_OFFSET) % CYCLE_PER_SECOND] = dWord[ADC_DUOTONE_BRD][DAC_DUOTONE_CHAN];
+        dt_diag.totalDac += dWord[ADC_DUOTONE_BRD][DAC_DUOTONE_CHAN];
+        dt_diag.adc[(cycleNum + DT_SAMPLE_OFFSET) % CYCLE_PER_SECOND] = dWord[ADC_DUOTONE_BRD][ADC_DUOTONE_CHAN];
+        dt_diag.totalAdc += dWord[ADC_DUOTONE_BRD][ADC_DUOTONE_CHAN];
 
 /// \> Cycle 16, perform duotone diag calcs.
         if(cycleNum == HKP_DT_CALC)
         {
-		duotoneTime = duotime(DT_SAMPLE_CNT, duotoneMean, duotone);
+		duotoneTime = duotime(DT_SAMPLE_CNT, dt_diag.meanAdc, dt_diag.adc);
 		pLocalEpics->epicsOutput.dtTime = duotoneTime;
 		if(((duotoneTime < MIN_DT_DIAG_VAL) || (duotoneTime > MAX_DT_DIAG_VAL)) &&
 		   syncSource != SYNC_SRC_1PPS) 
 			feStatus |= FE_ERROR_TIMING;
-		duotoneTimeDac = duotime(DT_SAMPLE_CNT, duotoneMeanDac, duotoneDac);
+		duotoneTimeDac = duotime(DT_SAMPLE_CNT, dt_diag.meanDac, dt_diag.dac);
                 pLocalEpics->epicsOutput.dacDtTime = duotoneTimeDac;
         }
 
 /// \> Cycle 17, set/reset DAC duotone switch if request has changed.
 	if(cycleNum == HKP_DAC_DT_SWITCH)
 	{
-		if(dacDuoEnable != pLocalEpics->epicsInput.dacDuoSet)
+		if(dt_diag.dacDuoEnable != pLocalEpics->epicsInput.dacDuoSet)
 		{
-			dacDuoEnable = pLocalEpics->epicsInput.dacDuoSet;
-			// printf("duo set = %d\n",dacDuoEnable);
-			if(dacDuoEnable)
+			dt_diag.dacDuoEnable = pLocalEpics->epicsInput.dacDuoSet;
+			if(dt_diag.dacDuoEnable)
 				CDIO1616Output[0] = TDS_START_ADC_NEG_DAC_POS;
 			else CDIO1616Output[0] = TDS_START_ADC_NEG_DAC_POS | TDS_NO_DAC_DUOTONE;
 			CDIO1616Input[0] = contec1616WriteOutputRegister(&cdsPciModules, tdsControl[0], CDIO1616Output[0]);
@@ -1202,36 +790,31 @@ udelay(1000);
 
 /// \> Cycle 18, Send timing info to EPICS at 1Hz
 	if(cycleNum ==HKP_TIMING_UPDATES)	
-        {
-	  pLocalEpics->epicsOutput.cpuMeter = timeHold;
-	  pLocalEpics->epicsOutput.cpuMeterMax = timeHoldMax;
+    {
+	  pLocalEpics->epicsOutput.cpuMeter = timeinfo.timeHold;
+	  pLocalEpics->epicsOutput.cpuMeterMax = timeinfo.timeHoldMax;
   	  pLocalEpics->epicsOutput.dacEnable = dacEnable;
-          timeHoldHold = timeHold;
-          timeHold = 0;
-	  timeHoldWhenHold = timeHoldWhen;
-
-#if defined(SERVO64K) || defined(SERVO32K) || defined(SERVO16K)
-	  memcpy(cycleHistMax, cycleHist, sizeof(cycleHist));
-	  memset(cycleHist, 0, sizeof(cycleHist));
-	  memcpy(cycleHistWhenHold, cycleHistWhen, sizeof(cycleHistWhen));
-	  memset(cycleHistWhen, 0, sizeof(cycleHistWhen));
-#endif
-	  if (timeSec % 4 == 0) pLocalEpics->epicsOutput.adcWaitTime = adcHoldTimeMin;
+      timeinfo.timeHoldHold = timeinfo.timeHold;
+      timeinfo.timeHold = 0;
+	  timeinfo.timeHoldWhenHold = timeinfo.timeHoldWhen;
+
+	  if (timeSec % 4 == 0) pLocalEpics->epicsOutput.adcWaitTime = 
+	  	adcinfo.adcHoldTimeMin;
 	  else if (timeSec % 4 == 1)
-		pLocalEpics->epicsOutput.adcWaitTime =  adcHoldTimeMax;
+		pLocalEpics->epicsOutput.adcWaitTime =  adcinfo.adcHoldTimeMax;
 	  else
-	  	pLocalEpics->epicsOutput.adcWaitTime = adcHoldTimeAvg/CYCLE_PER_SECOND;
-	  adcHoldTimeAvgPerSec = adcHoldTimeAvg/CYCLE_PER_SECOND;
-	  adcHoldTimeMax = 0;
-	  adcHoldTimeMin = 0xffff;
-	  adcHoldTimeAvg = 0;
-	  if((adcHoldTime > CYCLE_TIME_ALRM_HI) || (adcHoldTime < CYCLE_TIME_ALRM_LO)) 
+	  	pLocalEpics->epicsOutput.adcWaitTime = adcinfo.adcHoldTimeAvg/CYCLE_PER_SECOND;
+	  adcinfo.adcHoldTimeAvgPerSec = adcinfo.adcHoldTimeAvg/CYCLE_PER_SECOND;
+	  adcinfo.adcHoldTimeMax = 0;
+	  adcinfo.adcHoldTimeMin = 0xffff;
+	  adcinfo.adcHoldTimeAvg = 0;
+	  if((adcinfo.adcHoldTime > CYCLE_TIME_ALRM_HI) || (adcinfo.adcHoldTime < CYCLE_TIME_ALRM_LO)) 
 	  {
 	  	diagWord |= FE_ADC_HOLD_ERR;
 		feStatus |= FE_ERROR_TIMING;
 	  
 	  }
-	  if(timeHoldMax > CYCLE_TIME_ALRM) 
+	  if(timeinfo.timeHoldMax > CYCLE_TIME_ALRM) 
 	  {
 	  	diagWord |= FE_PROC_TIME_ERR;
 		feStatus |= FE_ERROR_TIMING;
@@ -1244,20 +827,20 @@ udelay(1000);
 		pLocalEpics->epicsInput.diagReset = 0;
 		pLocalEpics->epicsInput.ipcDiagReset = 1;
   		// pLocalEpics->epicsOutput.diags[1] = 0;
-		timeHoldMax = 0;
+		timeinfo.timeHoldMax = 0;
 	  	diagWord = 0;
 		ipcErrBits = 0;
 		
 		// feStatus = 0;
-               for(jj=0;jj<cdsPciModules.adcCount;jj++) adcRdTimeMax[jj] = 0;
+               for(jj=0;jj<cdsPciModules.adcCount;jj++) adcinfo.adcRdTimeMax[jj] = 0;
 	  }
 	  // Flip the onePPS various once/sec as a watchdog monitor.
 	  // pLocalEpics->epicsOutput.onePps ^= 1;
 	  pLocalEpics->epicsOutput.diagWord = diagWord;
        	  for(jj=0;jj<cdsPciModules.adcCount;jj++) {
-		if(adcRdTimeErr[jj] > MAX_ADC_WAIT_ERR_SEC)
+		if(adcinfo.adcRdTimeErr[jj] > MAX_ADC_WAIT_ERR_SEC)
 			pLocalEpics->epicsOutput.stateWord |= FE_ERROR_ADC;
-		adcRdTimeErr[jj] = 0;
+		adcinfo.adcRdTimeErr[jj] = 0;
 	  }
         }
 
@@ -1287,7 +870,7 @@ udelay(1000);
 	{
 
 		// Assign chan 32 to onePps 
-		onePps = adcData[ADC_DUOTONE_BRD][ADC_DUOTONE_CHAN];
+		onePps = adcinfo.adcData[ADC_DUOTONE_BRD][ADC_DUOTONE_CHAN];
 		if((onePps > ONE_PPS_THRESH) && (onePpsHi == 0))  
 		{
 			onePpsTime = cycleNum;
@@ -1302,8 +885,8 @@ udelay(1000);
 #ifdef DIAG_TEST
 	for(ii=0;ii<10;ii++)
 	{
-		if(ii<5) onePpsTest = adcData[0][ii];
-		else onePpsTest = adcData[1][(ii-5)];
+		if(ii<5) onePpsTest = adcinfo.adcData[0][ii];
+		else onePpsTest = adcinfo.adcData[1][(ii-5)];
 		if((onePpsTest > 400) && (onePpsHiTest[ii] == 0))  
 		{
 			onePpsTimeTest[ii] = cycleNum;
@@ -1321,148 +904,145 @@ udelay(1000);
 /// \>  Write data to DAQ.
 #ifndef NO_DAQ
 		
-		// Call daqLib
-		pLocalEpics->epicsOutput.daqByteCnt = 
-			daqWrite(1,dcuId,daq,DAQ_RATE,testpoint,dspPtr[0],myGmError2,(int *)(pLocalEpics->epicsOutput.gdsMon),xExc,pEpicsDaq);
-		// Send the current DAQ block size to the awgtpman for TP number checking
-	  	pEpicsComms->padSpace.feDaqBlockSize = curDaqBlockSize;
-	  	pLocalEpics->epicsOutput.tpCnt = tpPtr->count & 0xff;
-		feStatus |= (FE_ERROR_EXC_SET & tpPtr->count);
-		if (FE_ERROR_EXC_SET & tpPtr->count) odcStateWord |= ODC_EXC_SET;
-		else odcStateWord &= ~(ODC_EXC_SET);
-		if(pLocalEpics->epicsOutput.daqByteCnt > DAQ_DCU_RATE_WARNING) 
-			feStatus |= FE_ERROR_DAQ;
+	// Call daqLib
+	pLocalEpics->epicsOutput.daqByteCnt = 
+		daqWrite(1,dcuId,daq,DAQ_RATE,testpoint,dspPtr[0],myGmError2,(int *)(pLocalEpics->epicsOutput.gdsMon),xExc,pEpicsDaq);
+	// Send the current DAQ block size to the awgtpman for TP number checking
+  	pEpicsComms->padSpace.feDaqBlockSize = curDaqBlockSize;
+  	pLocalEpics->epicsOutput.tpCnt = tpPtr->count & 0xff;
+	feStatus |= (FE_ERROR_EXC_SET & tpPtr->count);
+	if (FE_ERROR_EXC_SET & tpPtr->count) odcStateWord |= ODC_EXC_SET;
+	else odcStateWord &= ~(ODC_EXC_SET);
+	if(pLocalEpics->epicsOutput.daqByteCnt > DAQ_DCU_RATE_WARNING) 
+		feStatus |= FE_ERROR_DAQ;
 #endif
 
 /// \> Cycle 19, write updated diag info to EPICS
 	if(cycleNum == HKP_DIAG_UPDATES)	
-        {
-	  pLocalEpics->epicsOutput.userTime = usrHoldTime;
-	  pLocalEpics->epicsOutput.ipcStat = ipcErrBits;
-	  if(ipcErrBits & 0xf) feStatus |= FE_ERROR_IPC;
-	  // Create FB status word for return to EPICS
-	  mxStat = 0;
-	  mxDiagR = daqPtr->reqAck;
-	  if((mxDiag & 1) != (mxDiagR & 1)) mxStat = 1;
-	  if((mxDiag & 2) != (mxDiagR & 2)) mxStat += 2;
+    {
+	  	pLocalEpics->epicsOutput.userTime = timeinfo.usrHoldTime;
+	  	pLocalEpics->epicsOutput.ipcStat = ipcErrBits;
+	  	if(ipcErrBits & 0xf) feStatus |= FE_ERROR_IPC;
+	  	// Create FB status word for return to EPICS
+	  	mxStat = 0;
+	  	mxDiagR = daqPtr->reqAck;
+	  	if((mxDiag & 1) != (mxDiagR & 1)) mxStat = 1;
+	  	if((mxDiag & 2) != (mxDiagR & 2)) mxStat += 2;
 #ifdef DUAL_DAQ_DC
-	  if((mxDiag & 4) != (mxDiagR & 4)) mxStat += 4;
-	  if((mxDiag & 8) != (mxDiagR & 8)) mxStat += 8;
+	  	if((mxDiag & 4) != (mxDiagR & 4)) mxStat += 4;
+	  	if((mxDiag & 8) != (mxDiagR & 8)) mxStat += 8;
 #endif
-	  pLocalEpics->epicsOutput.fbNetStat = mxStat;
-  	  mxDiag = mxDiagR;
-	  if(mxStat != MX_OK)
-		feStatus |= FE_ERROR_DAQ;;
-	  usrHoldTime = 0;
-  	  if(pLocalEpics->epicsInput.overflowReset)
-	  {
-                if (pLocalEpics->epicsInput.overflowReset) {
-                   for (ii = 0; ii < 16; ii++) {
-                      for (jj = 0; jj < cdsPciModules.adcCount; jj++) {
-                         overflowAdc[jj][ii] = 0;
-                         overflowAdc[jj][ii + 16] = 0;
-			pLocalEpics->epicsOutput.overflowAdcAcc[jj][ii] = 0;
-			pLocalEpics->epicsOutput.overflowAdcAcc[jj][ii + 16] = 0;
-                      }
-
-                      for (jj = 0; jj < cdsPciModules.dacCount; jj++) {
-                         pLocalEpics->epicsOutput.overflowDacAcc[jj][ii] = 0;
-                      }
-                   }
-                }
-	  }
-  	  if((pLocalEpics->epicsInput.overflowReset) || (overflowAcc > OVERFLOW_CNTR_LIMIT))
-	  {
-		pLocalEpics->epicsInput.overflowReset = 0;
-		pLocalEpics->epicsOutput.ovAccum = 0;
-		overflowAcc = 0;
-	  }
-        }
+	  	pLocalEpics->epicsOutput.fbNetStat = mxStat;
+  	  	mxDiag = mxDiagR;
+	  	if(mxStat != MX_OK)
+			feStatus |= FE_ERROR_DAQ;;
+	  	timeinfo.usrHoldTime = 0;
+  	  	if(pLocalEpics->epicsInput.overflowReset)
+	  	{
+       		if (pLocalEpics->epicsInput.overflowReset) {
+           		for (ii = 0; ii < 16; ii++) {
+               		for (jj = 0; jj < cdsPciModules.adcCount; jj++) {
+              			adcinfo.overflowAdc[jj][ii] = 0;
+                        adcinfo.overflowAdc[jj][ii + 16] = 0;
+						pLocalEpics->epicsOutput.overflowAdcAcc[jj][ii] = 0;
+						pLocalEpics->epicsOutput.overflowAdcAcc[jj][ii + 16] = 0;
+           		}
+                	for (jj = 0; jj < cdsPciModules.dacCount; jj++) {
+                        pLocalEpics->epicsOutput.overflowDacAcc[jj][ii] = 0;
+                	}
+        		}
+  			}
+	  	}
+  	  	if((pLocalEpics->epicsInput.overflowReset) || (overflowAcc > OVERFLOW_CNTR_LIMIT))
+	  	{
+			pLocalEpics->epicsInput.overflowReset = 0;
+			pLocalEpics->epicsOutput.ovAccum = 0;
+			overflowAcc = 0;
+	  	}
+	}
 
 /// \> Cycle 20, Update latest DAC output values to EPICS
-        if(subcycle == HKP_DAC_EPICS_UPDATES)
+    if(subcycle == HKP_DAC_EPICS_UPDATES)
 	{
-	      // Send DAC output values at 16Hzfb
-	      for(jj=0;jj<cdsPciModules.dacCount;jj++)
-	      {
+		// Send DAC output values at 16Hzfb
+	    for(jj=0;jj<cdsPciModules.dacCount;jj++)
+	    {
 	    	for(ii=0;ii<MAX_DAC_CHN_PER_MOD;ii++)
 	    	{
-			pLocalEpics->epicsOutput.dacValue[jj][ii] = dacOutEpics[jj][ii];
-		}
-	      }
+				pLocalEpics->epicsOutput.dacValue[jj][ii] = dacOutEpics[jj][ii];
+			}
+	    }
 	}
 
 /// \> Cycle 21, Update ADC/DAC status to EPICS.
-        if(cycleNum == HKP_ADC_DAC_STAT_UPDATES)
-        {
-	  pLocalEpics->epicsOutput.ovAccum = overflowAcc;
-	  for(jj=0;jj<cdsPciModules.adcCount;jj++)
-	  {
-	    // SET/CLR Channel Hopping Error
-	    if(adcChanErr[jj]) 
-	    {
-	    	pLocalEpics->epicsOutput.statAdc[jj] &= ~(2);
-		feStatus |= FE_ERROR_ADC;;
-	    }
- 	    else pLocalEpics->epicsOutput.statAdc[jj] |= 2;
-	    adcChanErr[jj] = 0;
-	    // SET/CLR Overflow Error
-	    if(adcOF[jj]) 
-	    {
-	    	pLocalEpics->epicsOutput.statAdc[jj] &= ~(4);
-		feStatus |= FE_ERROR_OVERFLOW;;
-	    }
- 	    else pLocalEpics->epicsOutput.statAdc[jj] |= 4;
-	    adcOF[jj] = 0;
-	    for(ii=0;ii<32;ii++)
-	    {
-
+	if(cycleNum == HKP_ADC_DAC_STAT_UPDATES)
+    {
+		pLocalEpics->epicsOutput.ovAccum = overflowAcc;
+	  	for(jj=0;jj<cdsPciModules.adcCount;jj++)
+	  	{
+	    	// SET/CLR Channel Hopping Error
+	    	if(adcinfo.adcChanErr[jj]) 
+	    	{
+	    		pLocalEpics->epicsOutput.statAdc[jj] &= ~(2);
+				feStatus |= FE_ERROR_ADC;;
+	    	}
+ 	    	else pLocalEpics->epicsOutput.statAdc[jj] |= 2;
+	    	adcinfo.adcChanErr[jj] = 0;
+	    	// SET/CLR Overflow Error
+	    	if(adcinfo.adcOF[jj]) 
+	    	{	
+	    		pLocalEpics->epicsOutput.statAdc[jj] &= ~(4);
+				feStatus |= FE_ERROR_OVERFLOW;;
+	    	}
+ 	    	else pLocalEpics->epicsOutput.statAdc[jj] |= 4;
+	    	adcinfo.adcOF[jj] = 0;
+	    	for(ii=0;ii<32;ii++)
+	    	{
                 if (pLocalEpics->epicsOutput.overflowAdcAcc[jj][ii] > OVERFLOW_CNTR_LIMIT) {
-		   pLocalEpics->epicsOutput.overflowAdcAcc[jj][ii] = 0;
-                }
-		pLocalEpics->epicsOutput.overflowAdc[jj][ii] = overflowAdc[jj][ii];
-		overflowAdc[jj][ii] = 0;
-
-	    }
-	  }
-	  // If ADC channels not where they should be, we have no option but to exit
-	  // from the RT code ie loops would be working with wrong input data.
-	  if (chanHop) {
-	  	pLocalEpics->epicsOutput.stateWord = FE_ERROR_ADC;
-	         stop_working_threads = 1;
-	         vmeDone = 1;
-	         printf("Channel Hopping Detected on one or more ADC modules !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
-	         printf("Check GDSTP screen ADC status bits to id affected ADC modules\n");
-	         printf("Code is exiting ..............\n");
-	 	 continue;    
-	  }
-	  for(jj=0;jj<cdsPciModules.dacCount;jj++)
-	  {
-	    if(dacOF[jj]) 
-	    {
-	    	pLocalEpics->epicsOutput.statDac[jj] &= ~(DAC_OVERFLOW_BIT);
-		feStatus |= FE_ERROR_OVERFLOW;;
-	    }
- 	    else pLocalEpics->epicsOutput.statDac[jj] |= DAC_OVERFLOW_BIT;
-	    dacOF[jj] = 0;
-	    if(dacChanErr[jj]) 
-	    {
-	    	pLocalEpics->epicsOutput.statDac[jj] &= ~(DAC_TIMING_BIT);
-	    }
- 	    else pLocalEpics->epicsOutput.statDac[jj] |= DAC_TIMING_BIT;
-	    dacChanErr[jj] = 0;
-	    for(ii=0;ii<MAX_DAC_CHN_PER_MOD;ii++)
-	    {
-
-                if (pLocalEpics->epicsOutput.overflowDacAcc[jj][ii] > OVERFLOW_CNTR_LIMIT) {
-		   pLocalEpics->epicsOutput.overflowDacAcc[jj][ii] = 0;
-                }
-		pLocalEpics->epicsOutput.overflowDac[jj][ii] = overflowDac[jj][ii];
-		overflowDac[jj][ii] = 0;
+		   		pLocalEpics->epicsOutput.overflowAdcAcc[jj][ii] = 0;
+            }
+			pLocalEpics->epicsOutput.overflowAdc[jj][ii] = adcinfo.overflowAdc[jj][ii];
+			adcinfo.overflowAdc[jj][ii] = 0;
 
-	    }
-	  }
-        }
+	    	}
+		}
+	    // If ADC channels not where they should be, we have no option but to exit
+	  	// from the RT code ie loops would be working with wrong input data.
+	  	if (adcinfo.chanHop) {
+	  		pLocalEpics->epicsOutput.stateWord = FE_ERROR_ADC;
+	        stop_working_threads = 1;
+	        vmeDone = 1;
+  			pLocalEpics->epicsOutput.fe_status = CHAN_HOP_ERROR;
+	         // printf("Channel Hopping Detected on one or more ADC modules !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
+	         // printf("Check GDSTP screen ADC status bits to id affected ADC modules\n");
+	         // printf("Code is exiting ..............\n");
+	 	 	continue;    
+	  	}
+	  	for(jj=0;jj<cdsPciModules.dacCount;jj++)
+	  	{
+	    	if(dacOF[jj]) 
+	    	{
+	    		pLocalEpics->epicsOutput.statDac[jj] &= ~(DAC_OVERFLOW_BIT);
+				feStatus |= FE_ERROR_OVERFLOW;;
+	    	}
+ 	    	else pLocalEpics->epicsOutput.statDac[jj] |= DAC_OVERFLOW_BIT;
+	    	dacOF[jj] = 0;
+	    	if(dacChanErr[jj]) 
+	    	{
+	    		pLocalEpics->epicsOutput.statDac[jj] &= ~(DAC_TIMING_BIT);
+	    	}
+ 	    	else pLocalEpics->epicsOutput.statDac[jj] |= DAC_TIMING_BIT;
+	    	dacChanErr[jj] = 0;
+	    	for(ii=0;ii<MAX_DAC_CHN_PER_MOD;ii++)
+	    	{
+				if (pLocalEpics->epicsOutput.overflowDacAcc[jj][ii] > OVERFLOW_CNTR_LIMIT) {
+		   			pLocalEpics->epicsOutput.overflowDacAcc[jj][ii] = 0;
+            	}
+				pLocalEpics->epicsOutput.overflowDac[jj][ii] = dacinfo.overflowDac[jj][ii];
+				dacinfo.overflowDac[jj][ii] = 0;
+	    	}
+	  	}
+	}
 /// \> Cycle 300, If IOP and RFM cards, check own data diagnostics
 	// Deal with the own-data bits on the VMIC 5565 rfm cards
 	if (cdsPciModules.rfmCount > 0) {
@@ -1625,84 +1205,69 @@ udelay(1000);
 
 #endif
 	// Capture end of cycle time.
-        rdtscl(cpuClock[CPU_TIME_CYCLE_END]);
+    rdtscl(cpuClock[CPU_TIME_CYCLE_END]);
 
 	/// \> Compute code cycle time diag information.
-	cycleTime = (cpuClock[CPU_TIME_CYCLE_END] - cpuClock[CPU_TIME_CYCLE_START])/CPURATE;
-	if (longestWrite2 < ((tempClock[3]-tempClock[2])/CPURATE)) longestWrite2 = (tempClock[3]-tempClock[2])/CPURATE;
+	timeinfo.cycleTime = (cpuClock[CPU_TIME_CYCLE_END] - cpuClock[CPU_TIME_CYCLE_START])/CPURATE;
 	// Hold the max cycle time over the last 1 second
-	if(cycleTime > timeHold) { 
-		timeHold = cycleTime;
-		timeHoldWhen = cycleNum;
+	if(timeinfo.cycleTime > timeinfo.timeHold) { 
+		timeinfo.timeHold = timeinfo.cycleTime;
+		timeinfo.timeHoldWhen = cycleNum;
 	}
 	// Hold the max cycle time since last diag reset
-	if(cycleTime > timeHoldMax) timeHoldMax = cycleTime;
-#if defined(SERVO64K) || defined(SERVO32K) || defined(SERVO16K)
-// This produces cycle time histogram in /proc file
-	{
-#if defined(SERVO64K) || defined(SERVO32K)
-		static const int nb = 31;
-#elif defined(SERVO16K)
-		static const int nb = 63;
-#endif
-
-		cycleHist[cycleTime<nb?cycleTime:nb]++;
-		cycleHistWhen[cycleTime<nb?cycleTime:nb] = cycleNum;
-	}
-#endif
-	adcHoldTime = (cpuClock[CPU_TIME_CYCLE_START] - adcTime)/CPURATE;
+	if(timeinfo.cycleTime > timeinfo.timeHoldMax) timeinfo.timeHoldMax = timeinfo.cycleTime;
+	adcinfo.adcHoldTime = (cpuClock[CPU_TIME_CYCLE_START] - adcinfo.adcTime)/CPURATE;
 	// Avoid calculating the max hold time for the first few seconds
-	if (cycleNum != 0 && (startGpsTime+3) < cycle_gps_time) {
-		if(adcHoldTime > adcHoldTimeMax) adcHoldTimeMax = adcHoldTime;
-		if(adcHoldTime < adcHoldTimeMin) adcHoldTimeMin = adcHoldTime;
-		adcHoldTimeAvg += adcHoldTime;
-		if (adcHoldTimeMax > adcHoldTimeEverMax)  {
-			adcHoldTimeEverMax = adcHoldTimeMax;
-			adcHoldTimeEverMaxWhen = cycle_gps_time;
-			//printf("Maximum adc hold time %d on cycle %d gps %d\n", adcHoldTimeMax, cycleNum, cycle_gps_time);
+	if (cycleNum != 0 && (timeinfo.startGpsTime+3) < cycle_gps_time) {
+		if(adcinfo.adcHoldTime > adcinfo.adcHoldTimeMax) 
+			adcinfo.adcHoldTimeMax = adcinfo.adcHoldTime;
+		if(adcinfo.adcHoldTime < adcinfo.adcHoldTimeMin) 
+			adcinfo.adcHoldTimeMin = adcinfo.adcHoldTime;
+		adcinfo.adcHoldTimeAvg += adcinfo.adcHoldTime;
+		if (adcinfo.adcHoldTimeMax > adcinfo.adcHoldTimeEverMax)  {
+			adcinfo.adcHoldTimeEverMax = adcinfo.adcHoldTimeMax;
+			adcinfo.adcHoldTimeEverMaxWhen = cycle_gps_time;
 		}
-		if (timeHoldMax > cpuTimeEverMax)  {
-			cpuTimeEverMax = timeHoldMax;
-			cpuTimeEverMaxWhen = cycle_gps_time;
+		if (timeinfo.timeHoldMax > timeinfo.cpuTimeEverMax)  {
+			timeinfo.cpuTimeEverMax = timeinfo.timeHoldMax;
+			timeinfo.cpuTimeEverMaxWhen = cycle_gps_time;
 		}
 	}
-	adcTime = cpuClock[CPU_TIME_CYCLE_START];
+	adcinfo.adcTime = cpuClock[CPU_TIME_CYCLE_START];
 	// Calc the max time of one cycle of the user code
 	// For IOP, more interested in time to get thru ADC read code and send to slave apps
-	usrTime = (cpuClock[CPU_TIME_USR_START] - cpuClock[CPU_TIME_CYCLE_START])/CPURATE;
-	if(usrTime > usrHoldTime) usrHoldTime = usrTime;
+	timeinfo.usrTime = (cpuClock[CPU_TIME_USR_START] - cpuClock[CPU_TIME_CYCLE_START])/CPURATE;
+	if(timeinfo.usrTime > timeinfo.usrHoldTime) timeinfo.usrHoldTime = timeinfo.usrTime;
 
-        /// \> Update internal cycle counters
-          cycleNum += 1;
+    /// \> Update internal cycle counters
+    cycleNum += 1;
 #ifdef DIAG_TEST
-          if(pLocalEpics->epicsInput.bumpCycle != 0) {
+    if(pLocalEpics->epicsInput.bumpCycle != 0) {
 	  	cycleNum += pLocalEpics->epicsInput.bumpCycle;
 		pLocalEpics->epicsInput.bumpCycle = 0;
-	  }
+  	}
 #endif
-          cycleNum %= CYCLE_PER_SECOND;
-	  clock1Min += 1;
-	  clock1Min %= CYCLE_PER_MINUTE;
-          if(subcycle == DAQ_CYCLE_CHANGE) 
-	  {
+	cycleNum %= CYCLE_PER_SECOND;
+  	clock1Min += 1;
+  	clock1Min %= CYCLE_PER_MINUTE;
+    if(subcycle == DAQ_CYCLE_CHANGE) 
+  	{
 		daqCycle = (daqCycle + 1) % DAQ_NUM_DATA_BLOCKS_PER_SECOND;
 		if(!(daqCycle % 2)) pLocalEpics->epicsOutput.epicsSync = daqCycle;
-	  }
-          if(subcycle == END_OF_DAQ_BLOCK) /*we have reached the 16Hz second barrier*/
-            {
-              /* Reset the data cycle counter */
-              subcycle = 0;
-  
-            }
-          else{
-            /* Increment the internal cycle counter */
-            subcycle ++;                                                
-          }
+  	}
+    if(subcycle == END_OF_DAQ_BLOCK) /*we have reached the 16Hz second barrier*/
+    {
+    	/* Reset the data cycle counter */
+        subcycle = 0;
+	} else {
+		/* Increment the internal cycle counter */
+		subcycle ++;                                                
+	}
 
 /// \> If not exit request, then continue INFINITE LOOP  *******
   }
 
-  printf("exiting from fe_code()\n");
+  // printf("exiting from fe_code()\n");
   pLocalEpics->epicsOutput.cpuMeter = 0;
 
 
diff --git a/src/fe/controllerIopUser.c b/src/fe/controllerIopUser.c
index 17b5c46c3..fa64b8951 100644
--- a/src/fe/controllerIopUser.c
+++ b/src/fe/controllerIopUser.c
@@ -38,6 +38,7 @@
 #include "inlineMath.h"
 
 
+#include "cds_types.h" 
 #include "fm10Gen.h"		// CDS filter module defs and C code
 #include "feComms.h"		// Lvea control RFM network defs.
 #include "daqmap.h"		// DAQ network layout
@@ -154,7 +155,7 @@ unsigned int getGpsTimeProc() {
 	fclose(timef);
 	return (mytime);
 }
-  void initAdcModules(void) {
+  void initAdcModules(adcInfo_t *adcinfo) {
 	  int status;
 	  int jj;
 
@@ -162,7 +163,7 @@ unsigned int getGpsTimeProc() {
 	  {
 		  // Set ADC Present Flag
 		  pLocalEpics->epicsOutput.statAdc[jj] = 1;
-		  adcRdTimeErr[jj] = 0;
+		  adcinfo->adcRdTimeErr[jj] = 0;
 	  }
     	  printf("ADC setup complete \n");
   }
@@ -198,14 +199,15 @@ int fe_start()
   struct timespec tp;
   static struct timespec cpuClock[CPU_TIMER_CNT];	///  @param cpuClock[] Code timing diag variables
   static int chanHop = 0;		/// @param chanHop Adc channel hopping status
+  int dacOF[MAX_DAC_MODULES];
 
   int adcData[MAX_ADC_MODULES][MAX_ADC_CHN_PER_MOD];	/// @param adcData[][]  ADC raw data
   int adcChanErr[MAX_ADC_MODULES];
-  int adcWait = 0;
+  // int adcWait = 0;
+  adcInfo_t adcInfo;
+  dacInfo_t dacInfo;
   int adcOF[MAX_ADC_MODULES];		/// @param adcOF[]  ADC overrange counters
 
-  // int dacChanErr[MAX_DAC_MODULES];
-  int dacOF[MAX_DAC_MODULES];		/// @param dacOF[]  DAC overrange counters
   static int dacWriteEnable = 0;	/// @param dacWriteEnable  No DAC outputs until >4 times through code
   					///< Code runs longer for first few cycles on startup as it settles in,
 					///< so this helps prevent long cycles during that time.
@@ -302,7 +304,7 @@ int fe_start()
     for (jj = 0; jj < 16; jj++) {
  	dacOut[ii][jj] = 0.0;
  	dacOutUsed[ii][jj] = 0;
-	dacOutBufSize[ii] = 0;
+	dacInfo.dacOutBufSize[ii] = 0;
 	// Zero out DAC channel map in the shared memory
 	// to be used to check on slaves' channel allocation
 	ioMemData->dacOutUsed[ii][jj] = 0;
@@ -449,6 +451,7 @@ usleep(1000);
   printf("Calling feCode() to initialize\n");
   iopDacEnable = feCode(cycleNum,dWord,dacOut,dspPtr[0],&dspCoeff[0], (struct CDS_EPICS *)pLocalEpics,1);
 
+
 /// \> Verify DAC channels defined for this app are not already in use. \n
 /// - ---- User apps are allowed to share DAC modules but not DAC channels.
 
@@ -462,7 +465,7 @@ usleep(1000);
   missedCycle = 0;
 
   /// \> If IOP,  Initialize the ADC modules
-  initAdcModules();
+  initAdcModules(&adcInfo);
 
   /// \> If IOP, Initialize the DAC module variables
   initDacModules();
@@ -511,18 +514,18 @@ printf("cycle time = %d\n",cycleTime);
 
 	    ioMemCntr = (cycleNum % IO_MEMORY_SLOTS);
 	    // Write GPS time and cycle count as indicator to slave that adc data is ready
-            for(jj=0;jj<cdsPciModules.adcCount;jj++)
+        for(jj=0;jj<cdsPciModules.adcCount;jj++)
 	    {
 		    for(ii=0;ii<IO_MEMORY_SLOT_VALS;ii++)
 		    {
-			ioMemData->iodata[jj][ioMemCntr].data[ii] = ioMemDataIop->iodata[jj][cycleNum].data[ii];
-			dWord[jj][ii] = ioMemData->iodata[jj][ioMemCntr].data[ii];
-			ioMemDataIop->iodata[jj][cycleNum].data[ii] = 0;
+				ioMemData->iodata[jj][ioMemCntr].data[ii] = ioMemDataIop->iodata[jj][cycleNum].data[ii];
+				dWord[jj][ii] = ioMemData->iodata[jj][ioMemCntr].data[ii];
+				ioMemDataIop->iodata[jj][cycleNum].data[ii] = 0;
 		    }
 	    	ioMemData->iodata[jj][ioMemCntr].timeSec = timeSec;;
 	    	ioMemData->iodata[jj][ioMemCntr].cycle = cycleNum;
-		ioMemDataIop->gpsSecond = timeSec;
-		ioMemDataIop->cycleNum = cycleNum;
+			ioMemDataIop->gpsSecond = timeSec;
+			ioMemDataIop->cycleNum = cycleNum;
 	    }
 	    ioMemData->gpsSecond = timeSec;
 	  clock_gettime(CLOCK_MONOTONIC, &cpuClock[CPU_TIME_CYCLE_START]);
@@ -548,7 +551,8 @@ printf("cycle time = %d\n",cycleTime);
 /// \> Call the front end specific application  ******************\n
 /// - -- This is where the user application produced by RCG gets called and executed. \n\n
          clock_gettime(CLOCK_MONOTONIC, &cpuClock[CPU_TIME_USR_START]);
- 	iopDacEnable = feCode(cycleNum,dWord,dacOut,dspPtr[0],&dspCoeff[0],(struct CDS_EPICS *)pLocalEpics,0);
+	iopDacEnable = feCode(cycleNum,dWord,dacOut,dspPtr[0],&dspCoeff[0], (struct CDS_EPICS *)pLocalEpics,0);
+
          clock_gettime(CLOCK_MONOTONIC, &cpuClock[CPU_TIME_USR_END]);
 
   	odcStateWord = 0;
@@ -632,7 +636,7 @@ printf("cycle time = %d\n",cycleTime);
                         /// - --------- If overflow, clip at DAC limits and report errors
                         if(dac_out > limit || dac_out < -limit)
                         {
-                                overflowDac[jj][ii] ++;
+                                dacInfo.overflowDac[jj][ii] ++;
 				pLocalEpics->epicsOutput.overflowDacAcc[jj][ii] ++;
                                 overflowAcc ++;
                                 dacOF[jj] = 1;
@@ -643,7 +647,7 @@ printf("cycle time = %d\n",cycleTime);
                         /// - ---- If DAQKILL tripped, set output to zero.
                         if(!iopDacEnable) dac_out = 0;
                         /// - ---- Load last values to EPICS channels for monitoring on GDS_TP screen.
-                        dacOutEpics[jj][ii] = dac_out;
+                        dacInfo.dacOutEpics[jj][ii] = dac_out;
 
                         /// - ---- Load DAC testpoints
                         floatDacOut[16*jj + ii] = dac_out;
@@ -714,15 +718,15 @@ printf("cycle time = %d\n",cycleTime);
 		ipcErrBits = 0;
 		
 		// feStatus = 0;
-               for(jj=0;jj<cdsPciModules.adcCount;jj++) adcRdTimeMax[jj] = 0;
+               for(jj=0;jj<cdsPciModules.adcCount;jj++) adcInfo.adcRdTimeMax[jj] = 0;
 	  }
 	  // Flip the onePPS various once/sec as a watchdog monitor.
 	  // pLocalEpics->epicsOutput.onePps ^= 1;
 	  pLocalEpics->epicsOutput.diagWord = diagWord;
        	  for(jj=0;jj<cdsPciModules.adcCount;jj++) {
-		if(adcRdTimeErr[jj] > MAX_ADC_WAIT_ERR_SEC)
+		if(adcInfo.adcRdTimeErr[jj] > MAX_ADC_WAIT_ERR_SEC)
 			pLocalEpics->epicsOutput.stateWord |= FE_ERROR_ADC;
-		adcRdTimeErr[jj] = 0;
+		adcInfo.adcRdTimeErr[jj] = 0;
 	  }
         }
 
@@ -787,8 +791,8 @@ printf("cycle time = %d\n",cycleTime);
                 if (pLocalEpics->epicsInput.overflowReset) {
                    for (ii = 0; ii < 16; ii++) {
                       for (jj = 0; jj < cdsPciModules.adcCount; jj++) {
-                         overflowAdc[jj][ii] = 0;
-                         overflowAdc[jj][ii + 16] = 0;
+                         adcInfo.overflowAdc[jj][ii] = 0;
+                         adcInfo.overflowAdc[jj][ii + 16] = 0;
 			pLocalEpics->epicsOutput.overflowAdcAcc[jj][ii] = 0;
 			pLocalEpics->epicsOutput.overflowAdcAcc[jj][ii + 16] = 0;
                       }
@@ -799,7 +803,7 @@ printf("cycle time = %d\n",cycleTime);
                    }
                 }
 	  }
-  	  if((pLocalEpics->epicsInput.overflowReset) || (overflowAcc > OVERFLOW_CNTR_LIMIT))
+  	  if((pLocalEpics->epicsInput.overflowReset) || (adcInfo.overflowAdc > OVERFLOW_CNTR_LIMIT))
 	  {
 		pLocalEpics->epicsInput.overflowReset = 0;
 		pLocalEpics->epicsOutput.ovAccum = 0;
@@ -815,7 +819,7 @@ printf("cycle time = %d\n",cycleTime);
 	      {
 	    	for(ii=0;ii<MAX_DAC_CHN_PER_MOD;ii++)
 	    	{
-			pLocalEpics->epicsOutput.dacValue[jj][ii] = dacOutEpics[jj][ii];
+			pLocalEpics->epicsOutput.dacValue[jj][ii] = dacInfo.dacOutEpics[jj][ii];
 		}
 	      }
 	}
@@ -823,7 +827,7 @@ printf("cycle time = %d\n",cycleTime);
 /// \> Cycle 21, Update ADC/DAC status to EPICS.
         if(cycleNum == HKP_ADC_DAC_STAT_UPDATES)
         {
-	  pLocalEpics->epicsOutput.ovAccum = overflowAcc;
+	  pLocalEpics->epicsOutput.ovAccum = adcInfo.overflowAdc;
 	  for(jj=0;jj<cdsPciModules.adcCount;jj++)
 	  {
 	    // SET/CLR Channel Hopping Error
@@ -848,8 +852,8 @@ printf("cycle time = %d\n",cycleTime);
                 if (pLocalEpics->epicsOutput.overflowAdcAcc[jj][ii] > OVERFLOW_CNTR_LIMIT) {
 		   pLocalEpics->epicsOutput.overflowAdcAcc[jj][ii] = 0;
                 }
-		pLocalEpics->epicsOutput.overflowAdc[jj][ii] = overflowAdc[jj][ii];
-		overflowAdc[jj][ii] = 0;
+		pLocalEpics->epicsOutput.overflowAdc[jj][ii] = adcInfo.overflowAdc[jj][ii];
+		adcInfo.overflowAdc[jj][ii] = 0;
 
 	    }
 	  }
@@ -885,8 +889,8 @@ printf("cycle time = %d\n",cycleTime);
                 if (pLocalEpics->epicsOutput.overflowDacAcc[jj][ii] > OVERFLOW_CNTR_LIMIT) {
 		   pLocalEpics->epicsOutput.overflowDacAcc[jj][ii] = 0;
                 }
-		pLocalEpics->epicsOutput.overflowDac[jj][ii] = overflowDac[jj][ii];
-		overflowDac[jj][ii] = 0;
+		pLocalEpics->epicsOutput.overflowDac[jj][ii] = dacInfo.overflowDac[jj][ii];
+		dacInfo.overflowDac[jj][ii] = 0;
 
 	    }
 	  }
diff --git a/src/fe/moduleLoadApp.c b/src/fe/moduleLoadApp.c
index 750062690..fcc0c9b96 100644
--- a/src/fe/moduleLoadApp.c
+++ b/src/fe/moduleLoadApp.c
@@ -22,7 +22,7 @@ struct task_struct *sthread;
 #include "moduleLoadCommon.c"
 
 /// Startup function for initialization of kernel module.
-int init_module (void)
+int rt_fe_init (void)
 {
  	int status;
 	int ii,jj,kk;		/// @param ii,jj,kk default loop counters
@@ -61,18 +61,17 @@ int init_module (void)
 
 	jj = 0;
 
-
 // Allocate EPICS shmem area
         ret =  mbuf_allocate_area(SYSTEM_NAME_STRING_LOWER, 64*1024*1024, 0);
         if (ret < 0) {
-                printf("mbuf_allocate_area() failed; ret = %d\n", ret);
+                printk("mbuf_allocate_area() failed; ret = %d\n", ret);
                 return -1;
         }
         _epics_shm = (unsigned char *)(kmalloc_area[ret]);
 // Allocate IPC shmem area
         ret =  mbuf_allocate_area("ipc", 4*1024*1024, 0);
         if (ret < 0) {
-                printf("mbuf_allocate_area(ipc) failed; ret = %d\n", ret);
+                printk("mbuf_allocate_area(ipc) failed; ret = %d\n", ret);
                 return -1;
         }
         _ipc_shm = (unsigned char *)(kmalloc_area[ret]);
@@ -84,7 +83,7 @@ int init_module (void)
         sprintf(fname, "%s_daq", SYSTEM_NAME_STRING_LOWER);
         ret =  mbuf_allocate_area(fname, 64*1024*1024, 0);
         if (ret < 0) {
-                printf("mbuf_allocate_area() failed; ret = %d\n", ret);
+                printk("mbuf_allocate_area() failed; ret = %d\n", ret);
                 return -1;
         }
         _daq_shm = (unsigned char *)(kmalloc_area[ret]);
@@ -248,7 +247,7 @@ int init_module (void)
 	// If no ADC cards were found, then SLAVE cannot run
 	if(!cdsPciModules.adcCount)
 	{
-		printf("No ADC cards found - exiting\n");
+		printk("No ADC cards found - exiting\n");
 		return -1;
 	}
 	// This did not quite work for some reason
@@ -256,7 +255,7 @@ int init_module (void)
 	//cdsPciModules.dacCount = ioMemData->dacCount;
 	if(status < cards)
 	{
-		printf(" ERROR **** Did not find correct number of cards! Expected %d and Found %d\n",cards,status);
+		printk(" ERROR **** Did not find correct number of cards! Expected %d and Found %d\n",cards,status);
 		cardCountErr = 1;
 	}
 
@@ -293,12 +292,14 @@ int init_module (void)
 
 	// Set Pointer to EPICS data
         pLocalEpics = (CDS_EPICS *)&((RFM_FE_COMMS *)_epics_shm)->epicsSpace;
+		pLocalEpics->epicsOutput.fe_status = WAIT_BURT;
 	// Ensure EPICS is running
 	for (cnt = 0;  cnt < 10 && pLocalEpics->epicsInput.burtRestore == 0; cnt++) {
         	msleep(1000);
 	}
 	// If EPICS not running, EXIT
 	if (cnt == 10) {
+		pLocalEpics->epicsOutput.fe_status = BURT_RESTORE_ERROR;
 		// Cleanup
 		return -1;
 	}
@@ -308,13 +309,14 @@ int init_module (void)
 #ifdef NO_CPU_SHUTDOWN
         sthread = kthread_create(fe_start, 0, "fe_start/%d", CPUID);
         if (IS_ERR(sthread)){
-                printf("Failed to kthread_create()\n");
+                printk("Failed to kthread_create()\n");
                 return -1;
         }
         kthread_bind(sthread, CPUID);
         wake_up_process(sthread);
 #endif
 
+		pLocalEpics->epicsOutput.fe_status = LOCKING_CORE;
 
 #ifndef NO_CPU_SHUTDOWN
         set_fe_code_idle(fe_start, CPUID);
@@ -327,7 +329,7 @@ int init_module (void)
         return 0;
 }
 
-void cleanup_module (void) {
+void rt_fe_cleanup (void) {
 	int i;
 	int ret;
 	extern int __cpuinit cpu_up(unsigned int cpu);
@@ -361,6 +363,8 @@ void cleanup_module (void) {
 
 }
 
+module_init(rt_fe_init);
+module_exit(rt_fe_cleanup);
 MODULE_DESCRIPTION("Control system");
 MODULE_AUTHOR("LIGO");
 MODULE_LICENSE("Dual BSD/GPL");
diff --git a/src/fe/moduleLoadCommon.c b/src/fe/moduleLoadCommon.c
index c9b4b29f2..4c00a1a2a 100644
--- a/src/fe/moduleLoadCommon.c
+++ b/src/fe/moduleLoadCommon.c
@@ -1,8 +1,9 @@
 ///     @file moduleLoadCommon.c
 ///     @brief File contains common routines for moduleLoadIop.c and moduleLoadApp.c.`
 
-int print_io_info(CDS_HARDWARE *cdsp) {
+void print_io_info(CDS_HARDWARE *cdsp) {
   int ii,jj,kk;
+  jj = 0;
 	printf("THIS IS A TEST \n");
 #ifndef USER_SPACE
 	printf("startup time is %ld\n", current_time());
diff --git a/src/fe/moduleLoadIop.c b/src/fe/moduleLoadIop.c
index 9ed1875c7..f6d38d223 100644
--- a/src/fe/moduleLoadIop.c
+++ b/src/fe/moduleLoadIop.c
@@ -25,7 +25,7 @@ extern void msleep(unsigned int);
 #include "moduleLoadCommon.c"
 
 /// Startup function for initialization of kernel module.
-int init_module (void)
+int rt_iop_init (void)
 {
  	int status;
 	int ii,jj,kk;		/// @param ii,jj,kk default loop counters
@@ -45,7 +45,7 @@ int init_module (void)
 
 #ifndef NO_CPU_SHUTDOWN
 	// See if our CPU core is free
-        if (is_cpu_taken_by_rcg_model(CPUID)) {
+    if (is_cpu_taken_by_rcg_model(CPUID)) {
 		printk(KERN_ALERT "Error: CPU %d already taken\n", CPUID);
 		return -1;
 	}
@@ -63,34 +63,39 @@ int init_module (void)
 
 
 // Allocate EPICS memory area
-        ret =  mbuf_allocate_area(SYSTEM_NAME_STRING_LOWER, 64*1024*1024, 0);
-        if (ret < 0) {
-                printf("mbuf_allocate_area() failed; ret = %d\n", ret);
-                return -1;
-        }
-        _epics_shm = (unsigned char *)(kmalloc_area[ret]);
-// Allocate IPC memory area
-        ret =  mbuf_allocate_area("ipc", 4*1024*1024, 0);
-        if (ret < 0) {
-                printf("mbuf_allocate_area(ipc) failed; ret = %d\n", ret);
-                return -1;
-        }
-        _ipc_shm = (unsigned char *)(kmalloc_area[ret]);
+	ret =  mbuf_allocate_area(SYSTEM_NAME_STRING_LOWER, 64*1024*1024, 0);
+    if (ret < 0) {
+		printk("mbuf_allocate_area() failed; ret = %d\n", ret);
+        return -1;
+    }
+    _epics_shm = (unsigned char *)(kmalloc_area[ret]);
+	// Set pointer to EPICS area
+    pLocalEpics = (CDS_EPICS *)&((RFM_FE_COMMS *)_epics_shm)->epicsSpace;
+    pLocalEpics->epicsOutput.fe_status = 0;
+
+	// Allocate IPC memory area
+	ret =  mbuf_allocate_area("ipc", 4*1024*1024, 0);
+    if (ret < 0) {
+		printk("mbuf_allocate_area(ipc) failed; ret = %d\n", ret);
+        return -1;
+	}
+    _ipc_shm = (unsigned char *)(kmalloc_area[ret]);
 
 // Assign pointer to IOP/USER app comms space
   	ioMemData = (IO_MEM_DATA *)(_ipc_shm+ 0x4000);
 
 
 // Allocate DAQ memory area
-        sprintf(fname, "%s_daq", SYSTEM_NAME_STRING_LOWER);
-        ret =  mbuf_allocate_area(fname, 64*1024*1024, 0);
-        if (ret < 0) {
-                printf("mbuf_allocate_area() failed; ret = %d\n", ret);
-                return -1;
-        }
-        _daq_shm = (unsigned char *)(kmalloc_area[ret]);
+	sprintf(fname, "%s_daq", SYSTEM_NAME_STRING_LOWER);
+    ret =  mbuf_allocate_area(fname, 64*1024*1024, 0);
+    if (ret < 0) {
+		printk("mbuf_allocate_area() failed; ret = %d\n", ret);
+        return -1;
+	}
+    _daq_shm = (unsigned char *)(kmalloc_area[ret]);
  	daqPtr = (struct rmIpcStr *) _daq_shm;
 
+    pLocalEpics->epicsOutput.fe_status = 1;
 	// Find and initialize all PCI I/O modules **************************************************
 	// Following I/O card info is from feCode
 	cards = sizeof(cards_used)/sizeof(cards_used[0]);
@@ -105,7 +110,7 @@ int init_module (void)
 	status = mapPciModules(&cdsPciModules);
 	if(status < cards)
 	{
-		printf(" ERROR **** Did not find correct number of cards! Expected %d and Found %d\n",cards,status);
+		printk(" ERROR **** Did not find correct number of cards! Expected %d and Found %d\n",cards,status);
 		cardCountErr = 1;
 	}
 
@@ -117,13 +122,13 @@ int init_module (void)
 	// kk will act as ioMem location counter for mapping modules
 	kk = cdsPciModules.adcCount;
 	for(ii=0;ii<cdsPciModules.adcCount;ii++)
-        {
+	{
 		// MASTER maps ADC modules first in ipc shm for SLAVES
 		ioMemData->model[ii] = cdsPciModules.adcType[ii];
 		ioMemData->ipc[ii] = ii;	// ioData memory buffer location for SLAVE to use
-        }
+    }
 	for(ii=0;ii<cdsPciModules.dacCount;ii++)
-        {
+    {
 		// Pass DAC info to SLAVE processes
 		ioMemData->model[kk] = cdsPciModules.dacType[ii];
 		ioMemData->ipc[kk] = kk;
@@ -186,11 +191,10 @@ int init_module (void)
 	if (cdsPciModules.adcCount == 0) run_on_timer = 1;
 
 	// Initialize buffer for daqLib.c code
-	// printf("Initializing space for daqLib buffers\n");
 	daqBuffer = (long)&daqArea[0];
  
-// Set pointer to EPICS area
-        pLocalEpics = (CDS_EPICS *)&((RFM_FE_COMMS *)_epics_shm)->epicsSpace;
+    pLocalEpics->epicsOutput.fe_status = 2;
+printk("Waiting for EPICS BURT Restore = %d\n", pLocalEpics->epicsInput.burtRestore);
 	// Ensure EPICS running else exit
 	for (cnt = 0;  cnt < 10 && pLocalEpics->epicsInput.burtRestore == 0; cnt++) {
         	msleep(1000);
@@ -202,13 +206,14 @@ int init_module (void)
 #endif
 		return -1;
 	}
+	printk("BURT Restore Complete\n");
 
         pLocalEpics->epicsInput.vmeReset = 0;
 
 #ifdef NO_CPU_SHUTDOWN
         sthread = kthread_create(fe_start, 0, "fe_start/%d", CPUID);
         if (IS_ERR(sthread)){
-                printf("Failed to kthread_create()\n");
+                printk("Failed to kthread_create()\n");
                 return -1;
         }
         kthread_bind(sthread, CPUID);
@@ -217,19 +222,18 @@ int init_module (void)
 
 
 #ifndef NO_CPU_SHUTDOWN
+    pLocalEpics->epicsOutput.fe_status = 3;
+	printk("Locking CPU core %d\n", CPUID);
 	// The code runs on the disabled CPU
-        set_fe_code_idle(fe_start, CPUID);
-        msleep(100);
-
+    set_fe_code_idle(fe_start, CPUID);
+    msleep(100);
 	cpu_down(CPUID);
 
 #endif
         return 0;
 }
 
-void cleanup_module (void) {
-	int i;
-	int ret;
+void rt_iop_cleanup(void) {
 	extern int __cpuinit cpu_up(unsigned int cpu);
 
 #ifndef NO_CPU_SHUTDOWN
@@ -237,9 +241,10 @@ void cleanup_module (void) {
         set_fe_code_idle(0, CPUID);
 #endif
 
-	printk("Setting stop_working_threads to 1\n");
+	// printk("Setting stop_working_threads to 1\n");
 	// Stop the code and wait
 #ifdef NO_CPU_SHUTDOWN
+	int ret;
 	ret = kthread_stop(sthread);
 #endif
         stop_working_threads = 1;
@@ -257,13 +262,16 @@ void cleanup_module (void) {
         msleep(1000);
 	// Bring the CPU back up
         cpu_up(CPUID);
-        //msleep(1000);
+        msleep(1000);
 	printk("Brought the CPU back up\n");
 #endif
 	printk("Just before returning from cleanup_module for " SYSTEM_NAME_STRING_LOWER "\n");
 
 }
 
+module_init(rt_iop_init);
+module_exit(rt_iop_cleanup);
+
 MODULE_DESCRIPTION("Control system");
 MODULE_AUTHOR("LIGO");
 MODULE_LICENSE("Dual BSD/GPL");
diff --git a/src/fe/moduleLoadVirtual.c b/src/fe/moduleLoadVirtual.c
index 1c068daec..76b8129ac 100644
--- a/src/fe/moduleLoadVirtual.c
+++ b/src/fe/moduleLoadVirtual.c
@@ -1,485 +1,19 @@
-///	@file moduleLoad.c
-///	@brief File contains startup routines for real-time code.
+///	@file moduleLoadIop.c
+///	@brief File contains startup routines for real-time IOP code.
 
 #include <asm/uaccess.h>
 #include <linux/ctype.h>
 #include <linux/spinlock_types.h>
 #include <proc.h>
 
-
 // These externs and "16" need to go to a header file (mbuf.h)
 extern void *kmalloc_area[16];
 extern int mbuf_allocate_area(char *name, int size, struct file *file);
 extern void *fe_start(void *arg);
 extern int run_on_timer;
 extern char daqArea[2*DAQ_DCU_SIZE];           // Space allocation for daqLib buffers
+struct task_struct *sthread;
 
-#include FE_PROC_FILE
-
-/// /proc filesystem directory entry
-struct proc_dir_entry *proc_dir_entry;
-/// /proc/{sysname}/status entry
-struct proc_dir_entry *proc_entry;
-/// /proc/{sysname}/gps entry
-struct proc_dir_entry *proc_gps_entry;
-/// /proc/{sysname}/epics directory entry
-struct proc_dir_entry *proc_epics_dir_entry;
-/// /proc/{sysname}/futures entry
-struct proc_dir_entry *proc_futures_entry;
-
-void remove_epics_proc_files(void);
-int create_epics_proc_files(void);
-
-/// Routine to read the /proc/{model}/status file. \n \n
-///	 We give all of our information in one go, so if the
-///	 user asks us if we have more information the \n
-///	 answer should always be no.
-///	 
-///	  This is important because the standard read
-///	  function from the library would continue to issue \n
-///	  the read system call until the kernel replies
-///	  that it has no more information, or until its \n
-///	  buffer is filled.
-int
-procfile_status_read(char *buffer,
-	      char **buffer_location,
-	      off_t offset, int buffer_length, int *eof, void *data)
-{
-	int ret, i;
-	i = 0;
-	*buffer = 0;
-
-	/* 
-	 * We give all of our information in one go, so if the
-	 * user asks us if we have more information the
-	 * answer should always be no.
-	 *
-	 * This is important because the standard read
-	 * function from the library would continue to issue
-	 * the read system call until the kernel replies
-	 * that it has no more information, or until its
-	 * buffer is filled.
-	 */
-	if (offset > 0) {
-		/* we have finished to read, return 0 */
-		ret  = 0;
-	} else {
-#if defined(SERVO64K) || defined(SERVO32K) || defined(SERVO16K) || defined(COMMDATA_INLINE)
-		char b[128];
-#if defined(SERVO64K) || defined(SERVO32K)
-		static const int nb = 32;
-#elif defined(SERVO16K)
-		static const int nb = 64;
-#endif
-#endif
-		/* fill the buffer, return the buffer size */
-		ret = sprintf(buffer,
-
-			"startGpsTime=%d\n"
-			"uptime=%d\n"
-			"cpuTimeEverMax=%d\n"
-			"cpuTimeEverMaxWhen=%d\n"
-			"adcHoldTime=%d\n"
-			"adcHoldTimeEverMax=%d\n"
-			"adcHoldTimeEverMaxWhen=%d\n"
-			"adcHoldTimeMax=%d\n"
-			"adcHoldTimeMin=%d\n"
-			"adcHoldTimeAvg=%d\n"
-			"usrTime=%d\n"
-			"usrHoldTime=%d\n"
-			"cycle=%d\n"
-			"gps=%d\n"
-			"buildDate=%s\n"
-			"cpuTimeMax(cur,past sec)=%d,%d\n"
-			"cpuTimeMaxCycle(cur,past sec)=%d,%d\n",
-
-			startGpsTime,
-			cycle_gps_time - startGpsTime,
-			cpuTimeEverMax,
-			cpuTimeEverMaxWhen,
-			adcHoldTime,
-			adcHoldTimeEverMax,
-			adcHoldTimeEverMaxWhen,
-			adcHoldTimeMax,
-			adcHoldTimeMin,
-			adcHoldTimeAvgPerSec,
-			usrTime,
-			usrHoldTime,
-			cycleNum,
-			cycle_gps_time,
-			build_date,
-			cycleTime, timeHoldHold,
-			timeHoldWhen, timeHoldWhenHold);
-#if defined(SERVO64K) || defined(SERVO32K) || defined(SERVO16K)
-		strcat(buffer, "cycleHist: ");
-		for (i = 0; i < nb; i++) {
-			if (!cycleHistMax[i]) continue;
-			sprintf(b, "%d=%d@%d ", i, cycleHistMax[i], cycleHistWhenHold[i]);
-			strcat(buffer, b);
-		}
-		strcat(buffer, "\n");
-#endif
-
-		/* Output DAC buffer size information */
-		for (i = 0; i < cdsPciModules.dacCount; i++) {
-			if (cdsPciModules.dacType[i] == GSC_18AO8) {
-				sprintf(b, "DAC #%d 18-bit buf_size=%d\n", i, dacOutBufSize[i]);
-			} else {
-				sprintf(b, "DAC #%d 16-bit fifo_status=%d (%s)\n", i, dacOutBufSize[i],
-					dacOutBufSize[i] & 8? "full":
-						(dacOutBufSize[i] & 1? "empty":
-							(dacOutBufSize[i] & 4? "high quarter": "OK")));
-			}
-			strcat(buffer, b);
-		}
-		/* Output ADC read time information */
-		for (i = 0; i < cdsPciModules.adcCount; i++) {
-			sprintf(b, "ADC #%d read time MAX=%d Current=%d\n", i, adcRdTimeMax[i],adcRdTime[i]);
-			strcat(buffer, b);
-		}
-#ifdef COMMDATA_INLINE
-		// See if we have any IPC with errors and print the numbers out
-		//
-		sprintf(b, "ipcErrBits=0x%x\n", ipcErrBits);
-		strcat(buffer, b);
-
-		// The following loop has a chance to overflow the buffer,
-		// which is set to PROC_BLOCK_SIZE. (PAGE_SIZE-1024 = 3072 bytes).
-		// We will simply stop printing at that point.
-#define PROC_BLOCK_SIZE (3*1024)
-		unsigned int byte_cnt = strlen(buffer) + 1;
-		for (i = 0; i < myIpcCount; i++) {
-	  	  if (ipcInfo[i].errTotal) {
-	  		unsigned int cnt =
-				sprintf(b, "IPC net=%d num=%d name=%s sender=%s errcnt=%d\n", 
-					ipcInfo[i].netType, ipcInfo[i].ipcNum,
-					ipcInfo[i].name, ipcInfo[i].senderModelName,
-					ipcInfo[i].errTotal);
-			if (byte_cnt + cnt > PROC_BLOCK_SIZE) break;
-			byte_cnt += cnt;
-	  		strcat(buffer, b);
-	  	  }
- 		}
-#endif
-		ret = strlen(buffer);
-	}
-
-	return ret;
-}
-
-/// Routine to read the /proc/{model}/gps file. \n \n
-///
-int
-procfile_gps_read(char *buffer,
-	      char **buffer_location,
-	      off_t offset, int buffer_length, int *eof, void *data)
-{
-	*buffer = 0;
-
-	if (offset > 0) {
-		/* we have finished to read, return 0 */
-		return 0;
-	} else {
-		/* fill the buffer, return the buffer size */
-		/* print current GPS time and zero padded fraction */
-		return sprintf(buffer, "%d.%02d\n", cycle_gps_time, (cycleNum*100/CYCLE_PER_SECOND)%100);
-	}
-	// Never reached
-}
-
-/// Routine to read the /proc/{model}/epics/{chname} files. \n \n
-///
-int
-procfile_epics_read(char *buffer,
-	      char **buffer_location,
-	      off_t offset, int buffer_length, int *eof, void *data)
-{
-	*buffer = 0;
-
-	if (offset > 0) {
-		/* we have finished to read, return 0 */
-		return 0;
-	} else {
-		/* fill the buffer, return the buffer size */
-		struct proc_epics *pe = (struct proc_epics *)data;
-		unsigned int ncel = pe->nrow * pe->ncol; // Matrix size
-		switch (pe -> type) {
-			case 0: /* int */
-				return sprintf(buffer, "%s%d\n",
-					(*((char *)(((void *)pLocalEpics) + pe->mask_idx)))? "\t": "",
-					*((int *)(((void *)pLocalEpics) + pe->idx)));
-	//			printf("Accessing data at %x\n", (((void *)pLocalEpics) + pe->idx));
-				break;
-			case 1: /* double */ {
-				char lb[64];
-				if (ncel) { /* Print Matrix */
-					unsigned int i, j;
-					unsigned int nrow = pe->nrow;
-					unsigned int ncol = pe->ncol;
-					unsigned int s = 0;
-					unsigned int masked = *((char *)(((void *)pLocalEpics) + pe->mask_idx));
-					for (i = 0; i < nrow; i++)  {
-						if (masked) s += sprintf(buffer + s, "\t");
-						for (j = 0; j < ncol; j++)  {
-							s += sprintf(buffer + s, "%s ", dtoa_r(lb, ((double *)(((void *)pLocalEpics) + pe->idx))[ncol*i + j]));
-						}
-						s += sprintf(buffer + s, "\n");
-					}
-					return s;
-				}  else { /* Print single value */
-					return sprintf(buffer, "%s%s\n",
-						(*((char *)(((void *)pLocalEpics) + pe->mask_idx)))? "\t": "",
-						dtoa_r(lb, *((double *)(((void *)pLocalEpics) + pe->idx))));
-				}
-				break;
-			}
-		}
-	}
-	// Never reached
-}
-
-#define PROC_BLOCK_SIZE (3*1024)
-
-// Scan a double
-double
-simple_strtod(char *start, char **end) {
-	int integer;
-	if (*start != '.') {
-		integer = simple_strtol(start, end, 10);
-        	if (*end == start) return 0.0;
-		start = *end;
-	} else integer = 0;
-	if (*start != '.') return integer;
-	else {
-		start++;
-		double frac = simple_strtol(start, end, 10);
-        	if (*end == start) return integer;
-		int i;
-		for (i = 0; i < (*end - start); i++) frac /= 10.0;
-		return ((double)integer) + frac;
-	}
-	// Never reached
-}
-
-
-int
-procfile_epics_write(struct file *file, const char __user *buf,
-                     unsigned long count, void *data)
-{
-        ssize_t ret = -ENOMEM;
-        char *page;
-        char *start;
- 	unsigned int future = 0;
-
-        if (count > PROC_BLOCK_SIZE)
-                return -EOVERFLOW;
-
-        start = page = (char *)__get_free_page(GFP_KERNEL);
-        if (page) {
-                ret = -EFAULT;
-                if (copy_from_user(page, buf, count))
-                        goto out;
-		page[count] = 0;
-		ret = count;
-		struct proc_epics *pe = (struct proc_epics *)data;
-	        char *end;
-		for(;isspace(*start);start++);
-		// See if this a single-character command
-		switch (*start) {
-			case 'm':
-				*((char *)(((void *)pLocalEpics) + pe->mask_idx)) = 1;
-				start++;
-				break;
-			case 'u':
-				*((char *)(((void *)pLocalEpics) + pe->mask_idx)) = 0;
-				start++;
-				break;
-			case 'f':
-				future=1;
-				start++;
-				break;
-		}
-		for(;isspace(*start);start++);
-		double new_double = 0.0;
-		int new_int = 0;
-		switch (pe -> type) {
-			case 0: /* int */ 
-			        new_int = simple_strtol(start, &end, 10);
-			        if (new_int > INT_MAX || new_int < INT_MIN) {
-                			ret = -EFAULT;
-					goto out;
-				}
-				break;
-			case 1: /* double */ 
-			        new_double = simple_strtod(start, &end);
-				//printf("User wrote %s\n", dtoa1(new_double));
-				break;
-		}
-	        if (end == start) goto out;
-		// See if this is a matrix
-		int idx = 0;
-		int ncel = pe->nrow * pe->ncol;
-		if (ncel) {
-			// Expect the cell index number next
-			start = end;
-			for(;isspace(*start);start++);
-			idx = simple_strtol(start, &end, 10);
-			if (idx >= ncel || idx < 0) {
-               			ret = -EFAULT;
-				goto out;
-			}
-			
-		}
-		if (!future) {
-			switch (pe -> type) {
-				case 0: /* int */ 
-					*((int *)(((void *)pLocalEpics) + pe->idx)) = new_int;
-					break;
-				case 1: /* double */
-					((double *)(((void *)pLocalEpics) + pe->idx))[idx] = new_double;
-					break;
-			}
-		} else if ((*((char *)(((void *)pLocalEpics) + pe->mask_idx)))) { // Allow to setup a future only if masked
-			unsigned long cycle;
-			start = end;
-			for(;isspace(*start);start++);
-			// check for gps seconds
-			double gps = simple_strtod(start, &end);
-			if (end == start) {
-				gps = cycle_gps_time + 5;
-				cycle = cycleNum;
-			} else {
-				// Convert gps time
-				unsigned long gps_int = gps;
-				gps -= gps_int;
-				cycle = gps * CYCLE_PER_SECOND;
-				gps = gps_int;
-			}
-			// Add new future setpoint
-			// Find first available slot
-			int i;
-			static DEFINE_SPINLOCK(fut_lock);
-			spin_lock(&fut_lock);
-			for (i = 0; (i < MAX_PROC_FUTURES) && proc_futures[i].proc_epics; i++);
-			if (i == MAX_PROC_FUTURES) {
-				spin_unlock(&fut_lock);
-				ret = -ENOMEM;
-			} else {
-				// Found a slot
-				proc_futures[i].cycle = cycle;
-				proc_futures[i].gps = gps;
-				proc_futures[i].val = pe->type? new_double: new_int;
-				proc_futures[i].idx = idx;
-
-				// This pointer has to be set last; Indicates a vailid entry for the
- 				// real-time code in controller.c
-				proc_futures[i].proc_epics = pe; // FE code reads/writes this variable
-				spin_unlock(&fut_lock);
-			}
-		} else ret = -EFAULT;
-        }
-out:
-        free_page((unsigned long)page);
-        return ret;
-}
-
-/// Routine to read the /proc/{model}/epics/futures files. \n \n
-///
-// :TODO: the function does not check for buffer overflow, Linux kernel catches it though,
-//  when proc_futures contains too many entries.
-int
-procfile_futures_read(char *buffer,
-	      char **buffer_location,
-	      off_t offset, int buffer_length, int *eof, void *data)
-{
-	*buffer = 0;
-
-	if (offset > 0) {
-		/* we have finished to read, return 0 */
-		return 0;
-	} else {
-		/* fill the buffer, return the buffer size */
-		char b[128];
-		int i;
-		for (i = 0; i < MAX_PROC_FUTURES; i++) {
-			// Copy the entry to avoid race with the FE code
-			struct proc_futures pf = proc_futures[i];
-			if (pf.proc_epics) {
-				char s[64];
-				char s1[64];
-				if (pf.idx) { /* matrix */
-					sprintf(b, "%s %s@%s %d %d\n", pf.proc_epics->name, dtoa_r(s, pf.val), dtoa_r(s1, pf.idx), pf.gps, pf.cycle);
-				} else {
-					sprintf(b, "%s %s %d %d\n", pf.proc_epics->name, dtoa_r(s, pf.val), pf.gps, pf.cycle);
-				}
-				strcat(buffer, b);
-			}
-		}
-		return strlen(buffer);
-	}
-	// Never reached
-}
-
-
-static const ner = sizeof(proc_epics)/sizeof(struct proc_epics);
-
-/// Function to create /proc/{model}/epics/* files
-///
-int
-create_epics_proc_files() {
-	int i;
-
-	for (i = 0; i < ner; i++) proc_epics_entry[i]  = 0;
-
-	for (i = 0; i < ner; i++) {
-		//printf("%s\n", proc_epics[i].name);
-        	proc_epics_entry[i] = create_proc_entry(proc_epics[i].name, PROC_MODE, proc_epics_dir_entry);
-        	if (proc_epics_entry[i]  == NULL) {
-		        remove_epics_proc_files();
-                	printk(KERN_ALERT "Error: Could not initialize /proc/%s/epics/%s\n", SYSTEM_NAME_STRING_LOWER, proc_epics[i].name);
-                	return 0;
-        	}
-		proc_epics_entry[i]->mode = S_IFREG | S_IRUGO;
-		switch (proc_epics[i].in) {
-			case 0:
-				proc_epics_entry[i]->write_proc = procfile_epics_write;
-				proc_epics_entry[i]->mode |= S_IWUGO;
-				// Fall through
-			case 1:
-				proc_epics_entry[i]->read_proc = procfile_epics_read;
-				break;
-		}
-		proc_epics_entry[i]->uid 	 = PROC_UID;
-		proc_epics_entry[i]->gid 	 = 0;
-		unsigned int ncel = proc_epics[i].nrow * proc_epics[i].ncol; // Enough space to deal with the matrix
-		proc_epics_entry[i]->size 	 = ncel? 64 * ncel: 128;
-		proc_epics_entry[i]->data 	 = proc_epics + i;
-	}
-	proc_futures_entry = create_proc_entry("futures", PROC_MODE, proc_epics_dir_entry);
-        if (proc_futures_entry  == NULL) {
-                remove_epics_proc_files();
-                printk(KERN_ALERT "Error: Could not initialize /proc/%s/epics/futures\n", SYSTEM_NAME_STRING_LOWER);
-                return 0;
-	}
-	proc_futures_entry->mode = S_IFREG | S_IRUGO;
-	proc_futures_entry->uid 	= PROC_UID;
-	proc_futures_entry->gid 	= 0;
-	proc_futures_entry->size	= 10240;
-	proc_futures_entry->read_proc = procfile_futures_read;
-	return 1;
-}
-
-/// Function to delete /proc/{model}/epics/* files
-///
-void remove_epics_proc_files() {
-	int i;
-	for (i = 0; i < ner; i++)
-		if (proc_epics_entry[i] != NULL) {
-			remove_proc_entry(proc_epics[i].name, proc_epics_dir_entry);
-			proc_epics_entry[i] = 0;
-		}
-	remove_proc_entry("futures", proc_epics_dir_entry);
-}
 
 // MAIN routine: Code starting point ****************************************************************
 int need_to_load_IOP_first;
@@ -488,6 +22,8 @@ EXPORT_SYMBOL(need_to_load_IOP_first);
 extern void set_fe_code_idle(void *(*ptr)(void *), unsigned int cpu);
 extern void msleep(unsigned int);
 
+#include "moduleLoadCommon.c"
+
 /// Startup function for initialization of kernel module.
 int init_module (void)
 {
@@ -517,77 +53,23 @@ int init_module (void)
 
 
 #ifdef DOLPHIN_TEST
-	status = init_dolphin();
+	status = init_dolphin(1);
 	if (status != 0) {
 		return -1;
 	}
 #endif
 
-	// Create /proc filesystem tree
-	proc_dir_entry = proc_mkdir(SYSTEM_NAME_STRING_LOWER, NULL);
-	if (proc_dir_entry == NULL) {
-		printk(KERN_ALERT "Error: Could not initialize /proc/%s\n", SYSTEM_NAME_STRING_LOWER);
-		return -ENOMEM;
-	}
-	
-	proc_entry = create_proc_entry("status", PROC_MODE, proc_dir_entry);
-	if (proc_entry == NULL) {
-		remove_proc_entry(SYSTEM_NAME_STRING_LOWER, NULL);
-		printk(KERN_ALERT "Error: Could not initialize /proc/%s/status\n", SYSTEM_NAME_STRING_LOWER);
-		return -ENOMEM;
-	}
-	
-	proc_gps_entry = create_proc_entry("gps", PROC_MODE, proc_dir_entry);
-	if (proc_gps_entry == NULL) {
-		remove_proc_entry("status", proc_dir_entry);
-		remove_proc_entry(SYSTEM_NAME_STRING_LOWER, NULL);
-		printk(KERN_ALERT "Error: Could not initialize /proc/%s/gps\n", SYSTEM_NAME_STRING_LOWER);
-		return -ENOMEM;
-	}
-
-	proc_epics_dir_entry = proc_mkdir("epics", proc_dir_entry);
-	if (proc_epics_dir_entry == NULL) {
-		remove_proc_entry("gps", proc_dir_entry);
-		remove_proc_entry("status", proc_dir_entry);
-		remove_proc_entry(SYSTEM_NAME_STRING_LOWER, NULL);
-		printk(KERN_ALERT "Error: Could not initialize /proc/%s/epics\n", SYSTEM_NAME_STRING_LOWER);
-		return -ENOMEM;
-	}
-
-	proc_entry->read_proc = procfile_status_read;
-	proc_entry->mode 	 = S_IFREG | S_IRUGO;
-	proc_entry->uid 	 = PROC_UID;
-	proc_entry->gid 	 = 0;
-	proc_entry->size 	 = 10240;
-
-	proc_gps_entry->read_proc = procfile_gps_read;
-	proc_gps_entry->mode 	 = S_IFREG | S_IRUGO;
-	proc_gps_entry->uid 	 = PROC_UID;
-	proc_gps_entry->gid 	 = 0;
-	proc_gps_entry->size 	 = 128;
-	proc_gps_entry->data 	 = &cycle_gps_time;
-
-	// Create all /proc/{system}/epics/* files, one file per  existing Epics channel
-  	if (create_epics_proc_files() == 0) {
-		remove_proc_entry("epics", proc_dir_entry);
-		remove_proc_entry("gps", proc_dir_entry);
-		remove_proc_entry("status", proc_dir_entry);
-		remove_proc_entry(SYSTEM_NAME_STRING_LOWER, NULL);
-		return -ENOMEM;
-	}
-
-	printf("startup time is %ld\n", current_time());
 	jj = 0;
-	printf("cpu clock %u\n",cpu_khz);
 
 
+// Allocate EPICS memory area
         ret =  mbuf_allocate_area(SYSTEM_NAME_STRING_LOWER, 64*1024*1024, 0);
         if (ret < 0) {
                 printf("mbuf_allocate_area() failed; ret = %d\n", ret);
                 return -1;
         }
         _epics_shm = (unsigned char *)(kmalloc_area[ret]);
-        printf("EPICSM at 0x%x\n", _epics_shm);
+// Allocate IPC memory area
         ret =  mbuf_allocate_area("ipc", 4*1024*1024, 0);
         if (ret < 0) {
                 printf("mbuf_allocate_area(ipc) failed; ret = %d\n", ret);
@@ -595,13 +77,11 @@ int init_module (void)
         }
         _ipc_shm = (unsigned char *)(kmalloc_area[ret]);
 
-	printf("IPC    at 0x%x\n",_ipc_shm);
+// Assign pointer to IOP/USER app comms space
   	ioMemData = (IO_MEM_DATA *)(_ipc_shm+ 0x4000);
-	printf("IOMEM  at 0x%x size 0x%x\n",(_ipc_shm + 0x4000),sizeof(IO_MEM_DATA));
 
 
-// If DAQ is via shared memory (Framebuilder code running on same machine or MX networking is used)
-// attach DAQ shared memory location.
+// Allocate DAQ memory area
         sprintf(fname, "%s_daq", SYSTEM_NAME_STRING_LOWER);
         ret =  mbuf_allocate_area(fname, 64*1024*1024, 0);
         if (ret < 0) {
@@ -609,88 +89,48 @@ int init_module (void)
                 return -1;
         }
         _daq_shm = (unsigned char *)(kmalloc_area[ret]);
-        // printf("Allocated daq shmem; set at 0x%x\n", _daq_shm);
-	printf("DAQSM at 0x%x\n",_daq_shm);
  	daqPtr = (struct rmIpcStr *) _daq_shm;
 
-	// Find and initialize all PCI I/O modules *******************************************************
-	  // Following I/O card info is from feCode
-	  cards = sizeof(cards_used)/sizeof(cards_used[0]);
-	  printf("configured to use %d cards\n", cards);
-	  cdsPciModules.cards = cards;
-	  cdsPciModules.cards_used = cards_used;
-          //return -1;
-	printf("Initializing PCI Modules\n");
-	cdsPciModules.adcCount = 5;
-	for(ii=0;ii<cdsPciModules.adcCount;ii++)
-		cdsPciModules.adcType[ii] = GSC_16AI64SSA;
-	cdsPciModules.dacCount = 10;
-	for(ii=0;ii<cdsPciModules.dacCount;ii++)
-		cdsPciModules.dacType[ii] = GSC_16AO16;
+	// Find and initialize all PCI I/O modules **************************************************
+	// Following I/O card info is from feCode
+	cards = sizeof(cards_used)/sizeof(cards_used[0]);
+	cdsPciModules.cards = cards;
+	cdsPciModules.cards_used = cards_used;
+	cdsPciModules.adcCount = 0;
+	cdsPciModules.dacCount = 0;
 	cdsPciModules.dioCount = 0;
 	cdsPciModules.doCount = 0;
 
-	status = 15;
-	printf("%d PCI cards found \n",status);
+	// Call PCI initialization routine in map.c file.
+	status = mapPciModules(&cdsPciModules);
 	if(status < cards)
 	{
 		printf(" ERROR **** Did not find correct number of cards! Expected %d and Found %d\n",cards,status);
 		cardCountErr = 1;
 	}
 
-	// Print out all the I/O information
-        printf("***************************************************************************\n");
-		// Master send module counds to SLAVE via ipc shm
-		ioMemData->totalCards = status;
-		ioMemData->adcCount = cdsPciModules.adcCount;
-		ioMemData->dacCount = cdsPciModules.dacCount;
-		ioMemData->bioCount = cdsPciModules.doCount;
-		// kk will act as ioMem location counter for mapping modules
-		kk = cdsPciModules.adcCount;
-	printf("%d ADC cards found\n",cdsPciModules.adcCount);
+	// Master send module counds to SLAVE via ipc shm
+	ioMemData->totalCards = status;
+	ioMemData->adcCount = cdsPciModules.adcCount;
+	ioMemData->dacCount = cdsPciModules.dacCount;
+	ioMemData->bioCount = cdsPciModules.doCount;
+	// kk will act as ioMem location counter for mapping modules
+	kk = cdsPciModules.adcCount;
 	for(ii=0;ii<cdsPciModules.adcCount;ii++)
         {
 		// MASTER maps ADC modules first in ipc shm for SLAVES
 		ioMemData->model[ii] = cdsPciModules.adcType[ii];
 		ioMemData->ipc[ii] = ii;	// ioData memory buffer location for SLAVE to use
-                if(cdsPciModules.adcType[ii] == GSC_16AI64SSA)
-                {
-                        printf("\tADC %d is a GSC_16AI64SSA module\n",ii);
-                        jj = 32;
-                        printf("\t\tChannels = %d \n",jj);
-                }
         }
-        printf("***************************************************************************\n");
-	printf("%d DAC cards found\n",cdsPciModules.dacCount);
 	for(ii=0;ii<cdsPciModules.dacCount;ii++)
         {
-                if(cdsPciModules.dacType[ii] == GSC_18AO8)
-		{
-                        printf("\tDAC %d is a GSC_18AO8 module\n",ii);
-		}
-                if(cdsPciModules.dacType[ii] == GSC_16AO16)
-                {
-                        printf("\tDAC %d is a GSC_16AO16 module\n",ii);
-                }
 		// Pass DAC info to SLAVE processes
 		ioMemData->model[kk] = cdsPciModules.dacType[ii];
 		ioMemData->ipc[kk] = kk;
 		// Following used by MASTER to point to ipc memory for inputting DAC data from SLAVES
                 cdsPciModules.dacConfig[ii]  = kk;
-		printf("MASTER DAC SLOT %d %d\n",ii,cdsPciModules.dacConfig[ii]);
 		kk ++;
 	}
-        printf("***************************************************************************\n");
-	printf("%d DIO cards found\n",cdsPciModules.dioCount);
-        printf("***************************************************************************\n");
-	printf("%d IIRO-8 Isolated DIO cards found\n",cdsPciModules.iiroDioCount);
-        printf("***************************************************************************\n");
-	printf("%d IIRO-16 Isolated DIO cards found\n",cdsPciModules.iiroDio1Count);
-        printf("***************************************************************************\n");
-	printf("%d Contec 32ch PCIe DO cards found\n",cdsPciModules.cDo32lCount);
-	printf("%d Contec PCIe DIO1616 cards found\n",cdsPciModules.cDio1616lCount);
-	printf("%d Contec PCIe DIO6464 cards found\n",cdsPciModules.cDio6464lCount);
-	printf("%d DO cards found\n",cdsPciModules.doCount);
 	// MASTER sends DIO module information to SLAVES
 	// Note that for DIO, SLAVE modules will perform the I/O directly and therefore need to
 	// know the PCIe address of these modules.
@@ -701,7 +141,6 @@ int init_module (void)
 		if(cdsPciModules.doType[ii] == CON_1616DIO)
 		{
 			tdsControl[tdsCount] = ii;
-			printf("TDS controller %d is at %d\n",tdsCount,ii);
 			tdsCount ++;
 		}
 		ioMemData->model[kk] = cdsPciModules.doType[ii];
@@ -710,69 +149,48 @@ int init_module (void)
 		ioMemData->ipc[kk] = cdsPciModules.pci_do[ii];
 		kk ++;
 	}
-	printf("Total of %d I/O modules found and mapped\n",kk);
-	for(ii=0;ii<kk;ii++) {
-		printf("Model = %d  ipc = %d \n",ioMemData->model[ii],ioMemData->ipc[ii]);
-		}
-        printf("***************************************************************************\n");
 // Following section maps Reflected Memory, both VMIC hardware style and Dolphin PCIe network style.
 // Slave units will perform I/O transactions with RFM directly ie MASTER does not do RFM I/O.
 // Master unit only maps the RFM I/O space and passes pointers to SLAVES.
 
-	cdsPciModules.rfmCount = 0;
-	printf("%d RFM cards found\n",cdsPciModules.rfmCount);
 	ioMemData->rfmCount = cdsPciModules.rfmCount;
+	for(ii=0;ii<cdsPciModules.rfmCount;ii++)
+        {
+		// Master sends RFM memory pointers to SLAVES
+		ioMemData->pci_rfm[ii] = cdsPciModules.pci_rfm[ii];
+		ioMemData->pci_rfm_dma[ii] = cdsPciModules.pci_rfm_dma[ii];
+	}
 	// ioMemData->dolphinCount = 0;
+#ifdef DOLPHIN_TEST
+	ioMemData->dolphinCount = cdsPciModules.dolphinCount;
+	ioMemData->dolphinRead[0] = cdsPciModules.dolphinRead[0];
+	ioMemData->dolphinWrite[0] = cdsPciModules.dolphinWrite[0];
+
+#else
 // Clear Dolphin pointers so the slave sees NULLs
 	ioMemData->dolphinCount = 0;
         ioMemData->dolphinRead[0] = 0;
-        ioMemData->dolphinRead[1] = 0;
-        ioMemData->dolphinRead[2] = 0;
-        ioMemData->dolphinRead[3] = 0;
         ioMemData->dolphinWrite[0] = 0;
-        ioMemData->dolphinWrite[1] = 0;
-        ioMemData->dolphinWrite[2] = 0;
-        ioMemData->dolphinWrite[3] = 0;
-        printf("***************************************************************************\n");
-  	if (cdsPciModules.gps) {
-	printf("IRIG-B card found %d\n",cdsPciModules.gpsType);
-        printf("***************************************************************************\n");
-  	}
+#endif
 
+	// Print out all the I/O information
+	  print_io_info(&cdsPciModules);
 
 	// Code will run on internal timer if no ADC modules are found
-	printf("Virtual IOP ******* running on timer\n");
-	run_on_timer = 1;
+	if (cdsPciModules.adcCount == 0) run_on_timer = 1;
 
 	// Initialize buffer for daqLib.c code
-	printf("Initializing space for daqLib buffers\n");
+	// printf("Initializing space for daqLib buffers\n");
 	daqBuffer = (long)&daqArea[0];
  
-#ifndef NO_DAQ
-#ifndef SHMEM_DAQ
-	printf("Initializing Network\n");
-	numFb = 1;
-	if (numFb <= 0) {
-		printf("Couldn't initialize Myrinet network connection\n");
-		return -1;
-	}
-	printf("Found %d frameBuilders on network\n",numFb);
-#endif
-#endif
-
-
+// Set pointer to EPICS area
         pLocalEpics = (CDS_EPICS *)&((RFM_FE_COMMS *)_epics_shm)->epicsSpace;
+	// Ensure EPICS running else exit
 	for (cnt = 0;  cnt < 10 && pLocalEpics->epicsInput.burtRestore == 0; cnt++) {
-        	printf("Epics burt restore is %d\n", pLocalEpics->epicsInput.burtRestore);
         	msleep(1000);
 	}
 	if (cnt == 10) {
 		// Cleanup
-		remove_epics_proc_files();
-		remove_proc_entry("epics", proc_dir_entry);
-		remove_proc_entry("gps", proc_dir_entry);
-		remove_proc_entry("status", proc_dir_entry);
-		remove_proc_entry(SYSTEM_NAME_STRING_LOWER, NULL);
 #ifdef DOLPHIN_TEST
 		finish_dolphin();
 #endif
@@ -782,38 +200,32 @@ int init_module (void)
         pLocalEpics->epicsInput.vmeReset = 0;
 
 #ifdef NO_CPU_SHUTDOWN
-        struct task_struct *p;
-        p = kthread_create(fe_start, 0, "fe_start/%d", CPUID);
-        if (IS_ERR(p)){
+        sthread = kthread_create(fe_start, 0, "fe_start/%d", CPUID);
+        if (IS_ERR(sthread)){
                 printf("Failed to kthread_create()\n");
                 return -1;
         }
-        kthread_bind(p, CPUID);
-        wake_up_process(p);
+        kthread_bind(sthread, CPUID);
+        wake_up_process(sthread);
 #endif
 
 
 #ifndef NO_CPU_SHUTDOWN
+	// The code runs on the disabled CPU
         set_fe_code_idle(fe_start, CPUID);
         msleep(100);
 
 	cpu_down(CPUID);
 
-	// The code runs on the disabled CPU
 #endif
         return 0;
 }
 
 void cleanup_module (void) {
 	int i;
+	int ret;
 	extern int __cpuinit cpu_up(unsigned int cpu);
 
-	remove_epics_proc_files();
-	remove_proc_entry("epics", proc_dir_entry);
-	remove_proc_entry("gps", proc_dir_entry);
-	remove_proc_entry("status", proc_dir_entry);
-	remove_proc_entry(SYSTEM_NAME_STRING_LOWER, NULL);
-
 #ifndef NO_CPU_SHUTDOWN
 	// Unset the code callback
         set_fe_code_idle(0, CPUID);
@@ -821,6 +233,9 @@ void cleanup_module (void) {
 
 	printk("Setting stop_working_threads to 1\n");
 	// Stop the code and wait
+#ifdef NO_CPU_SHUTDOWN
+	ret = kthread_stop(sthread);
+#endif
         stop_working_threads = 1;
         msleep(1000);
 
@@ -832,16 +247,12 @@ void cleanup_module (void) {
 
 	// Unset the code callback
         set_fe_code_idle(0, CPUID);
-	printkl("Will bring back CPU %d\n", CPUID);
+	// printkl("Will bring back CPU %d\n", CPUID);
         msleep(1000);
-	// Unmask all masked epics channels
-	for (i = 0; i < ner; i++) {
-  	  *((char *)(((void *)pLocalEpics) + proc_epics[i].mask_idx)) = 0;
-	}
 	// Bring the CPU back up
         cpu_up(CPUID);
         //msleep(1000);
-	printkl("Brought the CPU back up\n");
+	printk("Brought the CPU back up\n");
 #endif
 	printk("Just before returning from cleanup_module for " SYSTEM_NAME_STRING_LOWER "\n");
 
diff --git a/src/fe/rcguser.c b/src/fe/rcguser.c
index 77938c33a..64049a9b9 100644
--- a/src/fe/rcguser.c
+++ b/src/fe/rcguser.c
@@ -337,73 +337,7 @@ int main (int argc, char **argv)
 
 	// Print out all the I/O information
 
-#if 0
-        printf("***************************************************************************\n");
-	printf("%d ADC cards found\n",cdsPciModules.adcCount);
-	for(ii=0;ii<cdsPciModules.adcCount;ii++)
-        {
-                if(cdsPciModules.adcType[ii] == GSC_18AISS6C)
-                {
-                        printf("\tADC %d is a GSC_18AISS6C module\n",ii);
-                        printf("\t\tChannels = 6 \n");
-                        printf("\t\tFirmware Rev = %d \n\n",(cdsPciModules.adcConfig[ii] & 0xfff));
-                }
-                if(cdsPciModules.adcType[ii] == GSC_16AI64SSA)
-                {
-                        printf("\tADC %d is a GSC_16AI64SSA module\n",ii);
-                        if((cdsPciModules.adcConfig[ii] & 0x10000) > 0) jj = 32;
-                        else jj = 64;
-                        printf("\t\tChannels = %d \n",jj);
-                        printf("\t\tFirmware Rev = %d \n\n",(cdsPciModules.adcConfig[ii] & 0xfff));
-                }
-        }
-        printf("***************************************************************************\n");
-	printf("%d DAC cards found\n",cdsPciModules.dacCount);
-	for(ii=0;ii<cdsPciModules.dacCount;ii++)
-        {
-                if(cdsPciModules.dacType[ii] == GSC_18AO8)
-		{
-                        printf("\tDAC %d is a GSC_18AO8 module\n",ii);
-		}
-                if(cdsPciModules.dacType[ii] == GSC_16AO16)
-                {
-                        printf("\tDAC %d is a GSC_16AO16 module\n",ii);
-                        if((cdsPciModules.dacConfig[ii] & 0x10000) == 0x10000) jj = 8;
-                        if((cdsPciModules.dacConfig[ii] & 0x20000) == 0x20000) jj = 12;
-                        if((cdsPciModules.dacConfig[ii] & 0x30000) == 0x30000) jj = 16;
-                        printf("\t\tChannels = %d \n",jj);
-                        if((cdsPciModules.dacConfig[ii] & 0xC0000) == 0x0000)
-			{
-                        	printf("\t\tFilters = None\n");
-			}
-                        if((cdsPciModules.dacConfig[ii] & 0xC0000) == 0x40000)
-			{
-                        	printf("\t\tFilters = 10kHz\n");
-			}
-                        if((cdsPciModules.dacConfig[ii] & 0xC0000) == 0x80000)
-			{
-                        	printf("\t\tFilters = 100kHz\n");
-			}
-                        if((cdsPciModules.dacConfig[ii] & 0x100000) == 0x100000)
-			{
-                        	printf("\t\tOutput Type = Differential\n");
-			}
-                        printf("\t\tFirmware Rev = %d \n\n",(cdsPciModules.dacConfig[ii] & 0xfff));
-                }
-	}
-        printf("***************************************************************************\n");
-	printf("%d DIO cards found\n",cdsPciModules.dioCount);
-        printf("***************************************************************************\n");
-	printf("%d IIRO-8 Isolated DIO cards found\n",cdsPciModules.iiroDioCount);
-        printf("***************************************************************************\n");
-	printf("%d IIRO-16 Isolated DIO cards found\n",cdsPciModules.iiroDio1Count);
-        printf("***************************************************************************\n");
-	printf("%d Contec 32ch PCIe DO cards found\n",cdsPciModules.cDo32lCount);
-	printf("%d Contec PCIe DIO1616 cards found\n",cdsPciModules.cDio1616lCount);
-	printf("%d Contec PCIe DIO6464 cards found\n",cdsPciModules.cDio6464lCount);
-	printf("%d DO cards found\n",cdsPciModules.doCount);
-        printf("***************************************************************************\n");
-#endif
+
 // Following section maps Reflected Memory, both VMIC hardware style and Dolphin PCIe network style.
 // Slave units will perform I/O transactions with RFM directly ie MASTER does not do RFM I/O.
 // Master unit only maps the RFM I/O space and passes pointers to SLAVES.
-- 
GitLab