#ifndef _V4L2_OSDEP_H_
#define _V4L2_OSDEP_H_

#include "platform/platform_stdlib.h"
#include "basic_types.h"
//#include "osdep_api.h"  //deprecated use osdep_service.h instead
#include "osdep_service.h"
//#include "hal_util.h"
#include "dlist.h"
#include "v4l2_errno.h"

#define V4L2_LAYER_DEBUG 0
#if     V4L2_LAYER_DEBUG
#define V4L2_PRINTF(fmt, args...)	printf("\n\r%s: " fmt, __FUNCTION__, ## args)
#define V4L2_ERROR(fmt, args...)        printf("\n\r%s: " fmt, __FUNCTION__, ## args)
#else
#define V4L2_PRINTF(fmt, args...)
#define V4L2_ERROR(fmt, args...)        printf("\n\r%s: " fmt, __FUNCTION__, ## args)
#endif

/* misc items */
#ifndef ssize_t
#define ssize_t SSIZE_T
#endif
#ifndef size_t
#define size_t SIZE_T
#endif

#ifndef __user
#define __user
#endif

#ifndef loff_t
#define loff_t long
#endif
#ifndef __u8
#define __u8 	u8
#endif
#ifndef __u16
#define __u16	u16
#endif
#ifndef __u32
#define __u32	u32
#endif
#ifndef __u64
#define __u64	u64
#endif
#ifndef __s8
#define __s8	s8
#endif
#ifndef __s16
#define __s16	s16
#endif
#ifndef __s32
#define __s32	s32
#endif
#ifndef __s64
#define __s64	s64
#endif

#ifndef spinlock_t
#define spinlock_t _lock
#endif

#ifndef gfp_t
#define gfp_t	u32
#endif

#ifndef _atomic_spin_lock_irqsave
#define _atomic_spin_lock_irqsave(p, flags) 		save_and_cli()
#endif
#ifndef _atomic_spin_unlock_irqrestore
#define _atomic_spin_unlock_irqrestore(p, flags)	restore_flags()
#endif
#ifndef local_irq_save
#define local_irq_save(flags)				save_and_cli()
#endif
#ifndef local_irq_restore
#define local_irq_restore(flags)			restore_flags()
#endif
#ifndef cris_atomic_save
#define cris_atomic_save(addr, flags) 			local_irq_save(flags)
#endif
#ifndef cris_atomic_restore
#define cris_atomic_restore(addr, flags) 		local_irq_restore(flags)
#endif

/*
 * abs() handles unsigned and signed longs, ints, shorts and chars.  For all
 * input types abs() returns a signed long.
 * abs() should not be used for 64-bit types (s64, u64, long long) - use abs64()
 * for those.
 */

#ifndef abs
#define abs(x) ((x >= 0) ? (x) : (x * -1))
#endif

#ifndef min 
#define min(x, y) ((x) < (y) ? (x) : (y))
#endif
#ifndef max
#define max(x, y) ((x) > (y) ? (x) : (y))
#endif
#ifndef min_t 
#define min_t(type, x, y) ({                    \
         type __min1 = (x);                      \
         type __min2 = (y);                      \
         (__min1 < __min2) ? (__min1) : (__min2); })
#endif
#ifndef max_t
#define max_t(type, x, y) ({                    \
         type __max1 = (x);                      \
         type __max2 = (y);                      \
         (__max1 > __max2) ? (__max1) : (__max2); })
#endif
#ifndef max_tt
#define max_tt(ret,type,x,y) do{                    \
         type __max1 = (x);                      \
         type __max2 = (y);                      \
         ret = (__max1 > __max2) ? (__max1) : (__max2); }while(0) 
#endif
#ifndef min_tt 
#define min_tt(ret,type, x, y) do{                    \
         type __min1 = (x);                      \
         type __min2 = (y);                      \
         ret = (__min1 < __min2) ? (__min1) : (__min2); }while(0)
#endif 


/**
* container_of - cast a member of a structure out to the containing structure
* @p(ptr): 	   the pointer to the member.
* @t(type):	   the type of the container struct this is embedded in.
* @m(member):	   the name of the member within the struct.
*
*/
#ifndef container_of 
	#define container_of(ptr, type, member) \
			((type *)((char *)(ptr)-(SIZE_T)(&((type *)0)->member)))
