From edf852e0846fb2bb3115ee9ee1af6331614aa364 Mon Sep 17 00:00:00 2001
From: "ezekiel.dohmen" <ezekiel.dohmen@ligo.org>
Date: Mon, 7 Oct 2024 09:47:08 -0700
Subject: [PATCH] Fixing logic so two LIGO DACs can be run at same time, also
 fixing non-isolated kernel space mode

---
 src/epics/util/Makefile.kernel                |   4 +-
 src/fe/controllerIop.c                        |  10 +-
 src/fe/map.c                                  | 106 ++++++++++--------
 src/fe/moduleLoad.c                           |   4 +-
 src/fe/print_io_info.c                        |   9 +-
 src/include/drv/gsc20ao8.c                    |  52 +++++++--
 src/include/drv/iop_dac_functions.c           |   3 +-
 src/include/drv/ligo28ao32/ligo28ao32.c       |  33 +++---
 src/include/drv/ligo28ao32/ligo28ao32.h       |   2 +
 .../drv/ligo28ao32/ligo28ao32_private.h       |   3 +-
 10 files changed, 149 insertions(+), 77 deletions(-)

diff --git a/src/epics/util/Makefile.kernel b/src/epics/util/Makefile.kernel
index 30f5b0896..d4f18323f 100644
--- a/src/epics/util/Makefile.kernel
+++ b/src/epics/util/Makefile.kernel
@@ -59,6 +59,8 @@ COMMON_OBJ_FILES += src/fe/demod/Biquad.o
 COMMON_OBJ_FILES += src/fe/util/fenv.o
 COMMON_OBJ_FILES += src/fe/statespace/stateSpacePart.o
 COMMON_OBJ_FILES += src/fe/statespace/stateSpaceCtrl_cdev.o
+COMMON_OBJ_FILES += src/include/drv/ligo28ao32/ligo28ao32.o
+
 
 #
 # IOP Specific Object Files
@@ -80,7 +82,7 @@ IOP_EXTRA_OBJ += src/include/drv/ligoPcieTiming_core.o
 IOP_EXTRA_OBJ += src/include/drv/ligoPcieTiming.o
 IOP_EXTRA_OBJ += src/include/drv/plx_9056.o
 IOP_EXTRA_OBJ += src/include/drv/spectracomGPS.o
-IOP_EXTRA_OBJ += src/include/drv/ligo28ao32/ligo28ao32.o
+#IOP_EXTRA_OBJ += src/include/drv/ligo28ao32/ligo28ao32.o
 
 
 ifdef BUILD_WITH_DOLPHIN
diff --git a/src/fe/controllerIop.c b/src/fe/controllerIop.c
index 541eb9100..d7b268775 100644
--- a/src/fe/controllerIop.c
+++ b/src/fe/controllerIop.c
@@ -58,6 +58,9 @@
 #include <linux/delay.h> //udelay()
 #include <asm/cacheflush.h>
 
+#ifdef NO_CPU_SHUTDOWN
+#include <linux/kthread.h> //kthread_should_stop()
+#endif
 
 //
 // Start Exported Global data (controllerIop.h)
@@ -721,6 +724,7 @@ void fe_start_controller( void )
             // sync21pps routine, so don't read again.
             if ( !sync21pps )
                 status = iop_adc_read( padcinfo, cpuClock );
+
             // Clear sync21pps so reads now continue every cycle
             sync21pps = 0;
             adcinfo.startup_sync = 0;
@@ -734,9 +738,8 @@ void fe_start_controller( void )
                 pLocalEpics->epicsOutput.fe_status = ADC_TO_ERROR;
                 RTSLOG_ERROR("An ADC timeout error has been detected on ADC %d, waiting for an exit signal.\n", fe_status_return_subcode);
                 pLocalEpics->epicsOutput.epicsSync++;
-                atomic_set(&g_atom_should_exit, 1);
                 vmeDone = 1;
-                continue;
+                goto error_out;
             }
             // 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
@@ -747,10 +750,9 @@ void fe_start_controller( void )
                 pLocalEpics->epicsOutput.stateWord = FE_ERROR_ADC;
                 pLocalEpics->epicsOutput.fe_status = CHAN_HOP_ERROR;
                 RTSLOG_ERROR("A channel hop error has been detected on ADC %d, waiting for an exit signal.\n", fe_status_return_subcode);
-                atomic_set(&g_atom_should_exit, 1);
                 vmeDone = 1;
                 pLocalEpics->epicsOutput.epicsSync++;
-                continue;
+                goto error_out;
             }
 
             // Following captures time after ADC reads
diff --git a/src/fe/map.c b/src/fe/map.c
index ab6bff25a..2c728736f 100644
--- a/src/fe/map.c
+++ b/src/fe/map.c
@@ -69,6 +69,7 @@ static int mapPciModulesRealCards( CDS_HARDWARE* pCds );
 #endif
 
 
