/*
 *---------------------------------------------------------------------------
 *
 *                  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_META_C__
#define __DL_META_C__

#include <dl_meta.h>
 
//	Defines the default number of LW's (32 bits) of meta data.
//	XXX - Should this be changed to to 8?

#ifndef	META_CACHE_SIZE
#define	META_CACHE_SIZE		4
#endif

#if (META_CACHE_SIZE > 0)

// SRAM write registers used to flush meta data to SRAM. XXX

__declspec(sram_write_reg) dl_meta_t dlMetaFlush;

#ifdef DL_META_DATA_IN_READ_SXFER

// Use sram xfer registers for meta data cache in read only mode.

extern __declspec(sram_read_reg) dl_meta_t dlMeta;

#else 

#ifdef DL_META_DATA_IN_WRITE_SXFER

// Use sram xfer registers for meta data cache in write only mode.

extern __declspec(sram_write_reg) dl_meta_t dlMeta;

#else 

#ifdef DL_META_DATA_IN_READ_DXFER

// Use dram xfer registers for meta data cache in read only mode.

extern __declspec(dram_read_reg) dl_meta_t dlMeta;

#else 

#ifdef DL_META_DATA_IN_WRITE_DXFER

// Use dram xfer registers for meta data cache in write only mode.

extern __declspec(dram_write_reg) dl_meta_t dlMeta;

#else

// Use GPR's for meta data caching.

extern dl_meta_t dlMeta;

#endif	// META_DATA_IN_WRITE_DXFER	XXX
#endif	// META_DATA_IN_READ_DXFER
#endif	// META_DATA_IN_WRITE_SXFER
#endif	// META_DATA_IN_READ_SXFER

#endif	// (META_CACHE_SIZE > 0)

/**
******************************************************************************
* @ingroup Buffer Meta data API
* Dl_MetaLoadCache
*
* @description
*	Load Meta data from SRAM and cache it in regsiters.
*
* @param	bufHandle	IN	Buffer handle previously got from Dl_BufAlloc
* @param	numLw		IN	Number of Longwords (32bits) to load. 
* @param	sigRequested IN	Signal to use in I/O. 
* @return	Nothing
*
******************************************************************************/

INLINE void Dl_MetaLoadCache
(
	dl_buf_handle_t	bufHandle, 
	SIGNAL*			sigRequested, 
	unsigned int	numLongWords
)
{

	unsigned int	sramAddress;

	// Compute the SRAM address of the meta data. Convert start_lw to bytes.

	sramAddress = Dl_BufGetDesc(bufHandle);

	// Read the meta data from SRAM.

	sram_read((__declspec(sram_read_reg) void*) &dlMeta, 
		      (volatile __declspec(sram) void*) sramAddress, numLongWords, 
			  sig_done, sigRequested);

}


/**
******************************************************************************
* @ingroup Buffer Meta data API
* Dl_MetaFlushCache
*
* @description
*	Flush Meta data to SRAM
*
* @param	bufHandle	IN	Buffer handle previously got from Dl_BufAlloc
* @param	pReqSig		IN	Signal to use in I/O. 
* @param	sigActon	IN	What to do with the signal (sig_done, ctx_swap, sig_none)
* @param	startLw		IN	Starting Long Word (32bits) of the Meta Data. 
* @param	numLw		IN	Number of Longwords (32bits) to load. 
* @return	Nothing
*
******************************************************************************/

INLINE void
Dl_MetaFlushCache(
	dl_buf_handle_t	buf_handle, 
	SIGNAL*			req_sig, 
	unsigned int	sig_action,
	unsigned int	start_lw,
	unsigned int	num_lw)
{

	int sram_addr;
	int i;

	//	XXX - remember the dlMetaFlush variable is implicit in this function.
	//	But Dl_MetaLoadCache it passed as a parameter. Fix this.

	//	XXX Index mode with variable i is not yt supported.

#if	(META_CACHE_SIZE > 0)
	dlMetaFlush.value[0] = dlMeta.value[0];
#endif

#if	(META_CACHE_SIZE > 1)
	dlMetaFlush.value[1] = dlMeta.value[1];
#endif

#if	(META_CACHE_SIZE > 2)
	dlMetaFlush.value[2] = dlMeta.value[2];
#endif

#if	(META_CACHE_SIZE > 3)
	dlMetaFlush.value[3] = dlMeta.value[3];
#endif

#if	(META_CACHE_SIZE > 4)
	dlMetaFlush.value[4] = dlMeta.value[4];
#endif

#if	(META_CACHE_SIZE > 5)
	dlMetaFlush.value[5] = dlMeta.value[5];
#endif

#if	(META_CACHE_SIZE > 6)
	dlMetaFlush.value[6] = dlMeta.value[6];
#endif

#if	(META_CACHE_SIZE > 7)
	dlMetaFlush.value[7] = dlMeta.value[7];
#endif

	// Compute the SRAM address of the meta data. Convert start_lw to bytes.

	sram_addr = Dl_BufGetDesc(buf_handle) + (start_lw << 2);

	// Write the meta data to SRAM.

	sram_write((__declspec(sram_write_reg) void *) &dlMetaFlush, 
			   (volatile __declspec(sram) int *) sram_addr, num_lw, sig_done, req_sig);

}



