/*
 *---------------------------------------------------------------------------
 *
 *                  I N T E L   P R O P R I E T A R Y
 *
 *     COPYRIGHT (c)  2002 BY  INTEL  CORPORATION.  ALL RIGHTS
 *     RESERVED.   NO  PART  OF THIS PROGRAM  OR  PUBLICATION  MAY
 *     BE  REPRODUCED,   TRANSMITTED,   TRANSCRIBED,   STORED  IN  A
 *     RETRIEVAL SYSTEM, OR TRANSLATED INTO ANY LANGUAGE OR COMPUTER
 *     LANGUAGE IN ANY FORM OR BY ANY MEANS, ELECTRONIC, MECHANICAL,
 *     MAGNETIC,  OPTICAL,  CHEMICAL, MANUAL, OR OTHERWISE,  WITHOUT
 *     THE PRIOR WRITTEN PERMISSION OF :
 *
 *                        INTEL  CORPORATION
 *
 *                     2200 MISSION COLLEGE BLVD
 *
 *               SANTA  CLARA,  CALIFORNIA  95052-8119
 *
 *---------------------------------------------------------------------------
 */

#ifndef __DL_BUF_C__
#define __DL_BUF_C__
#include <dl_system.h>
#include <dl_buf.h>

/**
******************************************************************************
* @ingroup Packet Buffer API
* Dl_BufInit
*
* @description
*	Initializes the buffer free list. This function should be called 
*	once before any of the other Dl_Buf functions can be called.
*	Typically this function will create all the freelist of buffers.
*	Currently only one free list is created.
*
* @param	Nothing
* @return	Nothing
*
******************************************************************************/
INLINE void 
Dl_BufInit()
{
	ixp_buf_freelist_create(AVLBL_PKT_BUFFERS, BUF_FREE_LIST0, BUF_POOL);
}

/**
******************************************************************************
* @ingroup Packet Buffer API
* Dl_BufAlloc
*
* @description
*	Allocates a free packet buffer. If no buffer is available will 
*	return 0 in buffer handle. There may be multiple pool of buffers
*	in which case the caller specifies the pool from which this buffer
*	needs to be allocated.
*
* @param	bufHandle	OUT Handle of the newly allocated buffer. The SOP 
*							and count fields will be set to 0. EOP Field 
*							WILL be set to 1. bufHandle MUST be a SRAM 
*							Transfer Register.
* @param	freeList	IN	Specifies a free list ID. (0-63)
* @param	dBase		IN	DRAM base address for this pool
* @param	dSize		IN	Size of each buffer in DRAM
* @param	sBase		IN	SRAM base address for this pool. (for Meta data)
* @param	sSize		IN	Size of meta data for each buffer.
* @param	reqSig		IN	Signal to use in the I/O operation.
* @param	sigAction	IN	What to do with the signal(sig_done, ctx_swap).
* @param	Q_OPTION	IN	ignored. Pls specify ___ ( 3 underscores as argument)
* @return	Nothing
*
******************************************************************************/

INLINE void 
Dl_BufAlloc(
	__declspec(sram_read_reg)dl_buf_handle_t* bufHandle,
    pool_t			freeList, 
    unsigned int	dBase, 
    unsigned int	dSize, 
    unsigned int	sBase, 
    unsigned int	sSize,
	SIGNAL*			reqSig, 
	unsigned int	sigAction, 
	queue_t			Q_OPTION)
{

	ixp_buf_alloc((void *) bufHandle, freeList, dBase, dSize, sBase, sSize, reqSig, \
					sigAction, ___);
}