#endif
	
	/**
	* list_next_entry - get the next element in list
	* @pos: 	   the type * to cursor
	* @member:	   the name of the list_struct within the struct.
	*/

#define list_next_entry(pos, member, type)				\
			 list_entry((pos)->member.next, type, member)

	/**
	* list_for_each_entry_continue - continue iteration over list of given type
	* @pos: 	   the type * to use as a loop cursor.
	* @head:	   the head for your list.
	* @member:	   the name of the list_struct within the struct.
	*
	* Continue to iterate over list of given type, continuing after
	* the current position.
	*/

#define list_for_each_entry_continue(pos, head, member, type)		\
		for (pos = list_next_entry(pos, member, type);			\
			&pos->member != (head); 					\
				pos = list_next_entry(pos, member, type))           
           

/* spin lock */
#ifndef spin_lock_init
	#define spin_lock_init(plock) 			rtw_spinlock_init((plock))
#endif
#ifndef spin_lock_free
	#define spin_lock_free(plock) 			rtw_spinlock_free((plock))
#endif
#ifndef spin_lock
	#define spin_lock(plock) 			rtw_spin_lock((plock))
#endif
#ifndef spin_unlock 
	#define spin_unlock(plock) 			rtw_spin_unlock((plock))
#endif


/* mutex */
#ifndef Mutex
	#define Mutex _mutex
#endif
#ifndef Mutex_Init
	#define Mutex_Init(pmutex)			rtw_mutex_init((pmutex))
#endif
#ifndef Mutex_Lock
	#define Mutex_Lock(pmutex)			rtw_mutex_get((pmutex))
#endif
#ifndef Mutex_Unlock
	#define Mutex_Unlock(pmutex)		rtw_mutex_put((pmutex))	
#endif
#ifndef Mutex_Free
	#define Mutex_Free(pmutex)			rtw_mutex_free((pmutex))
#endif

/* semaphore */
#ifndef Sema
        #define Sema _sema
#endif
#ifndef Sema_Init
	#define Sema_Init(pmutex, pval)			rtw_init_sema(pmutex, pval)
#endif
#ifndef Sema_Free
	#define Sema_Free(pmutex)				rtw_free_sema(pmutex)
#endif
#ifndef Sema_Up
	#define Sema_Up(pmutex)				rtw_up_sema(pmutex)
#endif
#ifndef Sema_Down
	#define Sema_Down(pmutex)				rtw_down_sema(pmutex)
#endif
#ifndef Sema_Down_WithTimeout
	#define Sema_Down_WithTimeout(pmutex,ptimeout)			rtw_down_timeout_sema(pmutex,ptimeout) //
#endif

/* Atomic integer operations */
#ifndef atomic_set
	#define atomic_set(v, i)		ATOMIC_SET((v), (i))
#endif
#ifndef atomic_read
	#define atomic_read(v)			ATOMIC_READ((v))
#endif
#ifndef atomic_add
	#define atomic_add(v, i)		ATOMIC_ADD((v), (i))
#endif
#ifndef atomic_sub
	#define atomic_sub(v, i)		ATOMIC_SUB((v), (i))
#endif
#ifndef atomic_inc
	#define atomic_inc(v)			ATOMIC_INC((v))
#endif
#ifndef atomic_dec
	#define atomic_dec(v)			ATOMIC_DEC((v))
