From fe3f8e3e172818741f32f5ea0bba27f77ca56a1a Mon Sep 17 00:00:00 2001
From: "Suren A. Chilingaryan" <csa@suren.me>
Date: Fri, 14 Aug 2015 03:53:15 +0200
Subject: Add another workaround to handle cameras stuck in busy (disabled and
 untested)

---
 private.h |  1 +
 reader.c  | 36 +++++++++++++++++++++++++++++++++++-
 2 files changed, 36 insertions(+), 1 deletion(-)

diff --git a/private.h b/private.h
index 0e16044..38d6dd0 100644
--- a/private.h
+++ b/private.h
@@ -22,6 +22,7 @@
 #define IPECAMERA_BUG_MULTIFRAME_PACKETS	//**< This is by design, start of packet comes directly after the end of last one in streaming mode */
 #define IPECAMERA_BUG_MULTIFRAME_HEADERS	//**< UFO Camera operates with 32-byte entities, but some times there is 16-byte padding before the data which may result in spliting the header between 2 DMA packets. We still need to define a minimal number of bytes which are always in the same DMA packet (CMOSIS_ENTITY_SIZE) */
 #define IPECAMERA_BUG_REPEATING_DATA		//**< 16 bytes repeated at frame offset 4096, the problem start/stop happenning on board restart */
+//#define IPECAMERA_BUG_STUCKED_BUSY		//**< DMA may stuck in busy. According to Michele, the work-around is to disable triggering and read all data out. Not checked */
 //#define IPECAMERA_BUG_INCOMPLETE_PACKETS	//**< Support incomplete packets, i.e. check for frame magic even if full frame size is not reached yet (slow) */
 //#define IPECAMERA_ANNOUNCE_READY		//**< Announce new event only after the reconstruction is done */
 //#define IPECAMERA_CLEAN_ON_START		//**< Read all the data from DMA before starting of recording */
diff --git a/reader.c b/reader.c
index b603e47..3e2b444 100644
--- a/reader.c
+++ b/reader.c
@@ -21,6 +21,23 @@
 #include "private.h"
 #include "reader.h"
 
+
+#define GET_REG(reg, var) \
+    if (!err) { \
+	err = pcilib_read_register_by_id(pcilib, ctx->reg, &var); \
+	if (err) { \
+	    pcilib_error("Error reading %s register", model_info->registers[ctx->reg].name); \
+	} \
+    }
+
+#define SET_REG(reg, val) \
+    if (!err) { \
+	err = pcilib_write_register_by_id(pcilib, ctx->reg, val); \
+	if (err) { \
+	    pcilib_error("Error writting %s register", model_info->registers[ctx->reg].name); \
+	} \
+    }
+
 //#define CHECK_FRAME_MAGIC(buf) \
 //	memcmp(buf, ((void*)frame_magic) + 1, sizeof(frame_magic) - 1)
 
@@ -304,7 +321,12 @@ static int ipecamera_data_callback(void *user, pcilib_dma_flags_t flags, size_t
 void *ipecamera_reader_thread(void *user) {
     int err;
     ipecamera_t *ctx = (ipecamera_t*)user;
-    
+#ifdef IPECAMERA_BUG_STUCKED_BUSY
+    pcilib_register_value_t saved, value;
+    pcilib_t *pcilib = ctx->event.pcilib;
+    const pcilib_model_description_t *model_info = pcilib_get_model_description(pcilib);
+#endif /* IPECAMERA_BUG_STUCKED_BUSY */
+
     while (ctx->run_reader) {
 	err = pcilib_stream_dma(ctx->event.pcilib, ctx->rdma, 0, 0, PCILIB_DMA_FLAG_MULTIPACKET, IPECAMERA_DMA_TIMEOUT, &ipecamera_data_callback, user);
 	if (err) {
@@ -317,6 +339,18 @@ void *ipecamera_reader_thread(void *user) {
 		    ctx->run_reader = 0;
 		    break;
 		}
+#ifdef IPECAMERA_BUG_STUCKED_BUSY
+		GET_REG(status2_reg, value);
+		if (value&0x2FFFFFFF) {
+		    pcilib_warning("Camera stuck in busy, trying to recover...");
+		    GET_REG(control_reg, saved);
+		    SET_REG(control_reg, IPECAMERA_IDLE);
+		    while ((value&0x2FFFFFFF)&&(ctx->run_reader)) {
+			usleep(IPECAMERA_NOFRAME_SLEEP);
+		    }
+		    return 0;
+		}
+#endif /* IPECAMERA_BUG_STUCKED_BUSY */
 		usleep(IPECAMERA_NOFRAME_SLEEP);
 	    } else pcilib_error("DMA error while reading IPECamera frames, error: %i", err);
 	} 
-- 
cgit v1.2.3