/**
******************************************************************************
* @ingroup Packet Buffer API
* Dl_BufFree
*
* @description
*	Frees the buffer that was previously allocated using dl_BufAlloc.
*	Only one buffer can be freed at a time by this function. Chained buffers
*	(for big packets) are not supported by this function. EOP, SOP and cell count 
*	in the buffer handle will all be reset to zero by this function. So the user 
*	need not bother resetting them to zero before freeing.
*
* @param	bufHandle	IN	Buffer handle previously got from Dl_BufAlloc
* @param	freeList	IN	Specifies a free list ID. (0-63)
* @param	dBase		IN	DRAM base address for this pool
* @param	dSize		IN	Size of each buffer in DRAM
* @param	sBase		IN	SRAM base address for this pool. (for Meta data)
* @param	sSize		IN	Size of meta data for each buffer.
* @return	Nothing
*
******************************************************************************/
INLINE void 
Dl_BufFree(
	dl_buf_handle_t 	bufHandle, 
    pool_t				freeList, 
    unsigned int		dBase, 
    unsigned int		dSize, 
    unsigned int		sBase, 
    unsigned int		sSize)
{

	ixp_buf_free(bufHandle, freeList, dBase, dSize, sBase, sSize);
}

/**
******************************************************************************
* @ingroup Packet Buffer API
* Dl_BufGetDesc
*
* @description
*	Given an opaq handle, this function returns the sram address where the 
*	meta data (called the Buffer descriptor) refered to by the buffer handle 
*	is present. The lower 24 bits of the handle indicates the sram address.
*	Further arithmatic on this 24 bit content may or may not be required depending
*	on the implementation. (In this case no additional arithmatic is required. 
*	The address	returned is an absolute address and not an offset from a given 
*	base address).
*
* @note
*	Currently Only Channel of SRAM for Meta data is supported
*
* @param	bufHandle	IN	Buffer handle previously got from Dl_BufAlloc
* @return	sram byte address of the meta data.
*
******************************************************************************/
INLINE unsigned int 
Dl_BufGetDesc(dl_buf_handle_t bufHandle)
{
	// 	Mask off ms 8 bits of buf_handle.
	// 	The ls 24 bits of buf_handle represent the sram address in LW's.
	// 	Convert ls 24 bits of buf_handle from LW address to byte address.
	//	Note: Only Channel 0 of SRAM is supported by this function.
	return (bufHandle.lw_offset << 2);
}

/**
******************************************************************************
* @ingroup Packet Buffer API
* Dl_BufGetData
*
* @description
*	Given an opaq handle, this function returns the sdram address where the 
*	packet data for the buffer refered to by this handle  is present. 
*	The lower 24 bits of the buffer handle contains the sram offset for 
*	meta data. From this we calculate the dram offset as follows.
*
*	meta 	= buf_handle & 0xffffff;
*	index 	= (meta - sram base) / sizeof (meta data)
*	data 	= sdram base + index * size of packet buffer (in dram)
*
*	However the above calculation is optimised as follows (grouping all constants 
*	together)
*	
*	DL_DS_RATIO = Sizeof (Packet buffer) / Sizeof (Meta data)
*	DL_REL_BASE = BUF_SDRAM_BASE - (BUF_SRAM_BASE * DL_DS_RATIO)
*	Data = DL_REL_BASE + (HANDLE & 0xFFFFFF) * DL_DS_RATIO
*			
*	DL_DS_RATIO and DL_REL_BASE	are constants which can be defined at compile/load 
*	time so that Data = ...can be coded in two instructions.
*
* @note
*	Currently Only Channel of SRAM for Meta data is supported
*
* @param	bufHandle	IN	Buffer handle previously got from Dl_BufAlloc
* @return	sdram byte address where data begins for this buffer.
*
******************************************************************************/
INLINE unsigned int 
Dl_BufGetData(dl_buf_handle_t bufHandle)
{
	unsigned int sdramOffset;

	// 	Mask off ms 8 bits of buf_handle.
	// 	The ls 24 bits of buf_handle represent the sram address in LW's.
	// 	Convert ls 24 bits of buf_handle from LW address to byte address (shift by 2)
	// 	Convert this sram byte address to the corres. dram address (shift by MULT_FACTOR)
	//	Note: Only SRAM channel 0 is supported by this function.

	sdramOffset = (bufHandle.lw_offset) << (MULT_FACTOR + 2);

/* nizhner 8/17/04: added support for load-time constants */
#ifndef USE_IMPORT_VAR

#if (DL_REL_BASE > 0)			
	sdramOffset +=DL_REL_BASE;
#endif

#else /* USE_IMPORT_VAR */
	sdramOffset += DL_REL_BASE;
#endif
	return sdramOffset;
}