+
 // *****************************************************************************
 /// \brief Patch to properly handle PEX PCIe chip for newer (PCIe) General
 /// Standards
@@ -85,6 +86,9 @@ set_8111_prefetch( struct pci_dev* dacdev )
             dev->vendor );
     if ( ( dev->device == 0x8111 ) && ( dev->vendor == PLX_VID ) )
     {
+
+        pci_set_master( dev );
+
         unsigned int reg;
         // Handle PEX 8111 setup, enable prefetch, set pref size to 64
         // These numbers come from reverse engineering the GSC pxe8111 driver
@@ -340,7 +344,7 @@ mapPciModulesRealCards( CDS_HARDWARE* pCds )
 {
     static struct pci_dev* dacdev;
     int                    status;
-    int                    i;
+    int                    cur_card;
     int                    modCount = 0;
     int adc_750_cnt = 0;
     int adc_cnt = 0;
@@ -361,11 +365,14 @@ mapPciModulesRealCards( CDS_HARDWARE* pCds )
     pCds->adcDuoToneDivisor[ 0 ] = 1;
     pCds->dac_info[ 0 ].duoToneMultiplier = 1;
 
-   modCount = map_cards_2_slots ( &cdsPciModules ) ;
+    modCount = map_cards_2_slots ( &cdsPciModules ) ;
+
+
+
 
     // Map and Initialize ADC and DAC modules
     // This section map cards by model definition order
-    for ( i = 0; i < pCds->cards; i++ )
+    for ( cur_card = 0; cur_card < pCds->cards; cur_card++ )
     {
         adc_cnt = 0;
         fast_adc_cnt = 0;
@@ -379,16 +386,17 @@ mapPciModulesRealCards( CDS_HARDWARE* pCds )
         // Search system for any module with PLX-9056 and PLX id
         while ( ( dacdev = pci_get_device( PLX_VID, PLX_TID, dacdev ) ) )
         {
+
             // Check if it is an ADC module
             if ( ( dacdev->subsystem_device == ADC_SS_ID ) &&
                  ( dacdev->subsystem_vendor == PLX_VID ) )
             {
-                if ( pCds->cards_used[ i ].instance == adc_cnt &&
-                     pCds->cards_used[ i ].type == GSC_16AI64SSA )
+                if ( pCds->cards_used[ cur_card ].instance == adc_cnt &&
+                     pCds->cards_used[ cur_card ].type == GSC_16AI64SSA )
                 {
                     pCds->adcSlot[ pCds->adcCount] = find_card_slot( pCds, GSC_16AI64SSA, adc_cnt );
-                    pCds->adcTimeShift[ pCds->adcCount ] = pCds->cards_used[i].time_shift;
-                    pCds->adcRateSPS[ pCds->adcCount ] = pCds->cards_used[i].rate_sps;
+                    pCds->adcTimeShift[ pCds->adcCount ] = pCds->cards_used[ cur_card ].time_shift;
+                    pCds->adcRateSPS[ pCds->adcCount ] = pCds->cards_used[ cur_card ].rate_sps;
                     status = gsc16ai64Init( pCds, dacdev );
                     RTSLOG_INFO( "adc card on bus %x; device %x status %d time shift %d\n",
                             dacdev->bus->number,
@@ -408,12 +416,12 @@ mapPciModulesRealCards( CDS_HARDWARE* pCds )
             if ( ( dacdev->subsystem_device == ADC_18AI32_SS_ID ) &&
                  ( dacdev->subsystem_vendor == PLX_VID ) )
             {
-                if ( pCds->cards_used[ i ].instance == fast_adc_cnt &&
-                     pCds->cards_used[ i ].type == GSC_18AI32SSC1M )
+                if ( pCds->cards_used[ cur_card ].instance == fast_adc_cnt &&
+                     pCds->cards_used[ cur_card ].type == GSC_18AI32SSC1M )
                 {
                     pCds->adcSlot[ pCds->adcCount] = find_card_slot( pCds, GSC_18AI32SSC1M, fast_adc_cnt );
-                    pCds->adcTimeShift[ pCds->adcCount ] = pCds->cards_used[i].time_shift;
-                    pCds->adcRateSPS[ pCds->adcCount ] = pCds->cards_used[i].rate_sps;
+                    pCds->adcTimeShift[ pCds->adcCount ] = pCds->cards_used[ cur_card ].time_shift;
+                    pCds->adcRateSPS[ pCds->adcCount ] = pCds->cards_used[ cur_card ].rate_sps;
                     status = gsc18ai32Init( pCds, dacdev );
                     RTSLOG_INFO( "fast adc card on bus %x; device %x; time shift %d\n",
                             dacdev->bus->number,
@@ -422,7 +430,7 @@ mapPciModulesRealCards( CDS_HARDWARE* pCds )
                     if(status != 0)
                     {
                         RTSLOG_ERROR( "Map fault GSC18AI32 ADC number %d slot %d\n",
-                            fast_adc_cnt,pCds->adcSlot[ pCds->adcCount]);
+                            fast_adc_cnt, pCds->adcSlot[ pCds->adcCount]);
                         return IO_CARD_MAP_ERROR;
                     } 
                 }
@@ -433,12 +441,12 @@ mapPciModulesRealCards( CDS_HARDWARE* pCds )
             if ( ( dacdev->subsystem_device == ADC_18AI64_SS_ID ) &&
                  ( dacdev->subsystem_vendor == PLX_VID ) )
             {
-                if ( pCds->cards_used[ i ].instance == adc_750_cnt &&
-                     pCds->cards_used[ i ].type == GSC_18AI64SSC )
+                if ( pCds->cards_used[ cur_card ].instance == adc_750_cnt &&
+                     pCds->cards_used[ cur_card ].type == GSC_18AI64SSC )
                 {
                     pCds->adcSlot[ pCds->adcCount] = find_card_slot( pCds, GSC_18AI64SSC, adc_750_cnt );
-                    pCds->adcTimeShift[ pCds->adcCount ] = pCds->cards_used[i].time_shift;
-                    pCds->adcRateSPS[ pCds->adcCount ] = pCds->cards_used[i].rate_sps;
+                    pCds->adcTimeShift[ pCds->adcCount ] = pCds->cards_used[ cur_card ].time_shift;
+                    pCds->adcRateSPS[ pCds->adcCount ] = pCds->cards_used[ cur_card ].rate_sps;
                     status = gsc18ai64Init( pCds, dacdev );
                     RTSLOG_INFO( "750KHz adc card on bus %x; device %x; time shift %d\n",
                             dacdev->bus->number,
@@ -461,8 +469,8 @@ mapPciModulesRealCards( CDS_HARDWARE* pCds )
             if ( ( dacdev->subsystem_device == DAC_SS_ID ) &&
                  ( dacdev->subsystem_vendor == PLX_VID ) )
             {
-                if ( pCds->cards_used[ i ].instance == dac_cnt &&
-                     pCds->cards_used[ i ].type == GSC_16AO16 )
+                if ( pCds->cards_used[ cur_card ].instance == dac_cnt &&
+                     pCds->cards_used[ cur_card ].type == GSC_16AO16 )
                 {
                     pCds->dacSlot[ pCds->dacCount] = find_card_slot( pCds, GSC_16AO16, dac_cnt );
                     status = gsc16ao16Init( pCds, dacdev );
@@ -485,8 +493,8 @@ mapPciModulesRealCards( CDS_HARDWARE* pCds )
             if ( ( dacdev->subsystem_device == DAC_18BIT_SS_ID ) &&
                  ( dacdev->subsystem_vendor == PLX_VID ) )
             {
-                if ( pCds->cards_used[ i ].instance == dac_18bit_cnt &&
-                     pCds->cards_used[ i ].type == GSC_18AO8 )
+                if ( pCds->cards_used[ cur_card ].instance == dac_18bit_cnt &&
+                     pCds->cards_used[ cur_card ].type == GSC_18AO8 )
                 {
                     pCds->dacSlot[ pCds->dacCount] = find_card_slot( pCds, GSC_18AO8, dac_18bit_cnt );
                     status = gsc18ao8Init( pCds, dacdev );
@@ -497,7 +505,7 @@ mapPciModulesRealCards( CDS_HARDWARE* pCds )
                     if(status != 0)
                     {
                         RTSLOG_ERROR( "Map fault GSC18AO8 DAC number %d slot %d\n",
-                            dac_18bit_cnt,pCds->dacSlot[ pCds->dacCount]);
+                            dac_18bit_cnt, pCds->dacSlot[ pCds->dacCount]);
                         return IO_CARD_MAP_ERROR;
                     }
                 }
@@ -508,8 +516,8 @@ mapPciModulesRealCards( CDS_HARDWARE* pCds )
             if ( ( dacdev->subsystem_device == DAC_20BIT_SS_ID ) &&
                  ( dacdev->subsystem_vendor == PLX_VID ) )
             {
-                if ( pCds->cards_used[ i ].instance == dac_20bit_cnt &&
-                     pCds->cards_used[ i ].type == GSC_20AO8 )
+                if ( pCds->cards_used[ cur_card ].instance == dac_20bit_cnt &&
+                     pCds->cards_used[ cur_card ].type == GSC_20AO8 )
                 {
                     pCds->dacSlot[ pCds->dacCount] = find_card_slot( pCds, GSC_20AO8, dac_20bit_cnt );
                     status = gsc20ao8Init( pCds, dacdev );
@@ -517,6 +525,7 @@ mapPciModulesRealCards( CDS_HARDWARE* pCds )
                             dacdev->bus->number,
                             PCI_SLOT( dacdev->devfn ),
                             status );
+
                     if(status != 0)
                     {
                         RTSLOG_ERROR( "Map fault GSC18AO8 DAC number %d slot %d\n",
@@ -529,16 +538,24 @@ mapPciModulesRealCards( CDS_HARDWARE* pCds )
 
 
         } // end of while over all GSC cards
+
+        
+
     } // end of pci_cards useddrv/map.h
 
 
+    
+
     //Initialize LIGO 32AO32 DAC cards
-    dacdev = NULL;
     ligo28ao32_dev_t * temp_dac_ptr = NULL;
-    for ( int cur_card =0; cur_card < modCount; ++cur_card)
+    for ( cur_card =0; cur_card < modCount; ++cur_card)
     {
-        if ( pCds->ioc_config[ cur_card ] == LIGO_28AO32 )
+
+        if ( pCds->cards_used[ cur_card ].instance == dac_ligo_32ao32_cnt &&
+                 pCds->cards_used[ cur_card ].type == LIGO_28AO32 )
         {
+
+
             temp_dac_ptr = ligo28ao32_configureDevice(pCds->ioc_instance[ cur_card ]);
             if ( temp_dac_ptr == NULL ) {
                 RTSLOG_ERROR("mapPciModulesRealCards(): Could not configure device instance "
@@ -561,7 +578,6 @@ mapPciModulesRealCards( CDS_HARDWARE* pCds )
             _dacPtr[ pCds->dacCount ] = (GSC_DAC_REG*) kmalloc(0x200, GFP_ATOMIC);
             dacDma[ pCds->dacCount ] = (PLX_9056_DMA*) kmalloc(0x200, GFP_ATOMIC);
 
-
             ++pCds->dacCount;
         }
     }
@@ -579,10 +595,10 @@ mapPciModulesRealCards( CDS_HARDWARE* pCds )
         {
             use_it = 0;
             /* See if ought to use this one or not */
-            for ( i = 0; i < pCds->cards; i++ )
+            for ( cur_card = 0; cur_card < pCds->cards; cur_card++ )
             {
-                if ( pCds->cards_used[ i ].type == ACS_24DIO &&
-                     pCds->cards_used[ i ].instance == bo_cnt )
+                if ( pCds->cards_used[ cur_card ].type == ACS_24DIO &&
+                     pCds->cards_used[ cur_card ].instance == bo_cnt )
                 {
                     use_it = 1;
                     break;
@@ -615,10 +631,10 @@ mapPciModulesRealCards( CDS_HARDWARE* pCds )
         {
             use_it = 0;
             /* See if ought to use this one or not */
-            for ( i = 0; i < pCds->cards; i++ )
+            for ( cur_card = 0; cur_card < pCds->cards; cur_card++ )
             {
-                if ( pCds->cards_used[ i ].type == ACS_8DIO &&
-                     pCds->cards_used[ i ].instance == bo_cnt )
+                if ( pCds->cards_used[ cur_card ].type == ACS_8DIO &&
+                     pCds->cards_used[ cur_card ].instance == bo_cnt )
                 {
                     use_it = 1;
                     break;
@@ -652,10 +668,10 @@ mapPciModulesRealCards( CDS_HARDWARE* pCds )
         {
             use_it = 0;
             /* See if ought to use this one or not */
-            for ( i = 0; i < pCds->cards; i++ )
+            for ( cur_card = 0; cur_card < pCds->cards; cur_card++ )
             {
-                if ( pCds->cards_used[ i ].type == ACS_16DIO &&
-                     pCds->cards_used[ i ].instance == bo_cnt )
+                if ( pCds->cards_used[ cur_card ].type == ACS_16DIO &&
+                     pCds->cards_used[ cur_card ].instance == bo_cnt )
                 {
                     use_it = 1;
                     break;
@@ -685,10 +701,10 @@ mapPciModulesRealCards( CDS_HARDWARE* pCds )
         {
             use_it = 0;
             /* See if ought to use this one or not */
-            for ( i = 0; i < pCds->cards; i++ )
+            for ( cur_card = 0; cur_card < pCds->cards; cur_card++ )
             {
-                if ( pCds->cards_used[ i ].type == CON_6464DIO &&
-                     ( pCds->cards_used[ i ].instance * 2 ) == bo_cnt )
+                if ( pCds->cards_used[ cur_card ].type == CON_6464DIO &&
+                     ( pCds->cards_used[ cur_card ].instance * 2 ) == bo_cnt )
                 {
                     use_it = 1;
                     break;
@@ -737,10 +753,10 @@ mapPciModulesRealCards( CDS_HARDWARE* pCds )
         {
             use_it = 0;
             /* See if ought to use this one or not */
-            for ( i = 0; i < pCds->cards; i++ )
+            for ( cur_card = 0; cur_card < pCds->cards; cur_card++ )
             {
-                if ( pCds->cards_used[ i ].type == CON_32DO &&
-                     pCds->cards_used[ i ].instance == bo_cnt )
+                if ( pCds->cards_used[ cur_card ].type == CON_32DO &&
+                     pCds->cards_used[ cur_card ].instance == bo_cnt )
                 {
                     use_it = 1;
                     break;
@@ -761,9 +777,9 @@ mapPciModulesRealCards( CDS_HARDWARE* pCds )
     dacdev = NULL;
     status = 0;
 
-    for ( i = 0; i < MAX_RFM_MODULES; i++ )
+    for ( cur_card = 0; cur_card < MAX_RFM_MODULES; cur_card++ )
     {
-        pCds->pci_rfm[ i ] = 0;
+        pCds->pci_rfm[ cur_card ] = 0;
     }
 
     dacdev = NULL;
@@ -800,7 +816,7 @@ mapPciModulesRealCards( CDS_HARDWARE* pCds )
     return ( modCount );
 }
 
-void unmapPciModules(CDS_HARDWARE* pCds) 
+void unmapPciModules(CDS_HARDWARE* pCds)
 {
     //Clean up any DAC drivers we are using
     for (int i=0; i<MAX_DAC_MODULES; ++i) {
diff --git a/src/fe/moduleLoad.c b/src/fe/moduleLoad.c
index a9a36bf3a..486447c58 100644
--- a/src/fe/moduleLoad.c
+++ b/src/fe/moduleLoad.c
@@ -63,6 +63,8 @@ extern int need_to_load_IOP_first;
 
 #ifdef NO_CPU_SHUTDOWN
 
+#include <linux/kthread.h>
+
 static struct task_struct* sthread;
 
 /// @breif Wrapper function so kthread_create()
@@ -260,7 +262,7 @@ static int __init rt_fe_init( void )
     /// Start the controller thread
 #ifdef NO_CPU_SHUTDOWN
     sthread = kthread_create(
-        fe_start_controller_kthread, 0, "fe_start_controller_kthread/%d");
+        fe_start_controller_kthread, 0, "fe_start_controller_kthread/%d", 0);
     if ( IS_ERR( sthread ) )
     {
         RTSLOG_ERROR( "Failed to kthread_create()\n" );
diff --git a/src/fe/print_io_info.c b/src/fe/print_io_info.c
index 59d3a8407..c4213aae6 100644
--- a/src/fe/print_io_info.c
+++ b/src/fe/print_io_info.c
@@ -10,6 +10,8 @@
 
 #include "drv/rts-logger.h"
 
+#include "drv/ligo28ao32/ligo28ao32.h"
+
 
 void
 print_io_info(const char* model_name, CDS_HARDWARE* cdsp, int iopmodel )
@@ -81,8 +83,13 @@ print_io_info(const char* model_name, CDS_HARDWARE* cdsp, int iopmodel )
                 cdsp->dacSlot[ii] );
             RTSLOG_INFO( "\tChannels = %d \n",
                     cdsp->dac_info[ii].num_chans );
-            RTSLOG_INFO( "\tFirmware Rev = %d \n\n",
+            if ( cdsp->dacDrivers[ ii ] != NULL) {
+                RTSLOG_INFO( "\tFirmware Rev = 0x%x \n\n",
+                    ligo28ao32_get_fw_version(cdsp->dacDrivers[ ii ]) );
+            } else {
+                RTSLOG_INFO( "\tFirmware Rev = %d \n\n",
                     ( cdsp->dacAcr[ ii ] & 0xfff ) );
+            }
         }
     }
     kk += cdsp->doCount;
diff --git a/src/include/drv/gsc20ao8.c b/src/include/drv/gsc20ao8.c
index 5885bef8e..132ae65ef 100644
--- a/src/include/drv/gsc20ao8.c
+++ b/src/include/drv/gsc20ao8.c
@@ -14,8 +14,11 @@
 #include "drv/rts-logger.h"
 #include "drv/plx_9056.h"
 #include "drv/map.h"
+#include "drv/rts-logger.h"
+
 
 #include <linux/delay.h> //udelay()
+#include <linux/pci.h>
 
 
 // *****************************************************************************
@@ -35,7 +38,7 @@ gsc20ao8Init( CDS_HARDWARE* pHardware, struct pci_dev* dacdev )
     char* _dac_add; /// @param *_dac_add DAC register address space
     static unsigned int pci_io_addr; /// @param pci_io_addr Bus address of PCI
                                      /// card I/O register.
-    int pedStatus; /// @param pedStatus Status return from call to enable
+    int pci_status; /// @param pci_status Status return from call to enable
                    /// device.
     volatile GSC_DAC_REG*
         dac20bitPtr; /// @param *dac20bitPtr Pointer to DAC control registers.
@@ -44,26 +47,54 @@ gsc20ao8Init( CDS_HARDWARE* pHardware, struct pci_dev* dacdev )
     /// Get index into CDS_HARDWARE struct based on total number of DAC cards
     /// found by mapping routine in map.c
     devNum = pHardware->dacCount;
+
     /// Enable the device, PCI required
-    pedStatus = pci_enable_device( dacdev );
+    pci_status = pci_enable_device( dacdev );
+    if ( pci_status != 0 ) {
+        dev_err(&dacdev->dev, "gsc20ao8Init() pci_enable_device\n");
+        return -1;
+    }
+
+
     /// Register module as Master capable, required for DMA
     pci_set_master( dacdev );
+
+    if (dma_set_mask_and_coherent(&(dacdev->dev), DMA_BIT_MASK(32))) {    
+		dev_warn(&(dacdev->dev), "gsc20ao8Init() - No suitable DMA available\n");
+        return -1;	
+    }
+
     /// Get the PLX chip PCI address, it is advertised at address 0
-    pedStatus = pci_read_config_dword( dacdev, PCI_BASE_ADDRESS_0, &pci_io_addr );
-    if(pedStatus != 0)
+    pci_status = pci_read_config_dword( dacdev, PCI_BASE_ADDRESS_0, &pci_io_addr );
+    if(pci_status != 0) {
+        RTSLOG_ERROR("gsc20ao8Init() - pci_read_config_dword failed, base addr 0\n");
         return -1;
+    }
     RTSLOG_INFO( "pci0 = 0x%x\n", pci_io_addr );
     _dac_add = IOREMAP( (unsigned long)pci_io_addr, 0x200 );
+    if( _dac_add == NULL) {
+        RTSLOG_ERROR("gsc20ao8Init() - IOREMAP of PCI_BASE_ADDRESS_0 failed\n");
+        return -1;
+    }
+
+
     /// Set up a pointer to DMA registers on PLX chip
     dacDma[ devNum ] = (PLX_9056_DMA*)_dac_add;
 
     /// Get the DAC register address
-    pedStatus = pci_read_config_dword( dacdev, PCI_BASE_ADDRESS_2, &pci_io_addr );
-    if(pedStatus != 0)
+    pci_status = pci_read_config_dword( dacdev, PCI_BASE_ADDRESS_2, &pci_io_addr );
+    if(pci_status != 0) {
+        RTSLOG_ERROR("gsc20ao8Init() - pci_read_config_dword failed, base addr 2\n");
         return -1;
+    }
     // Send some info to dmesg
     RTSLOG_INFO( "dac pci2 = 0x%x\n", pci_io_addr );
     _dac_add = IOREMAP( (unsigned long)pci_io_addr, 0x200 );
+    if( _dac_add == NULL) {
+        RTSLOG_ERROR("gsc20ao8Init() - IOREMAP of PCI_BASE_ADDRESS_2 failed\n");
+        return -1;
+    }
+
     // Send some info to dmesg
     RTSLOG_INFO( "DAC I/O address=0x%x  0x%lx\n", pci_io_addr, (long)_dac_add );
 
@@ -138,7 +169,12 @@ gsc20ao8Init( CDS_HARDWARE* pHardware, struct pci_dev* dacdev )
             dac20bitPtr->BCR );
 
     pHardware->pci_dac[ devNum ] =
-        (volatile int *)dma_alloc_coherent( &dacdev->dev, 0x200, &dac_dma_handle[ devNum ], GFP_ATOMIC );
+        (volatile int *)dma_alloc_coherent( &dacdev->dev, 0x200, &dac_dma_handle[ devNum ], GFP_KERNEL );
+    if( pHardware->pci_dac[ devNum ] == NULL) {
+        RTSLOG_ERROR("gsc20ao8Init() - pci_alloc_consistent() failed\n");
+        return -1;
+    }
+
     pHardware->dacAcr[ devNum ] |= ((int)( dac20bitPtr->ASY_CONFIG )  & DAC_ACR_MASK);
 
     // Return the device type to main code.
@@ -153,6 +189,6 @@ gsc20ao8Init( CDS_HARDWARE* pHardware, struct pci_dev* dacdev )
 
     /// Call patch in map.c needed to properly write to native PCIe module
     set_8111_prefetch( dacdev );
-    return ( pedStatus );
+    return ( pci_status );
 }
 
diff --git a/src/include/drv/iop_dac_functions.c b/src/include/drv/iop_dac_functions.c
index d43ae52ab..c8d2fe8f9 100644
--- a/src/include/drv/iop_dac_functions.c
+++ b/src/include/drv/iop_dac_functions.c
@@ -525,7 +525,8 @@ check_dac_buffers( int cardNum, int report_all_faults )
         uint32_t status = ligo28ao32_dma_read_common_errors( cdsPciModules.dacDrivers[ cardNum ] );
         if ( (status & 0x3F000000) != 0 || ligo28ao32_samp_stat_is_timing_ok(status) != 1 ) { //TODO: const here
             pLocalEpics->epicsOutput.statDac[ cardNum ] |= DAC_TIMING_BIT;
-            RTSLOG_ERROR("LIGO_28AO32 DAC error detected, 0x%x, DAC error counter: %u, is_locked: %d\n", 
+            RTSLOG_ERROR("LIGO_28AO32(%d) DAC error detected, 0x%x, DAC error counter: %u, is_locked: %d\n",
+            cardNum,
             status, 
             ligo28ao32_dma_query_dac_error_ctr(cdsPciModules.dacDrivers[ cardNum ]), 
             ligo28ao32_samp_stat_is_timing_ok(status) );
diff --git a/src/include/drv/ligo28ao32/ligo28ao32.c b/src/include/drv/ligo28ao32/ligo28ao32.c
index 72792a301..c6375d815 100644
--- a/src/include/drv/ligo28ao32/ligo28ao32.c
+++ b/src/include/drv/ligo28ao32/ligo28ao32.c
@@ -42,9 +42,9 @@ struct ligo28ao32_dev_t * ligo28ao32_configureDevice(unsigned instance)
         ++cur_inst;
         if( cur_inst == (int)instance) {
             ctx->pci_dev = tmp_pci_dev;
-            RTSLOG_INFO("ligo28ao32_configureDevice(): Found the device %x:%x driver: %llx\n", tmp_pci_dev->vendor, 
+            RTSLOG_INFO("ligo28ao32_configureDevice(): Found the device %x:%x on bus: 0x%x\n", tmp_pci_dev->vendor, 
                                                         tmp_pci_dev->device, 
-                                                        (uint64_t)tmp_pci_dev->driver);
+                                                        tmp_pci_dev->bus->number);
             break;
         }
     }
@@ -60,6 +60,8 @@ struct ligo28ao32_dev_t * ligo28ao32_configureDevice(unsigned instance)
         goto cleanup_alloc;
     }
 
+    pci_set_master( ctx->pci_dev );
+
     char region_name[100];
     snprintf(region_name, 100, "ligo28ao32_region%d", instance);
     if (pci_request_region(ctx->pci_dev, BAR0_INDX, region_name)) {
@@ -78,9 +80,9 @@ struct ligo28ao32_dev_t * ligo28ao32_configureDevice(unsigned instance)
     ctx->control_regs_len = pci_resource_len(ctx->pci_dev, BAR0_INDX);
     ctx->ctrl_mm = pci_iomap(ctx->pci_dev, BAR0_INDX, ctx->control_regs_len);
     ctx->xilinx_dma_mm = pci_iomap(ctx->pci_dev, BAR2_INDX, pci_resource_len(ctx->pci_dev, BAR2_INDX));
-    //RTSLOG_INFO("pci_resource_len(ctx->pci_dev, BAR2_INDX): %llu\n", pci_resource_len(ctx->pci_dev, BAR2_INDX));
-    //RTSLOG_INFO("The BAR2 resource len is %llu\n", pci_resource_len(ctx->pci_dev, BAR2_INDX));
-    RTSLOG_INFO("ligo28ao32 : firmware_version : 0x%x\n", ioread32(&ctx->ctrl_mm->firmware_version));
+    //RTSLOG_INFO("The BAR0 resource len is %llu\n", pci_resource_len(ctx->pci_dev, BAR2_INDX));
+    //RTSLOG_INFO("The BAR2 resource len is %llu\n", pci_resource_len(ctx->pci_dev, BAR0_INDX));
+    //RTSLOG_INFO("ligo28ao32 : firmware_version : 0x%x\n", ioread32(&ctx->ctrl_mm->firmware_version));
 
 
 
@@ -362,7 +364,6 @@ ligo28ao32_error_t ligo28ao32_queue_next_dac_dma(ligo28ao32_dev_t * dev, uint32_
 
 void * ligo28ao32_get_next_dac_dma_queue(ligo28ao32_dev_t * dev, uint32_t gps_time_s, uint32_t cur_cycle_64kclk)
 {
-    static uint64_t index = 0;
 
 
     if( (cur_cycle_64kclk + dev->dac_write_next_ts) > (1<<16) - (DAC_NUM_CYCLES_TO_WRITE_AHEAD+1) ) {
@@ -377,11 +378,6 @@ void * ligo28ao32_get_next_dac_dma_queue(ligo28ao32_dev_t * dev, uint32_t gps_ti
     buffer_ptr->time_sec = gps_time_s;
     buffer_ptr->time_232_clk = cur_cycle_64kclk << 16; //To 2^32 clk domain
 
-    if (index < 10) {
-        //RTSLOG_INFO("Buffer at s: %u and ticks: %u, ptr: 0x%llx\n", gps_time_s, cur_cycle_64kclk, (uint64_t)buffer_ptr);
-        //uint64_t hold =  ligo28ao32_get_time_ns(dev);
-        //RTSLOG_INFO("Cur GPS time %lld ns, %llu ticks\n", hold, convert_ns_to_4GHz(GET_NANO_FROM_GPS_NS(hold)) >>16 );
-    }
 
     /*
     if(index > 655360 && index < 655460)
@@ -390,9 +386,11 @@ void * ligo28ao32_get_next_dac_dma_queue(ligo28ao32_dev_t * dev, uint32_t gps_ti
         //uint64_t hold =  ligo28ao32_get_time_ns(dev);
         //RTSLOG_INFO("Cur GPS time %lld ns, %llu ticks\n", hold, convert_ns_to_4GHz(GET_NANO_FROM_GPS_NS(hold)) >>16 );
     }*/
-    ++index;
 
-    if (index == 1) ligo28ao32_dma_start_dacs(dev);
+    if (dev->dac_first_dma == 0){
+        ligo28ao32_dma_start_dacs(dev);
+        ++dev->dac_first_dma;
+    }
 
     return (void*)&buffer_ptr->samples;
 }
@@ -435,11 +433,11 @@ void ligo28ao32_dma_config(ligo28ao32_dev_t * dev, unsigned sample_rate_hz, unsi
     ligo28ao32_dma_config_dac(dev, dac_dma_len_bytes, 2*dac_dma_len_bytes);
 
     uint32_t dma_config_reg = ioread32(&dev->ctrl_mm->samp_config);
-    RTSLOG_INFO("samp_config: 0x%x\n", dma_config_reg);
+    //RTSLOG_INFO("samp_config: 0x%x\n", dma_config_reg);
     dma_config_reg &= ~SAMP_CONF_LOG2_NUM_BUF_PER_DAC_DMA_CHAN; //Clear out any old config
     dma_config_reg |=  (LOG_2_NUM_DMA_BUFFERS_PER_CHAN << 24); //Set two buffer per chan 
     iowrite32(dma_config_reg, &dev->ctrl_mm->samp_config);
-    RTSLOG_INFO("samp_config: 0x%x\n", dma_config_reg);
+    //RTSLOG_INFO("samp_config: 0x%x\n", dma_config_reg);
 
     //Read and program the log2 number of dma buffers
     /* TODO: Not needed for 64K sample/dma
@@ -589,6 +587,11 @@ int ligo28ao32_get_temp_c(ligo28ao32_dev_t * dev)
     return temp; //In Celsius
 }
 
+int ligo28ao32_get_fw_version(ligo28ao32_dev_t * dev)
+{
+    return ioread32(&dev->ctrl_mm->firmware_version);
+}
+
 int ligo28ao32_get_adc_dma_length(ligo28ao32_dev_t * dev)
 {
     uint32_t dmaLength = LIGO_28AO32_BYTES_PER_SAMPLE * ligo28ao32_get_num_adc_chans(dev);
diff --git a/src/include/drv/ligo28ao32/ligo28ao32.h b/src/include/drv/ligo28ao32/ligo28ao32.h
index 822fe1a0a..8a1179ea0 100644
--- a/src/include/drv/ligo28ao32/ligo28ao32.h
+++ b/src/include/drv/ligo28ao32/ligo28ao32.h
@@ -81,6 +81,8 @@ uint32_t ligo28ao32_get_watchdog(ligo28ao32_dev_t * dev);
 int ligo28ao32_samp_stat_is_timing_ok(uint32_t samp_status_reg);
 int ligo28ao32_get_temp_c(ligo28ao32_dev_t * dev);
 
+int ligo28ao32_get_fw_version(ligo28ao32_dev_t * dev);
+
 void ligo28ao32_print_status_registers(ligo28ao32_dev_t * dev);
 void ligo28ao32_print_dma_and_converter_status(ligo28ao32_dev_t * dev);
 void ligo28ao32_print_sampling_config(ligo28ao32_dev_t * dev);
diff --git a/src/include/drv/ligo28ao32/ligo28ao32_private.h b/src/include/drv/ligo28ao32/ligo28ao32_private.h
index fa3ef4876..6f955a370 100644
--- a/src/include/drv/ligo28ao32/ligo28ao32_private.h
+++ b/src/include/drv/ligo28ao32/ligo28ao32_private.h
@@ -254,6 +254,7 @@ typedef struct ligo28ao32_dev_t {
     uint32_t dac_sample_delay;
     uint32_t dac_dma_delay;
     uint32_t dac_write_next_ts;
+    uint32_t dac_first_dma;
 
 } ligo28ao32_dev_t;
 
@@ -263,4 +264,4 @@ void ligo28ao32_dma_config_dac(ligo28ao32_dev_t * dev, uint32_t dma_len, uint32_
 
 int ligo28ao32_get_adc_dma_length(ligo28ao32_dev_t * dev);
 
-#endif //LIGO_28AO32_PRIVATE_H
\ No newline at end of file
+#endif //LIGO_28AO32_PRIVATE_H
-- 
GitLab