INLINE void
Dl_MetaFlushCacheSkip0(
	dl_buf_handle_t	buf_handle, 
	SIGNAL*			req_sig, 
	unsigned int	sig_action,
	unsigned int	num_lw)
{

	int sram_addr;
	int i;

	//	XXX - remember the dlMetaFlush variable is implicit in this function.
	//	But Dl_MetaLoadCache it passed as a parameter. Fix this.

	//	XXX Index mode with variable i is not yt supported.

#if	(META_CACHE_SIZE > 1)
	dlMetaFlush.value[0] = dlMeta.value[1];
#endif

#if	(META_CACHE_SIZE > 2)
	dlMetaFlush.value[1] = dlMeta.value[2];
#endif

#if	(META_CACHE_SIZE > 3)
	dlMetaFlush.value[2] = dlMeta.value[3];
#endif

#if	(META_CACHE_SIZE > 4)
	dlMetaFlush.value[3] = dlMeta.value[4];
#endif

#if	(META_CACHE_SIZE > 5)
	dlMetaFlush.value[4] = dlMeta.value[5];
#endif

#if	(META_CACHE_SIZE > 6)
	dlMetaFlush.value[5] = dlMeta.value[6];
#endif

#if	(META_CACHE_SIZE > 7)
	dlMetaFlush.value[6] = dlMeta.value[7];
#endif

	// Compute the SRAM address of the meta data. Convert start_lw to bytes.
	//	Start Long Word is always 1

	sram_addr = Dl_BufGetDesc(buf_handle) + (1 << 2);

	// Write the meta data to SRAM.

	sram_write((__declspec(sram_write_reg) void *) &dlMetaFlush, 
			   (volatile __declspec(sram) int *) sram_addr, num_lw, sig_done, req_sig);

}



INLINE void
Dl_MetaFlushCache2(
	dl_buf_handle_t	buf_handle, 
	__declspec(sram_write_reg) dl_meta_t *sram_wxfer,
	SIGNAL*			req_sig, 
	unsigned int	sig_action,
	unsigned int	start_lw,
	unsigned int	num_lw)
{

	int sram_addr;
	int i;

	//	XXX - remember the dlMetaFlush variable is implicit in this function.
	//	But Dl_MetaLoadCache it passed as a parameter. Fix this.

	//	XXX Index mode with variable i is not yt supported.

#if	(META_CACHE_SIZE > 0)
	sram_wxfer->value[0] = dlMeta.value[0];
#endif

#if	(META_CACHE_SIZE > 1)
	sram_wxfer->value[1] = dlMeta.value[1];
#endif

#if	(META_CACHE_SIZE > 2)
	sram_wxfer->value[2] = dlMeta.value[2];
#endif

#if	(META_CACHE_SIZE > 3)
	sram_wxfer->value[3] = dlMeta.value[3];
#endif

#if	(META_CACHE_SIZE > 4)
	sram_wxfer->value[4] = dlMeta.value[4];
#endif

#if	(META_CACHE_SIZE > 5)
	sram_wxfer->value[5] = dlMeta.value[5];
#endif

#if	(META_CACHE_SIZE > 6)
	sram_wxfer->value[6] = dlMeta.value[6];
#endif

#if	(META_CACHE_SIZE > 7)
	sram_wxfer->value[7] = dlMeta.value[7];
#endif

	// Compute the SRAM address of the meta data. Convert start_lw to bytes.

	sram_addr = Dl_BufGetDesc(buf_handle) + (start_lw << 2);

	// Write the meta data to SRAM.

	sram_write((__declspec(sram_write_reg) void *) sram_wxfer, 
			   (volatile __declspec(sram) int *) sram_addr, num_lw, sig_done, req_sig);

}