/**
******************************************************************************
* @ingroup Packet Buffer API
* Dl_BufGetDataFromMeta
*
* @description
*	This function is the same as the dl_BufGetData. Instead of taking a buffer 
*	handle as an input parameter, it takes the sram offset where the buffer meta
*	data is present (Calling dl_BufGetDesc[bufHandle] will give you that 
*	sram offset). It saves a couple of instruction.
*
* @note
*	Currently Only Channel of SRAM for Meta data is supported
*
* @param	sramOffset	IN	Meta data address in SRAM for this buffer
* @return	sdram byte address where data begins for this buffer.
*
* @see		dl_BufGetData
******************************************************************************/
INLINE unsigned int 
Dl_BufGetDataFromMeta(unsigned int sramOffset)
{
	unsigned int sdramOffset;

	// Convert sram byte address to the corres. dram address (shift by MULT_FACTOR)
	sdramOffset = sramOffset << MULT_FACTOR;

/* nizhner 8/17/04: added support for load-time constants */
#ifndef USE_IMPORT_VAR

#if (DL_REL_BASE > 0)			
	sdramOffset +=DL_REL_BASE;
#endif
#else /* USE_IMPORT_VAR */
	sdramOffset += DL_REL_BASE;
#endif

	return sdramOffset;
}


/**
******************************************************************************
* @ingroup Packet Buffer API
* Dl_BufDrop
*
* @description
*	Drop the buffer. This is the same as freeing a buffer.
*
* @note
*	Right now we assume only one free list. 
*
* @param	bufHandle	IN	Buffer handle previously got from Dl_BufAlloc
* @return	Nothing
*
* @see		dl_BufFree
******************************************************************************/
INLINE void 
Dl_BufDrop(dl_buf_handle_t bufHandle)
{
	Dl_BufFree(bufHandle, BUF_FREE_LIST0, BUF_POOL);
}


/**
******************************************************************************
* @ingroup Packet Buffer API
* Dl_BufDropChain
*
* @description
*	Drop a buffer chain, used for big packets.
*
* @note
*	Right now we assume only one free list. 
*
* @param	bufHandle		IN	Buffer handle previously got from Dl_BufAlloc
* @param	bufEopHandle	IN	Buffer handle containg EOP. 
* @return	Nothing
*
* @see		dl_BufFree
******************************************************************************/
INLINE void 
Dl_BufDropChain(dl_buf_handle_t bufHandle, dl_buf_handle_t bufEopHandle)
{

//#if	TO_BE_INCLUDED_LATER

	/*
	 *	This function requires the followinf #defines.
	 *	DL_DROP_RING_FULL and a value for dl_drop_ring.
	 */

	__declspec(sram_write_reg) int sWrite[3];
	SIGNAL sigScratchWrite;
	unsigned int dropRing;

	//	Check if the ring this full.

	while (inp_state_test(DL_DROP_RING_FULL))
		;

	sWrite[0] = bufHandle.value;
	sWrite[1] = bufEopHandle.value;
	sWrite[2] = QM_DROP_QUEUE | (1 << 31);	// The msb is always set to 1, to prevent producing a value of 0 on to the ring.

	dropRing  = DL_DROP_RING << 2;

	scratch_put_ring(sWrite, (volatile void __declspec(scratch) *)dropRing, 3, sig_done, &sigScratchWrite);

//#endif

}


#endif // __DL_BUF_C__