#endif

           
// IOCTL ...
#ifndef _IOC_NRBITS
#define _IOC_NRBITS 	(8) 	
#endif
#ifndef _IOC_TYPEBITS
#define _IOC_TYPEBITS 	(8) 	
#endif
#ifndef _IOC_SIZEBITS
#define _IOC_SIZEBITS 	(14) 	
#endif
#ifndef _IOC_DIRBITS
#define _IOC_DIRBITS 	(2) 	
#endif
#ifndef _IOC_NRMASK
#define _IOC_NRMASK 	((1 << _IOC_NRBITS) - 1) 
#endif
#ifndef _IOC_TYPEMASK
#define _IOC_TYPEMASK 	((1 << _IOC_TYPEBITS) - 1)
#endif
#ifndef _IOC_SIZEMASK
#define _IOC_SIZEMASK 	((1 << _IOC_SIZEBITS) - 1)
#endif
#ifndef _IOC_DIRMASK
#define _IOC_DIRMASK 	((1 << _IOC_DIRBITS) - 1) 
#endif
#ifndef _IOC_NRSHIFT 
#define _IOC_NRSHIFT 	(0) 
#endif
#ifndef _IOC_TYPESHIFT
#define _IOC_TYPESHIFT 	(_IOC_NRSHIFT + _IOC_NRBITS) 
#endif
#ifndef _IOC_SIZESHIFT
#define _IOC_SIZESHIFT 	(_IOC_TYPESHIFT + _IOC_TYPEBITS) 
#endif
#ifndef _IOC_DIRSHIFT
#define _IOC_DIRSHIFT 	(_IOC_SIZESHIFT + _IOC_SIZEBITS) 
#endif 

/*
 * Direction bits.
 */
#ifndef _IOC_NONE
#define _IOC_NONE (0U) 
#endif
#ifndef _IOC_WRITE
#define _IOC_WRITE (1U) 
#endif
#ifndef _IOC_READ
#define _IOC_READ (2U) 
#endif 


/*
 * combine the four dir，type，nr，size parameters to one cmd parameter
 *
 */
#ifndef _IOC
#define _IOC(dir,type,nr,size) \
       (((dir) << _IOC_DIRSHIFT) | \
        ((type) << _IOC_TYPESHIFT) | \
        ((nr) << _IOC_NRSHIFT) | \
        ((size) << _IOC_SIZESHIFT))
#endif
/*
 * used to create IOCTL cmd 
 */
#ifndef _IO
#define _IO(type,nr)        	_IOC(_IOC_NONE,(type), (nr), 0) 
#endif
#ifndef _IOR  
#define _IOR(type,nr,size)     	_IOC(_IOC_READ,(type), (nr), sizeof(size)) 
#endif
#ifndef _IOW
#define _IOW(type,nr,size)    	_IOC(_IOC_WRITE,(type), (nr), sizeof(size))
#endif
#ifndef _IOWR
#define _IOWR(type,nr,size) 	_IOC(_IOC_READ|_IOC_WRITE, (type), (nr), sizeof(size))
#endif
/* 
 * used to decode ioctl infoations..
 */
#ifndef _IOC_DIR
#define _IOC_DIR(nr) (((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK)
#endif
#ifndef _IOC_TYPE
#define _IOC_TYPE(nr) (((nr) >> _IOC_TYPESHIFT) & _IOC_TYPEMASK)
#endif
#ifndef _IOC_NR
#define _IOC_NR(nr) (((nr) >> _IOC_NRSHIFT) & _IOC_NRMASK)
#endif
#ifndef _IOC_SIZE
#define _IOC_SIZE(nr) (((nr) >> _IOC_SIZESHIFT) & _IOC_SIZEMASK)
#endif 
/* ...and for the drivers/sound files... */
#ifndef IOC_IN
#define IOC_IN (_IOC_WRITE << _IOC_DIRSHIFT)
#endif
#ifndef IOC_OUT
#define IOC_OUT (_IOC_READ << _IOC_DIRSHIFT)
#endif
#ifndef IOC_INOUT
#define IOC_INOUT ((_IOC_WRITE|_IOC_READ) << _IOC_DIRSHIFT)
#endif
#ifndef IOCSIZE_MASK
#define IOCSIZE_MASK (_IOC_SIZEMASK << _IOC_SIZESHIFT)
#endif
#ifndef IOCSIZE_SHIFT
#define IOCSIZE_SHIFT (_IOC_SIZESHIFT)
#endif