INLINE void
Dl_MetaWrite(
	dl_buf_handle_t	buf_handle, 
	__declspec(sram_write_reg) dl_meta_t *sram_wxfer,
	unsigned int	buffer_next,
	unsigned int	buffer_size,
	unsigned int	offset,
	unsigned int	packet_size,
	unsigned int	free_list_id,
	unsigned int	rx_stat,
	unsigned int	header_type,
	unsigned int	input_port,
	unsigned int	output_port,
	unsigned int	next_hop_id,
	unsigned int	fabric_port,
	unsigned int	flow_id,
	unsigned int	class_id,
	unsigned int	packet_next,
	SIGNAL*		    req_sig, 
	unsigned int	sig_action,
	unsigned int	start_lw,
	unsigned int	num_lw)
{

	unsigned int sram_addr;
	unsigned int tmp;

	//	XXX - remember the dlMetaFlush variable is implicit in this function.
	//	But Dl_MetaLoadCache it passed as a parameter. Fix this.

	//	XXX Index mode with variable i is not yt supported.
	sram_wxfer->value[0] = buffer_next;
	tmp = buffer_size << 16;
	sram_wxfer->value[1] = tmp | offset;
	tmp = packet_size << 16;
	tmp |= free_list_id << 12;
	tmp |=rx_stat << 8;
	sram_wxfer->value[2] = tmp | header_type;
	tmp = input_port << 16;
	sram_wxfer->value[3] = tmp | output_port;
	tmp = next_hop_id << 16;
	sram_wxfer->value[4] = tmp | (fabric_port << 8);
	sram_wxfer->value[5] = flow_id;
	sram_wxfer->value[6] = class_id << 16;
//	sram_wxfer->value[7] = packet_next;

	// Compute the SRAM address of the meta data. Convert start_lw to bytes.

	sram_addr = Dl_BufGetDesc(buf_handle) + (start_lw << 2);

	// Write the meta data to SRAM.

	sram_write((__declspec(sram_write_reg) void *) sram_wxfer, 
			   (volatile __declspec(sram) int *) sram_addr, num_lw, sig_done, req_sig);

}

