Commit 1769750d authored by Andrey Filippov's avatar Andrey Filippov

debugging initialization

parent b2b0813b
......@@ -41,7 +41,7 @@
#include "framepars.h"
#include "sensor_common.h"
#include "jpeghead.h"
#include "circbuf.h"
//#include "circbuf.h"
#include "exif.h"
#include "x393_macro.h"
#include "x393_helpers.h"
......@@ -59,6 +59,12 @@ static struct device *g_dev_ptr;
static const struct of_device_id elphel393_circbuf_of_match[];
unsigned long *ccam_dma_buf_ptr[SENSOR_PORTS] = {NULL};
/** Get structure describing selected circbuf channel (start virtual and physical, buffer size) */
struct circbuf_priv_t *get_circbuf(int chn) ///< compressor channel
///< @return pointer to requested structure
{
return &circbuf_priv[chn];
}
/**
* @brief Set up pointers to memory where circular buffers are located. The memory
* for circular buffers is reserved using CMA mechanism.
......@@ -91,9 +97,12 @@ int init_ccam_dma_buf_ptr(struct platform_device *pdev)
for (i = 0; i < SENSOR_PORTS; i++) {
circbuf_priv[i].buf_ptr = dma_buf_ptr + BYTE2DW(CIRCBUF_START_OFFSET + i * CCAM_DMA_SIZE);
circbuf_priv[i].phys_addr = dma_handle + CIRCBUF_START_OFFSET + i * CCAM_DMA_SIZE;
circbuf_priv[i].buf_size = CCAM_DMA_SIZE;
circbuf_priv[i].buf_size32 = circbuf_priv[i].buf_size; // used in many places
ccam_dma_buf_ptr[i] = circbuf_priv[i].buf_ptr;
// set circular buffer size in bytes
set_globalParam(i, G_CIRCBUFSIZE, CCAM_DMA_SIZE);
set_globalParam(i, G_CIRCBUFSIZE, circbuf_priv[i].buf_size);
}
return 0;
......@@ -184,7 +193,7 @@ loff_t circbuf_all_lseek(struct file *file, loff_t offset, int orig)
return circbuf_lseek(file, offset, orig);
case DEV393_MINOR(DEV393_JPEGHEAD0):
if (orig == SEEK_END && offset > 0) {
rp = BYTE2DW(X393_BUFFSUB(offset, CHUNK_SIZE)) & (~7); // convert to index to long, align to 32-bytes
rp = BYTE2DW(X393_BUFFSUB_CHN(offset, CHUNK_SIZE, chn)) & (~7); // convert to index to long, align to 32-bytes
fp = (struct interframe_params_t *) &circbuf_priv[chn].buf_ptr[rp];
}
return jpeghead_lseek(file, offset, orig, fp);
......@@ -307,7 +316,8 @@ unsigned int circbuf_all_poll(struct file *file, poll_table *wait)
*/
int circbuf_open(struct inode *inode, struct file *filp)
{
inode->i_size = CCAM_DMA_SIZE;
unsigned int minor = MINOR(inode->i_rdev);
inode->i_size = circbuf_priv[minor_to_chn(minor, NULL)].buf_size; // CCAM__DMA_SIZE;
dev_dbg(g_dev_ptr, "inode->i_size = 0x%lx\n", inode->i_size);
return 0;
......@@ -339,17 +349,17 @@ unsigned long get_image_length(int byte_offset, unsigned int chn, int *last_chun
{
unsigned int offset;
unsigned long len32;
int last_image_chunk = X393_BUFFSUB(byte_offset, OFFSET_X40);
int last_image_chunk = X393_BUFFSUB_CHN(byte_offset, OFFSET_X40, chn);
offset = X393_BUFFADD(last_image_chunk, CHUNK_SIZE - CCAM_MMAP_META_LENGTH);
offset = X393_BUFFADD_CHN(last_image_chunk, CHUNK_SIZE - CCAM_MMAP_META_LENGTH, chn);
len32 = circbuf_priv[chn].buf_ptr[BYTE2DW(offset)];
dev_dbg(g_dev_ptr, "[chn %d] byte_offset = 0x%x, calculated offset = 0x%x, len32 = 0x%lx\n", chn, byte_offset, offset, len32);
if ((len32 & MARKER_FF) != MARKER_FF) {
dev_dbg(g_dev_ptr, "[chn %u] failed to get 0xff marker at offset 0x%x\n", chn, offset);
last_image_chunk = X393_BUFFSUB(byte_offset, OFFSET_X40 + CHUNK_SIZE);
offset = X393_BUFFADD(last_image_chunk, CHUNK_SIZE - CCAM_MMAP_META_LENGTH);
last_image_chunk = X393_BUFFSUB_CHN(byte_offset, OFFSET_X40 + CHUNK_SIZE, chn);
offset = X393_BUFFADD_CHN(last_image_chunk, CHUNK_SIZE - CCAM_MMAP_META_LENGTH, chn);
len32 = circbuf_priv[chn].buf_ptr[BYTE2DW(offset)];
if ((len32 & MARKER_FF) != MARKER_FF) {
dev_dbg(g_dev_ptr, "[chn %u] failed to get 0xff marker at CORRECTED offset 0x%x\n", chn, offset);
......@@ -376,6 +386,7 @@ unsigned long get_image_length(int byte_offset, unsigned int chn, int *last_chun
* -1 if there is no frame at this index, -2 if the pointer is not 32-bytes aligned
* sets *fpp to the frame header, including signature and length
*/
//#ifdef PRE_FRAMEPARS
int circbuf_valid_ptr(loff_t *rp_offset, struct interframe_params_t **fpp, unsigned int chn)
{
int rp = *rp_offset;
......@@ -391,10 +402,10 @@ int circbuf_valid_ptr(loff_t *rp_offset, struct interframe_params_t **fpp, unsig
dev_dbg(g_dev_ptr, "misaligned pointer rp = 0x%x for channel %d\n", rp, chn);
return -2;
}
fp = (struct interframe_params_t *) &circbuf_priv[chn].buf_ptr[BYTE2DW(X393_BUFFSUB(rp, sizeof(struct interframe_params_t) - 4))];
fp = (struct interframe_params_t *) &circbuf_priv[chn].buf_ptr[BYTE2DW(X393_BUFFSUB_CHN(rp, sizeof(struct interframe_params_t) - 4, chn))];
*fpp = fp;
dump_interframe_params(fp, X393_BUFFSUB(rp, sizeof(struct interframe_params_t) - 4), chn);
dump_interframe_params(fp, X393_BUFFSUB_CHN(rp, sizeof(struct interframe_params_t) - 4, chn), chn);
if (BYTE2DW(rp) == wp)
// read pointer and write pointer coincide, frame not yet acquired
......@@ -409,14 +420,62 @@ int circbuf_valid_ptr(loff_t *rp_offset, struct interframe_params_t **fpp, unsig
} else {
dev_dbg(g_dev_ptr, "[chn %u] interframe pointer and file ponter is advanced by 0x20\n", chn);
*fpp = fp_off;
*rp_offset = X393_BUFFADD(*rp_offset, CHUNK_SIZE);
*rp_offset = X393_BUFFADD_CHN(*rp_offset, CHUNK_SIZE, chn);
dump_interframe_params(fp_off, rp, chn);
return 2;
}
}
return 1;
}
//#endif
/**
* returns 0 if rp is a valid read ponter
* returns 1 if there is a frame at this address
* returns 0 if the pointer is for the frame yet to be acquired
* returns -1 if there is no frame at this index
* returns -2 if the rp is not 32-bytes aligned
* sets *fpp to the frame header, including signature and length */
// ccam_dma_buf u32 array
//#define X313_LENGTH_MASK 0xff000000
#define X313_PADDED_FRAME(x)((((x)+67+CCAM_MMAP_META ) >>2) & 0xfffffff8)
//#define X313_BUFFSUB(x,y) (((x)>=(y))? ((x)-(y)) : ((x)+ (CCAM_DMA_SIZE-(y))))
//#define X313_BUFFADD(x,y) ((((x) + (y))<=CCAM_DMA_SIZE)? ((x) + (y)) : ((x) - (CCAM_DMA_SIZE-(y))))
int circbufValidPointer(int rp,
struct interframe_params_t ** fpp,
unsigned int chn)
{
if (rp & 0x1f) { //!rp is not 32-bytes aligned
dev_dbg(g_dev_ptr, "circbufValidPointer: misaligned pointer\n");
return -2;
}
int wp=camSeqGetJPEG_wp(chn);
int p= rp >> 2; // index in ccam_dma_buf
struct interframe_params_t * fp;
fp = (struct interframe_params_t *) &circbuf_priv[chn].buf_ptr[X393_BUFFSUB32(p, 8, chn)]; // 32 bytes before the frame pointer, may roll-over to the end of ccam_dma_buf
dev_dbg(g_dev_ptr, "rp=0x%x (0x%x), offset=0x%x\n",
rp, p, (int) &circbuf_priv[chn].buf_ptr[p]-(int)fp);
// dumpFrameParams(fp, "in circbufValidPointer:");
*fpp=fp;
dev_dbg(g_dev_ptr, "p=0x%x , wp==0x%x\n",p,wp);
if (p == wp) {
return 0; // frame not yet acquired, fp - not valid
}
if (fp->signffff != 0xffff) { //! signature is overwritten
dev_dbg(g_dev_ptr, "circbufValidPointer: signanure overwritten\n");
return -1;
}
if ((fp->timestamp_sec) & X313_LENGTH_MASK) {
dev_dbg(g_dev_ptr, "Should not get here - fp->timestamp_sec=0x%x\n",(int) fp->timestamp_sec);
return 0; //! should not get here - should be caught by (p==wp)
}
return 1;
}
/**
* @brief Get image start offset pointed by its last data chunk
......@@ -424,10 +483,18 @@ int circbuf_valid_ptr(loff_t *rp_offset, struct interframe_params_t **fpp, unsig
* @param[in] len32 length of image
* @return Image start offset
*/
#if 0
inline int get_image_start(int last_chunk_offset, unsigned int len32)
{
return X393_BUFFSUB(last_chunk_offset + CHUNK_SIZE - INSERTED_BYTES(len32) - CCAM_MMAP_META, len32);
return X393_BUFFSUB_(last_chunk_offset + CHUNK_SIZE - INSERTED_BYTES(len32) - CCAM_MMAP_META, len32);
}
#endif
inline int get_image_start_chn(int last_chunk_offset, unsigned int len32, int chn)
{
return X393_BUFFSUB_CHN(last_chunk_offset + CHUNK_SIZE - INSERTED_BYTES(len32) - CCAM_MMAP_META, len32, chn);
}
/* debug code follows */
void stop_compressor(unsigned int chn)
......@@ -458,8 +525,8 @@ void dump_state(unsigned int chn)
return;
}
len32 &= FRAME_LENGTH_MASK;
//img_start = X393_BUFFSUB(last_image_chunk + CHUNK_SIZE - INSERTED_BYTES(len32) - CCAM_MMAP_META, len32);
img_start = get_image_start(last_image_chunk, len32);
//img_start = X393__BUFFSUB(last_image_chunk + CHUNK_SIZE - INSERTED_BYTES(len32) - CCAM_MMAP_META, len32);
img_start = get_image_start_chn(last_image_chunk, len32, chn);
read_ptr = img_start;
// move back in history
while ((circbuf_valid_ptr(&read_ptr, &fp, chn) >= 0) && (nz >= 0)) {
......@@ -476,8 +543,8 @@ void dump_state(unsigned int chn)
}
len32 &= FRAME_LENGTH_MASK;
//printk(KERN_DEBUG "\t\tgot len32 = 0x%x", len32);
//img_start = X393_BUFFSUB(last_image_chunk + CHUNK_SIZE - INSERTED_BYTES(len32) - CCAM_MMAP_META, len32);
img_start = get_image_start(last_image_chunk, len32);
//img_start = X393__BUFFSUB(last_image_chunk + CHUNK_SIZE - INSERTED_BYTES(len32) - CCAM_MMAP_META, len32);
img_start = get_image_start_chn(last_image_chunk, len32, chn);
read_ptr = img_start;
if (read_ptr > prev_ptr)
nz--;
......@@ -524,7 +591,9 @@ void dump_state(unsigned int chn)
* @param[in] orig where the @e offset should start
* @return Current file pointer position if operation was successful and error code otherwise
*/
loff_t circbuf_lseek(struct file *file, loff_t offset, int orig)
#ifdef PRE_FRAMEPARS
loff_t circbuf_lseek_0(struct file *file, loff_t offset, int orig)
{
unsigned int len32 = 0;
int last_image_chunk;
......@@ -541,15 +610,20 @@ loff_t circbuf_lseek(struct file *file, loff_t offset, int orig)
file->f_pos = offset;
break;
case SEEK_CUR:
if (offset) file->f_pos += offset;
// New in NC393
// if (offset == 0) return get_compressor_frame(chn); // do not modify frame number
if (offset) file->f_pos += offset;
else if (circbuf_valid_ptr(&file->f_pos, &fp, chn) < 0 ) return -EINVAL; // no frames at the specified location or pointer is not 32-byte aligned
break;
case SEEK_END:
if (offset <= 0) {
file->f_pos = CCAM_DMA_SIZE + offset;
file->f_pos = circbuf_priv[chn].buf_size + offset; // CCAM__DMA_SIZE
} else {
// verify current frame pointer
switch (offset) {
case LSEEK_CIRC_GETFRAME:
return get_compressor_frame(chn); // New in NC393
case LSEEK_CIRC_TORP:
file->f_pos = camseq_get_jpeg_rp(chn) << 2;
case LSEEK_CIRC_PREV:
......@@ -578,11 +652,11 @@ loff_t circbuf_lseek(struct file *file, loff_t offset, int orig)
case LSEEK_CIRC_FREE:
dev_dbg(g_dev_ptr, "[chn %u] LSEEK_CIRC_FREE: checking remaining memory in circbuf\n", chn);
bp = file->f_pos - (camseq_get_jpeg_wp(chn) << 2);
return (file->f_pos = (bp > 0) ? bp : (bp + CCAM_DMA_SIZE)); // Has a side effect of moving a file pointer!
return (file->f_pos = (bp > 0) ? bp : (bp + circbuf_priv[chn].buf_size)); //CCAM__DMA_SIZE)); // Has a side effect of moving a file pointer!
case LSEEK_CIRC_USED:
dev_dbg(g_dev_ptr, "[chn %u] LSEEK_CIRC_USED: checking used memory in circbuf\n", chn);
bp = (camseq_get_jpeg_wp(chn) << 2) - file->f_pos;
return (file->f_pos = (bp > 0) ? bp : (bp + CCAM_DMA_SIZE)); // Has a side effect of moving a file pointer!
return (file->f_pos = (bp > 0) ? bp : (bp + circbuf_priv[chn].buf_size)); // CCAM__DMA_SIZE)); // Has a side effect of moving a file pointer!
case LSEEK_CIRC_TORP:
// no actions to be done here, the pointer was set on previous step
break;
......@@ -603,8 +677,8 @@ loff_t circbuf_lseek(struct file *file, loff_t offset, int orig)
return -EOVERFLOW;
}
len32 &= FRAME_LENGTH_MASK;
//img_start = X393_BUFFSUB(last_image_chunk + CHUNK_SIZE - INSERTED_BYTES(len32) - CCAM_MMAP_META, len32);
img_start = get_image_start(last_image_chunk, len32);
//img_start = X393__BUFFSUB(last_image_chunk + CHUNK_SIZE - INSERTED_BYTES(len32) - CCAM_MMAP_META, len32);
img_start = get_image_start_chn(last_image_chunk, len32,chn);
dev_dbg(g_dev_ptr, "[chn %u] calculated start address = 0x%x, length = 0x%x\n", chn, img_start, len32);
if (circbuf_valid_ptr(&img_start, &fp, chn) < 0)
return -EOVERFLOW;
......@@ -626,8 +700,8 @@ loff_t circbuf_lseek(struct file *file, loff_t offset, int orig)
return -EOVERFLOW;
}
len32 &= FRAME_LENGTH_MASK;
//img_start = X393_BUFFSUB(last_image_chunk + CHUNK_SIZE - INSERTED_BYTES(len32) - CCAM_MMAP_META, len32);
img_start = get_image_start(last_image_chunk, len32);
//img_start = X393__BUFFSUB(last_image_chunk + CHUNK_SIZE - INSERTED_BYTES(len32) - CCAM_MMAP_META, len32);
img_start = get_image_start_chn(last_image_chunk, len32, chn);
dev_dbg(g_dev_ptr, "[chn %u] LSEEK_CIRC_PREV: calculated start address = 0x%x, length = 0x%x\n", chn, img_start, len32);
// move file pointer only if previous frame valid
......@@ -647,7 +721,7 @@ loff_t circbuf_lseek(struct file *file, loff_t offset, int orig)
}
// calculate the full length of current frame and advance file pointer by this value
padded_frame = fp->frame_length + INSERTED_BYTES(fp->frame_length) + CHUNK_SIZE + CCAM_MMAP_META;
file->f_pos = X393_BUFFADD(file->f_pos, padded_frame); // do it even if the next frame does not yet exist
file->f_pos = X393_BUFFADD_CHN(file->f_pos, padded_frame, chn); // do it even if the next frame does not yet exist
dev_dbg(g_dev_ptr, "[chn %u] LSEEK_CIRC_NEXT: padded_frame = %d; moving file->f_pos to 0x%llx\n", chn, padded_frame, file->f_pos);
break;
case LSEEK_CIRC_FIRST:
......@@ -672,8 +746,8 @@ loff_t circbuf_lseek(struct file *file, loff_t offset, int orig)
if ((len32 & MARKER_FF) != MARKER_FF ) break; // no frames before rp (==prev_p)
// move rp to the previous frame
len32 &= FRAME_LENGTH_MASK;
//img_start = X393_BUFFSUB(last_image_chunk + CHUNK_SIZE - INSERTED_BYTES(len32) - CCAM_MMAP_META, len32);
img_start = get_image_start(last_image_chunk, len32);
//img_start = X393__BUFFSUB(last_image_chunk + CHUNK_SIZE - INSERTED_BYTES(len32) - CCAM_MMAP_META, len32);
img_start = get_image_start_chn(last_image_chunk, len32, chn);
dev_dbg(g_dev_ptr, "[chn %u] LSEEK_CIRC_FIRST or LSEEK_CIRC_SCND: calculated start address = 0x%x, length = 0x%x\n", chn,
img_start, len32);
rp_b = img_start;
......@@ -730,17 +804,166 @@ loff_t circbuf_lseek(struct file *file, loff_t offset, int orig)
return -EINVAL;
}
// roll-over position
while (file->f_pos < 0) file->f_pos += CCAM_DMA_SIZE;
while (file->f_pos > CCAM_DMA_SIZE) file->f_pos -= CCAM_DMA_SIZE;
if ((orig !=SEEK_END) && (file->f_pos == CCAM_DMA_SIZE)) file->f_pos=0; // only for lseek(fd,0,SEEK_END) the result will be file size, others will roll to 0
while (file->f_pos < 0) file->f_pos += circbuf_priv[chn].buf_size; // CCAM__DMA_SIZE;
while (file->f_pos > circbuf_priv[chn].buf_size) file->f_pos -= circbuf_priv[chn].buf_size; // CCAM__DMA_SIZE;
if ((orig !=SEEK_END) && (file->f_pos == circbuf_priv[chn].buf_size)) file->f_pos=0; // only for lseek(fd,0,SEEK_END) the result will be file size, others will roll to 0
dev_dbg(g_dev_ptr, "[chn %u] return file->f_pos = %lld\n", chn, file->f_pos);
return file->f_pos ;
}
#endif
//Restoring from NC353
loff_t circbuf_lseek(struct file * file, loff_t offset, int orig) {
// orig 0: position from begning
// orig 1: relative from current
// orig 2: position from last address
int l = (CCAM_DMA_SIZE << 2);
int fl=0;// frame length
struct interframe_params_t * fp;
int fvld=-1;
int rp, bp, prev_p, preprev_p; //, p;
int nf; //! number of frames;
int nz=1; //! number of crossing of start of the circular buffer (counter to prevent looping forever)
unsigned int minor = MINOR(file->f_inode->i_rdev);
unsigned int chn = minor_to_chn(minor, NULL);
//MD12(int dbg_i);
// int pf; // previous frame
dev_dbg(g_dev_ptr, "circbuf_lseek, offset=0x%x, orig=0x%x\n",(int) offset, (int) orig);
switch(orig) {
case SEEK_SET:
file->f_pos = offset;
break;
case SEEK_CUR:
if (offset) file->f_pos += offset;
else if (circbufValidPointer(file->f_pos, &fp, chn) <0 ) return -EINVAL; //!no frames at the specified location or pointer is not 32-byte aligned
break;
case SEEK_END:
if (offset <= 0) {
file->f_pos = l + offset;
} else { //! New functionality
//!verify the frame pointer
switch (offset) {
case LSEEK_CIRC_TORP:
file->f_pos=camSeqGetJPEG_rp(chn)<<2; //! set file pointer to global read pointer, and precoeed
case LSEEK_CIRC_PREV:
case LSEEK_CIRC_NEXT:
case LSEEK_CIRC_SETP:
case LSEEK_CIRC_VALID:
case LSEEK_CIRC_READY:
case LSEEK_CIRC_FREE:
case LSEEK_CIRC_USED:
if (((fvld=circbufValidPointer(file->f_pos, &fp, chn))) <0 )
return -EINVAL; //!no frames at the specified location
}
switch (offset) {
case LSEEK_CIRC_GETFRAME:
return get_compressor_frame(chn); // New in NC393
case LSEEK_CIRC_FREE:
bp=(file->f_pos - (camSeqGetJPEG_wp(chn)<<2));
// return (bp>0)?bp:(bp+l); //!will return full buffer size if current pointer is a write pointer (waiting for the next frame)
return (file->f_pos=(bp>0)?bp:(bp+l)); //!Has a side effect of moving a file pointer!
case LSEEK_CIRC_USED:
bp=((camSeqGetJPEG_wp(chn)<<2) - file->f_pos);
// return (bp>=0)?bp:(bp+l); //!will return 0 if current pointer is a write pointer (waiting for the next frame)
return (file->f_pos=(bp>0)?bp:(bp+l)); //!Has a side effect of moving a file pointer!
case LSEEK_CIRC_TORP:
break;
case LSEEK_CIRC_TOWP:
file->f_pos=camSeqGetJPEG_wp(chn)<<2; // no checking if it is valid
break;
case LSEEK_CIRC_LAST:
file->f_pos=camSeqGetJPEG_wp(chn)<<2;
fvld=circbufValidPointer(file->f_pos, &fp, chn); //!set fp
case LSEEK_CIRC_PREV:
rp= file->f_pos >> 2;
fl=circbuf_priv[chn].buf_ptr[X393_BUFFSUB32(rp, 9, chn)] ^ X313_LENGTH_MASK;
dev_dbg(g_dev_ptr, "LSEEK_CIRC_PREV: rp=0x%x, fvld=%d, fl=0x%x\n", rp, fvld,fl);
if (fl & X313_LENGTH_MASK) {
if (offset==LSEEK_CIRC_LAST) break; // just don't move pointer, leave it at write pointer and return no error
return -EOVERFLOW; //! no frames before current
}
bp = (X393_BUFFSUB32(rp, X313_PADDED_FRAME(fl),chn)<<2); // in bytes
dev_dbg(g_dev_ptr, "LSEEK_CIRC_PREV: bp=0x%x (0x%x), circbufValidPointer=%d\n", bp, bp>>2,circbufValidPointer(rp>>2, &fp,chn));
if (circbufValidPointer(bp, &fp, chn) < 0 ) { //! no valid frames before current
if (offset==LSEEK_CIRC_LAST) break; // just don't move pointer, leave it at write pointer and return no error
return -EOVERFLOW; //! no frames before current
}
//! move frame pointer only if there is a valid frame there
file->f_pos=bp;
break;
case LSEEK_CIRC_NEXT:
dev_dbg(g_dev_ptr, "LSEEK_CIRC_NEXT: rp=0x%llx, fvld=%d, fp->timestamp_sec=0x%lx\n", file->f_pos >> 2, fvld, fp->timestamp_sec);
if (fvld <=0)
return -EOVERFLOW; //! no frames after current
file->f_pos = X393_BUFFADD32(file->f_pos >> 2, X313_PADDED_FRAME(fp->timestamp_sec),chn) <<2 ;// do it even if the next frame does not yet exist
break;
case LSEEK_CIRC_FIRST:
case LSEEK_CIRC_SCND:
//! Starting from the write pointer do be able to count all the frames in the buffer
rp=camSeqGetJPEG_wp(chn);
prev_p=rp;
preprev_p=prev_p; // for second
nf=0;
nz=1;
file->f_pos=rp<<2;
while ((((fvld=circbufValidPointer(rp<<2, &fp, chn))) >= 0) & (nz>=0)) {
nf++;
// file->f_pos=rp<<2;
preprev_p=prev_p; //! second known good (at least first one)
prev_p=rp; //!now - current, known good
fl=circbuf_priv[chn].buf_ptr[X393_BUFFSUB32(rp, 9, chn)] ^ X313_LENGTH_MASK;
dev_dbg(g_dev_ptr, "\nf=%d, rp=0x%x, fvld=%d, fl=0x%x\n",nf, rp, fvld, fl);
if (fl & X313_LENGTH_MASK) break; //! no frames before rp (==prev_p)
//! move rp to the previous frame
rp= X393_BUFFSUB32(rp, X313_PADDED_FRAME(fl),chn);
if (rp > prev_p) nz-- ; // rolled through zero - make sure we'll not stuck in this loop forever
}
dev_dbg(g_dev_ptr, "after while{}: nf=%d, rp=0x%x, fvld=%d, fl=0x%x\n",nf, rp, fvld, fl);
file->f_pos=((offset==LSEEK_CIRC_SCND)?preprev_p:prev_p) << 2;
break;
case LSEEK_CIRC_SETP:
camSeqSetJPEG_rp(chn, file->f_pos>>2);
break;
case LSEEK_CIRC_VALID:
break;
case LSEEK_CIRC_READY:
if (fvld <=0) return -EINVAL; //! no frame is available better code?
break;
case LSEEK_CIRC_WAIT:
while (((fvld=circbufValidPointer(file->f_pos, &fp, chn)))==0) { //! only while not ready, ready or BAD - return
wait_event_interruptible (circbuf_wait_queue,(camSeqGetJPEG_wp(chn)<<2)!=file->f_pos);
}
if (fvld < 0) return -ESPIPE; //!invalid seek - have better code?
return file->f_pos ; //! data already available, return file pointer
default:
if ((offset & ~0x1f)==LSEEK_DAEMON_CIRCBUF) {
wait_event_interruptible (circbuf_wait_queue, get_imageParamsThis(chn, P_DAEMON_EN) & (1<<(offset & 0x1f)));
}
}
dev_dbg(g_dev_ptr, "return SEEK_END file->f_pos =0x%08llx\n",file->f_pos);
return ( file->f_pos ); //! file position >=0
}
break;
default:
return -EINVAL;
}
// roll-over position
while (file->f_pos < 0) file->f_pos+=l;
while (file->f_pos > l) file->f_pos-=l;
if ((orig !=SEEK_END) && (file->f_pos == l)) file->f_pos=0; //!only for lseek (fd,0,SEEK_END) the result will be file size, others will roll to 0
dev_dbg(g_dev_ptr, "return file->f_pos =0x%08llx\n",file->f_pos);
return file->f_pos ;
}
unsigned short circbuf_quality = 100;
unsigned short circbuf_height = 1936;
unsigned short circbuf_width = 2592;
unsigned char circbuf_byrshift = 3;
#ifdef PRE_FRAMEPARS
unsigned short circbuf_quality = 100;
unsigned short circbuf_height = 1936;
unsigned short circbuf_width = 2592;
unsigned char circbuf_byrshift = 3;
#endif
/**
* @brief This function handles write operations for circbuf files.
* @note Never use @e file->f_pos in this function.
......@@ -762,6 +985,7 @@ ssize_t circbuf_write(struct file *file, const char *buf, size_t count, loff_t *
dev_dbg(g_dev_ptr, "minor = 0x%x, count = 0x%x, off = 0x%llx", minor, count, off);
/* debug code follows*/
#ifdef PRE_FRAMEPARS
switch (buf[0] - 0x30) {
case 0:
compressor_interrupts(0,chn);
......@@ -831,12 +1055,12 @@ ssize_t circbuf_write(struct file *file, const char *buf, size_t count, loff_t *
break;
}
/* debug code end */
#endif
p = *off;
if (p >= CCAM_DMA_SIZE)
p = CCAM_DMA_SIZE;
if ((p + count) > CCAM_DMA_SIZE)
count = CCAM_DMA_SIZE - p;
if (p >= circbuf_priv[chn].buf_size) //CCAM__DMA_SIZE)
p = circbuf_priv[chn].buf_size; // CCAM__DMA_SIZE;
if ((p + count) > circbuf_priv[chn].buf_size) // CCAM_-MA_SIZE)
count = circbuf_priv[chn].buf_size-p; // CCAM__DMA_SIZE - p;
if (count) {
if (copy_from_user(&circbuf_priv[chn].buf_ptr[BYTE2DW(p)], buf, count))
return -EFAULT;
......@@ -862,10 +1086,10 @@ ssize_t circbuf_read(struct file *file, char *buf, size_t count, loff_t *off)
dev_dbg(g_dev_ptr, "minor = 0x%x, count = 0x%x, off = 0x%llx", minor, count, off);
p = *off;
if (p >= CCAM_DMA_SIZE)
p = CCAM_DMA_SIZE;
if ((p + count) > CCAM_DMA_SIZE)
count = CCAM_DMA_SIZE - p;
if (p >= circbuf_priv[chn].buf_size) // CCAM__DMA_SIZE)
p = circbuf_priv[chn].buf_size; // CCAM__DMA_SIZE;
if ((p + count) > circbuf_priv[chn].buf_size) // CCAM__DMA_SIZE)
count = circbuf_priv[chn].buf_size - p; // CCAM__DMA_SIZE - p;
if (count) {
if (copy_to_user(buf, &circbuf_priv[chn].buf_ptr[BYTE2DW(p)], count))
return -EFAULT;
......
......@@ -28,8 +28,11 @@
struct circbuf_priv_t {
int minor; ///< device file minor number
unsigned long *buf_ptr; ///< pointer to circular buffer memory region
unsigned long buf_size; ///< circular region size in bytes
unsigned long buf_size32; ///< circular region size in dwords
dma_addr_t phys_addr; ///< physical address of memory region reported by memory driver
};
struct circbuf_priv_t *get_circbuf(int chn); // alternative to use of extern struct circbuf_priv_ptr;
extern struct circbuf_priv_t *circbuf_priv_ptr;
extern wait_queue_head_t circbuf_wait_queue;
......
......@@ -28,6 +28,8 @@
#include <linux/init.h>
//#include <linux/autoconf.h>
#include <linux/vmalloc.h>
#include <linux/platform_device.h> // dev_*
//#include <asm/system.h>
//#include <asm/svinto.h>
......@@ -61,15 +63,18 @@
//#define X3X3_EXIF_EXIF 0 // read encoded Exif data (SEEK_END,
//#define X3X3_EXIF_META 1 // write metadata, concurently opened files. All writes atomic
// control/setup devices
//#define X3X3_EXIF_TEMPLATE 2 // write Exif template
//#define X3X3_EXIF_METADIR 3 // write metadata to Exif header translation (dir_table[MAX_EXIF_FIELDS])
//#define DEV393_MINOR(DEV393_EXIF_TEMPLATE) 2 // write Exif template
//#define DEV393_MINOR(DEV393_EXIF_METADIR) 3 // write metadata to Exif header translation (dir_table[MAX_EXIF_FIELDS])
// those 2 files will disable exif_enabled and exif_valid, truncate file size to file pointer on release.
//#define X3X3_EXIF_TIME 4 // write today/tomorrow date (YYYY:MM:DD) and number of seconds at today/tomorrow
//#define DEV393_MINOR(DEV393_EXIF_TIME) 4 // write today/tomorrow date (YYYY:MM:DD) and number of seconds at today/tomorrow
// midnight (00:00:00) in seconds from epoch (long, startting from LSB)
#define X3X3_EXIF_DRIVER_DESCRIPTION "Elphel (R) model 393 Exif device driver"
/** @brief Global pointer to basic device structure. This pointer is used in debugfs output functions */
static struct device *g_devfp_ptr = NULL;
static DEFINE_SPINLOCK(lock);
//#define MAX_EXIF_FIELDS 256 // number of Exif tags in the header
......@@ -123,7 +128,7 @@ static struct file_operations exif_fops = {
ssize_t minor_file_size(int minor) { //return current file size for different minors
int sensor_port;
switch (minor) {
case X3X3_EXIF_TEMPLATE:
case DEV393_MINOR(DEV393_EXIF_TEMPLATE):
return exif_template_size;
case DEV393_MINOR(DEV393_EXIF0):
case DEV393_MINOR(DEV393_EXIF1):
......@@ -137,16 +142,16 @@ ssize_t minor_file_size(int minor) { //return current file size for different mi
case DEV393_MINOR(DEV393_EXIF_META3):
sensor_port = minor - DEV393_MINOR(DEV393_EXIF_META0);
return aexif_meta_size[sensor_port];
case X3X3_EXIF_METADIR:
case DEV393_MINOR(DEV393_EXIF_METADIR):
return exif_fields * sizeof(struct exif_dir_table_t);
case X3X3_EXIF_TIME:
case DEV393_MINOR(DEV393_EXIF_TIME):
return sizeof(struct exif_time_t);
default:return 0;
}
}
ssize_t minor_max_size(int minor) { //return max file size for different minors
switch (minor) {
case X3X3_EXIF_TEMPLATE:
case DEV393_MINOR(DEV393_EXIF_TEMPLATE):
return MAX_EXIF_SIZE;
case DEV393_MINOR(DEV393_EXIF0):
case DEV393_MINOR(DEV393_EXIF1):
......@@ -158,9 +163,9 @@ ssize_t minor_max_size(int minor) { //return max file size for different minors
case DEV393_MINOR(DEV393_EXIF_META2):
case DEV393_MINOR(DEV393_EXIF_META3):
return MAX_EXIF_SIZE;
case X3X3_EXIF_METADIR:
case DEV393_MINOR(DEV393_EXIF_METADIR):
return MAX_EXIF_FIELDS * sizeof(struct exif_dir_table_t);
case X3X3_EXIF_TIME:
case DEV393_MINOR(DEV393_EXIF_TIME):
return sizeof(struct exif_time_t);
default:
return 0;
......@@ -204,12 +209,12 @@ int exif_rebuild_chn(int sensor_port, int frames) {
if (ml > aexif_meta_size[sensor_port]) aexif_meta_size[sensor_port] = ml;
}
if (aexif_meta_size[sensor_port] > MAX_EXIF_SIZE) {
printk ("%s:%d: Meta frame size (0x%x) is too big (>0x%x)\n",__FILE__,__LINE__, aexif_meta_size[sensor_port], MAX_EXIF_SIZE);
dev_warn(g_devfp_ptr,"%s:%d: Meta frame size (0x%x) is too big (>0x%x)\n",__FILE__,__LINE__, aexif_meta_size[sensor_port], MAX_EXIF_SIZE);
return -1;
}
meta_buffer= vmalloc(aexif_meta_size[sensor_port] * (MAX_EXIF_FRAMES+1));
if (!meta_buffer) {
printk ("%s:%d: Failed to allocate memory (%d bytes)\n",__FILE__,__LINE__, aexif_meta_size[sensor_port] * (MAX_EXIF_FRAMES+1));
dev_warn(g_devfp_ptr,"%s:%d: Failed to allocate memory (%d bytes)\n",__FILE__,__LINE__, aexif_meta_size[sensor_port] * (MAX_EXIF_FRAMES+1));
return -1;
}
memset(meta_buffer, 0, aexif_meta_size[sensor_port] * (MAX_EXIF_FRAMES+1));
......@@ -352,7 +357,7 @@ int putlong_meta(int sensor_port, unsigned long data, int * indx, unsigned long
*/
char * encode_time(char buf[27], unsigned long sec, unsigned long usec) {
unsigned long s,d,m,y,y4,lp,h;
spin_lock(&lock);
spin_lock_bh(&lock);
if (((sec-exif_time.today_sec)>86400) || (sec < exif_time.today_sec)) {// today's time is not valid, try tomorrow:
memcpy(&exif_time.today_date[0],&exif_time.tomorrow_date[0],sizeof(exif_time.today_date)+sizeof(exif_time.today_sec));
if (((sec-exif_time.today_sec)>86400) || (sec < exif_time.today_sec)) {// today's time is _still_ not valid, has to do it itself :-(
......@@ -411,7 +416,7 @@ char * encode_time(char buf[27], unsigned long sec, unsigned long usec) {
sprintf(&now_datetime.subsec[0],"%06ld",usec);
memcpy(buf,&now_datetime.datetime[0],sizeof(now_datetime));
// return &now_datetime.datetime[0];
spin_unlock(&lock);
spin_unlock_bh(&lock);
return buf;
}
......@@ -438,14 +443,14 @@ static int exif_open(struct inode *inode, struct file *filp) {
case DEV393_MINOR(DEV393_EXIF_META1):
case DEV393_MINOR(DEV393_EXIF_META2):
case DEV393_MINOR(DEV393_EXIF_META3):
case X3X3_EXIF_TEMPLATE:
case X3X3_EXIF_METADIR:
case X3X3_EXIF_TIME:
case DEV393_MINOR(DEV393_EXIF_TEMPLATE):
case DEV393_MINOR(DEV393_EXIF_METADIR):
case DEV393_MINOR(DEV393_EXIF_TIME):
break;
default:return -EINVAL;
}
D(printk("exif_open, minor=%d\n",p));
dev_dbg(g_devfp_ptr,"exif_open, minor=%d\n",p);
inode->i_size=minor_file_size(p);
pd[0]=p; // just a minor number
return 0;
......@@ -467,16 +472,16 @@ static int exif_release(struct inode *inode, struct file *filp){
case DEV393_MINOR(DEV393_EXIF_META2):
case DEV393_MINOR(DEV393_EXIF_META3):
break;
case X3X3_EXIF_TEMPLATE:
case DEV393_MINOR(DEV393_EXIF_TEMPLATE):
break;
case X3X3_EXIF_METADIR:
case DEV393_MINOR(DEV393_EXIF_METADIR):
break;
case X3X3_EXIF_TIME:
case DEV393_MINOR(DEV393_EXIF_TIME):
break;
default:return -EINVAL;
}
D(printk("exif_open, minor=%d\n",p));
dev_dbg(g_devfp_ptr,"exif_open, minor=%d\n",p);
inode->i_size=minor_file_size(p);
pd[0]=p; // just a minor number
return 0;
......@@ -488,6 +493,7 @@ static loff_t exif_lseek (struct file * file, loff_t offset, int orig) {
int p=(int)file->private_data;
int thissize=minor_file_size(p);
int maxsize=minor_max_size(p);
dev_dbg(g_devfp_ptr,"exif_lseek, minor=%d, offset = 0x%llx, orig=%d\n",p,offset,orig);
// int sensor_port;
int fp;
switch (orig) {
......@@ -504,7 +510,7 @@ static loff_t exif_lseek (struct file * file, loff_t offset, int orig) {
} else {
switch (p) {
case X3X3_EXIF_TEMPLATE: //enable/disable
case DEV393_MINOR(DEV393_EXIF_TEMPLATE): //enable/disable
switch (offset) {
case EXIF_LSEEK_DISABLE:
exif_enable(0);
......@@ -530,18 +536,16 @@ static loff_t exif_lseek (struct file * file, loff_t offset, int orig) {
// file->f_pos=exif_meta_size * offset;
file->f_pos=exif_template_size * offset;
break;
case X3X3_EXIF_META: // iterate
fp= dir_find_tag (offset);
if (fp < 0) return -EOVERFLOW; // tag is not in the directory
file->f_pos=fp;
break;
case DEV393_MINOR(DEV393_EXIF_META0):
case DEV393_MINOR(DEV393_EXIF_META1):
case DEV393_MINOR(DEV393_EXIF_META2):
case DEV393_MINOR(DEV393_EXIF_META3):
file->f_pos=offset*sizeof(struct exif_dir_table_t);
break;
case X3X3_EXIF_TIME:
case DEV393_MINOR(DEV393_EXIF_METADIR):
file->f_pos=offset*sizeof(struct exif_dir_table_t);
break;
case DEV393_MINOR(DEV393_EXIF_TIME):
switch (offset) {
case EXIF_LSEEK_TOMORROW_DATE:
file->f_pos=exif_time.tomorrow_date - ((char *) &exif_time);
......@@ -590,22 +594,22 @@ static ssize_t exif_write (struct file * file, const char * buf, size_t coun
unsigned long flags;
int disabled_err=0;
if ((*off+count)>maxsize) {
printk ("%s:%d: Data (0x%x) does not fit into 0x%x bytes\n",__FILE__,__LINE__, (int) (*off+count), maxsize);
dev_warn(g_devfp_ptr,"%s:%d: Data (0x%x) does not fit into 0x%x bytes\n",__FILE__,__LINE__, (int) (*off+count), maxsize);
return -EOVERFLOW;
}
switch (p) {
case X3X3_EXIF_TEMPLATE:
case DEV393_MINOR(DEV393_EXIF_TEMPLATE):
exif_invalidate();
if (copy_from_user(&exif_template[*off], buf, count)) return -EFAULT;