#ifndef DIV_ROUND_UP
#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
#endif
#ifndef BITS_PER_LONG
#define BITS_PER_LONG (32)
#endif
#ifndef BITS_PER_LONG_LONG
#define BITS_PER_LONG_LONG (32)
#endif
#ifndef BIT
#define BIT(nr)                 (1UL << (nr))
#endif
#ifndef BIT_ULL
#define BIT_ULL(nr)             (1ULL << (nr))
#endif
#ifndef BIT_MASK
#define BIT_MASK(nr)            (1UL << ((nr) % BITS_PER_LONG))
#endif
#ifndef BIT_WORD
#define BIT_WORD(nr)            ((nr) / BITS_PER_LONG)
#endif
#ifndef BIT_ULL_MASK
#define BIT_ULL_MASK(nr)        (1ULL << ((nr) % BITS_PER_LONG_LONG))
#endif
#ifndef BIT_ULL_WORD
#define BIT_ULL_WORD(nr)        ((nr) / BITS_PER_LONG_LONG)
#endif
#ifndef BITS_PER_BYTE
#define BITS_PER_BYTE           (8)
#endif
#ifndef BITS_TO_LONGS
#define BITS_TO_LONGS(nr)       DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long))
#endif

/* __ffs to find out the first exist 1 offset, from bit 0 ~ 31 */
#ifndef ffz
#define ffz(x)  __ffs(~(x))                     
#endif
/* __builtin_constant_p is gcc build-in function to check the parameter is const or not */
#ifndef small_const_nbits
#define small_const_nbits(nbits) \
         (__builtin_constant_p(nbits) && (nbits) <= BITS_PER_LONG)
#endif
/**
 * __ffs - find first bit in word.
 * @word: The word to search
 *
 * Undefined if no bit exists, so code should check against 0 first.
 */
static inline unsigned long __ffs(unsigned long word)
{
	int num = 0;

#if BITS_PER_LONG == 64
	if ((word & 0xffffffff) == 0) {
		num += 32;
		word >>= 32;
	}
#endif
	if ((word & 0xffff) == 0) {                         
		num += 16;                                      
		word >>= 16;
	}
	if ((word & 0xff) == 0) {                           
		num += 8;
		word >>= 8;
	}
	if ((word & 0xf) == 0) {
		num += 4;
		word >>= 4;
	}
	if ((word & 0x3) == 0) {
		num += 2;
		word >>= 2;
	}
	if ((word & 0x1) == 0)
		num += 1;
	
	return num;                                         
}

/**
  * __fls - find last (most-significant) set bit in a long word
  * @word: the word to search
  *
  * Undefined if no set bit exists, so code should check against 0 first.
  */
static inline unsigned long __fls(unsigned long word)
{
         int num = BITS_PER_LONG - 1;
 
 #if BITS_PER_LONG == 64
         if (!(word & (~0ul << 32))) {
                 num -= 32;
                 word <<= 32;
         }
 #endif
         if (!(word & (~0ul << (BITS_PER_LONG-16)))) {
                 num -= 16;
                 word <<= 16;
         }
         if (!(word & (~0ul << (BITS_PER_LONG-8)))) {
                 num -= 8;
                 word <<= 8;
         }
         if (!(word & (~0ul << (BITS_PER_LONG-4)))) {
                 num -= 4;
                 word <<= 4;
         }
         if (!(word & (~0ul << (BITS_PER_LONG-2)))) {
                 num -= 2;
                 word <<= 2;
         }
         if (!(word & (~0ul << (BITS_PER_LONG-1))))
                num -= 1;
        return num;
}

/**
 * test_bit - Determine whether a bit is set
 * @nr: bit number to test
 * @addr: Address to start counting from
 */
static inline int test_bit(int nr, const volatile unsigned long *addr)
{
        return ((1UL << (nr & 31)) & (addr[nr >> 5])) != 0;
}



/*
* Find the first cleared bit in a memory region.
*/
static inline unsigned long find_first_zero_bit(
	const unsigned long *addr, unsigned long size)
{
        const unsigned long *p = addr;
        unsigned long result = 0;
        unsigned long tmp;

        while (size & ~(BITS_PER_LONG-1)) {
                if (~(tmp = *(p++)))
                        goto found;
                result += BITS_PER_LONG;
                size -= BITS_PER_LONG;
        }
        if (!size)
                return result;

        tmp = (*p) | (~0UL << size);
        if (tmp == ~0UL)        /* Are any bits zero? */
                return result + size;   /* Nope. */
found:

	return result + ffz(tmp);
	//tmp = 0;
	//return result;

}

