#ifndef FIFOBUF_H
#define FIFOBUF_H


#define FIFO_BUFFER_IN_Y     (1 << 0) /* Buffer is allocated to Y-memory  */
#define FIFO_READ_NON_BLOCK  (1 << 1) /* Read always requested amount     */
#define FIFO_READ_PARTIAL    (1 << 2) /* Read multiple elementSize        */
#define FIFO_READ_SIZE_ONLY  (1 << 3) /* Read words%elementSize != 0 return 0 */

#define FIFO_WRITE_NON_BLOCK (1 << 4) /* Write always requested amount    */
#define FIFO_WRITE_PARTIAL   (1 << 5) /* Write multiple elementSize       */
#define FIFO_WRITE_OVER      (1 << 6) /* Overflow overwrites oldest data  */
#define FIFO_WRITE_SIZE_ONLY (1 << 7) /* Write words%elementSize != 0 return 0 */

#define FIFO_READ_FLAGS  (FIFO_READ_NON_BLOCK  | FIFO_READ_PARTIAL  | FIFO_READ_SIZE_ONLY)
#define FIFO_WRITE_FLAGS (FIFO_WRITE_NON_BLOCK | FIFO_WRITE_PARTIAL | FIFO_WRITE_OVER | FIFO_WRITE_SIZE_ONLY)
#define FIFO_USER_MASK   (FIFO_READ_FLAGS      | FIFO_WRITE_FLAGS)
#define FIFO_SYS_MASK    (FIFO_BUFFER_IN_Y)

union fifoPointer {
	u_int16 *x;
	__mem_y u_int16 *y;
	u_int16 u;
};

struct fifoBuf {
	union fifoPointer wr;        /* Write pointer       */
	union fifoPointer rd;        /* Read pointer        */
	union fifoPointer buf;       /* Buffer start        */
	u_int16 bufSize;             /* Buffer size         */
        u_int16 modifier;            /* Modifier for buf    */
	u_int16 mutex;               /* R/W access mutex    */
	u_int16 flags;               /* operation flags     */
	u_int16 elementSize;         /* Size of R/W element */
	/* Above: FifoBuf private. Below: User mod OK       */
	u_int32 overflows;           /* Overflow counter    */
	u_int32 underflows;          /* Underflow counter   */
	void *extension;             /* Res: FiFoBuf future */
	void *userData;              /* User pointer        */
};
/* Return number of words filling the FIFO */
u_int16 FifoFill(register struct fifoBuf *fifo);
/* Return number of words available in the FIFO */
u_int16 FifoFree(register struct fifoBuf *fifo);

/* Read words from fifo to Y-mem dest, return read words */
u_int16 FifoReadY(register struct fifoBuf *fifo, register __mem_y u_int16 *dest, register u_int16 words);
/* Read words from fifo to X-mem dest, return read words */
u_int16 FifoRead(register struct fifoBuf *fifo, register u_int16 *dest, register u_int16 words);

/* write words to fifo from Y-mem source, return written words */
u_int16 FifoWriteY(register struct fifoBuf *fifo, register __mem_y u_int16 *source, register u_int16 words);
/* write words to fifo from X-mem source, return written words */
u_int16 FifoWrite(register struct fifoBuf *fifo, register u_int16 *source, register u_int16 words);

/* Raw word based blocking fifo access */
u_int16 FifoGet(register struct fifoBuf *fifo);
void FifoPut(register struct fifoBuf *fifo, register u_int16 data);

/* Modify flags if non-NULL, modify elementSize if non-NULL and always return flags of the FIFO */
u_int16 FifoFeatures(register struct fifoBuf *fifo, register u_int16 *pUserFlags, register u_int16 *pSize);

/* (De-)Allocator for fifoBuf structure and memory buffers.
 *
 * Works somewhat similar like realloc() NULL fifo with size
 * allocates, fifo with size modifies buffer size and useY (bool)
 * selects buffer memory.  Size of 0 releases buffers and fifo
 * structure and return NULL.
 */
struct fifoBuf *FifoRealloc(register struct fifoBuf *fifo, register u_int16 size, register u_int16 useY);
#endif