/**
******************************************************************************
* InitScratchRing
*
* Abstract
*	Initialize and setup scratch ring. Ring is setup at address specified by
*	rbase, ring number is specified by ring and the size of the ring as specifed 
*	by rSize.
*
* @param	rbase		IN	The base address of the ring in scratch memory. Should
*							be aligned on a 4 byte boundary.
* @param	rsize		IN	The size of the ring. Either 128, 256, 512 or 1024.
* @param	ring		IN	Ring number (0-15).
* @return	Nothing
*
******************************************************************************/
INLINE void
InitScratchRing(int rbase, int rsize, int ring)
{
	// Signals used in cap[write]
	SIGNAL 	cw1, cw2, cw3;

	// Initialize ring head to 0.
	__declspec(sram_write_reg) int _rhead = 0x0;

	// Initialize ring tail to 0.
	__declspec(sram_write_reg) int _rtail = 0x0;

	// Sets ring base.
	__declspec(sram_write_reg) int _rbase;

	// Set ring size.
	int _rsize;

	switch (rsize)
	{
		case 128 : _rsize = 0; break;
		case 256 : _rsize = 1; break;
		case 512 : _rsize = 2; break;
		case 1024: _rsize = 3; break;
	}

	// Ring size [31:30]. Hardware representation
	// 00 = 128
	// 01 = 256
	// 10 = 512
	// 11 = 1024
	//
	// [31:30]==0 => Ring size is 128
	_rbase = rbase | (_rsize << 30);

	// Initialize the Scratch Ring base (and size), head and tail.

	// Note: We can queue a max. of 4 commands to any external unit 
	// (like sram, dram, cap, etc). Beyond this limit the ME will stall.
	// It is the programmers responsibility to ensure this.

	// Since this is the only thread and ME that is queuing cmds at this time,
	// we can queue 3 commands safely.

	//asv-do change SCRATCH_RING_BASE_0 to SCRATCH_RING_BASE_/**/RN
	switch(ring) {

	case 0:
		cap_csr_write(&_rbase, csr_scratch_ring_base_0, sig_done, &cw1);
		cap_csr_write(&_rhead, csr_scratch_ring_head_0, sig_done, &cw2);
		cap_csr_write(&_rtail, csr_scratch_ring_tail_0, sig_done, &cw3);
		break;
	case 1:
		cap_csr_write(&_rbase, csr_scratch_ring_base_1, sig_done, &cw1);
		cap_csr_write(&_rhead, csr_scratch_ring_head_1, sig_done, &cw2);
		cap_csr_write(&_rtail, csr_scratch_ring_tail_1, sig_done, &cw3);
		break;
	case 2:
		cap_csr_write(&_rbase, csr_scratch_ring_base_2, sig_done, &cw1);
		cap_csr_write(&_rhead, csr_scratch_ring_head_2, sig_done, &cw2);
		cap_csr_write(&_rtail, csr_scratch_ring_tail_2, sig_done, &cw3);
		break;
	case 3:
		cap_csr_write(&_rbase, csr_scratch_ring_base_3, sig_done, &cw1);
		cap_csr_write(&_rhead, csr_scratch_ring_head_3, sig_done, &cw2);
		cap_csr_write(&_rtail, csr_scratch_ring_tail_3, sig_done, &cw3);
		break;

	case 4:
		cap_csr_write(&_rbase, csr_scratch_ring_base_4, sig_done, &cw1);
		cap_csr_write(&_rhead, csr_scratch_ring_head_4, sig_done, &cw2);
		cap_csr_write(&_rtail, csr_scratch_ring_tail_4, sig_done, &cw3);
		break;

	case 5:
		cap_csr_write(&_rbase, csr_scratch_ring_base_5, sig_done, &cw1);
		cap_csr_write(&_rhead, csr_scratch_ring_head_5, sig_done, &cw2);
		cap_csr_write(&_rtail, csr_scratch_ring_tail_5, sig_done, &cw3);
		break;

	case 6:
		cap_csr_write(&_rbase, csr_scratch_ring_base_6, sig_done, &cw1);
		cap_csr_write(&_rhead, csr_scratch_ring_head_6, sig_done, &cw2);
		cap_csr_write(&_rtail, csr_scratch_ring_tail_6, sig_done, &cw3);
		break;

	case 7:
		cap_csr_write(&_rbase, csr_scratch_ring_base_7, sig_done, &cw1);
		cap_csr_write(&_rhead, csr_scratch_ring_head_7, sig_done, &cw2);
		cap_csr_write(&_rtail, csr_scratch_ring_tail_7, sig_done, &cw3);
		break;

	case 8:
		cap_csr_write(&_rbase, csr_scratch_ring_base_8, sig_done, &cw1);
		cap_csr_write(&_rhead, csr_scratch_ring_head_8, sig_done, &cw2);
		cap_csr_write(&_rtail, csr_scratch_ring_tail_8, sig_done, &cw3);
		break;

	case 9:
		cap_csr_write(&_rbase, csr_scratch_ring_base_9, sig_done, &cw1);
		cap_csr_write(&_rhead, csr_scratch_ring_head_9, sig_done, &cw2);
		cap_csr_write(&_rtail, csr_scratch_ring_tail_9, sig_done, &cw3);
		break;

	case 10:
		cap_csr_write(&_rbase, csr_scratch_ring_base_10, sig_done, &cw1);
		cap_csr_write(&_rhead, csr_scratch_ring_head_10, sig_done, &cw2);
		cap_csr_write(&_rtail, csr_scratch_ring_tail_10, sig_done, &cw3);
		break;

	case 11:
		cap_csr_write(&_rbase, csr_scratch_ring_base_11, sig_done, &cw1);
		cap_csr_write(&_rhead, csr_scratch_ring_head_11, sig_done, &cw2);
		cap_csr_write(&_rtail, csr_scratch_ring_tail_11, sig_done, &cw3);
		break;


	default:
		//	XXX - Put an error msg here???
		break;
	}

	wait_for_all(&cw1, &cw2, &cw3);

}

/**
******************************************************************************
* @ingroup Buffer Meta data API
* Dl_MetaGetBufferNext
*
* @description
*	Gets the next pointer in the meta data. In the case of chained (linked list)
*	buffer this next pointer indicates the next buffer in the chain. The format of 
*	this pointer (eop, sop, cellcount(6bits), offset (24 bits)) is such that it can
*	be directly used by the SRAM Q-Array to queue this buffer.
*
* @param	Nothing
* @return	The next pointer.
*
******************************************************************************/
INLINE int 
Dl_MetaGetBufferNext(void)
{
	/*	XXX - Is this function really required? Findout who is using.*/
	 return(dlMeta.value[0]);
}


#endif	// __DL_META_C__