static inline unsigned long find_next_zero_bit(
	const unsigned long *addr,unsigned long size, unsigned long offset)
{
    const unsigned long *p = addr + BIT_WORD(offset); // offset位于p指向的long地址32位空?
    unsigned long result = offset & ~(BITS_PER_LONG-1); // offset是第result?4字?
    unsigned long tmp;

    if (offset >= size)
        return size;
    size -= result;                                     // ?整32位整倍?上
    offset %= BITS_PER_LONG;                            // offset位于32位的第几位
    if (offset) {                                       // offset不在一?long?据的第0位上,在1-31位中[luther.gliethttp]
        tmp = *(p++);
        tmp |= ~0UL >> (BITS_PER_LONG - offset);        // ?0-offset?据填充上1.
        if (size < BITS_PER_LONG)                       // 不足32bits
            goto found_first;
        if (~tmp)                                       // 取非非0?明含有0值
            goto found_middle;
        size -= BITS_PER_LONG;                          // 如果上面~tmp等于0,那么?明?*p?据?32位全1.[luther.gliethttp]
        result += BITS_PER_LONG;
    }
    while (size & ~(BITS_PER_LONG-1)) {                 // 好了,?行到?里,我?的offset已??在4字?的第0位上,下面?行
        if (~(tmp = *(p++)))                            // 4字?快速查?.如果~tmp非0,?明?32位?据中含有0?据,找到.[luther.gliethttp]
            goto found_middle;
        result += BITS_PER_LONG;                        // 到下一?4字?空?
        size -= BITS_PER_LONG;                          // ?少4字??据
    }
    if (!size)                                          // size等于0,?明首先size等于4字?整倍?,其次所有?据已?查完,
        return result;                                  // 所有?据全部?1,?有??0位,result等于size.[luther.gliethttp]
    tmp = *p;                                           // size不是32位整倍?,?剩几?bit?有?查,???行下面?查工作.[luther.gliethtp]

found_first:
    tmp |= ~0UL << size;                                // ?在0-size?有效?据,size-31?未使用空?,所以先?size-31置成全1.
    if (tmp == ~0UL)    /* Are any bits zero? */        // 如果tmp全1,那么?明就?找找1?
        return result + size;    /* Nope. */             // result+size就等于函??入的??size大小.[luther.gliethttp]
found_middle:
    return result + ffz(tmp);                           // 我?在32位?据的0-31中??必定存在0位值,?算他是第几位.[luther.gliethttp]
}

//int find_next_zero_bit(const void * p, int size, int offset);
//int find_first_bit(const unsigned long *p, unsigned size);
//int find_next_bit(const unsigned long *p, int size, int offset);
/**
* set_bit - Atomically set a bit in memory
* @nr: the bit to set
* @addr: the address to start counting from
*
* This function is atomic and may not be reordered.  See __set_bit()
* if you do not require the atomic guarantees.
*
* Note: there are no guarantees that this function will not be reordered
* on non x86 architectures, so if you are writing portable code,
* make sure not to rely on its reordering guarantees.
*
* Note that @nr may be almost arbitrarily large; this function is not
* restricted to acting on a single-word quantity.
*/
static inline void set_bit(int nr, volatile unsigned long *addr)
{
	unsigned long mask = BIT_MASK(nr);
	unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
	unsigned long flags;

	//taskENTER_CRITICAL();
	_atomic_spin_lock_irqsave(p, flags);
	*p  |= mask;
	_atomic_spin_unlock_irqrestore(p, flags);
	//taskEXIT_CRITICAL();
}

/**
* clear_bit - Clears a bit in memory
* @nr: Bit to clear
* @addr: Address to start counting from
*
* clear_bit() is atomic and may not be reordered.  However, it does
* not contain a memory barrier, so if it is used for locking purposes,
* you should call smp_mb__before_clear_bit() and/or smp_mb__after_clear_bit()
* in order to ensure changes are visible on other processors.
*/
static inline void clear_bit(int nr, volatile unsigned long *addr)
{
	unsigned long mask = BIT_MASK(nr);
	unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
	unsigned long flags;

	_atomic_spin_lock_irqsave(p, flags);
	//taskENTER_CRITICAL();
	*p &= ~mask;
	_atomic_spin_unlock_irqrestore(p, flags);
	//taskEXIT_CRITICAL();
}
 
/**
* change_bit - Toggle a bit in memory
* @nr: Bit to change
* @addr: Address to start counting from
*
* change_bit() is atomic and may not be reordered. It may be
* reordered on other architectures than x86.
* Note that @nr may be almost arbitrarily large; this function is not
* restricted to acting on a single-word quantity.
*/
static inline void change_bit(int nr, volatile unsigned long *addr)
{
	unsigned long mask = BIT_MASK(nr);
	unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
	unsigned long flags;

	//taskENTER_CRITICAL();
	_atomic_spin_lock_irqsave(p, flags);
	*p ^= mask;
	_atomic_spin_unlock_irqrestore(p, flags);
	//taskEXIT_CRITICAL();
}
 
/**
* test_and_set_bit - Set a bit and return its old value
* @nr: Bit to set
* @addr: Address to count from
*
* This operation is atomic and cannot be reordered.
* It may be reordered on other architectures than x86.
* It also implies a memory barrier.
*/
static inline int test_and_set_bit(int nr, volatile unsigned long *addr)
{
	unsigned long mask = BIT_MASK(nr);
	unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
	unsigned long old;
	//unsigned long flags;

	//taskENTER_CRITICAL();
	
	_atomic_spin_lock_irqsave(p, flags);
	old = *p;
	*p = old | mask;
	_atomic_spin_unlock_irqrestore(p, flags);
	//taskEXIT_CRITICAL();

	return (old & mask) != 0;
}

/**
* test_and_clear_bit - Clear a bit and return its old value
* @nr: Bit to clear
* @addr: Address to count from
*
* This operation is atomic and cannot be reordered.
* It can be reorderdered on other architectures other than x86.
* It also implies a memory barrier.
*/
static inline int test_and_clear_bit(int nr, volatile unsigned long *addr)
{
	unsigned long mask = BIT_MASK(nr);
	unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
	unsigned long old;
	unsigned long flags;

	//taskENTER_CRITICAL();
	_atomic_spin_lock_irqsave(p, flags);
	old = *p;
	*p = old & ~mask;
	_atomic_spin_unlock_irqrestore(p, flags);
	//taskEXIT_CRITICAL();

	return (old & mask) != 0;
}
/**
* test_and_change_bit - Change a bit and return its old value
* @nr: Bit to change
* @addr: Address to count from
*
* This operation is atomic and cannot be reordered.
* It also implies a memory barrier.
*/
static inline int test_and_change_bit(int nr, volatile unsigned long *addr)
{
	unsigned long mask = BIT_MASK(nr);
	unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
	unsigned long old;
	unsigned long flags;

	
	_atomic_spin_lock_irqsave(p, flags);
	old = *p;
	*p = old ^ mask;
	_atomic_spin_unlock_irqrestore(p, flags);
	

	return (old & mask) != 0;
}


static inline int __bitmap_andnot(unsigned long *dst, const unsigned long *bitmap1,
				const unsigned long *bitmap2, int bits)
{
	int k;
	int nr = BITS_TO_LONGS(bits);
	unsigned long result = 0;

	for (k = 0; k < nr; k++)
	result |= (dst[k] = bitmap1[k] & ~bitmap2[k]);
	return result != 0;
}

static inline int bitmap_andnot(unsigned long *dst, const unsigned long *src1,
			const unsigned long *src2, int nbits)
{
//	if (small_const_nbits(nbits))
//		return (*dst = *src1 & ~(*src2)) != 0;
	return __bitmap_andnot(dst, src1, src2, nbits);
}

static inline int atomic_inc_return(volatile atomic_t *v)
{
         unsigned long flags;
         int retval;
         cris_atomic_save(v, flags);
         retval = ++(v->counter);
         cris_atomic_restore(v, flags);
         return retval;
}

typedef __u16 __le16;
typedef __u16 __be16;
typedef __u32 __le32;
typedef __u32 __be32;
typedef __u64 __le64;
typedef __u64 __be64; 
typedef __u16 __sum16;
typedef __u32 __wsum;

#endif /*_V4L2_OSDEP_H_*/